Nel corso di questa guida, abbiamo imparato molto sugli LLM, sulla libreria Langchain ma soprattutto su due architetture fondanti in questo periodo storico ovvero RAG e agenti AI.
E’ arrivato il momento di creare un esempio un po’ riassuntivo, non troppo complesso ma che metta al lavoro tutti i muscoli che abbiamo allenato sinora.
Il nostro progetto
Il nostro scopo è realizzare un agente di supporto a servizi turistici a Roma che permetta di ottenere informazioni sulla storia ed il meteo della Città Eterna. Parlando di un agente, incapsuleremo le funzionalità in tool che questo imparerà ad utilizzare al momento giusto. L’agente sarà specializzato in modo esclusivo, pertanto non dovrà rispondere a tematiche che non riguardino gli argomenti che abbiamo citato: un po’ quello che deve saper fare ogni agente progettato per supportare uno specifico servizio (aiuto in linea, customer care, etc.).
I tool che prospettiamo per l’agente si occupano di:
- ricerca di informazioni su monumenti di Roma. Il progetto ha una RAG a disposizione in cui vengono archiviate informazioni riguardanti la città ed i suoi monumenti. Come possiamo immaginare, non investiremo grandi energie sulla ricerca di documenti essendo noi interessati per lo più all’architettura dell’applicazione. Prenderemo però spunto dalla RAG di esempio creata in una lezione precedente che sfrutteremo come base da espandere;
- recupero di informazioni meteo dal servizio Open-Meteo che, tramite API, offre informazioni meteo gratuitamente. In questo caso, implementiamo un meccanismo molto comune che è quello del tool capace di accedere a servizi on line, il che rende l’agente potenzialmente in grado ad interagire con qualsiasi tipo di funzionalità.
Preparazione della RAG
Per prima cosa procediamo alla preparazione della RAG. Includeremo pochi documenti Wikipedia in un database vettoriale – cosa che abbiamo già imparato a fare – per averlo a disposizione del nostro agente.
Questo il codice:
from langchain_community.document_loaders import WikipediaLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# gli argomenti che vogliamo scaricare da Wikipedia
argomenti = ["Roma", "Basilica di San Pietro", "Colosseo"]
# struttura dati che accoglierà i documenti
documenti = []
# per ogni argomento procederemo allo scarico
for a in argomenti:
try:
print(f"Scaricamento in corso per: {a}...")
loader = WikipediaLoader(query=a, lang="it", load_max_docs=1)
documenti.extend(loader.load())
except:
print(f"Errore di scaricamento per: {a}...")
# i documenti vengono processati
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
chunks = splitter.split_documents(documenti)
embeddings = OpenAIEmbeddings(model="text-embedding-3-small", api_key=api_key)
# viene compilato un database vettoriale in modalità persistente
db = Chroma.from_documents(chunks, persist_directory="./chroma_db", embedding=embeddings)
Procediamo sulla falsa riga di quanto visto nella guida in precedenza. L’unica differenza è che creiamo una lista di argomenti che saranno tutti i topic ricercati in Wikipedia.
Il ciclo eseguirà gli scaricamenti per poi procedere al loro processamento mediante text splitting e embedding.
Al termine avremo un database pronto al lavoro salvato in maniera persistente. Quello che ci attende ora è la creazione dell’agente che conterrà i tool di cui uno incaricato di utilizzare proprio questo database.
Ricordiamo che questa fase, l’allestimento della RAG, va eseguito solo la prima volta al fine di istruire il database vettoriale. L’agente vero e proprio non dovrà mai ripeterla ma solo usare il database pronto.
Inoltre, gli stessi tool non dovranno rileggere il database ad ogni esecuzione ma lo troveranno già collegato in memoria in modo da utilizzarlo solo al momento di svolgere una query per fornire un contesto di lavoro al modello di Intelligenza Artificiale.
Qualche prova sul database
Prima di mettere al lavoro il database in un agente potremo fare alcune prove come:
-
il conteggio dei chunk, il numero di frammenti in cui i documenti sono stati spezzettati:
numero_frammenti = db._collection.count() print(f"Numero di chunks presenti nel DB: {numero_frammenti}")Nel nostro caso questa operazione ne restituirà 76. Questa verifica è importante per vedere se il database è stato allestito correttamente e se le operazioni di text splitting e embedding sono state completate;
- la ricerca nel database che rappresenta la verifica sulla qualità dei contenuti mediante una query come
db.similarity_search("chi ha fondato Roma?", k=2)che eseguirà un’interrogazione chiedendo al massimo due documenti (tramite il parametrokimpostabile a piacere). Il risultato sarà una lista di documenti dei quali sarà interessante verificare non solo i contenuti ma anche gli URL di origine. Questa prova sarà utile anche per capire se ilWikipediaLoaderabbia individuato gli indirizzi migliori in base agli argomenti forniti.
Chiariti questi aspetti possiamo passare a scrivere il codice dell’agente che abbiamo progettato.
Se vuoi aggiornamenti su Creare un agente AI per il turismo inserisci la tua email nel box qui sotto:

