Creazione di un agente LLaMa 2 potenziato con la conoscenza di Wikipedia

Sviluppo di un agente LLaMa 2 potenziato tramite l'utilizzo delle informazioni di Wikipedia

Potenziare LLaMa 2 con la generazione potenziata da recupero per cercare e utilizzare informazioni da Wikipedia.

Foto di Lysander Yuen su Unsplash

Introduzione

I Large Language Models (LLM) sono una delle tendenze più hot nell’ambito dell’AI. Hanno dimostrato impressionanti capacità di generazione di testo, dalla capacità di sostenere conversazioni con utenti umani alla scrittura di codice. La diffusione dei LLM open-source come LLama, Falcon, Stable Beluga, ecc. ha reso il loro potenziale accessibile a un’ampia comunità di AI, anche grazie alla focalizzazione sullo sviluppo di modelli più piccoli ed efficienti che possono essere eseguiti su hardware di consumo.

Uno degli ingredienti chiave che contribuiscono al successo dei LLM è la famosa architettura transformer introdotta nel rivoluzionario articolo Attention Is All You Need. Le impressionanti prestazioni dei LLM di ultima generazione sono raggiunte scalando questa architettura a miliardi di parametri e addestrandola su set di dati che comprendono trilioni di token. Questa pre-formazione produce modelli fondamentali potenti in grado di comprendere il linguaggio umano e che possono essere ulteriormente raffinati per casi d’uso specifici.

La pre-formazione dei Large Language Models viene eseguita in modo auto-supervisionato. Richiede una vasta raccolta di corpora di testo, ma non richiede l’annotazione umana. Ciò rende possibile scalare l’addestramento a enormi set di dati che possono essere creati in modo automatizzato. Dopo aver trasformato i testi di input in una sequenza di token, la pre-formazione viene eseguita con l’obiettivo di prevedere la probabilità di ciascun token nella sequenza condizionato a tutti i token precedenti. In questo modo, dopo l’addestramento, il modello è in grado di generare testo in modo auto-regressivo campionando un token alla volta condizionato a tutti i token campionati finora. I Large Language Models sono stati in grado di ottenere impressionanti capacità linguistiche solo con questa pre-formazione. Tuttavia, campionando token secondo le probabilità condizionali apprese dai dati di addestramento, il testo generato in generale non è allineato alle preferenze umane e i LLM faticano a seguire istruzioni specifiche o intenzioni umane.

Un passo significativo avanti nell’allineamento del testo generato dai LLM alle preferenze umane è stato raggiunto con il Reinforcement Learning from Human Feedback (RLHF). Questa tecnica è al centro dei modelli di chat di ultima generazione come ChatGPT. Con il RLHF, dopo la fase iniziale di pre-formazione auto-supervisionata, il Large Language Model viene ulteriormente raffinato con un algoritmo di apprendimento per rinforzo per massimizzare una ricompensa calibrata sulle preferenze umane. Per ottenere la funzione di ricompensa, è consueto addestrare un modello ausiliario per apprendere una ricompensa scalare che riflette le preferenze umane. In questo modo, la quantità effettiva di dati etichettati da umani necessari per la fase di apprendimento per rinforzo può essere mantenuta al minimo. I dati di addestramento per i modelli di ricompensa sono costituiti da testi generati che sono stati classificati dagli umani in base alle loro preferenze. Il modello mira a prevedere una ricompensa maggiore per il testo classificato più in alto. Addestrando un LLM con l’obiettivo di massimizzare una ricompensa che riflette le preferenze umane, si dovrebbero ottenere testi generati più allineati alle intenzioni umane. Infatti, i Large Language Models raffinati con il Reinforcement Learning from Human Feedback hanno dimostrato di seguire meglio le istruzioni dell’utente, riducendo anche la tossicità e aumentando la veridicità.

Generazione potenziata da recupero

Uno dei tipici inconvenienti dei Large Language Models è che sono addestrati offline e quindi non hanno informazioni sugli eventi che sono accaduti dopo la raccolta dei dati di addestramento. Allo stesso modo, non possono utilizzare alcuna conoscenza specifica che non fosse presente nei dati di addestramento. Ciò può essere problematico per specifici settori, poiché i dati utilizzati per addestrare i LLM di solito provengono da corpora generici. Un modo per superare questi problemi, senza richiedere costosi raffinamenti, è la Generazione Potenziata da Recupero (RAG). La RAG funziona aumentando le prompt alimentate a un LLM con informazioni testuali esterne. Queste informazioni vengono di solito recuperate da una fonte di dati esterna in base alla rilevanza rispetto al prompt corrente. In pratica, come primo passo, ciò comporta la trasformazione del prompt e dei testi esterni in embedding vettoriali. Questi possono essere ottenuti aggregando l’output di un modello di codificatore transformer (come BERT) addestrato a mappare i testi con significati simili in embedding che sono vicini l’uno all’altro secondo una metrica appropriata. Nel caso di testi lunghi, possono essere divisi in parti che vengono incorporate individualmente, portando al recupero dei passaggi più rilevanti. Successivamente, vengono recuperati i testi il cui embedding è più vicino all’embedding del prompt. La concatenazione del prompt e del testo recuperato, dopo opportuna formattazione, viene fornita come input al modello di linguaggio.

