Sviluppo di RAG guidato dalle metriche
In una recente presentazione al Zilliz Unstructured Data Meetup, Jithin James e Shahul Es, maintainer di Ragas, hanno condiviso approfondimenti su come sfruttare lo sviluppo guidato dalle metriche per valutare i sistemi Retrieval Augmented Generation (RAG). Gli sviluppatori possono perfezionare i loro sistemi in base ai risultati della valutazione per ottenere prestazioni migliori.
Nel loro intervento, Jithin e Shahul hanno discusso sia le basi teoriche sia le applicazioni pratiche della valutazione dei sistemi RAG. Hanno spiegato come comprendere la teoria alla base del codice di valutazione possa fornire approfondimenti più profondi sulla sua funzionalità. Dopo questa parte, hanno dimostrato il processo di valutazione utilizzando un vero sistema RAG alimentato da Milvus, un importante database vettoriale open-source noto per la sua efficienza nella ricerca di similarità e nelle applicazioni di IA.
Per una comprensione più dettagliata, guarda la registrazione dell'intervento al meetup.
Come valutare le prestazioni dei sistemi RAG
Shahul ha accennato a come Ragas calcola la veridicità di una risposta generata dal sistema RAG. Questa è una metrica di valutazione cruciale, poiché la risposta è ciò che vede l'utente finale. Rallentiamo un po' e analizziamo in profondità. Ragas utilizza la seguente formula per calcolare la veridicità di una risposta:
Fig 1- Formula di calcolo della metrica answer_truthfulness di Ragas
Calcolo della correttezza della risposta nei sistemi Retrieval-Augmented Generation (RAG)
Il processo coinvolge due metriche principali: similarità fattuale e similarità semantica. Queste metriche aiutano a determinare la qualità e la rilevanza della risposta generata rispetto alla verità di riferimento.
Metriche chiave
Similarità fattuale:
- Questa metrica misura la correttezza fattuale della risposta generata confrontando la presenza di informazioni fattuali tra la verità di riferimento e la risposta generata.
Similarità semantica:
- Questa metrica misura quanto la risposta generata sia semanticamente simile alla verità di riferimento, garantendo che il significato trasmesso dalla risposta generata sia allineato con la verità di riferimento.
Passaggi per calcolare la correttezza della risposta
Identificare veri positivi (TP), falsi positivi (FP) e falsi negativi (FN):
Veri positivi: Affermazioni correttamente presenti sia nella verità di riferimento sia nella risposta generata.
Falsi positivi: Affermazioni presenti nella risposta generata ma non nella verità di riferimento.
Falsi negativi: Affermazioni presenti nella verità di riferimento ma non nella risposta generata.
Calcolare il punteggio F1:
- Il punteggio F1 è una media di precisione e richiamo, fornendo un equilibrio tra i due. La formula per il punteggio F1 è mostrata nella Figura 1.
Esempio pratico
Considera un'affermazione di verità di riferimento e una risposta generata:
Verità di riferimento: "Alan Turing sviluppò il concetto di macchina di Turing."
Risposta generata: "Alan Turing è noto per aver sviluppato il concetto di macchina di Turing e di intelligenza artificiale."
Passaggio 1: Identificare TP, FP e FN
Veri positivi (TP):
- "Alan Turing sviluppò il concetto di macchina di Turing."
Falsi positivi (FP):
- "Alan Turing è noto per aver sviluppato l'intelligenza artificiale."
Falsi negativi (FN):
- Nessuno (poiché la risposta generata include tutti gli elementi della verità di riferimento).
Passaggio 2: Calcolare il punteggio F1
TP = 1
FP = 1
FN = 0
F1 = 1 / (1 + 0.5 * (1 + 0))
= 1 / 1.5
≈ 0.67
Interpretazione<
Similarità fattuale: La risposta generata è fattualmente corretta poiché include le informazioni essenziali dalla verità di riferimento.
Similarità semantica: La risposta generata mantiene l'allineamento semantico con la verità di riferimento, sebbene includa informazioni aggiuntive.
Il punteggio F1 combina questi aspetti per fornire una misura della correttezza della risposta, bilanciando precisione e recall. Questo metodo aiuta a valutare quanto bene la risposta generata corrisponda alla ground truth in termini sia di contenuto fattuale sia di significato complessivo.
Ma la veridicità della risposta non è l’unica metrica che puoi usare per valutare i tuoi sistemi RAG. Altre metriche sono faithfulness, answer relevancy, context recall e context precision. Diamo uno sguardo pratico a come puoi valutare e migliorare un sistema RAG basato su Mivus.
Valutare e migliorare un sistema RAG basato su Milvus
Ora che hai compreso la base teorica per valutare i sistemi RAG, entriamo in un esempio pratico di RAG costruito con il database vettoriale Milvus. Esamineremo la configurazione, l’implementazione e la valutazione di un sistema RAG. Sulla base dei risultati, vedremo poi come possiamo migliorare il sistema.
Configurazione dell’ambiente
Per prima cosa, dobbiamo configurare il nostro ambiente di sviluppo. Per farlo, innanzitutto, installa tutte le librerie richieste:
!pip install pymilvus[model] ragas langchain langchain_openai python-dotenv nest_asyncio pypdf langchain_community
Analizziamo quale sarà l’uso di ciascuna libreria nel codice:
Pymilvus[model]ti aiuterà a connetterti a Milvus, creare collection, inserire dati ed eseguire ricerche di similarità.Ragasfornirà metriche di valutazione, genererà set di test sintetici e valuterà pipeline RAG.Langchaincaricherà documenti, li suddividerà in chunk e preparerà i dati testuali per embedding e query.Langchain_openaisi interfaccerà con i modelli OpenAI, genererà embedding e risponderà alle domande usando chiamate API.Python-dotenvcaricherà variabili d’ambiente da un file .env per gestire informazioni sensibili come le chiavi API.Nest_asyncioabiliterà operazioni asincrone annidate all’interno di ambienti sincroni. Soprattutto se stai usando notebook Jupiter.Pypdfcaricherà documenti PDF, estrarrà contenuti e preparerà il testo per l’elaborazione.Langchain_communityfornirà loader di documenti aggiuntivi e utility per integrare risorse fornite dalla community. Dopo aver installato le librerie, importale nel tuo codice e configura le tue chiavi API:
import os
import pandas as pd
import nest_asyncio
import openai
from pymilvus import MilvusClient, model
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_recall,
context_precision,
answer_correctness,
)
from ragas.testset.generator import TestsetGenerator
from ragas.testset.evolutions import simple, reasoning, multi_context
from langchain_community.document_loaders import DirectoryLoader
from langchain.document_loaders import PyPDFLoader
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from dotenv import load_dotenv
from datasets import Dataset
# Load environment variables
# Apply nest_asyncio to allow nested event loops
nest_asyncio.apply()
# Set up OpenAI API key
os.environ["OPENAI_API_KEY"] = "Your API Key"
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
Importare le librerie e i moduli nel codice ti permetterà di chiamare e usare le loro funzioni. La chiave OpenAI ti aiuterà ad autenticarti presso OpenAI durante le chiamate API. Se non ne hai una, vai alla pagina API di OpenAI e generane una.
Caricamento e preparazione dei documenti
Successivamente, caricheremo i nostri documenti e li prepareremo per l’elaborazione:
# Load PDF documents from a directory
pdf_loader = DirectoryLoader("/content/data", loader_cls=PyPDFLoader)
documents = pdf_loader.load()
# Ensure each document has a filename in its metadata
for document in documents:
document.metadata['filename'] = document.metadata['source'
Il codice carica documenti PDF da una directory utilizzando la classe PyPDFLoader. Quindi crea un'istanza di DirectoryLoader, carica i documenti e itera attraverso ciascun documento per aggiungere un attributo filename ai suoi metadati. Questo garantisce che ogni documento sia correttamente identificato e gestito con il filename corrispondente. Questo passaggio è cruciale poiché costituisce la base di conoscenza per il nostro sistema RAG. In questo esempio utilizziamo documenti PDF, ma potresti adattarlo ad altri tipi di documenti secondo necessità.
Generazione di un Test Set
Ora che hai caricato i dati, hai bisogno di un insieme diversificato di domande di test per aiutare a valutare efficacemente il nostro sistema RAG. Useremo il framework Ragas per generare un test set sintetico.
# Initialize OpenAI models for test set generation
generator_llm = ChatOpenAI(model="gpt-3.5-turbo-16k")
critic_llm = ChatOpenAI(model="gpt-4")
embeddings = OpenAIEmbeddings()
# Create a TestsetGenerator
generator = TestsetGenerator.from_langchain(
generator_llm,
critic_llm,
embeddings
)
# Generate synthetic test set with 10 samples
testset = generator.generate_with_langchain_docs(documents, test_size=10, distributions={simple: 0.5, reasoning: 0.25, multi_context: 0.25})
# Convert test set to Pandas DataFrame
testset_df = testset.to_pandas()
print(testset_df)
Questo codice inizializza due modelli linguistici (gpt-3.5-turbo-16k per generare test set e gpt-4 per la valutazione) e un modello di embedding di OpenAI. Quindi crea un'istanza di TestsetGenerator utilizzando questi modelli. Il generatore produce un test set sintetico di 10 campioni dai documenti PDF caricati, con distribuzioni specificate per diversi tipi di domande. Questo test set ti aiuterà a valutare vari aspetti delle prestazioni del tuo sistema RAG, inclusa la sua capacità di gestire query semplici, attività di ragionamento e domande che richiedono più contesti. Ecco un esempio di un test set generato.
Fig 2- Test set generato usando Ragas
La ground truth è la risposta effettiva a una determinata domanda. La useremo in seguito per misurare quanto bene stia funzionando il nostro sistema RAG in base a quanto il suo output è vicino a queste risposte corrette. Come sottolinea Shahul nel talk, generare il test set sintetico usando Ragas non significa usarlo alla cieca. Devi filtrare e usare i campioni di cui hai bisogno.
Dato che hai il test set, costruiamo un semplice sistema RAG basato su Milvus e poi valutiamolo usando il test set sopra.
Configurazione di Milvus e inserimento degli embedding dei documenti
Ora, configuriamo il nostro database vettoriale Milvus e inseriamo gli embedding dei nostri documenti. Assicurati di avere Milvus installato e in esecuzione. In caso contrario, segui questa guida completa all'installazione di Milvus.
# Connect to Milvus instance
milvus_client = MilvusClient(uri="http://localhost:19530")
# Define collection name
collection_name = "pdf_collection"
# Drop the collection if it already exists
if milvus_client.has_collection(collection_name):
milvus_client.drop_collection(collection_name)
# Create a new collection
milvus_client.create_collection(
collection_name=collection_name,
dimension=768, # Dimension of vectors
overwrite=True
)
# Initialize the embedding function
embedding_fn = model.DefaultEmbeddingFunction()
# Extract document texts and generate embeddings
expanded_docs = [doc.page_content for doc in documents]
expanded_vectors = embedding_fn.encode_documents(expanded_docs)
# Prepare data for insertion
expanded_data = [
{"id": i, "vector": expanded_vectors[i], "text": expanded_docs[i], "subject": "pdf_documents"}
for i in range(len(expanded_vectors))
]
# Insert expanded data into the collection
milvus_client.insert(data=expanded_data, collection_name=collection_name)
Il codice sopra si connette a un'istanza Milvus e configura una collection chiamata pdf_collection per archiviare i vettori dei documenti. Se la collection esiste già, la elimina e la ricrea con una dimensione di 768 per i vettori. Inizializza una funzione di embedding, estrae il testo dai documenti caricati e genera i loro embedding. Il codice quindi prepara i dati con embedding e testo associato e inserisce questi dati nella collection Milvus. Questo passaggio è dove Milvus dà davvero il meglio, poiché consente di eseguire ricerche di similarità rapide ed efficienti sugli embedding dei dati archiviati, il che è fondamentale per la parte di retrieval del tuo sistema RAG.
Esecuzione della ricerca di similarità
Con i tuoi documenti indicizzati in Milvus, ora puoi eseguire ricerche di similarità per recuperare contesti rilevanti per le nostre domande:
# Define the search parameters
search_params = {"metric_type": "COSINE", "params": {"nprobe": 20}} # nprobe for better recall
# Perform the search
query_vectors = embedding_fn.encode_queries(testset_df['question'].tolist())
results = milvus_client.search(
collection_name=collection_name,
data=query_vectors,
anns_field="vector", # specify the vector field name
search_params=search_params,
limit=3, # number of top results to retrieve
output_fields=["id", "text"]
)
Il codice sopra configura i parametri di ricerca per la collection Milvus utilizzando la similarità del coseno e un valore nprobe di 20 per un richiamo migliore. Codifica le domande del set di test in vettori di query ed esegue una ricerca nella collection pdf_collection, recuperando i tre vettori più simili per ciascuna query. I risultati della ricerca includono gli IDs e il text dei documenti corrispondenti.
Generazione di risposte utilizzando un Large Language Model
Con i contesti rilevanti recuperati, ora puoi generare risposte utilizzando un modello linguistico. In questo caso, useremo GPT 3.5 turbo.
# Function to generate answers using OpenAI
def generate_answer(question, contexts):
context_text = " ".join(contexts)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": f"Context: {context_text}nnQuestion: {question}nAnswer:"}
]
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages,
max_tokens=100,
temperature=0.7,
)
return response.choices[0].message.content.strip()
# Extract contexts and generate answers using OpenAI
contexts = []
answers = []
for i, result in enumerate(results):
context = [match['entity']['text'] for match in result]
contexts.append(context)
question = testset_df['question'].iloc[i]
answer = generate_answer(question, context)
answers.append(answer)
Il codice definisce una funzione generate_answer che utilizza il modello gpt-3.5-turbo di OpenAI per generare risposte in base a una determinata domanda e a un contesto. Prepara i messaggi per la chiamata API, concatena il contesto e interroga il modello. Quindi estrae e restituisce la risposta generata. Il ciclo successivo itera attraverso i risultati della ricerca e utilizza la funzione generate_answer per generare risposte per ciascuna domanda nel set di test, archiviando i contesti e le risposte in liste. Le domande utilizzate nel ciclo per generare le risposte sono le stesse generate nel set di test.
Poiché ora hai le risposte generate dal sistema RAG e le risposte ground truth, valutiamo quanto bene sta funzionando il sistema RAG.
Valutazione del sistema RAG
Infine, valuteremo le prestazioni del nostro sistema RAG utilizzando le metriche discusse in precedenza:
# Ensure all lists are the same length
min_length = min(len(testset_df['question']), len(testset_df['ground_truth']), len(answers), len(contexts))
questions = testset_df['question'][:min_length]
ground_truths = testset_df['ground_truth'][:min_length]
answers = answers[:min_length]
contexts = contexts[:min_length]
# Create the dataset with correct column names
data = {
"question": questions,
"answer": answers,
"contexts": contexts,
"ground_truth": ground_truths
}
from datasets import Dataset
# Convert dict to dataset
dataset = Dataset.from_pandas(pd.DataFrame(data))
# Evaluate using RAGAS
metrics = evaluate(
dataset=dataset,
metrics=[
answer_correctness,
context_precision,
context_recall,
faithfulness,
answer_relevancy,
],
raise_exceptions=False #handle async issues
)
# Convert result to DataFrame for better readability
result_df = metrics.to_pandas()
print(result_df)
Il codice garantisce coerenza nel processo di valutazione riducendo tutte le liste pertinenti alla stessa lunghezza minima. Questo previene lunghezze non corrispondenti che potrebbero causare errori durante la valutazione. Crea quindi un dizionario con queste liste ridotte e lo converte in un DataFrame Pandas, che viene poi trasformato in un Dataset di Hugging Face. Questo dataset strutturato consente una valutazione sistematica utilizzando il framework RAGAS, che confronta le risposte generate con le ground truth. Le metriche di valutazione (correttezza della risposta, precisione del contesto, richiamo del contesto, fedeltà e pertinenza della risposta) forniscono una valutazione delle prestazioni della pipeline RAG.
Dai un’occhiata ai risultati della valutazione qui sotto:
Fig 3- risultati della valutazione del sistema RAG con Ragas
La precisione del contesto del nostro sistema RAG e il richiamo sono eccellenti e la pertinenza della risposta è lodevole. Ma la correttezza della risposta è piuttosto bassa.
Il lato del recupero è buono grazie all’eccellente richiamo e precisione del contesto. Quindi possiamo concludere che la parte di generazione potrebbe influire sulla correttezza delle nostre risposte. Per migliorarla, puoi usare un modello di generazione delle risposte più potente come GPT-4.
Conclusione
Valutare e migliorare i sistemi Retrieval-Augmented Generation (RAG) è un compito sfumato ma essenziale nell’ambito del recupero delle informazioni guidato dall’IA. Sfruttando un approccio basato sulle metriche, come dimostrato da Jithin James e Shahul Es, puoi perfezionare sistematicamente i tuoi sistemi RAG per assicurarti che forniscano informazioni accurate, pertinenti e affidabili.
Per maggiori dettagli su questo argomento, guarda la registrazione dell’intervento su YouTube.
Ulteriori risorse
Continua a leggere

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.

Balancing Precision and Performance: How Zilliz Cloud's New Parameters Help You Optimize Vector Search
Optimize vector search with Zilliz Cloud’s level and recall features to tune accuracy, balance performance, and power AI applications.

DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding
Explore DeepSeek-VL2, the open-source MoE vision-language model. Discover its architecture, efficient training pipeline, and top-tier performance.


