AGI e IA del futuro

Costruire Agenti LLM per RAG da Zero e Oltre: Una Guida Completa

mm
Aggiungi Unite.AI alle tue fonti preferite su Google

I LLM come GPT-3, GPT-4 e il loro counterpart open-source spesso lottano con il recupero di informazioni aggiornate e possono a volte generare allucinazioni o informazioni errate.

Retrieval-Augmented Generation (RAG) è una tecnica che combina il potere dei LLM con il recupero di conoscenze esterne. RAG ci consente di fondare le risposte dei LLM su informazioni fattuali e aggiornate, migliorando notevolmente l’accuratezza e l’affidabilità del contenuto generato dall’AI.

In questo post del blog, esploreremo come costruire agenti LLM per RAG da zero, immergendoci nell’architettura, nei dettagli di implementazione e nelle tecniche avanzate. Copriremo tutto, dalle basi del RAG alla creazione di agenti sofisticati in grado di ragionamento complesso e esecuzione di attività.

Prima di iniziare a costruire il nostro agente LLM, comprendiamo cosa sia RAG e perché sia importante.

RAG, o Retrieval-Augmented Generation, è un approccio ibrido che combina il recupero di informazioni con la generazione di testo. In un sistema RAG:

  • Una query viene utilizzata per recuperare documenti rilevanti da una base di conoscenze.
  • Questi documenti vengono quindi alimentati in un modello linguistico insieme alla query originale.
  • Il modello genera una risposta in base sia alla query che alle informazioni recuperate.
RAG

RAG

Questo approccio ha diversi vantaggi:

  • Miglioramento dell’accuratezza: Fondando le risposte sulle informazioni recuperate, RAG riduce le allucinazioni e migliora l’accuratezza fattuale.
  • Informazioni aggiornate: La base di conoscenze può essere aggiornata regolarmente, consentendo al sistema di accedere a informazioni correnti.
  • Trasparenza: Il sistema può fornire fonti per le sue informazioni, aumentando la fiducia e consentendo la verifica dei fatti.

Comprendere gli Agenti LLM

 

Quando si affronta un problema senza una risposta semplice, spesso è necessario seguire diversi passaggi, pensare attentamente e ricordare cosa si è già provato. Gli agenti LLM sono progettati per situazioni del genere nelle applicazioni dei modelli linguistici. Combinano un’analisi approfondita dei dati, una pianificazione strategica, il recupero di dati e la capacità di apprendere dalle azioni passate per risolvere problemi complessi.

Cosa sono gli Agenti LLM?

Gli agenti LLM sono sistemi AI avanzati progettati per creare testi complessi che richiedono ragionamento sequenziale. Possono pensare in anticipo, ricordare le conversazioni passate e utilizzare diversi strumenti per adattare le loro risposte in base alla situazione e allo stile necessario.

Consideriamo una domanda nel campo legale come: “Quali sono i possibili esiti legali di una specifica tipologia di violazione del contratto in California?” Un LLM di base con un sistema RAG può recuperare le informazioni necessarie dalle banche dati legali.

Per uno scenario più dettagliato: “Alla luce delle nuove leggi sulla privacy dei dati, quali sono le sfide legali comuni che le aziende affrontano e come i tribunali hanno affrontato queste questioni?” Questa domanda va oltre il semplice reperimento di fatti. Si tratta di comprendere nuove regole, il loro impatto sulle diverse aziende e le risposte dei tribunali. Un agente LLM suddividerebbe questo compito in sottocompiti, come il recupero delle leggi più recenti, l’analisi dei casi storici, la sintesi dei documenti legali e la previsione delle tendenze in base ai modelli.

Componenti degli Agenti LLM

Gli agenti LLM sono generalmente composti da quattro componenti:

  1. Agente/Cervello: Il modello linguistico di base che elabora e comprende il linguaggio.
  2. Pianificazione: La capacità di ragionare, suddividere i compiti e sviluppare piani specifici.
  3. Memoria: Mantiene registri delle interazioni passate e apprende da esse.
  4. Uso di Strumenti: Integra diverse risorse per eseguire compiti.

Agente/Cervello

Al centro di un agente LLM c’è un modello linguistico che elabora e comprende il linguaggio in base a grandi quantità di dati su cui è stato addestrato. Si inizia fornendogli una specifica promessa, guidando l’agente su come rispondere, quali strumenti utilizzare e quali obiettivi raggiungere. È possibile personalizzare l’agente con una persona adatta a compiti o interazioni specifici, migliorandone le prestazioni.

Memoria