Con il Generatore di Recupero Augmentato, il modello può accedere a informazioni che non erano disponibili durante il training e baserà le sue risposte su una selezione di testi presenti nel corpus. RAG consente anche di ispezionare le fonti utilizzate dal modello per rispondere, consentendo una valutazione più diretta delle uscite del modello da parte dell’utente.

In questo post del blog, spiegherò come creare un semplice agente capace di basare le sue risposte su contenuti recuperati da Wikipedia per dimostrare la capacità degli LLM di cercare e utilizzare informazioni esterne. Date le istruzioni dell’utente, il modello cercherà pagine appropriate su Wikipedia e baserà le sue risposte sui loro contenuti. Ho reso il codice completo disponibile in questo repository su GitHub.

Un agente Llama 2 potenziato con contenuti di Wikipedia

In questa sezione, descriverò i passaggi necessari per creare un semplice agente Llama 2 che risponde alle domande basandosi su informazioni recuperate da Wikipedia. In particolare, l’agente dovrà…

  • Creare query adeguate per cercare pagine su Wikipedia pertinenti alla domanda dell’utente.
  • Recuperare, tra le pagine trovate su Wikipedia, quella con il contenuto più pertinente alla domanda dell’utente.
  • Estrarre dalla pagina recuperata i passaggi più pertinenti alla richiesta dell’utente.
  • Rispondere alla domanda dell’utente basandosi sugli estratti dalla pagina.

Si noti che, in generale, il modello potrebbe ricevere un’istruzione potenziata con l’intero contenuto della pagina più pertinente o con più estratti provenienti dalle prime pagine collocate in cima alla classifica di pertinenza rispetto all’istruzione dell’utente. Sebbene questo potrebbe migliorare la qualità della risposta del modello, richiederà più memoria poiché inevitabilmente comporterà istruzioni più lunghe. Per semplicità, e al fine di eseguire un esempio minimo su GPU gratuite di Google Colab, ho limitato l’agente all’utilizzo di alcuni estratti dall’articolo più pertinente.

Addentriamoci ora nei vari passaggi in maggior dettaglio. Il primo passo che l’agente deve compiere è creare una query di ricerca adatta per recuperare contenuti da Wikipedia che contengano informazioni per rispondere alla richiesta dell’utente. Per fare ciò, invocheremo un modello di chat Llama 2 chiedendogli di restituire parole chiave che rappresentino l’istruzione dell’utente. Prima di entrare nello specifico della richiesta utilizzata, ricorderò brevemente il formato generale della richiesta per i modelli di chat Llama 2.

Il modello di chat Llama 2 utilizzato durante la procedura di allenamento ha la seguente struttura:

<s>[INST] <<SYS>>{{ system_prompt }}<</SYS>>{{ user_message }} [/INST]

La {{system_prompt}} specifica il comportamento del modello di chat rispetto alle richieste successive e può essere utile per adattare la risposta del modello a diversi compiti. Il {{user_message}} è l’istruzione dell’utente a cui il modello deve rispondere.

Tornando al problema di ottenere le query di ricerca per Wikipedia, il nostro agente utilizzerà un modello Llama 2 con la seguente richiesta:

<s>[INST] <<SYS>>Sei un assistente che restituisce query di testo per cercare articoli di Wikipedia contenenti informazioni pertinenti all'istruzione. Scrivi solo le query. Esempio: [istruzione] Parlami dell'ondata di calore in Europa nell'estate 2023 [query] ondata di calore, clima, temperature, Europa, estate 2023.<</SYS>>[istruzione] {prompt} [/INST] [query]

{prompt} verrà sostituito, prima della generazione, dall’input dell’utente. L’esempio fornito come parte dell’istruzione del sistema mira a sfruttare le capacità di apprendimento nel contesto del modello. L’apprendimento nel contesto si riferisce alla capacità del modello di risolvere nuovi compiti basandosi su alcuni esempi dimostrativi forniti come parte dell’istruzione. In questo modo, il modello può apprendere che ci aspettiamo che fornisca parole chiave pertinenti all’istruzione fornita, separate da virgole dopo il testo [query]. Quest’ultimo viene utilizzato come delimitatore per distinguere l’istruzione dalla risposta nell’esempio ed è anche utile per estrarre le query dall’output del modello. Viene già fornito come parte dell’input in modo che il modello debba generare solo ciò che viene dopo.

