Implementazione della catena di verifica utilizzando il linguaggio di espressione LangChain e LLM

Implementazione di un sistema di verifica utilizzando il linguaggio di espressione LangChain e LLM

Introduzione

La costante ricerca di precisione e affidabilità nel campo dell’Intelligenza Artificiale (AI) ha portato a innovazioni che rivoluzionano il gioco. Queste strategie sono fondamentali per guidare i modelli generativi nel fornire risposte pertinenti a una serie di domande. Uno dei più grandi ostacoli all’uso di AI generativa in diverse applicazioni sofisticate è l’allucinazione. Il recente articolo pubblicato da Meta AI Research intitolato “La catena di verifica riduce l’allucinazione nei modelli di linguaggio di grandi dimensioni” discute una semplice tecnica per ridurre direttamente l’allucinazione durante la generazione di testo.

In questo articolo, impareremo i problemi di allucinazione ed esploreremo i concetti di CoVe menzionati nell’articolo e come implementarli utilizzando LLM, LangChain Framework e LangChain Expression Language (LCEL) per creare catene personalizzate.

Obiettivi di apprendimento

  • Capire il problema dell’allucinazione in LLM.
  • Apprendere il meccanismo Chain of Verification (CoVe) per mitigare l’allucinazione.
  • Conoscere i vantaggi e gli svantaggi di CoVe.
  • Imparare a implementare CoVe utilizzando LangChain e comprendere il Linguaggio di Espressione LangChain (LCEL).

Questo articolo è stato pubblicato come parte del Data Science Blogathon.

Qual è il problema dell’allucinazione in LLM?

Proviamo prima a capire il problema dell’allucinazione in LLM. Utilizzando l’approccio di generazione autoregressiva, il modello LLM predice la parola successiva data il contesto precedente. Per temi frequenti, il modello ha visto abbastanza esempi per assegnare con sicurezza una probabilità elevata ai token corretti. Tuttavia, poiché il modello non è stato addestrato su argomenti insoliti o sconosciuti, potrebbe fornire token imprecisi con elevata fiducia. Ciò porta a allucinazioni di informazioni plausibili ma sbagliate.

Ecco un esempio di allucinazione in ChatGPT di Open AI, dove ho chiesto del libro “Economia delle Piccole Cose”, pubblicato nel 2020 da un autore indiano, ma il modello ha dato una risposta sbagliata con piena fiducia, confondendolo con il libro di un altro vincitore del premio Nobel, Abhijit Banerjee, intitolato “Economia dello Sviluppo”.

Tecnica Chain of Verification (CoVe)

Il meccanismo CoVe combina indicazioni e controlli di coerenza per creare un sistema di autoverifica per LLM. Di seguito sono elencati i principali passaggi descritti nell’articolo. Cercheremo di comprendere ogni passaggio in dettaglio uno per uno.

Panoramica del processo di Chain

  1. Generare la risposta di base: Dato una query, generare la risposta utilizzando LLM.
  2. Pianificare le verifiche: Dato sia la query che la risposta di base, generare una lista di domande di verifica che potrebbero aiutare a autoanalizzare se ci sono errori nella risposta originale.
  3. Eseguire le verifiche: Rispondere a ogni domanda di verifica a turno, e quindi controllare la risposta rispetto alla risposta originale per verificare eventuali incongruenze o errori.
  4. Generare la risposta finale verificata: Dato le incongruenze scoperte (se presenti), generare una risposta revisionata incorporando i risultati delle verifiche.

Comprendere il processo di Chain utilizzando un esempio dettagliato

Genera una risposta iniziale

Prima di tutto passiamo la nostra query a LLM senza alcuna richiesta particolare per generare una risposta iniziale. Questo serve come punto di partenza per il processo CoVe. Poiché le reazioni di base come queste sono spesso soggette ad allucinazioni, la tecnica CoVe cerca di scoprire e correggere questi errori nelle fasi successive.

Esempio –  “Qual è la causa principale della guerra messico-americana?”

Risposta del bot – La guerra messico-americana è stata un conflitto armato tra gli Stati Uniti e il Messico dal 1846 al 1848. È stata preceduta dall’annessione del Texas agli Stati Uniti nel 1845, considerato parte del suo territorio nonostante la sua secessione de facto nella rivoluzione texana del 1835.

Verifiche del piano

Crea domande di verifica basate sulla query e sulla risposta di base che ci consentono di esaminare le affermazioni di fatto della risposta di base. Per implementare questo, possiamo simulare una serie di domande di verifica basate sia sulla query che sulla risposta di base. Le domande di verifica possono essere flessibili e non devono corrispondere esattamente al testo originale.