La componente della memoria aiuta gli agenti LLM a gestire compiti complessi mantenendo un registro delle azioni passate. Ci sono due tipi principali di memoria:

  • Memoria a Breve Termine: Funziona come un bloc notes, tenendo traccia delle discussioni in corso.
  • Memoria a Lungo Termine: Funziona come un diario, archiviando informazioni dalle interazioni passate per apprendere modelli e prendere decisioni migliori.

Combinando questi tipi di memoria, l’agente può offrire risposte più personalizzate e ricordare le preferenze dell’utente nel tempo, creando un’interazione più connessa e rilevante.

Pianificazione

La pianificazione consente agli agenti LLM di ragionare, suddividere i compiti in parti gestibili e adattare i piani man mano che i compiti evolvono. La pianificazione coinvolge due fasi principali:

  • Formulazione del Piano: Suddividere un compito in sottocompiti più piccoli.
  • Riflessione sul Piano: Revisione e valutazione dell’efficacia del piano, incorporando feedback per raffinare le strategie.

Metodi come la Catena di Pensiero (CoT) e l’Albero di Pensiero (ToT) aiutano in questo processo di scomposizione, consentendo agli agenti di esplorare diversi percorsi per risolvere un problema.

Per approfondire il mondo degli agenti AI, inclusi le loro capacità attuali e potenziali, considera di leggere “Auto-GPT & GPT-Engineer: Una Guida Approfondita agli Agenti AI Leader di Oggi”

Configurazione dell’Ambiente

Per costruire il nostro agente RAG, dobbiamo configurare il nostro ambiente di sviluppo. Utilizzeremo Python e diverse librerie chiave:

  • LangChain: Per orchestrare i nostri componenti LLM e di recupero
  • Chroma: Come nostro archivio vettoriale per le embedding dei documenti
  • Modelli GPT di OpenAI: Come nostro modello LLM di base (puoi sostituirlo con un modello open-source se preferito)
  • FastAPI: Per creare una semplice API per interagire con il nostro agente

Iniziamo configurando il nostro ambiente:


<p># Crea un nuovo ambiente virtuale
python -m venv rag_agent_env
source rag_agent_env/bin/activate # Su Windows, utilizza `rag_agent_env\Scripts\activate`</p>

<p># Installa i pacchetti necessari
pip install langchain chromadb openai fastapi uvicorn

Ora, creiamo un nuovo file Python chiamato rag_agent.py e importiamo le librerie necessarie:


<p>from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
import os</p>

<p># Imposta la tua chiave API di OpenAI
os.environ[&quot;OPENAI_API_KEY&quot;] = &quot;la tua chiave api qui&quot;</p>

Costruire un Sistema RAG Semplice

Ora che abbiamo configurato il nostro ambiente, costruiamo un sistema RAG di base. Inizieremo creando una base di conoscenze da un set di documenti, quindi utilizzeremo questo per rispondere a query.

Passo 1: Preparare i Documenti

Innanzitutto, dobbiamo caricare e preparare i nostri documenti. Per questo esempio, supponiamo di avere un file di testo chiamato knowledge_base.txt con alcune informazioni su AI e apprendimento automatico.


<p># Carica il documento
loader = TextLoader(&quot;knowledge_base.txt&quot;)
documents = loader.load()</p>

<p># Suddividi i documenti in chunk
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)</p>

<p># Crea le embedding
embeddings = OpenAIEmbeddings()</p>

<p># Crea un archivio vettoriale
vectorstore = Chroma.from_documents(texts, embeddings)</p>

Passo 2: Creare una Catena di Domande e Risposte basata sul Recupero

Ora che abbiamo il nostro archivio vettoriale, possiamo creare una catena di domande e risposte basata sul recupero:


<p># Crea una catena di domande e risposte basata sul recupero
qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type=&quot;stuff&quot;, retriever=vectorstore.as_retriever())</p>

Passo 3: Interrogare il Sistema

Possiamo ora interrogare il nostro sistema RAG:


<p>query = &quot;Quali sono le principali applicazioni dell'apprendimento automatico?&quot;
result = qa.run(query)
print(result)

Passo 4: Creare un Agente LLM

Mentre il nostro sistema RAG semplice è utile, è abbastanza limitato. Miglioriamo questo creando un agente LLM che possa eseguire compiti più complessi e ragionare sulle informazioni che recupera.

Un agente LLM è un sistema AI che può utilizzare strumenti e prendere decisioni su quali azioni intraprendere. Creeremo un agente che non solo possa rispondere a domande, ma anche eseguire ricerche web e calcoli di base.