Una volta ottenute le query dall’output del modello, vengono utilizzate per cercare su Wikipedia e recuperare i metadati e il testo delle pagine restituite. Nel codice allegato al post, ho utilizzato il pacchetto wikipedia, che è un semplice pacchetto Python che avvolge l’API di MediaWiki, per cercare e recuperare i dati da Wikipedia.

Dopo aver estratto il testo dai risultati della ricerca, viene selezionata la pagina più rilevante rispetto all’input originale dell’utente. Questo permette di allineare le informazioni recuperate con la richiesta originale dell’utente, eliminando potenziali divergenze originate dalle query di ricerca generate dal modello. Per fare ciò, sia l’input dell’utente che il riassunto delle pagine dai risultati della ricerca vengono incorporati e memorizzati in un database vettoriale. Viene quindi recuperato l’articolo con la migliore incorporazione rispetto all’input dell’utente. Ho utilizzato il modello “all-MiniLM-L6-v2” di Sentence Transformers come modello di incorporazione e un database vettoriale FAISS con l’integrazione fornita dal pacchetto “langchain”.

Dopo aver trovato una pagina rilevante da Wikipedia, poiché l’aggiunta del suo intero testo all’input potrebbe richiedere molta memoria (o superare il limite di token del modello per la lunghezza del contesto), il nostro assistente troverà gli estratti più rilevanti da aggiungere all’input. Ciò viene fatto suddividendo prima il testo della pagina in blocchi e, successivamente, incorporandoli in uno spazio vettoriale e recuperando quelli più vicini all’incorporazione dell’input. Ho nuovamente utilizzato il modello “all-MiniLM-L6-v2” per incorporare i blocchi e un database vettoriale FAISS per memorizzarli e recuperarli.

Ora che abbiamo ottenuto i passaggi recuperati dall’articolo, possiamo combinarli con l’input dell’utente e inviarli al modello Llama 2 per ottenere una risposta. Il template utilizzato per l’input è il seguente:

<s>[INST] <<SYS>>Sei un assistente utile e onesto. Le tue risposte non dovrebbero includere contenuti dannosi, anti-etici, razzisti, sessisti, tossici, pericolosi o illegali. Hai recuperato gli estratti seguenti dalla pagina Wikipedia {title}:{extracts}. Si richiede che tu dia risposte veritiere basate sugli estratti precedenti. Se non contengono informazioni rilevanti per la richiesta, specificalo e non inventare false informazioni.<</SYS>>{prompt} [/INST]

Prima della generazione, {prompt} viene sostituito con l’input dell’utente, {title} con il titolo della pagina Wikipedia e {extracts} viene sostituito con i passaggi estratti. È possibile fornire anche alcuni esempi per sfruttare ulteriormente le capacità di apprendimento in contesto del modello, ma ciò aumenterebbe significativamente i requisiti di memoria.

Verifichiamo ora se il modello è in grado di rispondere utilizzando informazioni aggiornate che non erano presenti durante il suo addestramento, estrarrendole da Wikipedia. L’esempio seguente è stato ottenuto utilizzando la versione più piccola di LLaMa 2 con 7 miliardi di parametri in esecuzione su GPU gratuite di Google Colab.

Ho dato al modello il seguente input:

prompt: "Parlami del terremoto a Marrakesh"

Il modello ha creato la seguente query per cercare su Wikipedia:

"terremoto, Marrakesh, Marocco, terremoti recenti, attività sismica."

Dopo aver estratto i passaggi dalla pagina più rilevante, il modello ha restituito la seguente risposta:

Il terremoto che ha colpito Marrakesh l'8 settembre 2023 è stato un evento devastante che ha causato vasta distruzione e perdite di vite nella regione. Secondo le informazioni fornite su Wikipedia, il terremoto aveva una magnitudo di momento compresa tra 6,8 e 6,9 e un'intensità di Mercalli massima di VIII (Grave), rendendolo il terremoto strumentalmente registrato più forte in Marocco e il più mortale dal terremoto di Agadir del 1960. L'epicentro del terremoto si trovava a circa 73,4 km a sud-ovest di Marrakesh, vicino alla città di Ighil e alla stazione sciistica di Oukaïmeden nelle Montagne dell'Atlante. Il terremoto è avvenuto a seguito di un movimento di faglia obliqua poco profonda al di sotto della catena montuosa. Secondo l'Organizzazione Mondiale della Sanità, circa 300.000 persone di Marrakesh e delle zone circostanti sono state colpite dal terremoto, tra cui 100.000 bambini. Il terremoto ha causato almeno 2.946 morti, la maggior parte delle quali al di fuori di Marrakesh. È importante notare che le informazioni fornite su Wikipedia si basano sui dati disponibili e potrebbero non essere esaustive o aggiornate. Se hai domande specifiche 

