Notizia
Modelli
Prodotti
keyboard_arrow_down
Lettore
Leggi gli URL e cerca sul web per ottenere LLM più approfonditi.
Incorporamenti
Incorporamenti multilingue multimodali di livello mondiale.
Riclassificazione
Recupero neurale di livello mondiale per massimizzare la pertinenza della ricerca.
Ricerca profonda
Cerca, leggi e ragiona finché non trovi la risposta migliore.
Di più
keyboard_arrow_down
Classificatore
Classificazione zero-shot e few-shot per immagini e testo.
Segmentatore
Tagliare il testo lungo in blocchi ed effettuare la tokenizzazione.

Documentazione API
Generazione automatica di codice per il tuo IDE o LLM di Copilot
open_in_new


Azienda
keyboard_arrow_down
Chi siamo
Contatta le vendite
Programma di stagista
Unisciti a noi
open_in_new
Scarica il logo
open_in_new
Termini & Condizioni


Login
login
Selezionare Frammenti da Contenuti Lunghi
Classificazione degli URL per la prossima lettura
Conclusione
Blog tecnico
marzo 12, 2025

Selezione di Snippet e Ranking degli URL in DeepSearch/DeepResearch

Perfezionare questi due dettagli trasforma il tuo DeepSearch da mediocre a eccezionale: selezionare i migliori frammenti da pagine web lunghe e classificare gli URL prima del crawling.
Han Xiao
Han Xiao • 11 minuti letti
Una Guida Pratica all'Implementazione di DeepSearch/DeepResearch
QPS fuori, profondità dentro. DeepSearch è il nuovo standard. Trova risposte attraverso cicli di lettura-ricerca-ragionamento. Scopri cos'è e come costruirlo.
Jina AIHan Xiao

Se hai già letto la nostra guida all'implementazione di DeepSearch/DeepResearch, approfondiamo alcuni dettagli che possono migliorare notevolmente la qualità. In questo post, ci concentreremo su due sfide chiave: sfruttare gli embedding per la selezione di frammenti da pagine web lunghe e utilizzare i reranker per dare priorità agli URL durante il crawling.

Alcuni potrebbero ricordare la nostra precedente conclusione secondo cui "gli embedding erano utili solo per la deduplicazione delle query come i task STS (semantic textual similarity), mentre i reranker non facevano nemmeno parte della nostra implementazione originale di DeepSearch". Bene, si scopre che entrambi sono ancora molto utili - solo non nel modo convenzionale che ci si potrebbe aspettare. Abbiamo sempre seguito il percorso più snello possibile. Non aggiungiamo componenti solo per giustificare la loro esistenza o il nostro valore come fornitore di embedding e reranker. Siamo concentrati su ciò di cui la ricerca ha davvero bisogno come fondamento.

Quindi dopo settimane di esperimenti e iterazioni, abbiamo scoperto utilizzi insoliti ma efficaci per entrambi nei sistemi DeepSearch/DeepResearch. Applicandoli, abbiamo migliorato significativamente la qualità di Jina DeepSearch (sentiti libero di provarlo). Vorremmo condividere queste intuizioni con altri professionisti che lavorano in questo ambito.

tagSelezionare Frammenti da Contenuti Lunghi

Il problema è questo: dopo aver utilizzato Jina Reader per leggere il contenuto della pagina web, dobbiamo aggiungerlo come elemento di conoscenza al contesto dell'agente per il ragionamento. Mentre inserire l'intero contenuto nella finestra di contesto del LLM è il modo più semplice, non è ottimale considerando i costi dei token e la velocità di generazione. In pratica, dobbiamo identificare quali parti del contenuto sono più rilevanti per la domanda e aggiungere selettivamente solo quelle parti come conoscenza al contesto dell'agente.

💡
Stiamo parlando dei casi in cui il contenuto rimane troppo lungo anche dopo la pulizia markdown di Jina Reader. Questo accade spesso con pagine lunghe come issue di GitHub, thread di Reddit, discussioni nei forum e post dei blog (inclusi molti dei nostri da jina.ai/news).

Il filtraggio basato su LLM ha gli stessi problemi di costo e latenza, quindi cerchiamo soluzioni con modelli più piccoli: abbiamo bisogno di modelli più piccoli ed economici, ma ancora multilingue – un fattore cruciale poiché non possiamo garantire che sia la query che i documenti saranno sempre in inglese.