Esempio – Quando è iniziata e terminata la guerra messico-americana? Quando gli Stati Uniti hanno annesse il Texas? Quando il Texas si è separato dal Messico?

Eseguire le verifiche

Una volta pianificate le domande di verifica, è possibile rispondere a queste domande singolarmente. Nel paper vengono discussi 4 diversi metodi per eseguire le verifiche:

1. Congiunte – In questo metodo, la pianificazione e l’esecuzione delle domande di verifica vengono fatte in un’unica prompt. Le domande e le relative risposte vengono fornite nella stessa prompt LLM. Questo metodo generalmente non è consigliato in quanto può risultare in una risposta di verifica hallucinante.

2. 2-Passi – La pianificazione e l’esecuzione vengono fatte separatamente in due passaggi con prompt LLM separati. Prima generiamo le domande di verifica e poi rispondiamo a queste domande.

3. Fattorizzate – Qui, ogni domanda di verifica viene risposta indipendentemente anziché nella stessa grande risposta, e la risposta di base originale non è inclusa. Questo può aiutare ad evitare confusione tra diverse domande di verifica e anche ad affrontare un maggior numero di domande.

4. Fattorizzate + Riformulate – In questo metodo, viene aggiunto uno step aggiuntivo. Dopo aver risposto ad ogni domanda di verifica, il meccanismo CoVe controlla se le risposte corrispondono alla risposta di base originale. Questo viene fatto in uno step separato utilizzando un prompt aggiuntivo.

Strumenti esterni o Self LLM: Abbiamo bisogno di uno strumento che verifichi le nostre risposte e dia risposte di verifica. Ciò può essere fatto utilizzando sia il LLM stesso che uno strumento esterno. Se desideriamo una maggiore precisione, invece di affidarci al LLM, possiamo utilizzare strumenti esterni come un motore di ricerca su Internet, qualsiasi documento di riferimento o qualsiasi sito web a seconda del nostro caso d’uso.

Risposta Verificata Finale

In questo step finale, viene generata una risposta migliorata e verificata. Viene utilizzato un prompt few-shot e vengono inclusi tutti i contesti precedenti della risposta di base e delle risposte alle domande di verifica. Se è stato utilizzato il metodo “Fattorizzate + Riformulate”, viene fornito anche l’output dell’incongruenza controllata incrociata.

Limitazioni della tecnica di CoVe

Sebbene la Chain of Verification sembri una tecnica semplice ma efficace, ha comunque alcune limitazioni:

  1. Hallucinazione Non Completamente Rimossa: Non garantisce l’eliminazione completa delle risposte erronee e può quindi produrre informazioni sbagliate.
  2. Intensivo di Calcolo: Generare ed eseguire le verifiche insieme alla generazione delle risposte può aumentare i carichi computazionali e i costi. Quindi, può rallentare il processo o aumentare il costo di calcolo.
  3. Limitazione Specifica del Modello: Il successo di questo metodo CoVe dipende largamente dalle capacità del modello e dalla sua capacità di identificare e correggere i propri errori.

Implementazione di LangChain di CoVe

Schema di base dell’algoritmo

In questo caso, utilizzeremo 4 diversi template di prompt per ognuno dei 4 passaggi di CoVe e ad ogni passaggio l’output del passaggio precedente funge da input per il passaggio successivo. Inoltre, seguiamo un approccio fattorizzato all’esecuzione delle domande di verifica. Utilizziamo un agente esterno di ricerca su Internet per generare risposte alle nostre domande di verifica.

Passaggio 1: Installa e Carica le Librerie

!pip install langchain duckduckgo-search

Passaggio 2: Crea e Inizializza l’Istanza di LLM

In questo caso, utilizzo Google Palm LLM in Langchain poiché è liberamente disponibile. È possibile generare la chiave API per Google Palm utilizzando questo linke accedendo con il proprio account Google.

from langchain import PromptTemplatefrom langchain.llms import GooglePalmfrom langchain.schema.output_parser import StrOutputParserfrom langchain.schema.runnable import RunnablePassthrough, RunnableLambdaAPI_KEY='Generated API KEY'llm=GooglePalm(google_api_key=API_KEY)llm.temperature=0.4llm.model_name = 'models/text-bison-001'llm.max_output_tokens=2048

Step 3: Genera la Risposta di Baseline Iniziale

Ora creeremo un template di prompt per generare la risposta di baseline iniziale e, utilizzando questo template, creeremo la catena di risposta di baseline LLM.

