Architektur im Überblick
Quelldateien
Diese Seite wurde aus den folgenden Quelldateien erstellt:
- gpt_researcher/agent.py
- gpt_researcher/actions/init.py
- gpt_researcher/skills/init.py
- backend/server/app.py
- multi_agents/agent.py
- langgraph.json
- gpt_researcher/skills/image_generator.py
- gpt_researcher/skills/browser.py
- gpt_researcher/skills/deep_research.py
- backend/server/server_utils.py
- main.py
- setup.py
- multi_agents/main.py
- multi_agents_ag2/main.py
- docs/npm/index.js
- docs/discord-bot/index.js
- docs/src/pages/index.js
- frontend/nextjs/src/index.ts
- backend/report_type/deep_research/main.py
- Dockerfile
GPT Researcher ist eine autonome Forschungsplattform, die auf einer modularen Multi-Agenten-Architektur basiert. Das System kombiniert asynchrone Python-Backends mit WebSocket-basierter Echtzeitkommunikation und unterstützt sowohl einfache Forschungsanfragen als auch komplexe Multi-Agenten-Workflows.
Systemarchitektur
Die Architektur von GPT Researcher folgt einem Schichtenmodell, das die Trennung von Verantwortlichkeiten zwischen API-Schicht, Geschäftslogik und Agenten-Orchestrierung gewährleistet.
正在加载图表渲染器...
Erklärung der Architekturkomponenten:
-
Client-Ebene: Drei verschiedene Client-Typen können mit dem System interagieren — Web-Frontend, NPM-SDK für JavaScript-Integrationen und ein Discord-Bot für Community-Interaktionen (docs/npm/index.js:1-123, docs/discord-bot/index.js:17-78)
-
API-Schicht: FastAPI fungiert als zentrale Schnittstelle mit Pydantic-Modellen für Request-Validierung. Die Schicht unterstützt sowohl REST-Endpunkte als auch WebSocket-Verbindungen für Echtzeit-Streaming (backend/server/app.py:52-67)
-
Kern-Engine: Der GPT Researcher Haupt-Agent koordiniert alle Forschungsaktivitäten und nutzt Skills für spezialisierte Aufgaben sowie Actions für Workflow-Orchestrierung (gpt_researcher/skills/init.py:1-15)
-
Multi-Agenten-System: ChiefEditorAgent orchestriert komplexe Forschungsaufgaben durch Koordination mehrerer speialisierter Agenten über LangGraph (multi_agents/agent.py:1-16)
Backend-Architektur API-Endpunkte
Das Backend basiert auf FastAPI und bietet eine asynchrone Architektur mit umfassender WebSocket-Unterstützung für Echtzeit-Updates während des Forschungsprozesses.
Datenmodelle und Request-Handling
Die API definiert zwei primäre Request-Modelle:
python1class ResearchRequest(BaseModel): 2 task: str 3 report_type: str 4 report_source: str 5 tone: str 6 headers: dict | None = None 7 repo_name: str 8 branch_name: str 9 generate_in_background: bool = True 10 11class ChatRequest(BaseModel): 12 model_config = ConfigDict(extra="allow") 13 report: str 14 messages: List[Dict[str, Any]]
Verantwortlichkeiten der Modelle:
| Modell | Zweck | Pflichtfelder |
|---|---|---|
ResearchRequest | Startet neue Forschungsaufgaben | task, report_type, report_source, tone |
ChatRequest | Follow-up-Fragen zu bestehenden Reports | report, messages |
Server-Initialisierung und Logging
Der Haupteinstiegspunkt konfiguriert Uvicorn mit strukturierter Protokollierung:
python1logging.basicConfig( 2 level=logging.INFO, 3 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 4 handlers=[ 5 logging.FileHandler('logs/app.log'), 6 logging.StreamHandler() 7 ] 8)
Die Logging-Konfiguration unterdrückt zusätzlich verbose FontTools-Ausgaben, um die Lesbarkeit der Logs zu verbessern.
WebSocket-Kommunikation und Logs-Handler
Der CustomLogsHandler implementiert eine duale Speicherstrategie — Echtzeit-WebSocket-Streaming und persistente JSON-Protokollierung:
python1class CustomLogsHandler: 2 def __init__(self, websocket, task: str): 3 self.logs = [] 4 self.websocket = websocket 5 sanitized_filename = sanitize_filename(f"task_{int(time.time())}_{task}") 6 self.log_file = os.path.join("outputs", f"{sanitized_filename}.json")
(backend/server/server_utils.py:33-123)
Fehlerbehandlung:
- Automatische Dateinamen-Sanitisierung verhindert Path-Traversal-Angriffe
- Fallback auf lokale Speicherung bei WebSocket-Fehlern
- Strukturierte JSON-Logs mit Zeitstempeln für Nachvollziehbarkeit
Modulare Skills Komponenten
Das Skills-System implementiert eine klare Trennung der Verantwortlichkeiten durch spezialisierte Klassen, die jeweils einen definierten Aspekt des Forschungsprozesses abdecken.
Skill-Klassen-Übersicht
python1from .context_manager import ContextManager 2from .researcher import ResearchConductor 3from .writer import ReportGenerator 4from .browser import BrowserManager 5from .curator import SourceCurator 6from .image_generator import ImageGenerator 7 8__all__ = [ 9 'ResearchConductor', 10 'ReportGenerator', 11 'ContextManager', 12 'BrowserManager', 13 'SourceCurator', 14 'ImageGenerator', 15]
(gpt_researcher/skills/init.py:1-15)
Grenzen der Skill-Verantwortlichkeiten:
| Skill | Zuständig für | Nicht zuständig für |
|---|---|---|
ResearchConductor | Durchführung der Web-Recherche | Berichtsgenerierung |
ReportGenerator | Schreiben des finalen Reports | Quellensammlung |
BrowserManager | Bildverarbeitung, Deduplizierung | Textanalyse |
ImageGenerator | KI-gestützte Bilderstellung | Content-Extraktion |
SourceCurator | Quellenbewertung | Content-Generierung |
ImageGenerator: Erweiterbare Provider-Architektur
Der ImageGenerator demonstriert das Erweiterbarkeitsmuster des Systems:
python1class ImageGenerator: 2 def __init__(self, researcher): 3 self.researcher = researcher 4 self.cfg = researcher.cfg 5 self.image_provider = None 6 self.max_images = getattr(self.cfg, 'image_generation_max_images', 3) 7 self.generated_images: List[Dict[str, Any]] = [] 8 self._init_provider()
(gpt_researcher/skills/image_generator.py:20-419)
Initialisierungslogik:
- Provider-Instanziierung nur wenn
image_generation_enabled=True - Verfügbarkeitsprüfung vor Aktivierung
- Graceful Degradation bei fehlenden API-Keys
BrowserManager: Bildverarbeitung mit Deduplizierung
Die select_top_images-Methode implementiert Hash-basierte Deduplizierung:
python1def select_top_images(self, images: list[dict], k: int = 2) -> list[str]: 2 unique_images = [] 3 seen_hashes = set() 4 current_research_images = self.researcher.get_research_images() 5 6 for img in sorted(images, key=lambda im: im["score"], reverse=True): 7 img_hash = get_image_hash(img['url']) 8 if (img_hash and img_hash not in seen_hashes 9 and img['url'] not in current_research_images): 10 seen_hashes.add(img_hash) 11 unique_images.append(img["url"]) 12 if len(unique_images) == k: 13 break 14 return unique_images
(gpt_researcher/skills/browser.py:86-115)
Fehlerbehandlung:
get_image_hashgibtNonebei ungültigen URLs zurück- Sortierung nach Score stellt Relevanz sicher
- Cross-Reference mit existierenden Bildern verhindert Duplikate
Actions Workflow-Orchestrierung
Die Actions-Schicht stellt die operationale Schnittstelle zwischen High-Level-Workflows und Low-Level-Skills dar.
Verfügbare Actions
python1from .retriever import get_retriever, get_retrievers 2from .query_processing import plan_research_outline, get_search_results 3from .agent_creator import extract_json_with_regex, choose_agent 4from .web_scraping import scrape_urls 5from .report_generation import ( 6 write_conclusion, summarize_url, 7 generate_draft_section_titles, generate_report, 8 write_report_introduction 9) 10from .markdown_processing import ( 11 extract_headers, extract_sections, 12 table_of_contents, add_references 13) 14from .utils import stream_output
(gpt_researcher/actions/init.py:1-27)
Kategorisierung der Actions:
| Kategorie | Actions | Zweck |
|---|---|---|
| Retrieval | get_retriever, get_retrievers | Suchmaschinen-Integration |
| Query Processing | plan_research_outline, get_search_results | Abfrageoptimierung |
| Scraping | scrape_urls, summarize_url | Content-Extraktion |
| Generation | generate_report, write_conclusion | Berichtserstellung |
| Markdown | extract_headers, table_of_contents | Formatierung |
Deep Research: Kontext-Management
Für tiefe Forschungsaufgaben implementiert das System ein Wortlimit-basiertes Trimming:
python1def trim_context_to_word_limit( 2 context_list: List[str], 3 max_words: int = MAX_CONTEXT_WORDS 4) -> List[str]: 5 total_words = 0 6 trimmed_context = [] 7 8 for item in reversed(context_list): 9 words = count_words(item) 10 if total_words + words <= max_words: 11 trimmed_context.insert(0, item) 12 total_words += words 13 else: 14 break 15 return trimmed_context
(gpt_researcher/skills/deep_research.py:23-37)
Design-Entscheidung: Reverse-Processing priorisiert neuere/relevantere Kontexte.
Multi-Agenten-Architektur
Für komplexe Forschungsaufgaben bietet GPT Researcher eine Multi-Agenten-Architektur mit ChiefEditorAgent als Koordinator.
ChiefEditorAgent-Initialisierung
python1from multi_agents.agents import ChiefEditorAgent 2 3chief_editor = ChiefEditorAgent({ 4 "query": "Is AI in a hype cycle?", 5 "max_sections": 3, 6 "follow_guidelines": False, 7 "model": "gpt-4o", 8 "guidelines": [ 9 "The report MUST be written in APA format", 10 "Each sub section MUST include supporting sources", 11 "The report MUST be written in spanish" 12 ], 13 "verbose": False 14}, websocket=None, stream_output=None) 15graph = chief_editor.init_research_team() 16graph = graph.compile()
Konfigurationsparameter:
| Parameter | Typ | Zweck |
|---|---|---|
query | str | Hauptforschungsfrage |
max_sections | int | Maximale Report-Abschnitte |
model | str | LLM-Modell-Auswahl |
guidelines | List[str] | Formatierungsregeln |
verbose | bool | Detailliertheit der Logs |
Asynchrone Task-Ausführung
python1async def run_research_task( 2 query, websocket=None, stream_output=None, 3 tone=Tone.Objective, headers=None 4): 5 task = open_task() 6 task["query"] = query 7 8 chief_editor = ChiefEditorAgent( 9 task, websocket, stream_output, tone, headers 10 ) 11 research_report = await chief_editor.run_research_task() 12 13 if websocket and stream_output: 14 await stream_output("logs", "research_report", research_report, websocket) 15 16 return research_report
Fehlerbehandlung:
- Validierung der
task.json-Konfiguration - Environment-Variable-Override für
STRATEGIC_LLM - WebSocket-Optionalität für Batch-Processing
Alternative AG2-Implementierung
Das System bietet eine parallele Multi-Agenten-Implementierung:
python1from multi_agents_ag2.agents import ChiefEditorAgent 2 3async def run_research_task(query, websocket=None, stream_output=None, 4 tone=Tone.Objective, headers=None): 5 task = open_task() 6 task["query"] = query 7 8 chief_editor = ChiefEditorAgent(task, websocket, stream_output, tone, headers) 9 research_report = await chief_editor.run_research_task() 10 11 return research_report
(multi_agents_ag2/main.py:1-60)
Client-Integration SDKs
GPT Researcher bietet mehrere Integrationsmöglichkeiten für verschiedene Anwendungsfälle.
JavaScript/Node.js SDK
Das NPM-Paket implementiert eine vollständige Client-Bibliothek:
javascript1class GPTResearcher { 2 constructor(options = {}) { 3 this.host = options.host || 'http://localhost:8000'; 4 this.socket = null; 5 this.responseCallbacks = new Map(); 6 this.logListener = options.logListener; 7 this.tone = options.tone || 'Reflective'; 8 } 9 10 async initializeWebSocket() { 11 const protocol = this.host.includes('https') ? 'wss:' : 'ws:'; 12 const cleanHost = this.host.replace('http://', '').replace('https://', ''); 13 const ws_uri = `${protocol}//${cleanHost}/ws`; 14 this.socket = new WebSocket(ws_uri); 15 } 16}
SDK-Features:
- Automatische Protokoll-Erkennung (WS/WSS)
- Callback-basierte Progress-Updates
- HTTP-Fallback für nicht-WebSocket-Umgebungen
Discord-Bot-Integration
Der Discord-Bot demonstriert die Vielseitigkeit der API:
javascript1client.on(Events.InteractionCreate, async interaction => { 2 if (interaction.isChatInputCommand()) { 3 if (interaction.commandName === 'ask') { 4 const modal = new ModalBuilder() 5 .setCustomId('myModal') 6 .setTitle('Ask the AI Researcher'); 7 8 const queryInput = new TextInputBuilder() 9 .setCustomId('queryInput') 10 .setLabel('Your question') 11 .setStyle(TextInputStyle.Paragraph); 12 } 13 } 14});
(docs/discord-bot/index.js:17-78)
Cooldown-Mechanismus: 30-Minuten-Intervall verhindert Spam im Help-Forum.
Datenfluss End-to-End-Aufrufkette
Der folgende Sequenzdiagramm zeigt den vollständigen Datenfluss von der Client-Anfrage bis zum fertigen Report:
正在加载图表渲染器...
Erklärung der Datenflussphasen:
-
Request-Phase: Client sendet
ResearchRequestan FastAPI, das denCustomLogsHandlerinitialisiert (backend/server/server_utils.py:33-123) -
Research-Phase:
ResearchConductornutzt Actions für Suchabfragen und Scraping, LLM generiert optimierte Queries (gpt_researcher/actions/init.py:1-27) -
Streaming-Phase: Progress-Updates werden über WebSocket an den Client gestreamt
-
Generation-Phase:
ReportGeneratorerstellt den finalen Report mit Referenzen (gpt_researcher/skills/init.py:1-15)
Modulabhängigkeiten Dependency Graph
Die folgende Grafik zeigt die Abhängigkeitsrichtungen zwischen den Kernmodulen:
正在加载图表渲染器...
Abhängigkeitsregeln:
- Entry Points (
main.py) importieren nur die App-Schicht - App-Schicht importiert Utils, nie umgekehrt
- Core-Agent ist unabhängig von Multi-Agenten-Systemen
- Skills und Actions sind gleichberechtigte Dependencies des Core-Agent
Technologie-Stack Design-Entscheidungen
| Technologie | Verwendungszweck | Begründung | Alternativen |
|---|---|---|---|
| FastAPI | REST & WebSocket API | Asynchrone Unterstützung, automatische OpenAPI-Dokumentation | Flask, Django |
| Pydantic | Datenvalidierung | Type-Safety, automatische Serialisierung | Marshmallow, attrs |
| Uvicorn | ASGI Server | Produktionsreife Performance, WebSocket-Support | Gunicorn, Hypercorn |
| WebSocket | Echtzeit-Streaming | Bidirektionale Kommunikation, geringe Latenz | Server-Sent Events |
| LangGraph | Agenten-Orchestrierung | Zustandsmaschinen-basierte Workflows | LangChain, AutoGen |
| asyncio | Asynchrone I/O | Non-Blocking Operationen für parallele Scraping-Tasks | Threading, Multiprocessing |
| Python 3.11+ | Laufzeitumgebung | Type-Hints-Verbesserungen, Performance-Optimierungen | Python 3.10, 3.9 |
| JSON | Logging & Datenspeicherung | Strukturierte Logs, einfache Parsing | SQLite, CSV |
Kern-Design-Entscheidungen:
-
Modulare Skill-Architektur: Ermöglicht einfache Erweiterung durch neue Skills ohne Core-Änderungen (gpt_researcher/skills/init.py:1-15)
-
Dual-Storage Logging: Kombiniert Echtzeit-WebSocket mit persistenten JSON-Logs für Nachvollziehbarkeit (backend/server/server_utils.py:33-123)
-
Graceful Degradation: ImageGenerator und andere optionale Features fallen bei fehlenden Dependencies elegant zurück (gpt_researcher/skills/image_generator.py:20-419)
-
Multi-Agenten-Optionalität: Einfache Forschungsaufgaben benötigen nicht die Komplexität des Multi-Agenten-Systems (multi_agents/agent.py:1-16)
-
Client-Agnostizismus: API-Design unterstützt Web, CLI, Discord und beliebige andere Clients (docs/npm/index.js:1-123)
Konfiguration Startprozess
Umgebungsvariablen
Das System nutzt dotenv für die Konfiguration:
python1from dotenv import load_dotenv 2load_dotenv()
Wichtige Umgebungsvariablen:
| Variable | Zweck | Standard |
|---|---|---|
STRATEGIC_LLM | Überschreibt LLM-Modell in Multi-Agenten | Aus task.json |
LANGCHAIN_API_KEY | Aktiviert LangSmith-Tracing | Optional |
OPENAI_API_KEY | LLM-Provider-Authentifizierung | Erforderlich |
Server-Start
python1if __name__ == "__main__": 2 import uvicorn 3 logger.info("Starting server...") 4 uvicorn.run(app, host="0.0.0.0", port=8000)
Startsequenz:
- Logging-Konfiguration wird initialisiert
- Umgebungsvariablen aus
.envgeladen - FastAPI-App aus
backend.server.appimportiert - Uvicorn startet auf Port 8000 mit 0.0.0.0 Binding
Paket-Installation
python1setup( 2 name="gpt-researcher", 3 version="0.14.7", 4 python_requires='>=3.11', 5 package_dir={'gpt_researcher': 'gpt_researcher'}, 6 packages=find_packages(exclude=exclude_packages), 7)
Exkludierte Pakete: Selenium, FastAPI, LangGraph werden nicht als Dependencies installiert, um Konflikte zu vermeiden.