Abbiamo una domanda da un lato (sia la query originale che una domanda di gap) e un grande contenuto markdown dall'altro, dove la maggior parte del contenuto è irrilevante. Dobbiamo selezionare i frammenti più rilevanti per la query. Questo assomiglia al problema di chunking con cui la comunità RAG si è confrontata dal 2023 - recuperare solo i chunk rilevanti utilizzando modelli di retrieval da inserire nella finestra di contesto per la sintesi. Tuttavia, ci sono due differenze chiave nel nostro caso:

  1. Chunks limitati da un numero limitato di documenti. Se ogni chunk contiene circa 500 token, allora un tipico documento web lungo ha circa 200.000 token (p50) fino a 1.000.000 di token (p99), e noi usiamo Jina Reader per recuperare 4-5 URL ad ogni passo, questo produrrebbe approssimativamente centinaia di chunk - ovvero centinaia di vettori di embedding e centinaia di similarità del coseno. Questo è facilmente gestibile con JavaScript in memoria senza un database vettoriale.
  2. Abbiamo bisogno di chunk consecutivi per formare frammenti di conoscenza efficaci. Non possiamo accettare frammenti che combinano frasi sparse come [1-2, 6-7, 9, 14, 17, ...]. Un frammento di conoscenza più utile seguirebbe pattern come [3-15, 17-24, ...] - mantenendo sempre testo consecutivo. Questo rende più facile per il LLM copiare e citare dalla fonte di conoscenza e riduce le allucinazioni.

Il resto sono tutte le problematiche di cui si lamentano i professionisti: ogni chunk non può essere troppo lungo poiché i modelli di embedding non possono gestire bene contesti lunghi; il chunking introduce perdita di contesto e rende gli embedding dei chunk i.i.d; e come trovare i migliori indizi di confine che mantengano sia la leggibilità che la semantica? Se sai di cosa stiamo parlando, allora probabilmente sei stato perseguitato da questi problemi nelle tue implementazioni RAG.

Ma in breve - il late-chunking con jina-embeddings-v3 risolve magnificamente tutti e tre i problemi. Il late chunking mantiene le informazioni di contesto per ogni chunk, è insensibile agli indizi di confine, e jina-embeddings-v3 stesso è SOTA nei task di retrieval multilingue asimmetrico. I lettori interessati possono seguire i nostri post del blog o i paper per i dettagli, ma ecco l'implementazione complessiva.