Una catena LLM userà il Linguaggio di Espressione LangChain per comporre la catena. Qui forniamo il template di prompt concatenato (|) con il modello LLM (|) e infine con l’analizzatore di output.

BASELINE_PROMPT = """Rispondi alla domanda sottostante che richiede una risposta concisa e fattuale. NO DETTAGLI AGGIUNTIVI.Domanda: {query}Risposta:"""# Catena per generare una risposta inizialebaseline_response_prompt_template = PromptTemplate.from_template(BASELINE_PROMPT)baseline_response_chain = baseline_response_prompt_template | llm | StrOutputParser()

Step 4: Genera il Template di Domanda per la Domanda di Verifica

Ora costruiremo un template di domanda di verifica che aiuterà a generare le domande di verifica nel prossimo passaggio.

VERIFICATION_QUESTION_TEMPLATE = """Il tuo compito è creare una domanda di verifica basata sulla seguente domanda fornita.Esempio Domanda: Chi ha scritto il libro 'Il dio delle piccole cose'?Esempio Domanda di Verifica: È stato scritto il libro [Il dio delle piccole cose] da [scrittore]? Se no, chi ha scritto [Il dio delle piccole cose]? Spiegazione: Nell'esempio sopra, la domanda di verifica si è concentrata solo sull'ENTITÀ_RISPOSTA (nome dello scrittore) e l'ENTITÀ_DOMANDA (nome del libro). Allo stesso modo, è necessario concentrarsi sull'ENTITÀ_RISPOSTA e l'ENTITÀ_DOMANDA della domanda reale e generare la domanda di verifica.Domanda Reale: {query}Domanda di Verifica Finale:"""# Catena per generare un template di domanda per le risposte di verificaverification_question_template_prompt_template = PromptTemplate.from_template(VERIFICATION_QUESTION_TEMPLATE)verification_question_template_chain = verification_question_template_prompt_template | llm | StrOutputParser()

Step 5: Genera la Domanda di Verifica

Ora genereremo le domande di verifica utilizzando il template di domanda di verifica definito in precedenza:

VERIFICATION_QUESTION_PROMPT= """Il tuo compito è creare una serie di domande di verifica basate sulla seguente domanda, sul template di domanda di verifica e sulla risposta di baseline.Esempio Domanda: Chi ha scritto il libro 'Il dio delle piccole cose'?Esempio Template Domanda di Verifica: È stato scritto il libro [Il dio delle piccole cose] da [scrittore]? Se no, chi ha scritto [Il dio delle piccole cose]?Esempio Risposta di Baseline: Jhumpa LahiriEsempio Domanda di Verifica: 1. È stato scritto 'Il dio delle piccole cose' da Jhumpa Lahiri? Se no, chi ha scritto 'Il dio delle piccole cose'? Spiegazione: Nell'esempio sopra, le domande di verifica si sono concentrate solo sull'ENTITÀ_RISPOSTA (nome dello scrittore) e l'ENTITÀ_DOMANDA (nome del libro) basandosi sul template e sostituendo i valori delle entità dalla risposta di baseline. Allo stesso modo, è necessario concentrarsi sull'ENTITÀ_RISPOSTA e l'ENTITÀ_DOMANDA della domanda reale e sostituire i valori delle entità dalla risposta di baseline per generare le domande di verifica.Domanda Reale: {query}Risposta di Baseline: {base_response}Template Domanda di Verifica: {verification_question_template}Domande di Verifica Finali:"""# Catena per generare le domande di verificaverification_question_generation_prompt_template = PromptTemplate.from_template(VERIFICATION_QUESTION_PROMPT)verification_question_generation_chain = verification_question_generation_prompt_template | llm | StrOutputParser()

Step 6: Esegui la Domanda di Verifica

Qui useremo l’agente di ricerca esterna per eseguire la domanda di verifica. Questo agente è costruito utilizzando il modulo di Agent e Strumenti di LangChain e il modulo di ricerca DuckDuckGo.

Nota: Ci sono limitazioni di tempo negli agenti di ricerca, quindi utilizzali con attenzione poiché richieste multiple possono causare un errore dovuto alle restrizioni di tempo tra le richieste