Innanzitutto, definiamo alcuni strumenti per il nostro agente:


<p>from langchain.agents import Tool
from langchain.tools import DuckDuckGoSearchRun
from langchain.tools import BaseTool
from langchain.agents import initialize_agent
from langchain.agents import AgentType</p>

<p># Definisci uno strumento di calcolo
class CalculatorTool(BaseTool):
nome = &quot;Calcolatore&quot;
descrizione = &quot;Utile per quando si devono rispondere a domande di matematica&quot;</p>

<p>def _run(self, query: str)
try:
return str(eval(query))
except:
return &quot;Non sono riuscito a calcolare. Assicurati che il tuo input sia un'espressione matematica valida.&quot;</p>

<p># Crea istanze di strumenti
search = DuckDuckGoSearchRun()
calculator = CalculatorTool()</p>

<p># Definisci gli strumenti
tools = [Tool(name=&quot;Ricerca&quot;, func=search.run, description=&quot;Utile per quando si devono rispondere a domande su eventi correnti&quot;),
Tool(name=&quot;RAG-QA&quot;, func=qa.run, description=&quot;Utile per quando si devono rispondere a domande su AI e apprendimento automatico&quot;),
Tool(name=&quot;Calcolatore&quot;, func=calculator._run, description=&quot;Utile per quando si devono eseguire calcoli matematici&quot;)
]</p>

<p># Inizializza l'agente
agent = initialize_agent(tools, OpenAI(temperature=0), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)</p>

Ora abbiamo un agente che può utilizzare il nostro sistema RAG, eseguire ricerche web e calcoli. Proviamo:


<p>result = agent.run(&quot;Qual è la differenza tra apprendimento supervisionato e non supervisionato? Inoltre, qual è il 15% di 80?&quot;)
print(result)</p>

Questo agente dimostra un vantaggio chiave degli agenti LLM: possono combinare più strumenti e passaggi di ragionamento per rispondere a query complesse.

Migliorare l’Agente con Tecniche RAG Avanzate

Mentre il nostro sistema RAG attuale funziona bene, ci sono diverse tecniche avanzate che possiamo utilizzare per migliorarne le prestazioni:

a) Ricerca Semantica con Recupero di Passaggi Densi (DPR)

Invece di utilizzare il recupero basato su embedding semplice, possiamo implementare il DPR per una ricerca semantica più precisa:


<p>from transformers import DPRQuestionEncoder, DPRContextEncoder</p>

<p>question_encoder = DPRQuestionEncoder.from_pretrained(&quot;facebook/dpr-question_encoder-single-nq-base&quot;)
context_encoder = DPRContextEncoder.from_pretrained(&quot;facebook/dpr-ctx_encoder-single-nq-base&quot;)</p>

<p># Funzione per codificare i passaggi
def encode_passages(passages):
return context_encoder(passages, max_length=512, return_tensors=&quot;pt&quot;).pooler_output</p>

<p># Funzione per codificare la query
def encode_query(query):
return question_encoder(query, max_length=512, return_tensors=&quot;pt&quot;).pooler_output</p>

b) Espansione della Query

Possiamo utilizzare l’espansione della query per migliorare le prestazioni del recupero:


<p>from transformers import T5ForConditionalGeneration, T5Tokenizer</p>

<p>model = T5ForConditionalGeneration.from_pretrained(&quot;t5-small&quot;)
tokenizer = T5Tokenizer.from_pretrained(&quot;t5-small&quot;)</p>

<p>def expand_query(query):
input_text = f&quot;espandi query: {query}&quot;
input_ids = tokenizer.encode(input_text, return_tensors=&quot;pt&quot;)
outputs = model.generate(input_ids, max_length=50, num_return_sequences=3)
expanded_queries = [tokenizer.decode(output, skip_special_tokens=True) for output in outputs]
return expanded_queries</p>

c) Raffinamento Iterativo

Possiamo implementare un processo di raffinamento iterativo in cui l’agente può porre domande di follow-up per chiarire o ampliare la sua ricerca iniziale:


