I modelli linguistici di grandi dimensioni (LLM) sono incredibilmente potenti, ma la loro conoscenza è limitata ai set di dati di addestramento. Quando rispondono a domande, in particolare su informazioni specifiche, in evoluzione o proprietarie, gli LLM possono avere allucinazioni o fornire risposte generali e irrilevanti. La retrieval-augmented generation (RAG) aiuta fornendo all'LLM informazioni rilevanti recuperate da fonti di dati esterne.
Tuttavia, non tutte le RAG sono uguali. La retrieval-augmented generation correttiva (cRAG) non si basa semplicemente sulla RAG più tradizionale, ma rappresenta un miglioramento significativo. È stata concepita per essere più affidabile attraverso la valutazione della qualità e della pertinenza dei risultati recuperati. Se il contesto è debole, irrilevante o proviene da una fonte inaffidabile, la cRAG tenta di trovare informazioni migliori attraverso azioni correttive o si rifiuta esplicitamente di rispondere piuttosto che inventare una risposta. Questa tecnica rende i sistemi cRAG più affidabili e sicuri per applicazioni critiche, come rispondere a domande relative alle polizze.
In questo tutorial, potrai imparare come creare un sistema RAG correttivo (CRag) affidabile, utilizzando i modelli IBM® Granite su Watsonx e LangChain. Framework simili come LlamaIndex o LangGraph possono essere utilizzati anche per creare flussi RAG complessi con nodi distinti. Tecniche come la messa a punto possono migliorare ulteriormente le prestazioni LLM specifiche per RAG distintive del dominio. Anche gli LLM come quelli di OpenAI (ad esempio, i modelli GPT come ChatGPT) sono scelte diffuse per questi agenti, sebbene questo tutorial si concentri su IBM Granite.
Qui ci concentreremo su un caso d'uso: rispondere a domande su uno specifico documento relativo a una polizza assicurativa (PDF). Questo tutorial ti guiderà nell'implementazione di un sofisticato algoritmo RAG che:
Recupera informazioni dal tuo documento PDF.
Se i documenti interni non sono sufficienti per generare la risposta, l'agente può utilizzare una ricerca web esterna (Tavily) come fallback.
L'agente filtra in modo intelligente i risultati esterni irrilevanti in modo che le risposte siano adattate alle polizze private.
L'agente fornirà risposte chiare e limitate con informazioni parziali se disponibili o un chiaro rifiuto laddove manchi il contesto.
Questo tutorial è una dimostrazione della creazione di un agente di query sulle polizze assicurative progettato per analizzare i documenti delle polizze (una brochure PDF) e rispondere in modo accurato alle domande degli utenti. Utilizziamo i modelli IBM® Granite e LangChain per creare l'agente con solide fasi di recupero e verifica che garantiscono risposte di alta qualità e vincolate all'origine.
Vediamo ora come si applicano i principi chiave di un RAG affidabile nel nostro caso d'uso.
Knowledge base interna (PDF): la principale fonte di verità dell'agente è il PDF della polizza assicurativa fornita. Converte questo documento in un database vettoriale.
Fallback per la ricerca esterna (Tavily): se la knowledge base interna non dispone di informazioni sufficienti, l'agente può consultare fonti web esterne tramite Tavily. Tavily è un motore di ricerca creato specificamente per agenti AI e LLM che consente un recupero più rapido e in tempo reale tramite l'application programming interface (API) per le applicazioni basate su RAG.
Punteggio contestuale: il valutatore del recupero basato su LLM (che funge da selezionatore) fornirà un punteggio in base alla pertinenza degli elementi recuperati dal PDF interno, garantendo al contempo che siano inclusi solo gli elementi recuperati di alta qualità.
Riscrittura delle query: per le ricerche sul web, l'agente può riformulare la query dell'utente per aumentare le possibilità di trovare informazioni esterne pertinenti.
Verifica della fonte: un controllo basato su un LLM valuta se i risultati di ricerca web esterni sono pertinenti per una polizza assicurativa privata, filtrando le informazioni generali o i dettagli sui programmi di salute (come Medi-Cal). Questa funzione impedisce la generazione di risposte fuorvianti e consente l'autocorrezione, aiutando nell'affinamento delle conoscenze.
Generazione vincolata: il prompt finale all'LLM lo istruisce rigorosamente a utilizzare solo il contesto fornito, offrire risposte esatte, indicare quando le informazioni non sono disponibili o fornire risposte parziali con limitazioni esplicite. Questa funzione migliora l'adattabilità e l'affidabilità delle risposte generate.
Per creare un progetto watsonx.ai è necessario un account IBM Cloud . Assicurati di avere accesso sia alla tua chiave API watsonx che all'ID progetto. Avrai anche bisogno di una chiave API per Tavily AI per le funzionalità di ricerca web.
Sebbene sia possibile scegliere tra diversi strumenti, questo tutorial illustra come configurare un account IBM utilizzando un Jupyter Notebook.
Questo passaggio apre un ambiente notebook in cui è possibile copiare il codice da questo tutorial. In alternativa, puoi scaricare questo notebook sul tuo sistema locale e caricarlo nel tuo progetto watsonx.ai come asset. Per visualizzare altri tutorial su Granite, visita l' IBM Granite Community. Questo tutorial è disponibile anche su Github.
Per lavorare con il framework LangChain e integrare IBM WatsonXLLM, è necessario installare alcune librerie essenziali. Iniziamo installando i pacchetti richiesti. Questo set include langchain per il framework RAG, langchain-ibm per l'integrazione di watsonx, faiss-cpu per lo storage efficiente, PyPDF2 per l'elaborazione di PDF, sentence-transformer per ottenere un embedding e richieste per chiamate API web. Queste librerie sono critiche per applicare soluzioni di machine learning e NLP.
Nota: non è richiesta alcuna GPU, ma l'esecuzione può essere più lenta su sistemi basati su CPU. Questo passaggio apre un ambiente notebook in cui è possibile copiare il codice da questo tutorial, a sua volta disponibile anche su GitHub.
Successivamente, importa tutti i moduli richiesti e fornisci in modo sicuro le tue chiavi API per watsonx e Tavily, insieme al tuo ID progetto watsonx.
os aiuta a lavorare con il sistema operativo.
io permette di lavorare con flussi di dati.
getpass utilizza un metodo sicuro per catturare informazioni sensibili come le chiavi API e non visualizza l'input sullo schermo.
PyPDF2.PdfReader consente di estrarre il contenuto dai PDF.
langchain_ibm. WatsonxLLM ci permette di utilizzare facilmente l'LLM IBM watsonx Granite all'interno del framework LangChain.
langchain.embedding.HuggingFaceEmbeddings prende un modello HuggingFace e genera gli embedding testuali importanti per la ricerca semantica.
langchain.vectorstores.FAISS è una libreria per il storage vettoriale efficiente e la ricerca di similarità che consente di creare un indice vettoriale e interrogarlo.
langchain.text_splitter.RecursiveCharacterTextSplitter aiuta a suddividere grandi componenti di testo nei blocchi più piccoli necessari per elaborare documenti che altrimenti non entrerebbero in memoria.
langchain.schema.Document rappresenta un'unità di testo arbitraria con metadati associati che lo rendono un elemento costitutivo di langchain.
requests viene utilizzato per effettuare richieste HTTP esternamente alle API.
Botocore.client.config è una classe di configurazione utilizzata per definire le impostazioni di configurazione per un client AWS/IBM Cloud Object Storage.
ibm_boto3 è IBM Cloud Object Storage SDK per Python che aiuta a interagire con il cloud object storage.
langchain.prompts.PromptTemplate offre un modo per creare prompt strutturati e riutilizzabili per i modelli linguistici.
langchain.tools.BaseTool è la classe base da cui crei strumenti personalizzati che possono essere forniti agli agenti LangChain per l'uso.
Questo passaggio configura tutti gli strumenti e i moduli necessari per elaborare testo, creare embedding, memorizzarli in un database vettoriale e interagire con IBM watsonx LLM. Stabilisce tutte le parti necessarie per creare un sistema RAG del mondo reale, in grado di reperire, interrogare e cercare una serie di tipi di dati.
In questa fase, caricheremo il PDF della polizza assicurativa da IBM Cloud Object Storage. Il codice legge il PDF e il contenuto del testo per poi suddividere quest'ultimo in blocchi più piccoli e gestibili. Questi blocchi vengono convertiti in embedding e memorizzati in un database vettoriale FAISS che ci prepara per la successiva ricerca di similarità semantica nel contesto locale per ottimizzare i risultati.
ibm_boto3.client consente al client di interagire con IBM Cloud Object Storage.
Bucket è il nome del bucket di cloud object storage che contiene il PDF.
object_key è il nome del PDF nel bucket di cloud object storage.
cos_client.get_object(...).read() recupera il contenuto del file PDF nel cloud object storage come byte.
io.BytesIO converte i byte grezzi del PDF in un flusso binario in memoria in un formato che utilizzabile da PdfReader.
PdfReader crea un oggetto che può analizzare ed estrarre il testo dal PDF.
page.extract_text() estrae il testo di una singola pagina del PDF.
RecursiveCharacterTextSplitter è configurato per dividere il testo estratto in blocchi di 500 caratteri con una sovrapposizione di 50 caratteri, mantenendo quindi tutto in contesto.
splitter.split_text(text) esegue la suddivisione di tutte le pagine del testo PDF nei blocchi più piccoli.
HuggingFaceEmbeddings carica un modello di trasformatore di frasi che è stato preaddestrato per convertire i blocchi di testo in rappresentazioni vettoriali dense.
FAISS.from_texts(chunks, embeddings) costruisce un indice FAISS in memoria che consente di ricercare blocchi di testo in base alle loro similarità semantiche.
Questo passaggio gestisce l'acquisizione completa di un documento PDF dal cloud al testo pronto per l'LLM e la comoda indicizzazione per il recupero in tempo reale.
In questo passaggio, configurerai l'LLM IBM Granite per guidare il ragionamento del tuo agente e integrarlo con la funzione di ricerca web di Tavily. I parametri dell'LLM sono impostati per risposte fattuali e stabili.
WatsonXLLM crea un'istanza del wrapper LLM per IBM watsonx, consentendo l'interazione con i modelli Granite.
model_id="ibm/granite-3-2b-instruct" è il modello IBM Granite (un modello di istruzione di parametri da 2,7 miliardi) progettato per attività di AI generativa basate su istruzioni.
class TavilySearch(BaseTool) definisce uno strumento LangChain personalizzato per l'esecuzione di ricerche web utilizzando l'API Tavily.
tavily_tool = TavilySearch() crea un'istanza eseguibile dello strumento di ricerca personalizzato Tavily.
Quando inizializziamo watsonxLLM, i valori url, apikey e project_id delle nostre credenziali precedentemente configurate vengono passati per l'autenticazione e la connessione al servizio. I suoi parametri, come "max_new_tokens": 300, limitano la lunghezza della risposta e "temperature": 0.2 controlla la creatività dell'output, favorendo risultati più deterministici.
La definizione della classe TavilySearch include una descrizione della sua funzione. La sua logica è contenuta nel metodo def _run(self, query: str). In questo metodo, effettuiamo una richiesta HTTP POST all'endpoint dell'API Tavily, inclusi TAVILY_API_KEY e la query di ricerca nel payload JSON. Verifichiamo, quindi, se ci sono errori HTTP con response.raise_for_status() e analizziamo la risposta JSON per accedere allo snippet di contenuto dal primo risultato di ricerca.
Questo passaggio configura il modello linguistico per la generazione di testo e include uno strumento di ricerca web esterno per aumentare la conoscenza del modello linguistico.
Questo passaggio definisce i vari modelli di prompt che guidano il comportamento dell'LLM nelle diverse fasi del processo RAG. Questo approccio include la richiesta di valutare la pertinenza dei blocchi di documenti interni, la riscrittura delle query degli utenti per una migliore ricerca sul Web e un nuovo prompt critico per la verifica dell'origine dei risultati della ricerca Web. Vengono inoltre definite le funzioni di supporto per l'assegnazione dei punteggi ai blocchi e il loro recupero dal database vettoriale.
Questo passaggio definisce i vari modelli di prompt che guidano il comportamento dell'LLM nelle diverse fasi del processo RAG. Prompt per verificare la pertinenza di blocchi di documenti interni, riscrivere le query degli utenti per una migliore ricerca sul web e un prompt critico per verificare che la fonte dei risultati della ricerca sul web sia inclusa. Sono definite anche le funzioni di supporto per assegnare punteggi ai blocchi e recuperarli dal database vettoriale.
PromptTemplate.from_template è una utility di LangChain per creare un modello riutilizzabile per la costruzione di prompt.
scoring_prompt_template definisce un prompt che indica all'LLM di agire come valutatore e assegnare un punteggio di pertinenza (0—5) a un blocco di contesto specifico in base a una domanda.
rewrite_prompt_template definisce un prompt che guida l'LLM a migliorare o rendere più chiara la domanda originale dell'utente per la ricerca.
CONTEXT_SOURCE_VERIFICATION_PROMPT definisce un prompt che indica all'LLM di verificare se un blocco di testo (ad esempio, dalla ricerca web) proviene da un contesto di policy privata o da una fonte generale o pubblica.
def score_chunks(chunks, query)definisce una funzione che richiede un elenco di blocchi di testo e una query utilizza quindi l'LLM per valutare la rilevanza di ogni blocco.
def retrieve_from_vectorstore(query) definisce una funzione per recuperare i documenti più simili dal database vettoriale FAISS.
All'interno della funzione score_chunks, viene inizializzato un elenco di punteggi vuoto. Per ogni blocco, il scoring_prompt_template viene formattato con la query e il blocco specifici. Questo prompt formattato viene quindi inviato all'LLM e la risposta viene rimossa. La funzione tenta di estrarre il punteggio intero (un punteggio binario se semplificato in rilevante o non rilevante) identificando la riga "Score:" nella risposta del modello. Il blocco insieme al suo punteggio analizzato o predefinito viene quindi aggiunto all'elenco dei punteggi. Questa parte del sistema funge da valutatore o classificatore del recupero.
La funzione retrieve_from_vectorstore implementa un vectorstore.similarity_search per trovare gli otto blocchi di documento più pertinenti in base alla query e recuperare il page_content da questi oggetti LangChain Document recuperati.
Questa fase costruisce la struttura concettuale per il sistema RAG correttivo in modo che l'LLM valuti sia il contesto che come recuperare la conoscenza da fonti interne ed esterne.
Recupero iniziale è la funzione che scansiona il database vettoriale del PDF.
Punteggio contestuale prende i blocchi PDF che sono stati recuperati per attribuire un punteggio contestuale in base alla pertinenza.
Fallback a tavily è la funzione per cui interroga Tavily (ricerca web) se non c'è abbastanza contesto pertinente dal PDF.
La verifica della fonte è un passaggio basato su LLM che verifica se i risultati di Tavily sono rilevanti per una polizza privata prima di utilizzarli. Questa funzione impedisce risposte fuorvianti dai programmi di sanità pubblica.
Riscrittura delle query e seconda ricerca tavily se non c'è ancora un buon contesto, riscrive la query e riprova la ricerca su Tavily.
Decisione finale quando c'è un contesto pertinente, viene inviata all'LLM con un prompt (rigoroso) per creare la risposta. Se non c'è un contesto rilevante dopo tutti i tentativi fattibili, invia un cortese rifiuto.
Il primo passaggio del parametro policy_context_keywords consente di aggiungere termini specifici della polizza (ad esempio, nome, assicuratore) per restringere le ricerche di Tavily.
MIN_CONTEXT_LENGTH definisce la lunghezza minima accettabile del contesto recuperato.
SIMILARITY_THRESHOLD definisce il punteggio minimo di rilevanza che un blocco deve avere per essere considerato "buono."
def corrective_rag(...) definisce la funzione principale che orchestra l'intero workflow RAG correttivo.
La funzione corrective_rag inizia creando retrieved_context_pieces per raccogliere il contesto pertinente. Prima recupera e valuta chunks_from_vectorstore dal database vettoriale PDF in base alla query, poi scored_chunks_vector ne analizza la rilevanza utilizzando il modello linguistico. Vengono mantenuti solo good_chunks_vector che soddisfano i SIMILARITY_THRESHOLD. Il current_context viene poi compilato a partire da questi pezzi.
Se il current_context è inferiore a MIN_CONTEXT_LENGTH, il sistema tenta una ricerca sul web. Costruisce tavily_search_query, incorporando potenzialmente policy_context_keywords. Viene eseguita una ricerca diretta(tavily_context_direct). Fondamentalmente, viene creato un verification_prompt e inviato all'LLM per determinare se il risultato della ricerca web (is_relevant_source) proviene da una polizza privata anziché da un programma pubblico. In caso affermativo, viene aggiunto il contesto.
Se il contesto rimane insufficiente, il sistema si prepara a riscrivere la query. Utilizza rewrite_prompt per ottenere una improved_query dall'LLM, quindi esegue una seconda ricerca sul web (tavily_context_rewritten). Anche questo nuovo contesto viene sottoposto alla stessa verifica della fonte.
Infine, if len(current_context.strip()) == 0 è un ultimo controllo. Se dopo tutti i tentativi non viene trovato alcun contesto rilevante, viene restituito un messaggio di rifiuto predefinito. Altrimenti, viene creato un final_prompt con tutto il contesto verificato e inviato al modello linguistico per generare la risposta finale.
L'intera funzione corrective_rag gestisce in dettaglio le funzioni graduali di recupero, punteggio e verifica del RAG correttivo. Consente l'aggiornamento costante della knowledge base e del flusso di conoscenze e offre il beneficio di risposte affidabili e consapevoli del contesto.
Infine, esegui la funzione corrective_rag con una query di esempio. È fondamentale fornire policy_context_keywords specifiche per il tuo documento PDF. Queste parole chiave aiuteranno la ricerca web di Tavily a essere più pertinente alla tua politica effettiva, evitando che informazioni generiche o relative a programmi di salute pubblica contaminino il contesto.
Osserva le istruzioni di stampa per il contesto, la lunghezza e i risultati della verifica per comprendere il flusso di informazioni.
policy_specific_keywords = ["Super Star Health", "Care Health Insurance"] definisce una lista di parole chiave pertinenti alla polizza assicurativa caricata, contribuendo a restringere il campo di ricerca sul web.
query = "... " definisce la domanda particolare che un utente potrebbe porre.
result = corrective_rag(query, policy_context_keywords=policy_specific_keywords) chiama la funzione principale corrective_rag e passa la query dell'utente e le parole chiave specifiche della politica per iniziare l'intero processo RAG.
print("\n FINAL ANSWER (...)") visualizza un'intestazione chiara prima di stampare la risposta generata.
print(result) restituisce la risposta finale restituita dal sistema corrective_rag.
Questo passaggio mostra come richiamare il sistema RAG correttivo completo con una query di esempio e delle parole chiave, dimostrandone la funzionalità end-to-end in uno scenario reale.
Il RAG correttivo implementato ha coordinato completamente una knowledge base PDF interna con un servizio esterno (Tavily) per recuperare informazioni complete per richieste complesse.
Ha valutato accuratamente e filtrato il contesto recuperato utilizzando una valutazione basata su LLM e una verifica critica delle fonti per garantire che vengano utilizzate informazioni valide e affidabili.
Il sistema ha dimostrato la capacità di migliorare la ricerca esterna riscrivendo in modo intelligente le query degli utenti per richiedere informazioni più mirate e di qualità superiore.
Utilizzando la generazione vincolata, veniva comunemente generata una risposta affidabile e contestualmente accurata e il sistema si rifiutava cortesemente di rispondere se non c'erano abbastanza informazioni di verifica note.
Questo esempio ha dimostrato come gli LLM LangChain e IBM Granite su watsonx possono essere utilizzati per sviluppare applicazioni potenti e basate su AI affidabile in domini sensibili, come ad esempio porre domande sulle polizze assicurative.
Crea, implementa e gestisci assistenti e agenti AI potenti che automatizzano workflow e processi con l'AI generativa.
Costruisci il futuro della tua azienda con soluzioni AI di cui puoi fidarti.
I servizi di AI di IBM Consulting aiutano a reinventare il modo in cui le aziende lavorano con l'AI per la trasformazione.