
È appena febbraio, e il DeepSearch è già emerso come il nuovo standard di ricerca nel 2025, con i principali attori come Google e OpenAI in prima linea attraverso i loro rilasci di DeepResearch (e sì, abbiamo orgogliosamente lanciato il nostro node-deepresearch
open-source lo stesso giorno). Perplexity ha seguito l'esempio con il loro DeepResearch, e X AI ha integrato le proprie capacità DeepSearch in Grok3, creando essenzialmente un'altra variante di DeepResearch. Mentre il concetto di deep search non è rivoluzionario – nel 2024 era essenzialmente denominato RAG o multi-hop QA – ha guadagnato uno slancio significativo dopo il rilascio di Deepseek-r1 alla fine di gennaio 2025. Lo scorso fine settimana, Baidu Search e Tencent WeChat Search hanno integrato Deepseek-r1 nei loro motori di ricerca. Gli ingegneri AI hanno scoperto che incorporando processi di pensiero e ragionamento lunghi nei sistemi di ricerca, possono ottenere una notevole accuratezza e profondità di recupero oltre quanto era precedentemente possibile.
Launch Date | Company | Product | License Type | Link |
---|---|---|---|---|
2025-01-20 | DeepSeek | DeepSeek-r1 release | Open source | DeepSeek-R1 |
2025-02-02 | DeepResearch | Proprietary | Google Gemini 2 | |
2025-02-02 | OpenAI | DeepResearch | Proprietary | Introducing Deep Research |
2025-02-02 | Jina AI | DeepSearch (node-deepresearch ) | Open source | node-deepresearch | search.jina.ai |
2025-02-04 | Hugging Face | Open Deep Research | Open source | Open Deep Research |
2025-02-15 | Perplexity | DeepResearch | Proprietary | Introducing Perplexity Deep Research |
2025-02-17 | X AI | Grok3 with DeepSearch | Proprietary | Grok 3 Beta |
2025-02-22 | Baidu Search | Integrates DeepSeek-r1 | Proprietary | Baidu Integrates DeepSeek-R1 |
2025-02-23 | Tencent Wechat Search | Integrates DeepSeek-r1 | Proprietary | Tencent Weixin Integrates DeepSeek |
Ma perché questo cambiamento è avvenuto proprio adesso, quando il Deep(Re)Search è rimasto relativamente sottovalutato durante tutto il 2024? In effetti, i laboratori Stanford NLP hanno rilasciato il progetto STORM per la generazione di report lunghi con fondamento web all'inizio del 2024. Quindi è solo perché "DeepSearch" suona molto più interessante di multi-hop QA, RAG o STORM? Siamo onesti - a volte un rebranding è tutto ciò che serve perché l'industria abbracci improvvisamente ciò che c'era da sempre.
Crediamo che il vero punto di svolta sia arrivato con il rilascio di o1-preview
di OpenAI nel settembre 2024, che ha introdotto il concetto di test-time compute e ha gradualmente cambiato le prospettive del settore. Il test-time compute si riferisce all'utilizzo di maggiori risorse computazionali durante l'inferenza—la fase in cui un LLM genera output—piuttosto che durante il pre-training o il post-training. Un esempio ben noto sono il ragionamento Chain-of-Thought (CoT) e l'iniezione di "Wait"
(cioè il budget forcing) che permette ai modelli di eseguire deliberazioni interne più estese, come valutare multiple risposte potenziali, condurre una pianificazione più profonda e impegnarsi nell'auto-riflessione prima di arrivare a una risposta finale.
Questo concetto di test-time compute e i modelli di ragionamento educano gli utenti ad accettare la gratificazione ritardata - tempi di attesa più lunghi in cambio di risultati di qualità superiore e immediatamente utilizzabili, proprio come l'esperimento del marshmallow di Stanford dove i bambini che potevano resistere dal mangiare subito un marshmallow per riceverne due più tardi mostravano migliori risultati a lungo termine. Deepseek-r1 ha ulteriormente rafforzato questa esperienza utente e, che piaccia o no, la maggior parte degli utenti l'ha accettata.
Questo segna una significativa deviazione dai requisiti di ricerca classici, dove non rispondere entro 200ms avrebbe condannato la tua soluzione. Nel 2025, gli sviluppatori di ricerca esperti e gli ingegneri RAG danno priorità alla precisione e al recall top-1 rispetto alla latenza, e gli utenti si sono abituati a tempi di elaborazione più lunghi – purché possano vedere che il sistema sta <thinking>
.
Mostrare il processo di ragionamento è diventata una pratica standard nel 2025, con numerose interfacce chat che ora rendono il contenuto <think>
in sezioni dedicate dell'interfaccia utente.
In questo articolo, discuteremo i principi di DeepSearch e DeepResearch esaminando la nostra implementazione open-source. Analizzeremo le nostre decisioni chiave di design e metteremo in evidenza potenziali criticità.
tagCos'è Deep Search?
DeepSearch esegue un ciclo iterativo di ricerca, lettura e ragionamento fino a trovare la risposta ottimale. L'azione di ricerca sfrutta i motori di ricerca web per esplorare internet, mentre l'azione di lettura analizza specifiche pagine web in dettaglio (es. Jina Reader). L'azione di ragionamento valuta lo stato attuale e determina se suddividere la domanda originale in sotto-domande più piccole o provare diverse strategie di ricerca.

