Un nuovo indice di riepilogo dei documenti per i sistemi di controllo qualità basati su LLM
In questo post del blog, introduciamo una nuovissima struttura di dati LlamaIndex: un indice di riepilogo dei documenti. Descriviamo come può aiutare a offrire prestazioni di recupero migliori rispetto alla ricerca semantica tradizionale e passiamo anche attraverso un esempio.
Sfondo
Uno dei casi d'uso principali dei Large Language Models (LLM) è rispondere a domande sui propri dati. Per fare ciò, abbiniamo il LLM a un modello di "recupero" che può eseguire il recupero delle informazioni su un corpus di conoscenza ed eseguire la sintesi della risposta sui testi recuperati utilizzando il LLM. Questo quadro generale è chiamato Retrieval-Augmented Generation.
La maggior parte degli utenti che oggi costruiscono sistemi di QA basati su LLM tende a eseguire una delle seguenti operazioni:
- Prendi i documenti di origine, dividili ciascuno in blocchi di testo
- Memorizza blocchi di testo in un vettore db
- Durante la fase di query, recupera blocchi di testo incorporando somiglianze e/o filtri per parole chiave.
- Eseguire la sintesi della risposta
Limitazioni degli approcci esistenti
Ci sono alcune limitazioni nell'incorporamento del recupero usando blocchi di testo.
- I blocchi di testo mancano di contesto globale. Spesso la domanda richiede un contesto al di là di ciò che è indicizzato in un blocco specifico.
- Attenta messa a punto delle soglie del punteggio top-k/somiglianza. Rendi il valore troppo piccolo e perderai il contesto. Rendi il valore troppo grande e il costo/latenza potrebbe aumentare con un contesto più irrilevante.
- Gli incorporamenti non sempre selezionano il contesto più pertinente per una domanda. Gli incorporamenti sono intrinsecamente determinati separatamente tra il testo e il contesto.
Indice di riepilogo del documento
Proponiamo un nuovo indice in LlamaIndex che estrarrà/indicizzerà un sommario di testo non strutturato per ogni documento . Questo indice può aiutare a migliorare le prestazioni di recupero oltre gli approcci di recupero esistenti. Aiuta a indicizzare più informazioni rispetto a un singolo blocco di testo e ha un significato semantico maggiore rispetto ai tag delle parole chiave. Consente inoltre una forma di recupero più flessibile: possiamo eseguire sia il recupero LLM che il recupero basato sull'incorporamento.
Come funziona
Durante la fase di compilazione, ingeriamo ogni documento e utilizziamo un LLM per estrarre un riepilogo da ogni documento. Abbiamo anche suddiviso il documento in blocchi di testo (nodi). Sia il riepilogo che i nodi sono archiviati all'interno della nostra astrazione dell'archivio documenti . Manteniamo una mappatura dal riepilogo al documento/nodi di origine.
Durante la fase della query, recuperiamo i documenti pertinenti alla query in base ai relativi riepiloghi, utilizzando i seguenti approcci:
- Recupero basato su LLM: presentiamo serie di riepiloghi di documenti al LLM e chiediamo al LLM di determinare quali documenti sono rilevanti + il loro punteggio di pertinenza.
- Recupero basato sull'incorporamento: recuperiamo i documenti pertinenti in base alla somiglianza dell'incorporamento riepilogativo (con un limite massimo-k).
La memorizzazione di riepiloghi per un documento consente anche il recupero basato su LLM . Invece di fornire l'intero documento all'LLM all'inizio, possiamo prima fare in modo che l'LLM ispezioni il riepilogo conciso del documento per vedere se è pertinente alla query. Ciò sfrutta le capacità di ragionamento di LLM che sono più avanzate della ricerca basata sull'incorporamento, ma evita il costo/la latenza di alimentare l'intero documento al LLM
Approfondimenti aggiuntivi
Il recupero di documenti con riepiloghi può essere considerato una "via di mezzo" tra la ricerca semantica e il riepilogo a forza bruta in tutti i documenti. Cerchiamo i documenti in base alla pertinenza riassuntiva con la query data, quindi restituiamo tutti i *nodi* corrispondenti ai documenti recuperati.
Perché dovremmo farlo? Questo metodo di recupero offre all'utente più contesto rispetto a top-k su una porzione di testo, recuperando il contesto a livello di documento. Ma è anche un approccio più flessibile/automatico rispetto alla modellazione degli argomenti; non dovrai più preoccuparti se il tuo testo ha i tag parole chiave giusti!
Esempio
Esaminiamo un esempio che mette in mostra l'indice di riepilogo del documento, su articoli di Wikipedia su diverse città.
Il resto di questa guida mostra i frammenti di codice pertinenti. Puoi trovare la procedura dettagliata completa qui (e qui c'è il collegamento al taccuino ).
Possiamo costruire GPTDocumentSummaryIndex
su una serie di documenti e passare un ResponseSynthesizer
oggetto per sintetizzare i riassunti per i documenti.
from llama_index import (
SimpleDirectoryReader,
LLMPredictor,
ServiceContext,
ResponseSynthesizer
)
from llama_index.indices.document_summary import GPTDocumentSummaryIndex
from langchain.chat_models import ChatOpenAI
# load docs, define service context
...
# build the index
response_synthesizer = ResponseSynthesizer.from_args(response_mode="tree_summarize", use_async=True)
doc_summary_index = GPTDocumentSummaryIndex.from_documents(
city_docs,
service_context=service_context,
response_synthesizer=response_synthesizer
)
summary = doc_summary_index.get_document_summary("Boston")
from llama_index.indices.document_summary import DocumentSummaryIndexRetriever
retriever = DocumentSummaryIndexRetriever(
doc_summary_index,
# choice_select_prompt=choice_select_prompt,
# choice_batch_size=choice_batch_size,
# format_node_batch_fn=format_node_batch_fn,
# parse_choice_select_answer_fn=parse_choice_select_answer_fn,
# service_context=service_context
)
retrieved_nodes = retriever.retrieve("What are the sports teams in Toronto?")
print(retrieved_nodes[0].score)
print(retrieved_nodes[0].node.get_text())The retriever will retrieve a set of relevant nodes for a given index.
8.0
Toronto ( (listen) tə-RON-toh; locally [təˈɹɒɾ̃ə] or [ˈtɹɒɾ̃ə]) is the capital city of the Canadian province of Ontario. With a recorded population of 2,794,356 in 2021, it is the most populous city in Canada...
API di alto livello
query_engine = doc_summary_index.as_query_engine(
response_mode="tree_summarize", use_async=True
)
response = query_engine.query("What are the sports teams in Toronto?")
print(response)
# use retriever as part of a query engine
from llama_index.query_engine import RetrieverQueryEngine
# configure response synthesizer
response_synthesizer = ResponseSynthesizer.from_args()
# assemble query engine
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=response_synthesizer,
)
# query
response = query_engine.query("What are the sports teams in Toronto?")
print(response)
L'approccio del riepilogo automatico su qualsiasi parte di testo è davvero entusiasmante. Siamo entusiasti di sviluppare estensioni in due aree:
- Continua a esplorare il riepilogo automatico in diversi livelli. Attualmente è a livello di documento, ma che ne dici di riassumere un grosso pezzo di testo in uno più piccolo? (ad esempio una riga).
- Continua a esplorare il recupero basato su LLM, che il riepilogo aiuta a sbloccare.
Guida riassuntiva del documento
Collegamento taccuino