Questo diagramma illustra l'algoritmo di selezione dei frammenti, che funziona in modo simile a Conv1D. Il processo inizia dividendo un documento lungo in chunk di lunghezza fissa, che vengono poi incorporati con jina-embeddings-v3 con l'opzione late-chunking attivata. Dopo aver calcolato i punteggi di similarità tra ogni chunk e la query, una finestra scorrevole si muove attraverso i punteggi di similarità per trovare la finestra con il valore medio più alto.
Cosa è Realmente il Late Chunking e Cosa Non è: Parte II
Parte 2 della nostra esplorazione del Late Chunking, un approfondimento sul perché è il miglior metodo per gli embedding dei chunk e il miglioramento delle prestazioni di ricerca/RAG.
Jina AIHan Xiao
jina-embeddings-v3: Embedding Multilingue con Task LoRA
Presentiamo jina-embeddings-v3, un nuovo modello di embedding testuale con 570 milioni di parametri, che raggiunge prestazioni allo stato dell'arte su dati multilingue e task di retrieval con contesto lungo, supportando lunghezze di contesto fino a 8192 token. Il modello include un set di adattatori Low-Rank Adaptation (LoRA) specifici per task per generare embedding di alta qualità per il retrieval query-documento, clustering, classificazione e matching del testo. La valutazione sul benchmark MTEB mostra che jina-embeddings-v3 supera gli ultimi embedding proprietari di OpenAI e Cohere su task in inglese, mentre raggiunge prestazioni superiori rispetto a multilingual-e5-large-instruct in tutti i task multilingue. Con una dimensione di output predefinita di 1024, gli utenti possono ridurre flessibilmente le dimensioni degli embedding fino a 32 senza compromettere le prestazioni, abilitato dal Matryoshka Representation Learning.
arXiv.orgSaba Sturua
Late Chunking: Embedding di Chunk Contestuali Utilizzando Modelli di Embedding con Contesto Lungo
Molti casi d'uso richiedono il recupero di porzioni più piccole di testo, e i sistemi di retrieval basati su vettori densi spesso funzionano meglio con segmenti di testo più brevi, poiché è meno probabile che la semantica sia sovra-compressa negli embedding. Di conseguenza, i professionisti spesso dividono i documenti di testo in chunk più piccoli e li codificano separatamente. Tuttavia, gli embedding dei chunk creati in questo modo possono perdere informazioni contestuali dai chunk circostanti, risultando in rappresentazioni sub-ottimali. In questo articolo, introduciamo un nuovo metodo chiamato late chunking, che sfrutta i modelli di embedding con contesto lungo per incorporare prima tutti i token del testo lungo, con il chunking applicato dopo il modello transformer e appena prima del mean pooling - da qui il termine 'late' nel suo nome. Gli embedding dei chunk risultanti catturano l'informazione contestuale completa, portando a risultati superiori in vari task di retrieval. Il metodo è abbastanza generico da essere applicato a un'ampia gamma di modelli di embedding con contesto lungo e funziona senza addestramento aggiuntivo. Per aumentare ulteriormente l'efficacia del late chunking, proponiamo un approccio dedicato di fine-tuning per i modelli di embedding.
arXiv.orgMichael Günther
function cherryPick(question, longContext, options) {
  if (longContext.length < options.snippetLength * options.numSnippets)
    return longContext;
  
  const chunks = splitIntoChunks(longContext, options.chunkSize);
  
  const chunkEmbeddings = getEmbeddings(chunks, "retrieval.passage");
  const questionEmbedding = getEmbeddings([question], "retrieval.query")[0];
  
  const similarities = chunkEmbeddings.map(embed => 
    cosineSimilarity(questionEmbedding, embed));
  
  const chunksPerSnippet = Math.ceil(options.snippetLength / options.chunkSize);
  const snippets = [];
  const similaritiesCopy = [...similarities];
  
  for (let i = 0; i < options.numSnippets; i++) {
    let bestStartIndex = 0;
    let bestScore = -Infinity;
    
    for (let j = 0; j <= similarities.length - chunksPerSnippet; j++) {
      const windowScores = similaritiesCopy.slice(j, j + chunksPerSnippet);
      const windowScore = average(windowScores);
      
      if (windowScore > bestScore) {
        bestScore = windowScore;
        bestStartIndex = j;
      }
    }
    
    const startIndex = bestStartIndex * options.chunkSize;
    const endIndex = Math.min(startIndex + options.snippetLength, longContext.length);
    snippets.push(longContext.substring(startIndex, endIndex));
    
    for (let k = bestStartIndex; k < bestStartIndex + chunksPerSnippet; k++)
      similaritiesCopy[k] = -Infinity;
  }
  
  return snippets.join("\n\n");
}

Utilizzo del late chunking e del pooling medio tipo Conv1D per selezionare il miglior snippet rispetto alla domanda.

Assicurati di chiamare l'API Jina Embeddings con i parametri task, late_chunking e truncate impostati come segue:

await axios.post(
  'https://api.jina.ai/v1/embeddings',
  {
    model: "jina-embeddings-v3",
    task: "retrieval.passage",
    late_chunking: true,
    input: chunks,
    truncate: true
  }, 
  { headers }); 

Per l'embedding della domanda, assicurati di cambiare task in retrieval.query e disattivare late_chunking

L'implementazione completa può essere trovata su Github:

node-DeepResearch/src/tools/jina-latechunk.ts at main · jina-ai/node-DeepResearch
Continua a cercare, leggere pagine web e ragionare finché non trova la risposta (o supera il budget di token) - jina-ai/node-DeepResearch
GitHubjina-ai

tagClassificazione degli URL per la prossima lettura

Il problema è questo: durante una sessione DeepSearch, probabilmente raccoglierai molti URL dalle pagine dei risultati del motore di ricerca (SERP) e ne scoprirai ancora di più ogni volta che leggi singole pagine web (quei link nelle pagine). Il conteggio totale degli URL unici può facilmente raggiungere le centinaia. Ancora una volta, inserire semplicemente tutti gli URL direttamente nel contesto dell'LLM è inefficiente - spreca prezioso spazio nella finestra di contesto e, più problematicamente, abbiamo scoperto che gli LLM essenzialmente selezionano gli URL in modo casuale. È fondamentale guidare l'LLM verso gli URL che hanno la più alta probabilità di contenere la risposta necessaria.

curl https://r.jina.ai/https://example.com \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Retain-Images: none" \
  -H "X-Md-Link-Style: discarded" \
  -H "X-Timeout: 20" \
  -H "X-With-Links-Summary: all"