L’assistente restituisce anche i metadati e gli estratti della pagina utilizzata per la risposta, consentendo all’utente di verificare la correttezza e approfondire ulteriormente leggendo la pagina originale. Ecco i metadati per la risposta precedente:

PAGINA WIKIPEDIA RECUPERATA: titolo: Terremoto di Marrakesh-Safi del 2023 url: https://it.wikipedia.org/wiki/Terremoto_di_Marrakesh-Safi_del_2023 Estratti recuperati: Estratto_0: Conseguenze del terremoto a Marrakesh e Moulay Brahim  Estratto_1: I danni sono stati diffusi e monumenti storici a Marrakesh sono stati distrutti. Il terremoto è stato avvertito anche in Spagna, Portogallo e Algeria. È il terremoto strumentalmente registrato più forte in Marocco, il più mortale nel paese dal terremoto di Agadir del 1960 e il secondo terremoto più mortale del 2023 dopo il terremoto Turchia-Siria. L'Organizzazione Mondiale della Sanità ha stimato che circa 300.000 persone di Marrakesh e delle zone circostanti sono state colpite, tra cui 100.000 bambini.  Estratto_2: L'8 settembre 2023 alle 23:11 DST (22:11 UTC), un terremoto con una magnitudo di momento compresa tra 6,8 e 6,9 e un'intensità di Mercalli massima di VIII (Grave) ha colpito la regione Marrakesh-Safi del Marocco. L'epicentro del terremoto si trovava a 73,4 km a sud-ovest di Marrakesh, vicino alla città di Ighil e alla stazione sciistica di Oukaïmeden nelle Montagne dell'Atlante. È avvenuto a seguito di un movimento di faglia obliqua poco profonda al di sotto della catena montuosa. Sono stati segnalati almeno 2.946 morti, la maggior parte delle quali al di fuori di Marrakesh

Conclusion

In questo articolo, ho spiegato come creare un semplice agente in grado di rispondere ad una richiesta dell’utente cercando su Wikipedia e basando la sua risposta sulla pagina trovata. Nonostante la sua semplicità, l’agente è in grado di fornire risposte aggiornate e accurate anche con il modello Llama 2 7B più piccolo. L’agente restituisce anche gli estratti della pagina utilizzata per generare la risposta, consentendo all’utente di verificare la correttezza delle informazioni fornite dal modello e di approfondire leggendo l’intera pagina originale.

Wikipedia è un interessante campo di prova per dimostrare le capacità di un agente LLM di cercare e utilizzare informazioni esterne non presenti nei dati di allenamento, ma lo stesso approccio può essere applicato in altri contesti dove è necessaria una conoscenza esterna. Questo è il caso, ad esempio, per applicazioni che richiedono risposte aggiornate, campi che necessitano di conoscenze specifiche non presenti nei dati di allenamento o l’estrazione di informazioni da documenti privati. Questo approccio sottolinea anche il potenziale di collaborazione tra LLM e esseri umani. Il modello può restituire rapidamente una risposta significativa cercando informazioni rilevanti da una vasta base di conoscenze esterne, mentre l’utente umano può verificare la validità della risposta del modello e approfondire il tema ispezionando la fonte originale.

Un miglioramento diretto dell’agente descritto in questo articolo può essere ottenuto combinando più estratti provenienti da diverse pagine al fine di fornire una maggior quantità di informazioni al modello. Infatti, in caso di richieste complesse, potrebbe essere utile estrarre informazioni da più pagine di Wikipedia. L’aumento risultante dei requisiti di memoria dovuti ai contesti più lunghi può essere parzialmente compensato con l’implementazione di tecniche di quantizzazione come GPTQ. I risultati potrebbero essere ulteriormente migliorati dando al modello la possibilità di ragionare sui risultati della ricerca e sul contenuto recuperato prima di fornire la sua risposta finale agli utenti, seguendo ad esempio il framework ReAct descritto nel documento ReAct: Synergizing Reasoning and Acting in Language Models. In questo modo, ad esempio, è possibile costruire un modello che raccoglie in modo iterativo i passaggi più rilevanti da diverse pagine, scartando quelli non necessari e combinando informazioni provenienti da argomenti diversi.

Grazie per aver letto!