0Pricing
AI Agents · Lección

Patrón de ciclo de investigación profunda

Consulta → lectura → extracción → síntesis → nueva consulta: investigación de varios saltos.

Patrón de ciclo de investigación profunda es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.

¿Qué es el ciclo de investigación profunda?

Un ciclo de investigación profunda es un patrón de agente en el que este busca y lee información de forma iterativa, identifica lagunas de conocimiento y vuelve a buscar hasta reunir información suficiente para redactar una respuesta completa.

A diferencia de una única búsqueda, este patrón imita la forma de trabajar de un investigador: explorar → aprender → descubrir lo que se desconoce → profundizar.

Descripción general de la arquitectura del ciclo

El ciclo de investigación profunda consta de cinco fases que se repiten:

  1. Consulta inicial — busque utilizando la pregunta original del usuario
  2. Lea los resultados principales — extraiga los datos clave de las 3 mejores fuentes
  3. Identifique las lagunas — ¿qué preguntas importantes siguen sin respuesta?
  4. Consultas de seguimiento — genere búsquedas específicas para cubrir las lagunas
  5. Sintetice — combine todos los datos recopilados en una respuesta final
def deep_research(question, max_iterations=3):
    all_facts = []
    queries_used = [question]

    for iteration in range(max_iterations):
        results = search_and_rank(queries_used[-1])
        facts = extract_facts(results, question)
        all_facts.extend(facts)

        gaps = identify_knowledge_gaps(question, all_facts)
        if not gaps:
            print(f'Research complete after {iteration + 1} iterations')
            break

        follow_up = generate_follow_up_query(gaps)
        queries_used.append(follow_up)
        print(f'Iteration {iteration + 1}: {follow_up}')

    return synthesize_answer(question, all_facts)

Fase 1: búsqueda inicial

La primera búsqueda utiliza la pregunta original del usuario. Obtenga entre 3 y 5 resultados y extraiga el contenido de texto sin procesar. Esta fase busca amplitud: obtener una visión general del panorama del tema.

from tavily import TavilyClient
import os

client = TavilyClient(api_key=os.getenv('TAVILY_API_KEY'))

def initial_search(question, n_results=5):
    results = client.search(
        query=question,
        max_results=n_results,
        search_depth='advanced'  # deeper extraction for research tasks
    )
    return results.get('results', [])

# Also capture the direct answer if available
def get_direct_answer(question):
    results = client.search(query=question, max_results=3)
    return results.get('answer', '')  # Tavily's synthesized answer

Fase 2: extracción de datos clave

Envíe los resultados de búsqueda sin procesar al LLM y pídale que extraiga datos específicos y verificables relevantes para la pregunta de investigación. Los datos deben ser atómicos: una afirmación por elemento.

EXTRACT_FACTS_PROMPT = '''You are a research assistant.
From the search results below, extract all factual claims relevant to the question.

Question: {question}

Search results:
{results_text}

Return a JSON list of facts:
["GPT-4 was released in March 2023",
 "GPT-4 supports 128k context window",
 ...]

Only include verifiable facts. No opinions or summaries. JSON:'''

def extract_facts(results, question):
    import json
    results_text = '\n\n'.join(
        f"[{i+1}] {r['title']}\n{r['content'][:600]}"
        for i, r in enumerate(results)
    )
    response = llm_call(EXTRACT_FACTS_PROMPT.format(
        question=question, results_text=results_text
    ))
    return json.loads(response)

Fase 3: identificación de lagunas de conocimiento

Después de cada iteración de búsqueda, pregunte al LLM: dado lo que sabemos hasta ahora, ¿qué aspectos importantes de la pregunta original siguen sin abordarse?

Estas lagunas se convierten en las consultas de búsqueda de la siguiente ronda.

GAPS_PROMPT = '''You are a research analyst.

Original research question: {question}

Facts gathered so far:
{facts}

What important aspects of the question are still NOT covered by these facts?
List 2-3 specific knowledge gaps as a JSON array of strings.
If the question is fully answered, return an empty array [].

JSON:'''

def identify_knowledge_gaps(question, facts):
    import json
    facts_text = '\n'.join(f'- {f}' for f in facts)
    response = llm_call(GAPS_PROMPT.format(
        question=question, facts=facts_text
    ))
    return json.loads(response)

Fase 4: generación de consultas de seguimiento

Transforme las lagunas de conocimiento en consultas de búsqueda eficaces. Una laguna como «No conocemos el modelo de precios» se convierte en una consulta específica como «precio de la API de GPT-4 por token en 2024».

QUERY_GEN_PROMPT = '''Convert these knowledge gaps into specific web search queries.

Original topic: {topic}
Knowledge gaps:
{gaps}

Return a JSON array of search query strings.
Make each query specific and searchable.
JSON:'''

def generate_follow_up_queries(topic, gaps):
    import json
    gaps_text = '\n'.join(f'- {g}' for g in gaps)
    response = llm_call(QUERY_GEN_PROMPT.format(
        topic=topic, gaps=gaps_text
    ))
    queries = json.loads(response)
    return queries[:3]  # max 3 follow-up queries per iteration

Criterios de terminación

Sin unos criterios de terminación claros, el ciclo se ejecuta indefinidamente. Deténgalo cuando: (1) no se identifiquen lagunas, (2) se alcance el número máximo de iteraciones, (3) se agote el presupuesto de tokens o (4) los datos nuevos sean demasiado similares a los ya existentes (rendimientos decrecientes).

MAX_ITERATIONS = 4
MAX_FACTS = 50
MIN_NEW_FACTS_TO_CONTINUE = 3

