Entwurf mehrstufiger Recherche-Schleifen
Planen → suchen → lesen → extrahieren → zusammenführen → wiederholen, bis die gewünschte Tiefe erreicht ist.
Entwurf mehrstufiger Recherche-Schleifen ist eine kostenlose AI Agents-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Agents-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.
Was ist eine Recherche-Schleife?
Eine Recherche-Schleife ist ein agentisches Muster, bei dem ein LLM plant, sucht, liest, extrahiert, Lücken erkennt und wiederholt, bis das Rechercheziel erreicht ist.
Im Gegensatz zu einer einmaligen Suche passt sich die Schleife an ihre Ergebnisse an – sie verfolgt unerwartete Hinweise und verwirft Sackgassen.
Phase 1: Frage in Teilfragen zerlegen
Der erste Schritt besteht darin, die Recherchefrage in Teilfragen zu zerlegen. Dadurch entsteht ein strukturierter Suchplan, und der Agent wird daran gehindert, ziellos zu browsen.
import openai, json
client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')
def decompose_question(question: str) -> list[str]:
prompt = (
f'Break this research question into 3-5 focused sub-questions.\n'
f'Each sub-question should be independently searchable.\n'
f'Question: "{question}"\n'
f'Return JSON: {{"sub_questions": ["..."]}}'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
return json.loads(resp.choices[0].message.content)['sub_questions']
questions = decompose_question('What are the main causes of inflation in 2024?')
print(questions)Phase 2: Websuche
Führen Sie für jede Teilfrage eine Websuche durch. Verwenden Sie eine Such-API (Serper, Brave, Bing), um eine Liste von URLs und Snippets abzurufen. Lesen Sie nicht alle Seiten – priorisieren Sie zunächst hochwertige Quellen.
import requests
SERPER_KEY = 'YOUR_SERPER_API_KEY'
def search_web(query: str, num_results: int = 5) -> list[dict]:
resp = requests.post(
'https://google.serper.dev/search',
headers={'X-API-KEY': SERPER_KEY, 'Content-Type': 'application/json'},
json={'q': query, 'num': num_results}
)
resp.raise_for_status()
results = resp.json().get('organic', [])
return [
{'title': r['title'], 'url': r['link'], 'snippet': r.get('snippet', '')}
for r in results
]Phase 3: Fakten lesen und extrahieren
Rufen Sie jede URL ab und extrahieren Sie die für die Teilfrage relevanten Schlüsselfakten. Verwenden Sie ein LLM, um den Artikel zu lesen und eine Liste von Fakten mit der Quell-URL zu erstellen.
import httpx
from bs4 import BeautifulSoup
def fetch_text(url: str, max_chars: int = 4000) -> str:
try:
resp = httpx.get(url, timeout=10, follow_redirects=True,
headers={'User-Agent': 'ResearchAgent/1.0'})
soup = BeautifulSoup(resp.text, 'html.parser')
for tag in soup(['script', 'style', 'nav', 'footer']):
tag.decompose()
return soup.get_text(separator=' ', strip=True)[:max_chars]
except Exception:
return ''
def extract_facts(text: str, question: str, url: str) -> list[dict]:
prompt = (
f'Extract key facts from the text that answer: "{question}"\n'
f'Return JSON: {{"facts": ["fact1", ...]}}\n\n'
f'TEXT:\n{text[:3000]}'
)
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
facts = json.loads(resp.choices[0].message.content).get('facts', [])
return [{'fact': f, 'source': url} for f in facts]Phase 4: Wissenslücken erkennen
Bitten Sie das LLM nach dem Lesen, die gesammelten Fakten zu überprüfen und zu ermitteln, was noch unbekannt ist. Diese Lücken werden zu den Suchanfragen der nächsten Runde.
def identify_gaps(original_question: str, facts: list[dict]) -> list[str]:
fact_text = '\n'.join(f'- {f["fact"]}' for f in facts[:20])
prompt = (
f'Original question: "{original_question}"\n'
f'Facts gathered so far:\n{fact_text}\n\n'
f'What key aspects are still unanswered? '
f'Return 0-3 follow-up search queries (0 if research is complete).\n'
f'JSON: {{"gaps": ["search query 1", ...]}}'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
return json.loads(resp.choices[0].message.content).get('gaps', [])Abbruchbedingungen
Die Schleife benötigt eine klare Abbruchbedingung, damit sie nicht endlos läuft. Beenden Sie sie, wenn:
- keine neuen Lücken erkannt werden
- in der letzten Iteration keine neuen Fakten hinzugefügt wurden
- die maximale Anzahl an Iterationen erreicht ist (Sicherheitslimit)
- die Gesamtzahl der Fakten einen Schwellenwert überschreitet (ausreichende Tiefe)
def should_continue(gaps: list[str], new_facts_this_round: int,
iteration: int, total_facts: int) -> bool:
if iteration >= 5:
return False # Hard cap: 5 iterations
if new_facts_this_round == 0:
return False # No new information found
if not gaps:
return False # LLM says research is complete
if total_facts >= 50:
return False # Sufficient depth reached
return True
if __name__ == '__main__':
print('Continue (has gaps, new facts)?', should_continue(['gap1'], 4, iteration=1, total_facts=10))
print('Continue (no new facts)?', should_continue(['gap1'], 0, iteration=1, total_facts=10))
Fakten deduplizieren
Mehrere Quellen berichten häufig über denselben Fakt. Deduplizieren Sie die Fakten, indem Sie das LLM bitten, semantisch gleichwertige Fakten zusammenzuführen und dabei die am besten belegte Version beizubehalten.
def deduplicate_facts(facts: list[dict]) -> list[dict]:
if len(facts) <= 3:
return facts
fact_text = '\n'.join(
f'{i}: {f["fact"]} (source: {f["source"]})' for i, f in enumerate(facts)
)
prompt = (
f'Remove duplicate or near-duplicate facts. Keep the most informative version.\n'
f'Return JSON: {{"keep_indices": [0, 1, ...]}}\n\n'
f'FACTS:\n{fact_text}'
)
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
indices = json.loads(resp.choices[0].message.content).get('keep_indices', [])
return [facts[i] for i in indices if i < len(facts)]Die vollständige Recherche-Schleife
Fassen Sie alle Phasen in einer einzigen Funktion research() zusammen, die die Schleife bis zum Abbruch steuert.
def research(question: str) -> dict:
all_facts = []
iteration = 0
# Phase 1: Decompose into sub-questions
queries = decompose_question(question)
while True:
new_facts_this_round = 0
for query in queries:
results = search_web(query, num_results=3)
for result in results:
text = fetch_text(result['url'])
if not text:
continue
facts = extract_facts(text, query, result['url'])
all_facts.extend(facts)
new_facts_this_round += len(facts)
all_facts = deduplicate_facts(all_facts)
gaps = identify_gaps(question, all_facts)
iteration += 1
if not should_continue(gaps, new_facts_this_round, iteration, len(all_facts)):
break
queries = gaps # next iteration searches for the gaps
return {'facts': all_facts, 'iterations': iteration}Quellenherkunft nachverfolgen
Jeder Fakt muss seine Quell-URL enthalten, damit der Abschlussbericht Quellenangaben einfügen kann. Entfernen Sie während der Verarbeitung niemals Quellenmetadaten – sie werden für die Zitierfunktion benötigt.
def add_fact(fact_list: list, fact_text: str, source_url: str, iteration: int):
fact_list.append({
'fact': fact_text,
'source': source_url,
'iteration': iteration,
'verified': False # set to True after cross-referencing
})
# Example:
facts_store = []
add_fact(facts_store, 'Global inflation peaked at 9.1% in June 2022',
'https://bls.gov/news.release/cpi.htm', iteration=1)
print(f'Logged {len(facts_store)} fact(s):')
for f in facts_store:
print(f" - {f['fact']} (source: {f['source']})")
Parallele Suche zur Beschleunigung
Sequenzielle Suchen sind langsam: 5 Abfragen × 3 URLs × 1 Abruf ergeben 15 sequenzielle HTTP-Aufrufe. Verwenden Sie concurrent.futures, um die Abrufe innerhalb jeder Iteration zu parallelisieren.
from concurrent.futures import ThreadPoolExecutor, as_completed
def parallel_research_round(queries: list[str]) -> list[dict]:
collected = []
def process_query(query):
results = search_web(query, num_results=3)
facts = []
for r in results:
text = fetch_text(r['url'])
if text:
facts.extend(extract_facts(text, query, r['url']))
return facts
with ThreadPoolExecutor(max_workers=4) as ex:
futures = {ex.submit(process_query, q): q for q in queries}
for future in as_completed(futures):
collected.extend(future.result())
return collectedFortschritt der Schleife überwachen
Protokollieren Sie jede Iteration, damit Sie nachvollziehen können, warum die Schleife beendet wurde oder länger als erwartet lief. Erfassen Sie die Anzahl der Abfragen, die hinzugefügten Fakten und die erkannten Lücken.
import logging
log = logging.getLogger('research_loop')
import sys
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
def log_iteration(iteration: int, queries: list[str],
new_facts: int, total_facts: int, gaps: list[str]):
log.info(
'Iteration %d | Queries: %d | New facts: %d | Total: %d | Gaps: %d',
iteration, len(queries), new_facts, total_facts, len(gaps)
)
if gaps:
for g in gaps:
log.debug(' Gap query: %s', g)
if __name__ == '__main__':
log_iteration(iteration=2, queries=['who are our top competitors?'], new_facts=4, total_facts=12, gaps=['pricing data'])
Was beendet die Recherche-Schleife, wenn keine neuen Informationen gefunden werden?
Das Verständnis der Abbruchbedingungen verhindert Endlosschleifen und stellt sicher, dass der Agent innerhalb eines angemessenen Zeitfensters Ergebnisse liefert.
Zusammenfassung zum Design von Recherche-Schleifen
Die mehrstufige Recherche-Schleife folgt dem Ablauf: zerlegen → suchen → lesen → extrahieren → Lücken erkennen → wiederholen. Beenden Sie sie, wenn keine Lücken mehr vorhanden sind, keine neuen Fakten gefunden werden oder eine feste maximale Iterationszahl erreicht ist.
Erfassen Sie immer die Quell-URLs zu jedem Fakt, parallelisieren Sie Suchen zur Beschleunigung und deduplizieren Sie Fakten vor der Synthese.
Häufig gestellte Fragen
Ist die Lektion „Entwurf mehrstufiger Recherche-Schleifen“ kostenlos?
Ja — der vollständige Text von „Entwurf mehrstufiger Recherche-Schleifen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Agents-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Entwurf mehrstufiger Recherche-Schleifen“?
Planen → suchen → lesen → extrahieren → zusammenführen → wiederholen, bis die gewünschte Tiefe erreicht ist. Du übst AI Agents mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um AI Agents zu starten?
Keine Vorkenntnisse erforderlich. AI Agents auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Entwurf mehrstufiger Recherche-Schleifen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser AI Agents-Lektion Code schreiben und ausführen?
Ja. Jede AI Agents-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Entwurf mehrstufiger Recherche-Schleifen
- Quellenprüfung und Zitierung
- Strukturierte Berichte generieren
- Faktenprüfung und Vermeidung von Halluzinationen