Migliore opzione per utilizzare Jina Reader per crawlare una pagina in DeepSearch. Questo raccoglierà tutti i link della pagina in un campo links separato, rimuovendoli dal campo content.

Pensa a questo problema come a un PageRank contestuale dove dobbiamo pesare centinaia di URL durante una sessione. Classifichiamo gli URL basandoci su molteplici fattori che combinano l'ultimo tempo di aggiornamento, la frequenza del dominio, la struttura del percorso e, più importante, la rilevanza semantica rispetto alla query per creare un punteggio composito. Ricorda che possiamo utilizzare solo le informazioni disponibili prima di visitare effettivamente l'URL:

Segnali di Frequenza: Gli URL che appaiono più volte attraverso diverse fonti ricevono un peso aggiuntivo. Gli URL da domini che appaiono frequentemente nei risultati di ricerca ricevono un boost, poiché i domini popolari spesso contengono contenuti autorevoli.

Struttura del Percorso: Analizziamo i percorsi degli URL per identificare cluster di contenuti. Gli URL all'interno di gerarchie di percorsi comuni ricevono punteggi più alti, con un fattore di decadimento applicato ai percorsi più profondi.

Rilevanza Semantica: Utilizziamo jina-reranker-v2-base-multilingual per valutare la rilevanza semantica tra la domanda e le informazioni testuali di ciascun URL, che è un classico problema di riordinamento. Le informazioni testuali di ciascun URL provengono da:

  • Titolo e snippet dai risultati delle API SERP (https://s.jina.ai/ con 'X-Respond-With': 'no-content')
  • Testo ancora degli URL nella pagina (https://r.jina.ai con 'X-With-Links-Summary': 'all')

Ultimo Tempo di Aggiornamento: Alcune query DeepSearch sono sensibili al tempo, quindi gli URL aggiornati recentemente sono più preziosi di quelli più vecchi. Senza essere un motore di ricerca importante come Google, determinare in modo affidabile l'ultimo tempo di aggiornamento è una sfida. Abbiamo implementato un approccio multi-livello che combina i seguenti segnali e fornisce un timestamp con punteggio di confidenza che dà priorità ai contenuti più recenti quando necessario.

  • Filtri API SERP (come il parametro tbs di s.jina.ai per filtrare per recenza)
  • Analisi dell'header HTTP (Last-Modified, ETag)
  • Estrazione dei metadati (meta tag, timestamp Schema.org)
  • Riconoscimento dei pattern di contenuto (date visibili in HTML)
  • Indicatori specifici per CMS per piattaforme come WordPress, Drupal e Ghost

Contenuto Protetto: Alcuni contenuti sulle piattaforme di social media sono protetti o semplicemente dietro paywall, e senza effettuare l'accesso o violare i loro ToS, non c'è modo legittimo di recuperare questi contenuti. Dovremmo mantenere attivamente una lista di URL e nomi host problematici per abbassare i loro ranking, evitando di perdere tempo su contenuti inaccessibili.

Diversità di Dominio: In alcuni casi, gli URL con il peso più alto provengono tutti dagli stessi nomi host, il che può intrappolare DeepSearch in un ottimo locale e ridurre la qualità finale dei risultati. Controlla gli esempi sopra dove tutti gli URL principali provengono da StackOverflow. Per migliorare la diversità, possiamo implementare un approccio di esplorazione-sfruttamento selezionando i k URL con il ranking più alto da ciascun nome host.

L'implementazione completa della classificazione degli URL può essere trovata sul nostro Github.

node-DeepResearch/src/utils/url-tools.ts at main · jina-ai/node-DeepResearch
Continua a cercare, leggere pagine web e ragionare finché non trova la risposta (o supera il budget di token) - jina-ai/node-DeepResearch
GitHubjina-ai
<action-visit>
- Crawl and read full content from URLs, you can get the fulltext, last updated datetime etc of any URL.  
- Must check URLs mentioned in <question> if any
- Choose and visit relevant URLs below for more knowledge. higher weight suggests more relevant:
<url-list>
  + weight: 0.20 "https://huggingface.co/docs/datasets/en/loading": "Load - Hugging FaceThis saves time because instead of waiting for the Dataset builder download to time out, Datasets will look directly in the cache. Set the environment ...Some datasets may have more than one version based on Git tags, branches, or commits. Use the revision parameter to specify the dataset version you want to load ..."
  + weight: 0.20 "https://huggingface.co/docs/datasets/en/index": "Datasets - Hugging Face🤗 Datasets is a library for easily accessing and sharing datasets for Audio, Computer Vision, and Natural Language Processing (NLP) tasks. Load a dataset in a ..."
  + weight: 0.17 "https://github.com/huggingface/datasets/issues/7175": "[FSTimeoutError] load_dataset · Issue #7175 · huggingface/datasetsWhen using load_dataset to load HuggingFaceM4/VQAv2, I am getting FSTimeoutError. Error TimeoutError: The above exception was the direct cause of the following ..."
  + weight: 0.15 "https://github.com/huggingface/datasets/issues/6465": "`load_dataset` uses out-of-date cache instead of re-downloading a ...When a dataset is updated on the hub, using load_dataset will load the locally cached dataset instead of re-downloading the updated dataset."
  + weight: 0.12 "https://stackoverflow.com/questions/76923802/hugging-face-http-request-on-data-from-parquet-format-when-the-only-way-to-get-i": "Hugging face HTTP request on data from parquet format when the ...I've had to get the data from their data viewer using the parquet option. But when I try to run it, there is some sort of HTTP error. I've tried downloading ..."
</url-list>
</action-visit>

Ricorda di inserire i pesi degli URL nel contesto dell'agente e di istruire i LLM a rispettare i pesi.

tagConclusione

Dal rilascio del nostro sistema DeepSearch il 2 febbraio 2025, abbiamo scoperto due dettagli implementativi che hanno migliorato sostanzialmente la qualità. Sorprendentemente, entrambi utilizzano embedding e reranker multilingue in modo "in-context" - operando su una scala molto più piccola rispetto agli indici pre-calcolati che questi modelli tipicamente richiedono. Questo spiega la nostra iniziale svista.

Ciò indica un'affascinante polarizzazione nel futuro della tecnologia di ricerca. Consideriamo un framework analogo alla teoria del doppio processo di Kahneman:

  • Fast-think (grep, BM25, SQL): Corrispondenza di pattern rapida e governata da regole con minime esigenze computazionali.
  • Slow-think (LLM): Ragionamento completo con profonda comprensione contestuale, che richiede una computazione significativa.
  • Mid-think (embedding, reranker): Intrappolati nel limbo? Troppo "avanzati"/semantici per la semplice corrispondenza di pattern ma privi di vere capacità di ragionamento.

Potremmo star assistendo alla popolarità di un'architettura biforcata dove SQL/BM25 leggeri ed efficienti gestiscono il recupero iniziale dei contenuti, alimentando direttamente potenti LLM per l'elaborazione profonda. Questi LLM incorporano sempre più le funzioni semantiche che prima richiedevano modelli specializzati di livello intermedio. Il ruolo rimanente per i modelli mid-think si sposta verso attività in-context specializzate: filtraggio, deduplicazione e operazioni di portata limitata dove un ragionamento completo sarebbe inefficiente.

Tuttavia, la selezione di snippet critici e il ranking degli URL rimangono componenti fondamentali con un impatto diretto sulla qualità dei sistemi DeepSearch/DeepResearch. Speriamo che le nostre intuizioni stimolino miglioramenti nelle vostre implementazioni.

L'espansione delle query continua a essere un altro determinante cruciale della qualità. Stiamo valutando attivamente molteplici approcci—dai basic prompt-based rewrite ai small language model e metodi basati sul ragionamento. Cercate i nostri prossimi risultati su questo fronte presto. Restate sintonizzati.

Categorie:
Blog tecnico
rss_feed
Uffici
location_on
Sunnyvale, California
710 Lakeway Dr, Ste 200, Sunnyvale, CA 94085, Stati Uniti
location_on
Berlino, Germania (sede centrale)
Prinzessinnenstraße 19-20, 10969 Berlino, Germania
location_on
Pechino, Cina
Livello 5, Edificio 6, No.48 Haidian West St. Pechino, Cina
location_on
Shenzen, Cina
402 Piano 4, Fu'an Technology Building, Shenzhen, Cina
Fondazione di ricerca
Lettore
Incorporamenti
Riclassificazione
Ricerca profonda
Classificatore
Segmentatore
Documentazione API
Ottieni la chiave API Jina
Limite di velocità
Stato dell'API
Azienda
Chi siamo
Contatta le vendite
Sala stampa
Programma di stagista
Unisciti a noi
open_in_new
Scarica il logo
open_in_new
Termini
Sicurezza
Termini & Condizioni
Privacy
Gestisci i cookie
email
Jina AI © 2020-2025.