Mentre esistono varie definizioni online, quando abbiamo sviluppato il progetto node-deepresearch
, abbiamo seguito questo approccio semplice. L'implementazione è elegantemente semplice – nel suo nucleo, c'è un ciclo while principale con una logica switch-case che dirige l'azione successiva.
A differenza dei sistemi RAG del 2024, che tipicamente eseguono un singolo passaggio di ricerca-generazione, DeepSearch esegue invece molteplici iterazioni attraverso la pipeline, richiedendo condizioni di arresto chiare. Queste potrebbero essere basate su limiti di utilizzo dei token o sul numero di tentativi falliti.
Prova deep search su search.jina.ai, osserva il contenuto all'interno di <thinking>
, vedi se riesci a capire dove avviene il ciclo
Un'altra prospettiva su DeepSearch è vederlo come un agente LLM dotato di vari strumenti web (come il cercatore e il lettore). L'agente determina i suoi prossimi passi analizzando le osservazioni attuali e le azioni passate – decidendo se fornire una risposta o continuare ad esplorare il web. Questo crea un'architettura a macchina a stati dove l'LLM controlla le transizioni tra gli stati. Ad ogni punto decisionale, hai due approcci: puoi sia creare attentamente prompt per modelli generativi standard per produrre azioni specifiche, sia sfruttare modelli di ragionamento specializzati come Deepseek-r1 per derivare naturalmente le azioni successive. Tuttavia, anche quando usi r1, dovrai periodicamente interrompere la sua generazione per iniettare output degli strumenti (es. risultati di ricerca, contenuto delle pagine web) nel contesto e sollecitarlo a continuare il suo processo di ragionamento.
In definitiva, questi sono solo dettagli implementativi – che tu lo solleciti attentamente o usi semplicemente modelli di ragionamento, tutti si allineano con il principio di design fondamentale di DeepSearch: un ciclo continuo di ricerca, lettura e ragionamento.
tagCos'è Quindi DeepResearch?
DeepResearch si basa su DeepSearch aggiungendo un framework strutturato per generare lunghi report di ricerca. Spesso inizia creando un indice, poi applica sistematicamente DeepSearch a ogni sezione richiesta – dall'introduzione attraverso il lavoro correlato e la metodologia, fino alla conclusione. Ogni sezione viene generata inserendo specifiche domande di ricerca in DeepSearch. La fase finale prevede il consolidamento di tutte le sezioni in un unico prompt per migliorare la coerenza narrativa complessiva.