def should_continue(gaps, all_facts, new_facts, iteration):
    if iteration >= MAX_ITERATIONS:
        print(f'Stopping: max iterations ({MAX_ITERATIONS}) reached')
        return False
    if not gaps:
        print('Stopping: no knowledge gaps found')
        return False
    if len(all_facts) >= MAX_FACTS:
        print(f'Stopping: fact budget ({MAX_FACTS}) reached')
        return False
    if len(new_facts) < MIN_NEW_FACTS_TO_CONTINUE:
        print(f'Stopping: diminishing returns ({len(new_facts)} new facts)')
        return False
    return True

if __name__ == '__main__':
    print('Continue?', should_continue(gaps=['gap1'], all_facts=['f'] * 10, new_facts=['f1', 'f2', 'f3'], iteration=1))
    print('Continue?', should_continue(gaps=[], all_facts=['f'] * 10, new_facts=['f1'], iteration=1))

Fase 5: síntesis de la respuesta final

Cuando termine el ciclo, envíe todos los datos recopilados al LLM para que los sintetice. La tarea del LLM es organizar los datos en una respuesta coherente y bien estructurada, con atribución de las fuentes.

SYNTHESIS_PROMPT = '''You are a research writer.

Original question: {question}

Researched facts (gathered from {n_iterations} search iterations):
{facts}

Write a comprehensive, well-structured answer based on these facts.
Format with clear sections. Be specific and cite facts where relevant.
If any aspect of the question could not be fully answered, say so.

Answer:'''

def synthesize_answer(question, all_facts, n_iterations):
    facts_text = '\n'.join(f'- {f}' for f in all_facts)
    return llm_call(SYNTHESIS_PROMPT.format(
        question=question,
        facts=facts_text,
        n_iterations=n_iterations
    ))

Seguimiento de fuentes entre iteraciones

En un ciclo con varias iteraciones, recopila datos de muchas fuentes diferentes. Registre la fuente de la que procede cada dato para que la respuesta final pueda citarlos con precisión.

def extract_facts_with_sources(results, question):
    import json

    PROMPT = '''Extract facts from these search results. For each fact include the source URL.

Question: {question}
Results: {results_text}

Return JSON list:
[{{"fact": "GPT-4 supports 128k context", "source": "https://openai.com/..."}}, ...]
JSON:'''

    results_text = '\n\n'.join(
        f"[URL: {r['url']}]\n{r['content'][:500]}"
        for r in results
    )
    response = llm_call(PROMPT.format(
        question=question, results_text=results_text
    ))
    return json.loads(response)

Ejecución de búsquedas en paralelo

Cuando tenga varias consultas de seguimiento, ejecútelas en paralelo mediante asyncio para reducir el tiempo total de investigación. Esto puede reducir un ciclo de 3 iteraciones de 30 a 15 segundos.

import asyncio

async def async_search(client, query):
    # Tavily has async support
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(
        None,
        lambda: client.search(query=query, max_results=3)
    )
    return result.get('results', [])

async def parallel_search(queries):
    tasks = [async_search(client, q) for q in queries]
    results_list = await asyncio.gather(*tasks)
    # Flatten
    return [r for results in results_list for r in results]

# Run in event loop
all_results = asyncio.run(parallel_search(follow_up_queries))

Eliminación de duplicados entre datos

A menudo, distintas fuentes expresan el mismo dato con palabras diferentes. Antes de la síntesis, elimine los datos duplicados mediante la similitud entre embeddings para evitar repetir varias veces la misma información en la respuesta final.

def deduplicate_facts(facts, similarity_threshold=0.92):
    if not facts:
        return facts

    # Get embeddings for all facts
    embeddings = [embed(f) for f in facts]
    unique_indices = [0]  # always keep first

    for i in range(1, len(facts)):
        is_duplicate = False
        for j in unique_indices:
            sim = cosine_similarity(embeddings[i], embeddings[j])
            if sim > similarity_threshold:
                is_duplicate = True
                break
        if not is_duplicate:
            unique_indices.append(i)

    unique_facts = [facts[i] for i in unique_indices]
    print(f'Deduplicated: {len(facts)} -> {len(unique_facts)} facts')
    return unique_facts

Comprobación de conocimientos

¿Cuál es la condición de terminación correcta para un ciclo de investigación profunda cuando no se encuentran lagunas de conocimiento?

Repaso: patrón de ciclo de investigación profunda

El patrón de ciclo de investigación profunda es: buscar → extraer datos → encontrar lagunas → generar consultas de seguimiento → repetir → sintetizar. Este proceso refleja la forma de trabajar de un investigador humano.

Decisiones clave de diseño: criterios de terminación (número máximo de iteraciones, ausencia de lagunas y rendimientos decrecientes), seguimiento de fuentes para la atribución, búsquedas en paralelo para aumentar la velocidad y eliminación de duplicados entre datos antes de la síntesis. Limite el ciclo a 3 o 4 iteraciones para equilibrar profundidad, coste y latencia.

Preguntas frecuentes

¿La lección «Patrón de ciclo de investigación profunda» es gratis?

Sí — el texto completo de «Patrón de ciclo de investigación profunda» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.

¿Qué aprenderé en «Patrón de ciclo de investigación profunda»?

Consulta → lectura → extracción → síntesis → nueva consulta: investigación de varios saltos. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Agents?

No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Patrón de ciclo de investigación profunda»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Agents?

Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Tavily y SerpAPI para búsquedas de agentes
  2. Clasificación y filtrado de resultados de búsqueda
  3. Patrón de ciclo de investigación profunda
  4. Combinación de búsqueda web con RAG
← Volver a AI Agents