Metrikgetriebene Entwicklung von RAGs
In einer kürzlich gehaltenen Präsentation beim Zilliz Unstructured Data Meetup teilten Jithin James und Shahul Es, Maintainer von Ragas, Einblicke in die Nutzung von metrikgetriebener Entwicklung zur Bewertung von Retrieval Augmented Generation (RAG)-Systemen. Entwickler können ihre Systeme auf Grundlage der Bewertungsergebnisse für eine bessere Leistung anpassen.
In ihrem Vortrag diskutierten Jithin und Shahul sowohl die theoretischen Grundlagen als auch praktische Anwendungen der Bewertung von RAG-Systemen. Sie erklärten, wie das Verständnis der Theorie hinter dem Bewertungscode tiefere Einblicke in dessen Funktionsweise bieten kann. Im Anschluss an diesen Teil demonstrierten sie den Bewertungsprozess anhand eines tatsächlichen RAG-Systems, das von Milvus unterstützt wird, einer führenden Open-Source-Vektordatenbank, die für ihre Effizienz bei der Ähnlichkeitssuche und in KI-Anwendungen bekannt ist.
Für ein detaillierteres Verständnis, sehen Sie sich die Aufzeichnung des Meetup-Vortrags an.
Wie man die Leistung von RAG-Systemen bewertet
Shahul ging darauf ein, wie Ragas die Wahrhaftigkeit einer vom RAG-System generierten Antwort berechnet. Dies ist eine entscheidende Bewertungsmetrik, da die Antwort das ist, was der Endbenutzer sieht. Lassen Sie uns das etwas verlangsamen und tiefer eintauchen. Ragas verwendet die folgende Formel, um die Wahrhaftigkeit einer Antwort zu berechnen:
Abb. 1- Formel zur Berechnung der Ragas-Metrik answer_truthfulness
Berechnung der Antwortkorrektheit in Retrieval-Augmented Generation (RAG)-Systemen
Der Prozess umfasst zwei Hauptmetriken: faktische Ähnlichkeit und semantische Ähnlichkeit. Diese Metriken helfen dabei, die Qualität und Relevanz der generierten Antwort im Vergleich zur Ground Truth zu bestimmen.
Wichtige Metriken
Faktische Ähnlichkeit:
- Diese Metrik misst die faktische Korrektheit der generierten Antwort, indem sie das Vorhandensein faktischer Informationen zwischen der Ground Truth und der generierten Antwort vergleicht.
Semantische Ähnlichkeit:
- Diese Metrik misst, wie semantisch ähnlich die generierte Antwort der Ground Truth ist, und stellt sicher, dass die durch die generierte Antwort vermittelte Bedeutung mit der Ground Truth übereinstimmt.
Schritte zur Berechnung der Antwortkorrektheit
Identifizieren Sie True Positives (TP), False Positives (FP) und False Negatives (FN):
True Positives: Aussagen, die sowohl in der Ground Truth als auch in der generierten Antwort korrekt vorhanden sind.
False Positives: Aussagen, die in der generierten Antwort vorhanden sind, aber nicht in der Ground Truth.
False Negatives: Aussagen, die in der Ground Truth vorhanden sind, aber nicht in der generierten Antwort.
Berechnen Sie den F1-Score:
- Der F1-Score ist ein Mittelwert aus Precision und Recall und bietet ein Gleichgewicht zwischen beiden. Die Formel für den F1-Score ist in Abbildung 1 dargestellt.
Praktisches Beispiel
Betrachten Sie eine Ground-Truth-Aussage und eine generierte Antwort:
Ground Truth: "Alan Turing entwickelte das Konzept der Turingmaschine."
Generierte Antwort: "Alan Turing ist bekannt für die Entwicklung des Konzepts der Turingmaschine und der künstlichen Intelligenz."
Schritt 1: TP, FP und FN identifizieren
True Positives (TP):
- "Alan Turing entwickelte das Konzept der Turingmaschine."
False Positives (FP):
- "Alan Turing ist bekannt für die Entwicklung künstlicher Intelligenz."
False Negatives (FN):
- Keine (da die generierte Antwort alle Elemente der Ground Truth enthält).
Schritt 2: Den F1-Score berechnen
TP = 1
FP = 1
FN = 0
F1 = 1 / (1 + 0.5 * (1 + 0))
= 1 / 1.5
≈ 0.67
Interpretation<
Faktische Ähnlichkeit: Die generierte Antwort ist faktisch korrekt, da sie die wesentlichen Informationen aus der Ground Truth enthält.
Semantische Ähnlichkeit: Die generierte Antwort bleibt semantisch mit der Ground Truth abgestimmt, obwohl sie zusätzliche Informationen enthält.
Der F1-Score kombiniert diese Aspekte, um ein Maß für die Korrektheit der Antwort bereitzustellen, indem Präzision und Recall ausbalanciert werden. Diese Methode hilft dabei zu bewerten, wie gut die generierte Antwort in Bezug auf sowohl faktischen Inhalt als auch Gesamtbedeutung mit der Ground Truth übereinstimmt.
Aber die Wahrhaftigkeit der Antwort ist nicht die einzige Metrik, die Sie zur Bewertung Ihrer RAG-Systeme verwenden können. Weitere Metriken sind Faithfulness, Answer Relevancy, Context Recall und Context Precision. Werfen wir einen praktischen Blick darauf, wie Sie ein Mivus-gestütztes RAG-System bewerten und verbessern können.
Bewertung und Verbesserung eines Milvus-gestützten RAG-Systems
Nachdem Sie nun die theoretische Grundlage für die Bewertung von RAG-Systemen verstanden haben, steigen wir in ein praktisches RAG-Beispiel ein, das mit der Milvus-Vektordatenbank erstellt wurde. Wir werden das Einrichten, Implementieren und Bewerten eines RAG-Systems durchgehen. Basierend auf den Ergebnissen werden wir anschließend betrachten, wie wir das System verbessern können.
Einrichten der Umgebung
Zuerst müssen wir unsere Entwicklungsumgebung einrichten. Installieren Sie dazu zunächst alle erforderlichen Bibliotheken:
!pip install pymilvus[model] ragas langchain langchain_openai python-dotenv nest_asyncio pypdf langchain_community
Schauen wir uns an, wofür jede Bibliothek im Code verwendet wird:
Pymilvus[model]hilft Ihnen dabei, eine Verbindung zu Milvus herzustellen, Collections zu erstellen, Daten einzufügen und Ähnlichkeitssuchen durchzuführen.Ragasstellt Bewertungsmetriken bereit, generiert synthetische Testsets und bewertet RAG-Pipelines.Langchainlädt Dokumente, teilt sie in Chunks auf und bereitet Textdaten für Embedding und Abfragen vor.Langchain_openaistellt eine Schnittstelle zu OpenAI-Modellen bereit, generiert Embeddings und beantwortet Fragen mithilfe von API-Aufrufen.Python-dotenvlädt Umgebungsvariablen aus einer .env-Datei, um sensible Informationen wie API-Schlüssel zu verwalten.Nest_asyncioermöglicht verschachtelte asynchrone Operationen innerhalb synchroner Umgebungen. Besonders, wenn Sie Jupiter notebooks verwenden.Pypdflädt PDF-Dokumente, extrahiert Inhalte und bereitet Text für die Verarbeitung vor.Langchain_communitystellt zusätzliche Dokument-Loader und Hilfsprogramme zur Integration von von der Community beigetragenen Ressourcen bereit. Nachdem Sie die Bibliotheken installiert haben, importieren Sie sie in Ihren Code und konfigurieren Sie Ihre API-Schlüssel:
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"))
Das Importieren der Bibliotheken und Module in den Code ermöglicht es Ihnen, deren Funktionen aufzurufen und zu verwenden. Der OpenAI-Schlüssel hilft Ihnen, sich bei OpenAI zu authentifizieren, während Sie API-Aufrufe durchführen. Wenn Sie keinen haben, gehen Sie zur OpenAI API-Seite und generieren Sie einen.
Laden und Vorbereiten von Dokumenten
Als Nächstes laden wir unsere Dokumente und bereiten sie für die Verarbeitung vor:
# 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'
Der Code lädt PDF-Dokumente aus einem Verzeichnis mithilfe der Klasse PyPDFLoader. Anschließend erstellt er eine DirectoryLoader-Instanz, lädt die Dokumente und iteriert durch jedes Dokument, um seinen Metadaten ein filename-Attribut hinzuzufügen. Dadurch wird sichergestellt, dass jedes Dokument ordnungsgemäß identifiziert und mit seinem entsprechenden Dateinamen verwaltet wird. Dieser Schritt ist entscheidend, da er die Wissensbasis für unser RAG-System bildet. In diesem Beispiel verwenden wir PDF-Dokumente, aber du könntest dies bei Bedarf an andere Dokumenttypen anpassen.
Generieren eines Testsets
Nachdem du die Daten geladen hast, benötigst du eine vielfältige Reihe von Testfragen, um unser RAG-System effektiv bewerten zu können. Wir verwenden das Ragas-Framework, um ein synthetisches Testset zu generieren.
# 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)
Dieser Code initialisiert zwei Sprachmodelle (gpt-3.5-turbo-16k zum Generieren von Testsets und gpt-4 zur Bewertung) sowie ein Embedding-Modell von OpenAI. Anschließend erstellt er mithilfe dieser Modelle eine TestsetGenerator-Instanz. Der Generator erzeugt aus den geladenen PDF-Dokumenten ein synthetisches Testset mit 10 Beispielen und festgelegten Verteilungen für verschiedene Fragetypen. Dieses Testset hilft dir, verschiedene Aspekte der Leistung deines RAG-Systems zu bewerten, einschließlich seiner Fähigkeit, einfache Abfragen, Reasoning-Aufgaben und Fragen zu bearbeiten, die mehrere Kontexte erfordern. Hier ist ein Beispiel für ein generiertes Testset.
Abb. 2 – Mit Ragas generiertes Testset
Die Ground Truth ist die tatsächliche Antwort auf eine bestimmte Frage. Wir werden sie später verwenden, um zu messen, wie gut unser RAG-System abschneidet, indem wir prüfen, wie nah seine Ausgabe an diesen Ground-Truth-Antworten liegt. Wie Shahul im Vortrag betont, bedeutet das Generieren des synthetischen Testsets mit Ragas nicht, dass du es blind verwendest. Du musst die benötigten Beispiele herausfiltern und verwenden.
Da du nun das Testset hast, bauen wir ein einfaches RAG-System, das von Milvus unterstützt wird, und bewerten es anschließend mit dem obigen Testset.
Einrichten von Milvus und Einfügen von Dokument-Embeddings
Richten wir nun unsere Milvus-Vektordatenbank ein und fügen unsere Dokument-Embeddings ein. Stelle sicher, dass Milvus installiert ist und läuft. Falls nicht, folge diesem umfassenden Milvus-Installationsleitfaden.
# 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)
Der obige Code stellt eine Verbindung zu einer Milvus-Instanz her und richtet eine Collection namens pdf_collection zum Speichern von Dokumentvektoren ein. Wenn die Collection bereits existiert, wird sie gelöscht und mit einer Dimension von 768 für die Vektoren neu erstellt. Er initialisiert eine Einbettungsfunktion, extrahiert Text aus geladenen Dokumenten und generiert deren Einbettungen. Anschließend bereitet der Code die Daten mit Einbettungen und zugehörigem Text vor und fügt diese Daten in die Milvus-Collection ein. Dieser Schritt ist der Punkt, an dem Milvus wirklich glänzt, da es Ihnen ermöglicht, schnelle und effiziente Ähnlichkeitssuchen auf den gespeicherten Dateneinbettungen durchzuführen, was für den Retrieval-Teil Ihres RAG-Systems entscheidend ist.
Durchführen einer Ähnlichkeitssuche
Nachdem Ihre Dokumente in Milvus indexiert sind, können Sie nun Ähnlichkeitssuchen durchführen, um relevante Kontexte für unsere Fragen abzurufen:
# 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"]
)
Der obige Code richtet Suchparameter für die Milvus-Collection ein, indem er Kosinus-Ähnlichkeit und einen nprobe-Wert von 20 für einen besseren Recall verwendet. Er kodiert die Fragen des Testsatzes in Abfragevektoren und führt eine Suche in der Collection pdf_collection durch, wobei die drei ähnlichsten Vektoren für jede Abfrage abgerufen werden. Die Suchergebnisse enthalten die IDs und den text der übereinstimmenden Dokumente.
Generieren von Antworten mit einem großen Sprachmodell
Nachdem die relevanten Kontexte abgerufen wurden, können Sie nun Antworten mit einem Sprachmodell generieren. In diesem Fall verwenden wir 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)
Der Code definiert eine Funktion generate_answer, die das Modell gpt-3.5-turbo von OpenAI verwendet, um Antworten auf Grundlage einer gegebenen Frage und eines Kontexts zu generieren. Er bereitet Nachrichten für den API-Aufruf vor, verkettet den Kontext und fragt das Modell ab. Anschließend extrahiert er die generierte Antwort und gibt sie zurück. Die anschließende Schleife iteriert durch die Suchergebnisse und verwendet die Funktion generate_answer, um Antworten für jede Frage im Testsatz zu generieren, wobei die Kontexte und Antworten in Listen gespeichert werden. Die in der Schleife verwendeten Fragen zur Generierung von Antworten sind dieselben, die im Testsatz generiert wurden.
Da Sie nun die vom RAG-System generierten Antworten und die Ground-Truth-Antworten haben, lassen Sie uns bewerten, wie gut das RAG-System abschneidet.
Evaluierung des RAG-Systems
Abschließend bewerten wir die Leistung unseres RAG-Systems mit den zuvor besprochenen Metriken:
# 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)
Der Code stellt Konsistenz im Evaluierungsprozess sicher, indem alle relevanten Listen auf dieselbe Mindestlänge gekürzt werden. Dies verhindert nicht übereinstimmende Längen, die während der Evaluierung Fehler verursachen könnten. Anschließend erstellt er ein Dictionary mit diesen gekürzten Listen und wandelt es in einen Pandas DataFrame um, der danach in ein Hugging Face Dataset transformiert wird. Dieser strukturierte Datensatz ermöglicht eine systematische Evaluierung mithilfe des RAGAS-Frameworks, das die generierten Antworten mit den Ground Truths vergleicht. Die Evaluierungsmetriken (Antwortkorrektheit, Kontextpräzision, Kontext-Recall, Faktentreue und Antwortrelevanz) liefern eine Bewertung der Leistung der RAG-Pipeline.
Werfen Sie einen Blick auf die folgenden Evaluierungsergebnisse:
Abb. 3 – Evaluierungsergebnisse des Ragas-RAG-Systems
Die Kontextpräzision unseres RAG-Systems und der Recall sind ausgezeichnet, und die Antwortrelevanz ist lobenswert. Aber die Antwortkorrektheit ist ziemlich niedrig.
Die Retrieval-Seite ist aufgrund des ausgezeichneten Kontext-Recalls und der Präzision gut. Daher können wir schlussfolgern, dass der Generierungsteil unsere Antwortkorrektheit beeinflussen könnte. Um dies zu verbessern, können Sie ein leistungsfähigeres Modell zur Antwortgenerierung wie GPT-4 verwenden.
Fazit
Die Evaluierung und Verbesserung von Retrieval-Augmented Generation (RAG)-Systemen ist eine nuancierte, aber wesentliche Aufgabe im Bereich der KI-gestützten Informationsbeschaffung. Durch die Nutzung eines metrikgetriebenen Ansatzes, wie von Jithin James und Shahul Es demonstriert, können Sie Ihre RAG-Systeme systematisch verfeinern, um sicherzustellen, dass sie genaue, relevante und vertrauenswürdige Informationen liefern.
Weitere Details zu diesem Thema finden Sie in der Aufzeichnung des Vortrags auf YouTube.
Weitere Ressourcen
Weiterlesen

Expanding Our Global Reach: Zilliz Cloud Launches in Azure Central India
Zilliz Cloud expands to Azure Central India. This new region helps customers meet compliance, reduce latency, and optimize cloud costs when building AI applications.

Zilliz Cloud Introduces Advanced BYOC-I Solution for Ultimate Enterprise Data Sovereignty
Explore Zilliz Cloud BYOC-I, the solution that balances AI innovation with data control, enabling secure deployments in finance, healthcare, and education sectors.

1 Table = 1000 Words? Foundation Models for Tabular Data
TableGPT2 automates tabular data insights, overcoming schema variability, while Milvus accelerates vector search for efficient, scalable decision-making.


