AGI e IA del futuro
Costruire Agenti LLM per RAG da Zero e Oltre: Una Guida Completa
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.
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:
- Agente/Cervello: Il modello linguistico di base che elabora e comprende il linguaggio.
- Pianificazione: La capacità di ragionare, suddividere i compiti e sviluppare piani specifici.
- Memoria: Mantiene registri delle interazioni passate e apprende da esse.
- 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["OPENAI_API_KEY"] = "la tua chiave api qui"</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("knowledge_base.txt") 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="stuff", retriever=vectorstore.as_retriever())</p>
Passo 3: Interrogare il Sistema
Possiamo ora interrogare il nostro sistema RAG:
<p>query = "Quali sono le principali applicazioni dell'apprendimento automatico?" 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 = "Calcolatore" descrizione = "Utile per quando si devono rispondere a domande di matematica"</p> <p>def _run(self, query: str) try: return str(eval(query)) except: return "Non sono riuscito a calcolare. Assicurati che il tuo input sia un'espressione matematica valida."</p> <p># Crea istanze di strumenti search = DuckDuckGoSearchRun() calculator = CalculatorTool()</p> <p># Definisci gli strumenti tools = [Tool(name="Ricerca", func=search.run, description="Utile per quando si devono rispondere a domande su eventi correnti"), Tool(name="RAG-QA", func=qa.run, description="Utile per quando si devono rispondere a domande su AI e apprendimento automatico"), Tool(name="Calcolatore", func=calculator._run, description="Utile per quando si devono eseguire calcoli matematici") ]</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("Qual è la differenza tra apprendimento supervisionato e non supervisionato? Inoltre, qual è il 15% di 80?") 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("facebook/dpr-question_encoder-single-nq-base") context_encoder = DPRContextEncoder.from_pretrained("facebook/dpr-ctx_encoder-single-nq-base")</p> <p># Funzione per codificare i passaggi def encode_passages(passages): return context_encoder(passages, max_length=512, return_tensors="pt").pooler_output</p> <p># Funzione per codificare la query def encode_query(query): return question_encoder(query, max_length=512, return_tensors="pt").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("t5-small")
tokenizer = T5Tokenizer.from_pretrained("t5-small")</p>
<p>def expand_query(query):
input_text = f"espandi query: {query}"
input_ids = tokenizer.encode(input_text, return_tensors="pt")
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"Sulla base di questo risultato: '{result}', quale domanda di follow-up dovrei porre per ottenere informazioni più specifiche?")
if clarification.lower().strip() == "nessuna":
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("Ricerca", [Tool(name="RAG-QA", func=qa.run, description="Per domande su AI e ML")])
math_agent = SpecialistAgent("Matematica", [Tool(name="Calcolatore", func=calculator._run, description="Per calcoli")])
general_agent = SpecialistAgent("Generale", [Tool(name="Ricerca", func=search.run, description="Per query generali")])</p>
<p>class Coordinator:
def __init__(self, agents):
self.agents = agents</p>
<p>def run(self, query):
# Determina quale agente utilizzare
if "calcola" in query.lower() or any(op in query for op in ['+', '-', '*', '/']):
return self.agents['Matematica'].run(query)
elif any(term in query.lower() for term in ['ai', 'machine learning', 'deep learning']):
return self.agents['Ricerca'].run(query)
else:
return self.agents['Generale'].run(query)</p>
<p>coordinator = Coordinator({'Ricerca': research_agent, 'Matematica': math_agent, 'Generale': general_agent})</p>
<p># Testa il sistema multi-agente
result = coordinator.run("Qual è la differenza tra CNN e RNN? Inoltre, calcola il 25% di 120.")
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="en") 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.














