Un semplice esempio di Retrieval-Augmented Generation (RAG)¶
Luca Mari, settembre 2024
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stesso modo 4.0 Internazionale.
Obiettivo: comprendere qualche aspetto della logica delle architetture ad agenti e dell'esecuzione automatica di funzioni.
Precompetenze: basi di Python.
Per eseguire questo notebook, supponiamo con VSCode, occorre:
- installare un interprete Python
- scaricare da https://code.visualstudio.com/download e installare VSCode
- eseguire VSCode e attivare le estensioni per Python e Jupyter
- ancora in VSCode:
- creare una cartella di lavoro e renderla la cartella corrente
- copiare nella cartella il file di questa attività: rag.ipynb
- aprire il notebook
rag.ipynb
- creare un ambiente virtuale locale Python (Select Kernel | Python Environments | Create Python Environment | Venv, e scegliere un interprete Python):
- installare i moduli Python richiesti, eseguendo dal terminale:
pip install torch sentence_transformers
Importiamo il modulo Python necessario per realizzare il sentence embedding (la documentazione è qui: https://www.sbert.net).
Dopo aver specificato che, per semplicità, faremo eseguire il codice sempre in CPU anche nel caso una GPU sia disponibile, carichiamo il modello.
from sentence_transformers import SentenceTransformer
device = "cpu"
model = SentenceTransformer('intfloat/multilingual-e5-large', device=device)
Supponiamo di avere un archivio di testi da cui recuperare l'informazione utile per rispondere in modo appropriato a richieste che vengono poste. Qui per semplicità l'archivio è costituito da 5 frasi, generate sinteticamente e con contenuto evidentemente non noto in precedenza, in modo che sia chiaro se il processo di recupero funziona correttamente.
sentences = [
"Nel 2015, gli scienziati hanno scoperto una nuova forma di vita basata su silicio nelle profondità del pianeta Venere.",
"La città di Aqualia, sommersa nel 1723, è stata recentemente riscoperta sotto l'Oceano Atlantico, perfettamente conservata.",
"Gli archeologi hanno decifrato un antico manoscritto che descrive tecnologie avanzate utilizzate dai Sumeri per costruire ponti sospesi.",
"Una misteriosa foresta bioluminescente è stata scoperta sotto i ghiacciai dell'Antartide, rivelando specie mai documentate prima.",
"Un team di astrofisici ha confermato l'esistenza di un buco nero artificiale creato durante esperimenti militari segreti negli anni '60."
]
Costruiamo il vettore di embedding di ogni frase.
embeddings = [model.encode(sentence) for sentence in sentences]
print(f'Ogni frase è rappresentata da un vettore di {len(embeddings[0])} numeri.')
Ogni frase è rappresentata da un vettore di 1024 numeri.
Per curiosità, calcoliamo la similarità di ogni coppia di vettori-frasi.
model.similarity(embeddings, embeddings)
tensor([[1.0000, 0.8135, 0.8232, 0.8399, 0.8220], [0.8135, 1.0000, 0.8088, 0.8132, 0.7971], [0.8232, 0.8088, 1.0000, 0.8047, 0.8398], [0.8399, 0.8132, 0.8047, 1.0000, 0.8310], [0.8220, 0.7971, 0.8398, 0.8310, 1.0000]])
Data una domanda, calcoliamone la similarità con le frasi dell'archivio.
query = "Sei informato di una scoperta a proposito di una nuova forma di vita su Venere?"
query_embedding = model.encode(query)
similarities = model.similarity(embeddings, query_embedding)
similarities
tensor([[0.8912], [0.7918], [0.8110], [0.8224], [0.7989]])
Recuperiamo la frase dell'archivio più simile alla domanda.
best_index = torch.argmax(similarities).item()
retrieved_sentence = sentences[best_index]
retrieved_sentence
'Nel 2015, gli scienziati hanno scoperto una nuova forma di vita basata su silicio nelle profondità del pianeta Venere.'
Prima di tutto, poniamo la domanda senza consentire al modello di accedere al nostro archivio.
from transformers import pipeline
from pprint import pprint
model = "microsoft/Phi-3.5-mini-instruct"
generator = pipeline("text-generation", model=model, device=device)
res = generator(
[
{ "role": "system", "content": "Sei un esperto che risponde in italiano." },
{
"role": "user",
"content": f"{query}"
}
],
max_new_tokens=200
)
pprint(res[0]["generated_text"][2]['content'])
Loading checkpoint shards: 0%| | 0/2 [00:00<?, ?it/s]
(' Al momento non ho informazioni su una scoperta relativa a una nuova forma ' 'di vita su Venere. Fino al mio ultimo aggiornamento, non ci sono prove ' 'scientificamente accettate di vita extraterrestre su Venere.\n' '\n' 'Tuttavia, la ricerca scientifica continua e nuove scoperte potrebbero ' 'emergere. La ricerca di vita su Venere si concentra principalmente sui suoi ' 'ambienti estremi, come le alte temperature, la pressione atmosferica e la ' 'presenza di acqua allo stato liquido sotto forma di acque sotterranee.\n' '\n' 'Se hai trovato qualche notizia o documentazione recente, ti invito a ' 'condividere i dettagli affinché possa aiutarti a interpretare o spiegare ' 'meglio le informazioni.')
Ora ripetiamo la domanda anteponendo la frase che era stata recuperata.
res = generator(
[
{ "role": "system", "content": "Sei un esperto che risponde in italiano." },
{
"role": "user",
"content": f"""
Tenendo conto di questa informazione: {retrieved_sentence},
{query}
"""
}
],
max_new_tokens=200
)
pprint(res[0]["generated_text"][2]['content'])
(' Sì, sono informato di una scoperta relativa a una nuova forma di vita su ' 'Venere. Secondo la tua dichiarazione, nel 2015 gli scienziati hanno ' 'identificato una forma di vita basata su silicio nelle profondità del ' 'pianeta Venere. Questa scoperta è significativa poiché sfida le nostre ' 'attuali comprensioni della vita, poiché il silicio è un elemento comune ' 'sulla Terra ma non è stato considerato un substrato per la vita in ambienti ' 'simili a Venere. Questa scoperta potrebbe portare a ulteriori ricerche e ' 'discussioni sulla possibilità di vita in condizioni estreme e su altri ' 'pianeti.')