from langchain.agents import ConversationalChatAgent, AgentExecutorfrom langchain.tools import DuckDuckGoSearchResults#crea l'agente di ricercasearch = DuckDuckGoSearchResults()tools = [search]custom_system_message = "L'assistente non assume alcuna conoscenza e si basa sulla ricerca su Internet per rispondere alle domande dell'utente."max_agent_iterations = 5max_execution_time = 10chat_agent = ConversationalChatAgent.from_llm_and_tools(    llm=llm, tools=tools, system_message=custom_system_message)search_executor = AgentExecutor.from_agent_and_tools(    agent=chat_agent,    tools=tools,    return_intermediate_steps=True,    handle_parsing_errors=True,    max_iterations=max_agent_iterations,    max_execution_time = max_execution_time)# Catena per eseguire le domande di verificaverification_chain = RunnablePassthrough.assign(    split_questions=lambda x: x['verification_questions'].split("\n"), # ogni domanda di verifica viene passata una alla voltamodalità basata sui fatti) | RunnablePassthrough.assign(    answers = (lambda x: [{"input": q,"chat_history": []} for q in x['split_questions']])| search_executor.map() # la ricerca viene eseguita per ogni domanda in modo indipendente) | (lambda x: "\n".join(["Domanda: {} Risposta: {}\n".format(question, answer['output']) for question, answer in zip(x['split_questions'], x['answers'])]))# Crea una risposta finale raffinata

Passo 7: Generare una Risposta Definitiva Raffinata

Ora genereremo la risposta definitiva raffinata per la quale definiremo il template della domanda e la catena llm.

FINAL_ANSWER_PROMPT= """Dato il seguente `Query Originale` e `Risposta di Base`, analizza le `Domande di Verifica e le Risposte` per fornire infine la risposta raffinata.Query Originale: {query}Risposta di Base: {base_response}Coppie di Domande e Risposte di Verifica:{verification_answers}Risposta Definitiva Raffinata:"""# Catena per generare la risposta finaledefinizione del template della domanda della risposta finale = PromptTemplate.from_template(PROMPT_RISPOSTA_DEFINITIVA)catena_risposta_finale = template_domanda_risposta_finale | llm | StrOutputParser()

Passo 8: Unire Tutte le Catene Insieme

Ora uniamo tutte le catene che abbiamo definito in precedenza in modo che vengano eseguite in sequenza in un’unica volta.

catena = RunnablePassthrough.assign(base_response=catena_risposta_di_base) | RunnablePassthrough.assign(template_domanda_verifica=catena_template_domanda_verifica) | RunnablePassthrough.assign(domande_verifica=catena_generazione_domande_verifica) | RunnablePassthrough.assign(risposte_verifica=catena_verifica) | RunnablePassthrough.assign(risposta_finale=catena_risposta_finale)risposta = catena.invoke({"query": "Chi ha scritto il libro 'Economia delle Piccole Cose'?")print(risposta)

#output della risposta{'query': "Chi ha scritto il libro 'Economia delle Piccole Cose'?", 'base_response': 'Sanjay Jain', 'template_domanda_verifica': 'Il libro [Economia delle Piccole Cose] è stato scritto da [scrittore]? Se no, chi ha scritto [Economia delle Piccole Cose]?', 'domande_verifica': '1. L'Economia delle Piccole Cose è stata scritta da Sanjay Jain? Se no, chi ha scritto L'Economia delle Piccole Cose?', 'risposte_verifica': 'Domanda: 1. L'Economia delle Piccole Cose è stata scritta da Sanjay Jain? Se no, chi ha scritto L'Economia delle Piccole Cose? Risposta: L'Economia delle Piccole Cose è stata scritta da Sudipta Sarangi \n', 'risposta_finale': 'Sudipta Sarangi'}

Immagine di output:

Conclusioni

La tecnica Chain-of-Verification (CoVe) proposta nello studio è una strategia che mira a costruire modelli di linguaggio avanzati, pensare in modo più critico alle loro risposte e correggersi se necessario. Questo perché questo metodo divide la verifica in query più piccole e gestibili. È stato dimostrato anche che vietare al modello di rivedere le sue risposte precedenti aiuta a evitare di ripetere errori o “allucinazioni”. Richiedere semplicemente al modello di verificare nuovamente le sue risposte migliora notevolmente i risultati. Dare a CoVe ulteriori capacità, come consentirgli di attingere informazioni da fonti esterne, potrebbe essere un modo per aumentare la sua efficacia.

Punti Chiave

  • Il processo Chain è uno strumento utile con varie combinazioni di tecniche che ci permette di verificare diverse parti della nostra risposta.
  • Oltre a molti vantaggi, ci sono certe limitazioni del processo Chain che possono essere attenuate utilizzando diversi strumenti e meccanismi.
  • Possiamo sfruttare il pacchetto LangChain per implementare questo processo CoVe.

Domande Frequenti

I media mostrati in questo articolo non sono di proprietà di Analytics Vidhya e sono utilizzati a discrezione dell’autore.