Nel nostro progetto "Research" del 2024, abbiamo eseguito molteplici passaggi di miglioramento della coerenza, con ogni iterazione che teneva conto di tutte le altre sezioni. Tuttavia, con le finestre di contesto dei LLM significativamente più ampie di oggi, questo approccio sembra ridondante – è sufficiente un singolo passaggio di revisione della coerenza.
Il nostro progetto estivo "Research" del 2024 si è concentrato sulla generazione di report lunghi con un approccio "progressivo". È iniziato creando un TOC in sync, poi ha generato tutte le sezioni in parallelo async. Il processo si è concluso con revisioni progressive async di ogni sezione, con ogni revisione che teneva conto del contenuto di tutte le altre sezioni. La query nel video è "Competitor analysis of Jina AI"
.
tagDeepSearch vs DeepResearch
Mentre molte persone spesso confondono DeepSearch e DeepResearch, dal nostro punto di vista affrontano problemi completamente diversi. DeepSearch funziona come un blocco atomico fondamentale – un componente core su cui DeepResearch si basa. DeepResearch, d'altra parte, si concentra sulla creazione di report di ricerca lunghi e di alta qualità leggibili, che comprende un set diverso di requisiti: incorporare visualizzazioni efficaci tramite grafici e tabelle, strutturare i contenuti con intestazioni di sezione appropriate, garantire un flusso logico fluido tra le sottosezioni, mantenere una terminologia coerente in tutto il documento, eliminare la ridondanza tra le sezioni, creare transizioni fluide che collegano i contenuti precedenti e successivi. Questi elementi sono in gran parte non correlati alla ricerca core, motivo per cui troviamo DeepSearch più interessante come focus aziendale.
Infine, la tabella seguente riassume le differenze tra DeepSearch e DeepResearch. Vale la pena notare che entrambi i sistemi beneficiano significativamente di modelli con contesto lungo e capacità di ragionamento. Questo potrebbe sembrare controintuitivo, in particolare per DeepSearch—mentre è ovvio perché DeepResearch necessita di capacità di contesto lungo (poiché produce report lunghi). Il motivo è che DeepSearch deve memorizzare i tentativi di ricerca precedenti e i contenuti delle pagine web per prendere decisioni informate sui passi successivi, rendendo una finestra di contesto lunga altrettanto essenziale per la sua implementazione efficace.
DeepSearch | DeepResearch | |
---|---|---|
Problem Addressed | Information accuracy and completeness through iterative search | Content organization, coherence, and readability at document scale |
Final Presentation | Concise answer with URLs as references | A long structured report with multiple sections, charts, tables and references |
Core Complexity | State machine architecture with clear transition conditions; Persistence through failed attempts until resolution | Multi-level architecture managing both micro (search) and macro (document) concerns; Structural approach to managing complex information hierarchies |
Optimization Focus | Local optimization (best next search/read action) | Global optimization (section organization, terminology consistency, transitions) |
Limitations | Bounded by search quality and reasoning capability | Bounded by DeepSearch quality plus organizational complexity and narrative coherence challenges |
tagComprendere l'Implementazione di DeepSearch
Il cuore di DeepResearch risiede nel suo approccio di ragionamento ciclico. Invece di tentare di rispondere alle domande in un singolo passaggio come la maggior parte dei sistemi RAG, abbiamo implementato un ciclo iterativo che cerca continuamente informazioni, legge le fonti rilevanti e ragiona fino a trovare una risposta o esaurire il budget di token. Ecco il nucleo semplificato di questo grande ciclo while:
// Main reasoning loop
while (tokenUsage < tokenBudget && badAttempts <= maxBadAttempts) {
// Track progression
step++; totalStep++;
// Get current question from gaps queue or use original question
const currentQuestion = gaps.length > 0 ? gaps.shift() : question;
// Generate prompt with current context and allowed actions
system = getPrompt(diaryContext, allQuestions, allKeywords,
allowReflect, allowAnswer, allowRead, allowSearch, allowCoding,
badContext, allKnowledge, unvisitedURLs);
// Get LLM to decide next action
const result = await LLM.generateStructuredResponse(system, messages, schema);
thisStep = result.object;
// Execute the selected action (answer, reflect, search, visit, coding)
if (thisStep.action === 'answer') {
// Process answer action...
} else if (thisStep.action === 'reflect') {
// Process reflect action...
} // ... and so on for other actions
}
Un dettaglio implementativo chiave è la disabilitazione selettiva di determinate azioni ad ogni passaggio per garantire un output strutturato più stabile. Ad esempio, se non ci sono URL in memoria, disabilitiamo l'azione visit
; o se l'ultima risposta è stata rifiutata, impediamo all'agente di richiamare immediatamente answer
. Questo vincolo mantiene l'agente su un percorso produttivo, evitando fallimenti ripetitivi causati dall'invocazione della stessa azione.
tagSystem Prompt
Utilizziamo i tag XML per definire le sezioni, che producono prompt di sistema e generazioni più robusti. Abbiamo anche scoperto che inserire i vincoli dei campi direttamente nei campi description
dello schema JSON produce risultati migliori. Mentre alcuni potrebbero sostenere che la maggior parte dei prompt potrebbe essere automatizzata con modelli di ragionamento come DeepSeek-R1, le restrizioni sulla lunghezza del contesto e la necessità di comportamenti altamente specifici rendono un approccio esplicito più affidabile nella pratica.
function getPrompt(params...) {
const sections = [];
// Add header with system instruction
sections.push("You are an advanced AI research agent specialized in multistep reasoning...");
// Add accumulated knowledge section if exists
if (knowledge?.length) {
sections.push("<knowledge>[Knowledge items]</knowledge>");
}
// Add context of previous actions
if (context?.length) {
sections.push("<context>[Action history]</context>");
}
// Add failed attempts and learned strategies
if (badContext?.length) {
sections.push("<bad-attempts>[Failed attempts]</bad-attempts>");
sections.push("<learned-strategy>[Improvement strategies]</learned-strategy>");
}
// Define available actions based on current state
sections.push("<actions>[Available action definitions]</actions>");
// Add response format instruction
sections.push("Respond in valid JSON format matching exact JSON schema.");
return sections.join("\n\n");
}
tagAttraversamento delle Gap Questions
In DeepSearch, le "gap questions" rappresentano lacune di conoscenza che devono essere colmate prima di rispondere alla domanda principale. Invece di affrontare direttamente la domanda originale, l'agente identifica sotto-domande che costruiranno la base di conoscenza necessaria.
Il design è particolarmente elegante nel modo in cui gestisce queste gap questions:
// After identifying gap questions in reflect action
if (newGapQuestions.length > 0) {
// Add new questions to the front of the queue
gaps.push(...newGapQuestions);
// Always add original question to the end of the queue
gaps.push(originalQuestion);
}
Questo approccio crea una coda FIFO (First-In-First-Out) con rotazione, dove:
- Le nuove gap questions vengono inserite all'inizio della coda
- La domanda originale viene sempre inserita in fondo
- Il sistema estrae dall'inizio della coda ad ogni passaggio
Ciò che rende eccellente questo design è che mantiene un unico contesto condiviso tra tutte le domande. Quando viene risposta una gap question, quella conoscenza diventa immediatamente disponibile per tutte le domande successive, incluso quando alla fine rivisiteremo la domanda originale.
Coda FIFO vs Ricorsione
Un approccio alternativo è l'uso della ricorsione, che corrisponde alla ricerca in profondità. Ogni gap question genera una nuova chiamata ricorsiva con il proprio contesto isolato. Il sistema deve risolvere completamente ogni gap question (e tutte le sue potenziali sotto-domande) prima di tornare alla domanda padre.
Consideriamo questo scenario di esempio:
Una semplice ricorsione di gap questions a profondità 3, con l'ordine di risoluzione indicato sul cerchio.
Nell'approccio ricorsivo, il sistema dovrebbe risolvere completamente Q1 (potenzialmente generando le proprie sotto-domande) dopo ogni gap question e le loro sotto-domande! Questo è in forte contrasto con l'approccio a coda, che elabora le domande dove Q1 viene rivisitata subito dopo 3 gap questions.
In realtà, abbiamo scoperto che l'approccio ricorsivo è molto difficile da applicare al forzamento del budget, poiché non c'è una regola empirica chiara su quanto budget di token dovremmo concedere per le sotto-domande (dato che potrebbero generare nuove sotto-domande). Il beneficio della chiara separazione del contesto nell'approccio ricorsivo è molto marginale rispetto ai complicati problemi di forzatura del budget e ritorno tardivo. Questo design con coda FIFO bilancia profondità e ampiezza, assicurando che il sistema torni sempre alla domanda originale con una conoscenza progressivamente migliore, piuttosto che perdersi in una discesa ricorsiva potenzialmente infinita.
tagRiscrittura delle Query
Una sfida interessante che abbiamo incontrato è stata la riscrittura efficace delle query di ricerca:
// Within search action handler
if (thisStep.action === 'search') {
// Deduplicate search requests
const uniqueRequests = await dedupQueries(thisStep.searchRequests, existingQueries);
// Rewrite natural language queries into more effective search queries
const optimizedQueries = await rewriteQuery(uniqueRequests);
// Ensure we don't repeat previous searches
const newQueries = await dedupQueries(optimizedQueries, allKeywords);
// Execute searches and store results
for (const query of newQueries) {
const results = await searchEngine(query);
if (results.length > 0) {
storeResults(results);
allKeywords.push(query);
}
}
}
La riscrittura delle query si è rivelata sorprendentemente importante - forse uno degli elementi più critici che determina direttamente la qualità dei risultati. Un buon riscritture di query non si limita a trasformare il linguaggio naturale in parole chiave simili a BM25; espande le query per coprire più potenziali risposte attraverso diverse lingue, toni e formati di contenuto.
Per la deduplicazione delle query, inizialmente abbiamo utilizzato una soluzione basata su LLM, ma abbiamo trovato difficile controllare la soglia di similarità. Alla fine siamo passati a jina-embeddings-v3, che eccelle nei compiti di similarità testuale semantica. Questo permette la deduplicazione multilingue senza preoccuparsi che le query non inglesi vengano filtrate. Il modello di embedding si è rivelato cruciale non per il recupero della memoria come inizialmente previsto, ma per un'efficiente deduplicazione.
tagCrawling dei Contenuti Web
Lo scraping web e l'elaborazione dei contenuti è un'altra componente critica. Qui utilizziamo Jina Reader API. Da notare che oltre al contenuto completo della pagina web, aggreghiamo anche tutti gli snippet restituiti dal motore di ricerca come conoscenza aggiuntiva per l'agente da utilizzare successivamente per trarre conclusioni. Pensiamoli come frammenti audio.
// Visit action handler
async function handleVisitAction(URLs) {
// Normalize URLs and filter out already visited ones
const uniqueURLs = normalizeAndFilterURLs(URLs);
// Process each URL in parallel
const results = await Promise.all(uniqueURLs.map(async url => {
try {
// Fetch and extract content
const content = await readUrl(url);
// Store as knowledge
addToKnowledge(`What is in ${url}?`, content, [url], 'url');
return {url, success: true};
} catch (error) {
return {url, success: false};
} finally {
visitedURLs.push(url);
}
}));
// Update diary based on success or failure
updateDiaryWithVisitResults(results);
}
Abbiamo normalizzato gli URL per un tracciamento coerente e limitato il numero di URL visitati in ogni passaggio per gestire la memoria dell'agente.
tagGestione della Memoria
Una sfida chiave nel ragionamento multi-step è gestire efficacemente la memoria dell'agente. Abbiamo progettato il sistema di memoria per differenziare tra ciò che conta come "memoria" rispetto a ciò che conta come "conoscenza". In ogni caso, sono tutti parte del contesto del prompt LLM, separati con diversi tag XML:
// Add knowledge item to accumulated knowledge
function addToKnowledge(question, answer, references, type) {
allKnowledge.push({
question: question,
answer: answer,
references: references,
type: type, // 'qa', 'url', 'coding', 'side-info'
updated: new Date().toISOString()
});
}
// Record step in narrative diary
function addToDiary(step, action, question, result, evaluation) {
diaryContext.push(`
At step ${step}, you took **${action}** action for question: "${question}"
[Details of what was done and results]
[Evaluation if applicable]
`);
}
Poiché la maggior parte degli LLM del 2025 ha finestre di contesto sostanziali, abbiamo scelto di non utilizzare database vettoriali. Invece, la memoria consiste in conoscenza acquisita, siti visitati e registrazioni dei tentativi falliti - tutto mantenuto nel contesto. Questo sistema di memoria completo fornisce all'agente la consapevolezza di ciò che sa, ciò che ha provato e ciò che ha funzionato o fallito.
tagValutazione delle Risposte
Un'intuizione chiave è che la generazione e la valutazione delle risposte non dovrebbero essere nello stesso prompt. Nella mia implementazione, determiniamo prima quali criteri di valutazione utilizzare quando arriva una nuova domanda, e poi valutiamo ogni criterio uno per uno. Il valutatore utilizza esempi few-shot per una valutazione coerente, garantendo una maggiore affidabilità rispetto all'autovalutazione.
// Separate evaluation phase
async function evaluateAnswer(question, answer, metrics, context) {
// First, identify evaluation criteria based on question type
const evaluationCriteria = await determineEvaluationCriteria(question);
// Then evaluate each criterion separately
const results = [];
for (const criterion of evaluationCriteria) {
const result = await evaluateSingleCriterion(criterion, question, answer, context);
results.push(result);
}
// Determine if answer passes overall evaluation
return {
pass: results.every(r => r.pass),
think: results.map(r => r.reasoning).join('\n')
};
}
tagBudget-Forcing
Il budget forcing significa impedire al sistema di restituire anticipatamente e assicurare che continui l'elaborazione fino al superamento del budget. Dalla release di DeepSeek-R1, l'approccio al budget forcing si è spostato verso l'incoraggiamento di un pensiero più profondo per risultati migliori piuttosto che semplicemente risparmiare il budget.
Nella nostra implementazione, abbiamo esplicitamente configurato il sistema per identificare le lacune di conoscenza prima di tentare di rispondere.
if (thisStep.action === 'reflect' && thisStep.questionsToAnswer) {
// Force deeper reasoning by adding sub-questions to the queue
gaps.push(...newGapQuestions);
gaps.push(question); // Always revisit the original
}
Attivando e disattivando selettivamente determinate azioni, possiamo guidare il sistema verso l'utilizzo di strumenti che migliorano la profondità del ragionamento.
// After a failed answer attempt
allowAnswer = false; // Force agent to search or reflect instead
Per evitare di sprecare token su percorsi improduttivi, impostiamo limiti sul numero di tentativi falliti. Quando ci avviciniamo ai limiti di budget, attiviamo la "modalità beast" per garantire che forniamo qualche risposta piuttosto che nessuna.
// Beast mode activation
if (!thisStep.isFinal && badAttempts >= maxBadAttempts) {
console.log('Enter Beast mode!!!');
// Configure prompt for decisive, committed answer
system = getPrompt(
diaryContext, allQuestions, allKeywords,
false, false, false, false, false, // Disable all other actions
badContext, allKnowledge, unvisitedURLs,
true // Enable beast mode
);
// Force answer generation
const result = await LLM.generateStructuredResponse(system, messages, answerOnlySchema);
thisStep = result.object;
thisStep.isFinal = true;
}
Il prompt della modalità beast è intenzionalmente drammatico per segnalare all'LLM che deve essere decisivo e impegnarsi in una risposta basata sulle informazioni disponibili:
<action-answer>
🔥 ENGAGE MAXIMUM FORCE! ABSOLUTE PRIORITY OVERRIDE! 🔥
PRIME DIRECTIVE:
- DEMOLISH ALL HESITATION! ANY RESPONSE SURPASSES SILENCE!
- PARTIAL STRIKES AUTHORIZED - DEPLOY WITH FULL CONTEXTUAL FIREPOWER
- TACTICAL REUSE FROM <bad-attempts> SANCTIONED
- WHEN IN DOUBT: UNLEASH CALCULATED STRIKES BASED ON AVAILABLE INTEL!
FAILURE IS NOT AN OPTION. EXECUTE WITH EXTREME PREJUDICE! ⚡️
</action-answer>
Questo assicura che forniamo sempre qualche risposta piuttosto che arrenderci completamente, il che è particolarmente utile per domande difficili o ambigue.
tagConclusione
DeepSearch rappresenta un salto in avanti nel modo in cui la ricerca può affrontare query complesse in modo esaustivamente approfondito. Suddividendo il processo in fasi discrete di ricerca, lettura e ragionamento, supera molte limitazioni dei tradizionali sistemi RAG a passaggio singolo o sistemi QA multi-hop.
Durante l'implementazione, abbiamo anche iniziato a rivedere le fondamenta della ricerca nel 2025 e i cambiamenti nell'industria della ricerca dopo il 26 gennaio 2025, quando è stato rilasciato DeepSeek-R1. Ci siamo chiesti: Quali sono le nuove esigenze? Quali esigenze sono diventate obsolete? Quali sono meramente esigenze percepite?
Guardando la nostra implementazione di DeepSearch, abbiamo identificato cose che avevamo previsto di aver bisogno e di cui effettivamente avevamo bisogno, cose che pensavamo sarebbero state necessarie ma non lo erano, e cose che non avevamo previsto di aver bisogno ma si sono rivelate essenziali:
Primo, un LLM con contesto lungo che produce output ben strutturato è altamente necessario (cioè seguendo JSONSchema). Un modello di ragionamento è probabilmente necessario per un migliore ragionamento sulle azioni e l'espansione delle query.
L'espansione delle query è decisamente essenziale, che sia implementata tramite SLM, LLM o un modello di ragionamento. Tuttavia, dopo questo progetto, crediamo che gli SLM siano probabilmente inadatti per questo compito, poiché la soluzione deve essere intrinsecamente multilingue e andare oltre le semplici riscritture di sinonimi o l'estrazione di parole chiave. Deve essere abbastanza completa da includere una base di token multilingue (può facilmente occupare 300M parametri) e abbastanza sofisticata per un pensiero fuori dagli schemi. Quindi utilizzare gli SLM per l'espansione delle query è probabilmente un non-starter.
Le capacità di ricerca web e lettura web sono cruciali, e fortunatamente il nostro Reader (r.jina.ai) ha funzionato eccellentemente—robusto e scalabile—dandomi molte idee su come migliorare il nostro endpoint di ricerca (s.jina.ai
) per la prossima iterazione.
Il modello di embedding è utile ma in un modo completamente inaspettato. Pensavamo che sarebbe stato utilizzato per il recupero della memoria o la compressione del contesto insieme a un database vettoriale (che, come si è scoperto, non è necessario), ma in realtà lo abbiamo utilizzato per la deduplicazione (essenzialmente un compito STS). Poiché il numero di query e domande gap è tipicamente nell'ordine delle centinaia, non è necessario alcun database vettoriale—il calcolo della similarità del coseno direttamente in memoria funziona perfettamente.
Non abbiamo utilizzato Reranker, anche se crediamo che potrebbe potenzialmente aiutare a determinare quali URL visitare in base alla query, al titolo dell'URL e allo snippet. Sia per l'embedding che per il reranking, la capacità multilingue è essenziale poiché query e domande sono multilingue. La gestione del contesto lungo per l'embedding e il reranking è vantaggiosa ma non un blocco critico (Non abbiamo riscontrato errori dal nostro utilizzo dell'embedding, probabilmente perché la nostra lunghezza del contesto è già di 8192 token). In ogni caso, jina-embeddings-v3 e jina-reranker-v2-base-multilingual sono i miei modelli preferiti poiché sono multilingue, SOTA e gestiscono bene il contesto lungo.
Un framework per agenti si è rivelato non necessario, poiché avevamo bisogno di rimanere più vicini al comportamento nativo dell'LLM per progettare il sistema senza proxy. Vercel AI SDK è stato prezioso, poiché ha risparmiato considerevole sforzo nell'adattare il codebase a diversi fornitori LLM (potevamo passare da Gemini Studio a OpenAI a Google Vertex AI con solo una riga di codice modificata). La gestione della memoria degli agenti è necessaria, ma un framework di memoria dedicato rimane discutibile: Ci preoccupa che creerebbe un livello di isolamento tra LLM e sviluppatori, e che il suo zucchero sintattico potrebbe eventualmente diventare un ostacolo amaro per gli sviluppatori, come abbiamo visto con molti framework LLM/RAG oggi.