<p>def iterative_retrieval(initial_query, max_iterations=3):
query = initial_query
for _ in range(max_iterations):
result = qa.run(query)
clarification = agent.run(f&quot;Sulla base di questo risultato: &#039;{result}&#039;, quale domanda di follow-up dovrei porre per ottenere informazioni più specifiche?&quot;)
if clarification.lower().strip() == &quot;nessuna&quot;:
break
query = clarification
return result</p>

# Utilizza questo nel processo del tuo agente

Implementazione di un Sistema Multi-Agente

Per gestire compiti più complessi, possiamo implementare un sistema multi-agente in cui diversi agenti si specializzano in aree diverse. Ecco un semplice esempio:


<p>class SpecialistAgent:
def __init__(self, name, tools):
self.name = name
self.agent = initialize_agent(tools, OpenAI(temperature=0), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)</p>

<p>def run(self, query):
return self.agent.run(query)</p>

<p># Crea agenti specialisti
research_agent = SpecialistAgent(&quot;Ricerca&quot;, [Tool(name=&quot;RAG-QA&quot;, func=qa.run, description=&quot;Per domande su AI e ML&quot;)])
math_agent = SpecialistAgent(&quot;Matematica&quot;, [Tool(name=&quot;Calcolatore&quot;, func=calculator._run, description=&quot;Per calcoli&quot;)])
general_agent = SpecialistAgent(&quot;Generale&quot;, [Tool(name=&quot;Ricerca&quot;, func=search.run, description=&quot;Per query generali&quot;)])</p>

<p>class Coordinator:
def __init__(self, agents):
self.agents = agents</p>

<p>def run(self, query):
# Determina quale agente utilizzare
if &quot;calcola&quot; in query.lower() or any(op in query for op in [&#039;+&#039;, &#039;-&#039;, &#039;*&#039;, &#039;/&#039;]):
return self.agents[&#039;Matematica&#039;].run(query)
elif any(term in query.lower() for term in [&#039;ai&#039;, &#039;machine learning&#039;, &#039;deep learning&#039;]):
return self.agents[&#039;Ricerca&#039;].run(query)
else:
return self.agents[&#039;Generale&#039;].run(query)</p>

<p>coordinator = Coordinator({&#039;Ricerca&#039;: research_agent, &#039;Matematica&#039;: math_agent, &#039;Generale&#039;: general_agent})</p>

<p># Testa il sistema multi-agente
result = coordinator.run(&quot;Qual è la differenza tra CNN e RNN? Inoltre, calcola il 25% di 120.&quot;)
print(result)</p>

Questo sistema multi-agente consente la specializzazione e può gestire una gamma più ampia di query in modo più efficace.

Valutazione e Ottimizzazione degli Agenti RAG

Per assicurarci che il nostro agente RAG stia funzionando bene, dobbiamo implementare metriche di valutazione e tecniche di ottimizzazione:

a) Valutazione della Rilevanza

Possiamo utilizzare metriche come BLEU, ROUGE o BERTScore per valutare la rilevanza dei documenti recuperati:


from bert_score import score

<p>def evaluate_relevance(query, retrieved_doc, generated_answer):
P, R, F1 = score([generated_answer], [retrieved_doc], lang=&quot;en&quot;)
return F1.mean().item()</p>

b) Valutazione della Qualità della Risposta

Possiamo utilizzare la valutazione umana o metriche automatiche per valutare la qualità della risposta:


<p>from nltk.translate.bleu_score import sentence_bleu</p>

<p>def evaluate_answer_quality(reference_answer, generated_answer):
return sentence_bleu([reference_answer.split()], generated_answer.split())</p>

<p># Utilizza questo per valutare le risposte del tuo agente

Future Direzioni e Sfide

Mentre guardiamo al futuro degli agenti RAG, emergono diverse direzioni e sfide interessanti:

a) RAG Multi-Modale: Estendere il RAG per incorporare dati di immagini, audio e video.

b) RAG Federato: Implementare il RAG su basi di conoscenze distribuite e preservare la privacy.

c) Apprendimento Continuo: Sviluppare metodi per gli agenti RAG per aggiornare le loro basi di conoscenze e modelli nel tempo.

d) Considerazioni Etiche: Affrontare pregiudizi, equità e trasparenza nei sistemi RAG.

e) Scalabilità: Ottimizzare il RAG per applicazioni su larga scala e in tempo reale.

Conclusione

Costruire agenti LLM per RAG da zero è un processo complesso ma gratificante. Abbiamo coperto le basi del RAG, implementato un sistema semplice, creato un agente LLM, migliorato con tecniche avanzate, esplorato sistemi multi-agente e discusso strategie di valutazione e ottimizzazione.

Ho trascorso gli ultimi cinque anni immergendomi nel mondo affascinante del Machine Learning e del Deep Learning. La mia passione e la mia esperienza mi hanno portato a contribuire a oltre 50 progetti di ingegneria del software diversi, con un focus particolare su AI/ML. La mia curiosità in corso mi ha anche portato verso l'elaborazione del linguaggio naturale, un campo che sono ansioso di esplorare ulteriormente.