Cosa costruiremo
L’implementazione di riferimento è un piccolo progetto Python con poche parti ben definite:| Parte | Cosa fa |
|---|---|
| CLI | Accetta un argomento di ricerca, modello, provider, impostazioni di profondità, percorso di output e directory degli artefatti |
| Client Venice | Chiama chat completions, streaming chat completions e POST /augment/scrape |
| Layer di ricerca | Cerca su DuckDuckGo come default, con discovery opzionale di paper arXiv |
| Data model | Tiene traccia di URL delle fonti, URL canonici, chunk, evidenza, note, errori e report |
| Agente di ricerca | Pianifica le ricerche, legge le fonti, estrae l’evidenza, analizza le lacune, genera query di follow-up e scrive il report finale |
| Artifact writer | Memorizza record JSONL auditable per query, lacune di ricerca, risultati, fetch, chunk, source notes, bozze di report, errori e report |
- Chiedi a Venice di generare query di ricerca diversificate per l’argomento.
- Cerca sul web con uno o più provider.
- Deduplica gli URL prima di leggerli.
- Usa l’endpoint di scrape di Venice per convertire ogni pagina sorgente pubblica in Markdown.
- Suddividi le pagine lunghe in chunk.
- Chiedi a Venice di estrarre l’evidenza da ogni chunk.
- Chiedi a Venice di trasformare l’evidenza dei chunk in source notes.
- Identifica lacune di ricerca e problemi di bilanciamento delle fonti prima di generare query di follow-up.
- Chiedi a Venice di sintetizzare il report finale con citazioni in stile footnote.
Configurare il progetto
Il progetto di riferimento usa Python 3.13 euv, ma lo stesso codice funziona anche con un normale virtual environment.
Crea un nuovo progetto:
pip, crea un virtual environment e installa gli stessi pacchetti:
.env per lo sviluppo locale:
VENICE_MODEL così puoi cambiare il modello senza modificare il codice. L’implementazione di riferimento attualmente usa openai-gpt-55 come default, ma puoi sostituirlo con un altro modello di chat disponibile per il tuo account Venice.
Creare i data model
Prima di scrivere la logica dell’agente, definiremo gli oggetti che attraversano la pipeline. Questi modelli mantengono il resto del codice più facile da ragionare perché ogni fonte porta con sé la provenienza: da dove proviene, quale query l’ha trovata, quando è stata recuperata e come è stata suddivisa in chunk. Crearesearch_agent/models.py:
canonical_url, content_hash e chunks.
canonical_url permette all’agente di evitare di leggere ripetutamente la stessa fonte quando i risultati di ricerca differiscono solo per parametri di tracking o frammenti. content_hash aiuta a beccare pagine duplicate anche quando vivono a URL diversi. chunks ci permette di riassumere pagine lunghe in pezzi più piccoli invece di perdere evidenza utile per i limiti di contesto.
Aggiungi le funzioni helper sotto i dataclass:
Costruire il client Venice
Successivamente, creeremo un piccolo client Venice. Potresti usare l’SDK Python di OpenAI per chat completions perché Venice è compatibile con OpenAI, ma l’implementazione di riferimento usahttpx direttamente così lo stesso client può chiamare l’endpoint POST /augment/scrape di Venice.
Crea research_agent/venice.py:
from_env() tiene i segreti fuori dal codice sorgente. Rende anche conveniente lo sviluppo locale perché python-dotenv può caricare VENICE_API_KEY e VENICE_MODEL dal .env.
Ora aggiungi le chat completions:
_post_chat_stream() che legge eventi server-sent dalle streaming chat completions. Puoi iniziare senza streaming e poi aggiungerlo una volta che il resto del flusso di ricerca funziona.
Aggiungere i search provider
Il layer di ricerca ha due lavori: trovare URL di fonti e recuperare quegli URL tramite lo scraper di Venice. L’implementazione di riferimento usa l’endpoint HTML di DuckDuckGo per la ricerca web generale e l’Atom API di arXiv per i paper. Crearesearch_agent/web.py:
WebSearch coordina i provider e recupera le pagine:
Scrivere artefatti locali
Per i workflow di ricerca, l’auditability conta. Se il report finale dice qualcosa di sorprendente, dovresti poter ispezionare quale fonte ha portato a quella conclusione. Crearesearch_agent/artifacts.py:
Costruire l’agente di ricerca
Ora che abbiamo Venice, search, model e artefatti, possiamo costruire l’agente vero e proprio. Crearesearch_agent/agent.py:
models.py se non li hai ancora aggiunti:
ResearchAgent:
run() coordina i pass di ricerca:
seen_* sono ciò che impedisce all’agente di sprecare tempo su fonti duplicate. La dedupe per URL becca i link ripetuti. La dedupe per content hash becca mirror, post syndicati e pagine che redirezionano allo stesso contenuto finale.
Pianificare ricerche iniziali e di follow-up
La prima chiamata al modello trasforma l’argomento in query di ricerca:_gap_follow_up_queries(), che chiede a Venice di restituire sia record di lacune che query:
--artifacts è abilitato, questi record vengono scritti in research_gaps.jsonl. Questo ti dà un utile audit trail del perché l’agente ha cercato una particolare query di secondo pass.
Il parser dovrebbe essere indulgente. Se il modello restituisce JSON malformato, l’agente fa fallback all’argomento originale:
Leggere e riassumere le fonti
Ora raccogliamo le source notes. L’agente cerca ogni query, recupera ogni risultato tramite Venice scrape, suddivide il Markdown in chunk e riassume l’evidenza utile.Scrivere il report finale
Una volta che l’agente ha le source notes, può scrivere il report. Inizia con un report writer a singolo pass:Aggiungere la CLI
Ora ci serve un entry point da command-line. Creamain.py:
| Opzione | Cosa controlla |
|---|---|
--iterations | Numero di pass di ricerca |
--queries | Query di ricerca generate per pass |
--results | Risultati letti per provider per ogni query |
--providers | Provider di ricerca, come duckduckgo o duckduckgo,arxiv |
--max-sources | Numero massimo di fonti utili da raccogliere |
--chunk-chars | Dimensione approssimativa dei chunk prima dell’estrazione dell’evidenza dalla fonte |
--max-chunks-per-source | Numero di chunk riassunti per fonte |
--report-style | Profondità del report finale: brief, standard o deep |
--artifacts | Directory per record JSONL di audit |
--output | Path per il report Markdown finale |
Eseguire l’agente
Esegui un rapido pass di ricerca:brief per un briefing conciso source-backed, standard per un survey più completo e deep per il workflow a fasi outline/section/editor.
Salva artefatti auditable:
source_notes.jsonl mostra l’evidenza riassunta delle fonti, research_gaps.jsonl mostra perché sono state generate ricerche di follow-up ed errors.jsonl mostra le pagine che sono fallite durante search, scraping o sommarizzazione.
Note su privacy e affidabilità
Un agente di ricerca tocca diversi sistemi, quindi aiuta essere precisi su cosa va dove:| Layer | Cosa vede i dati |
|---|---|
| CLI locale | Argomento, configurazione, source notes, artefatti e report finali restano sulla tua macchina |
| Provider di ricerca | Le query di ricerca vengono inviate al provider che scegli, come DuckDuckGo o arXiv |
| Venice scrape | Gli URL di fonti pubbliche vengono inviati all’endpoint di scrape di Venice |
| Venice chat completions | Prompt, chunk delle fonti, source notes e istruzioni di generazione del report vengono inviati a Venice |
| File di output | I report Markdown e gli artefatti JSONL vengono scritti localmente |
POST /augment/search di Venice invece di interrogare DuckDuckGo direttamente. L’implementazione di riferimento usa provider pubblici leggeri così la demo resta facile da eseguire e comprendere.
Per l’affidabilità, mantieni questi default conservativi:
- Usa retry per le chiamate Venice e le richieste web.
- Aggiungi un piccolo
--request-delayse stai leggendo molte pagine dallo stesso host. - Limita
--max-sourcescosì argomenti ampi non corrono indefinitamente. - Salva
--artifactsper report importanti così puoi auditare l’output finale. - Tratta il report come un briefing, non come verità di base. Segui le citazioni fino alla fonte originale quando l’accuratezza conta.
Testare i pezzi
Non hai bisogno di richieste web live o chiamate Venice per testare la maggior parte del sistema. Il repo di riferimento usa classi fake di Venice e fake web per testare il loop di ricerca, il comportamento di dedupe, gli artefatti e i prompt del report. Un utile primo test è la canonicalizzazione degli URL:Benchmarking
Molti provider AI hanno ora i propri workflow di deep research, quindi il repo di riferimento include un semplice benchmark contro il tool Deep Research di Perplexity. A entrambi gli agenti è stato chiesto di scrivere un report sull’architettura dei framework di AI agent, poi i report generati sono stati committati nel repo GitHub. Non è inteso essere un benchmark formale. È un modo pratico per ispezionare la struttura del report, la copertura delle fonti, la qualità delle citazioni e se l’agente si concentra troppo su un singolo cluster di fonti. È anche per questo che l’implementazione aggiornata tracciaresearch_gaps.jsonl e il bilanciamento delle fonti prima delle ricerche di follow-up.
Estendere questo esempio
Una volta che l’agente baseline funziona, ecco alcuni modi pratici per migliorarlo:- Aggiungi un Venice search provider usando
POST /augment/search. - Memorizza report e artefatti in un piccolo database SQLite invece che in file JSONL.
- Aggiungi allowlist o blocklist di fonti per domini di ricerca affidabili.
- Aggiungi il supporto PDF combinando Venice scrape con il parsing di documenti per fonti che non espongono HTML pulito.
- Aggiungi un evaluation set di argomenti e tipi di fonti attesi così puoi confrontare la qualità della ricerca dopo modifiche ai prompt.
- Aggiungi uno step di review che chieda a Venice di trovare affermazioni non supportate nel report finale prima di salvarlo.