Docs Menu
Docs Home
/ /

RG アプリケーションを評価する

このチュートリアルでは、 RAGアプリケーション を評価する方法を学びます。評価は、正しいモデルを選択し、モデルのパフォーマンスがプロトタイプから本番環境に変換されることを確認し、パフォーマンスの低下を防ぐのに役立ちます。

具体的には、次のアクションを実行します。

  • 環境を設定します。

  • 評価データセット をダウンロードします。

  • ドキュメントチャンクと埋め込みを作成します。

  • 埋め込みを Atlas に取り込みます。

  • 取得のために埋め込みモデルを比較します。

  • 生成の完了モデルを比較します。

  • 全体的な RAG パフォーマンスを測定します。

  • MongoDB Charts でパフォーマンスの一定期間を追跡する。

注意

このチュートリアルでは、LM モデルではなく、LM アプリケーションの評価に焦点を当てています。 LVM モデルを評価するには、さまざまなタスクにわたって特定のモデルのパフォーマンスを測定する必要があります。 LMアプリケーション評価では、プロンプトや検索バーなどの LMアプリケーションのさまざまなコンポーネントと、システム全体を評価する方法について説明します。

このチュートリアルの実行可能なバージョンを Python エディタとして操作します。

このチュートリアルでは、RAM オープンソース評価フレームワークを使用して、次のメトリクスで RAG のパフォーマンスを測定します。

  • 検索メトリクス: コンテキスト精度とコンテキスト呼び出しは、検索バーが関連情報をどの程度見つけているかを測定します。

  • 生成メトリクス: 成功率と応答の関連性は、LM が正確で関連性の高い応答をどの程度生成するかを測定します。

  • 全体的なメトリクス: 応答の類似性と応答の正確性は、生成された応答を真実と比較します。

これらのメトリクスの詳細については、RAM ドキュメントの「 R内の メトリクス 」を参照してください。

このチュートリアルでは、Hubingface の las-wikia230 データセットを使用します。このデータセットには、フィールド 真実の応答を持つ約 の一般知識の質問が含まれています。

Atlas の サンプル データ セット からの映画データを含むコレクションを使用します。

1

必要なライブラリをインストールするには、次のコマンドを実行します。

pip install -qU datasets ragas langchain langchain-mongodb langchain-openai \
pymongo pandas tqdm matplotlib seaborn nest_asyncio
2

ノートように次のコードを実行して、 MongoDB接続文字列と OpenAI APIキーを設定します。

import getpass
import os
from openai import OpenAI
MONGODB_URI = getpass.getpass("Enter your MongoDB connection string:")
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key:")
openai_client = OpenAI()

Hドキュメントから las-wikia データセットをダウンロードし、pandas データフレームに変換します。

from datasets import load_dataset
import pandas as pd
data = load_dataset("explodinggradients/ragas-wikiqa", split="train")
df = pd.DataFrame(data)

データセットには、次の列が含まれています。

  • question: ユーザーの質問

  • correct_answer: 真実の結果

  • context: 質問に答えるための参照テキストのリスト

埋め込み前に、参照テキストを小さなチャンクに分割します。

from langchain.text_splitter import RecursiveCharacterTextSplitter
# Split text by tokens using the tiktoken tokenizer
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
encoding_name="cl100k_base", keep_separator=False, chunk_size=200, chunk_overlap=30
)
def split_texts(texts):
chunked_texts = []
for text in texts:
chunks = text_splitter.create_documents([text])
chunked_texts.extend([chunk.page_content for chunk in chunks])
return chunked_texts
# Split the context field into chunks
df["chunks"] = df["context"].apply(lambda x: split_texts(x))
# Aggregate list of all chunks
all_chunks = df["chunks"].tolist()
docs = [item for chunk in all_chunks for item in chunk]

Tip

検索を評価するときは、さまざまなチャンク戦略を試してください。このチュートリアルでは、埋め込みモデルの評価に焦点を当てます。

チャンクされたドキュメントを埋め込み、Atlas に取り込みます。比較する埋め込みモデルごとに個別のコレクションを作成します。

1

OpenAI APIを使用して埋め込みを生成する関数を作成します。

from typing import List
def get_embeddings(docs: List[str], model: str) -> List[List[float]]:
"""Generate embeddings using the OpenAI API."""
docs = [doc.replace("\n", " ") for doc in docs]
response = openai_client.embeddings.create(input=docs, model=model)
return [r.embedding for r in response.data]
2

チャンクされたドキュメントを Atlas コレクションに埋め込み、取り込みます。

from pymongo import MongoClient
from tqdm.auto import tqdm
client = MongoClient(MONGODB_URI)
DB_NAME = "ragas_evals"
db = client[DB_NAME]
batch_size = 128
EVAL_EMBEDDING_MODELS = ["text-embedding-ada-002", "text-embedding-3-small"]
for model in EVAL_EMBEDDING_MODELS:
embedded_docs = []
print(f"Getting embeddings for the {model} model")
for i in tqdm(range(0, len(docs), batch_size)):
end = min(len(docs), i + batch_size)
batch = docs[i:end]
batch_embeddings = get_embeddings(batch, model)
batch_embedded_docs = [
{"text": batch[i], "embedding": batch_embeddings[i]}
for i in range(len(batch))
]
embedded_docs.extend(batch_embedded_docs)
collection = db[model]
collection.delete_many({})
collection.insert_many(embedded_docs)
print(f"Finished inserting embeddings for the {model} model")
3

各コレクションに対してMongoDB ベクトル検索インデックスを作成します。インデックス名 vector_index を持つ次のインデックス定義を使用します。

{
"fields": [
{
"numDimensions": 1536,
"path": "embedding",
"similarity": "cosine",
"type": "vector"
}
]
}

インデックスの作成方法については、 「 MongoDB ベクトル検索インデックスの作成 」を参照してください。

Tip

text-embedding-ada-002text-embedding-3-small の両方に 1536 次元があるため、同じインデックス定義が両方のコレクションで機能します。

LM に適したコンテキストを取得するには、さまざまな埋め込みモデルを比較します。このチュートリアルでは、text-embedding-ada-002text-embedding-3-small を比較します。

1

LgChuin とMongoDB Atlasを使用してベクトルストア検索を取得する関数を作成します。

from langchain_openai import OpenAIEmbeddings
from langchain_mongodb import MongoDBAtlasVectorSearch
from langchain_core.vectorstores import VectorStoreRetriever
def get_retriever(model: str, k: int) -> VectorStoreRetriever:
"""
Get a vector store retriever for a given embedding model.
Args:
model (str): Embedding model to use
k (int): Number of results to retrieve
Returns:
VectorStoreRetriever: A vector store retriever object
"""
embeddings = OpenAIEmbeddings(model=model)
vector_store = MongoDBAtlasVectorSearch.from_connection_string(
connection_string=MONGODB_URI,
namespace=f"{DB_NAME}.{model}",
embedding=embeddings,
index_name="vector_index",
text_key="text",
)
retriever = vector_store.as_retriever(
search_type="similarity", search_kwargs={"k": k}
)
return retriever
2

データセットから質問と証明機関の結果を抽出します。

QUESTIONS = df["question"].to_list()
GROUND_TRUTH = df["correct_answer"].tolist()
3

RAM ライブラリの context_precisioncontext_recall メトリクスを使用して、各埋め込みモデルを評価します。

from datasets import Dataset
from ragas import evaluate, RunConfig
from ragas.metrics import context_precision, context_recall
import nest_asyncio
# Allow nested use of asyncio (used by RAGAS)
nest_asyncio.apply()
for model in EVAL_EMBEDDING_MODELS:
data = {"question": [], "ground_truth": [], "contexts": []}
data["question"] = QUESTIONS
data["ground_truth"] = GROUND_TRUTH
retriever = get_retriever(model, 2)
# Get relevant documents for the evaluation dataset
for i in tqdm(range(0, len(QUESTIONS))):
data["contexts"].append(
[doc.page_content for doc in retriever.invoke(QUESTIONS[i])]
)
# RAGAS expects a Dataset object
dataset = Dataset.from_dict(data)
# RAGAS runtime settings to avoid hitting OpenAI rate limits
run_config = RunConfig(max_workers=4, max_wait=180)
result = evaluate(
dataset=dataset,
metrics=[context_precision, context_recall],
run_config=run_config,
raise_exceptions=False,
)
print(f"Result for the {model} model: {result}")

サンプルデータセットの埋め込みモデルの評価結果は次のとおりです。

モデル
コンテキストの精度
コンテキスト呼び出し

text- embedded-da-002

0.9310

0.8561

text- embedded-3-small

0.9116

0.8826

これらの結果に基づいて、text-embedding-ada-002 は最も関連性の高い結果をより高くランク付けしますが、text-embedding-3-small は除外された結果とより整合性のあるコンテキストを検索します。このチュートリアルでは、埋め込みモデルとして text-embedding-3-small を使用します。

最適な埋め込みモデルを選択したので、 RGアプリケーションの生成コンポーネントの完了モデルを比較します。

1

LgChuin を使用して RG チェーンを構築する関数を作成します。

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.runnables.base import RunnableSequence
from langchain_core.output_parsers import StrOutputParser
def get_rag_chain(retriever: VectorStoreRetriever, model: str) -> RunnableSequence:
"""
Create a basic RAG chain.
Args:
retriever (VectorStoreRetriever): Vector store retriever object
model (str): Chat completion model to use
Returns:
RunnableSequence: A RAG chain
"""
# Generate context using the retriever, and pass the user question through
retrieve = {
"context": retriever
| (lambda docs: "\n\n".join([d.page_content for d in docs])),
"question": RunnablePassthrough(),
}
template = """Answer the question based only on the following context: \
{context}
Question: {question}
"""
# Define the chat prompt
prompt = ChatPromptTemplate.from_template(template)
# Define the model for chat completion
llm = ChatOpenAI(temperature=0, model=model)
# Parse output as a string
parse_output = StrOutputParser()
# RAG chain
rag_chain = retrieve | prompt | llm | parse_output
return rag_chain
2

faithfulnessanswer_relevancy メトリクスを使用して、さまざまな完了モデルを評価します。

from ragas.metrics import faithfulness, answer_relevancy
for model in ["gpt-3.5-turbo-1106", "gpt-3.5-turbo"]:
data = {"question": [], "ground_truth": [], "contexts": [], "answer": []}
data["question"] = QUESTIONS
data["ground_truth"] = GROUND_TRUTH
# Use the best embedding model from the retriever evaluation
retriever = get_retriever("text-embedding-3-small", 2)
rag_chain = get_rag_chain(retriever, model)
for i in tqdm(range(0, len(QUESTIONS))):
question = QUESTIONS[i]
data["answer"].append(rag_chain.invoke(question))
data["contexts"].append(
[doc.page_content for doc in retriever.invoke(question)]
)
# RAGAS expects a Dataset object
dataset = Dataset.from_dict(data)
# RAGAS runtime settings to avoid hitting OpenAI rate limits
run_config = RunConfig(max_workers=4, max_wait=180)
result = evaluate(
dataset=dataset,
metrics=[faithfulness, answer_relevancy],
run_config=run_config,
raise_exceptions=False,
)
print(f"Result for the {model} model: {result}")

サンプルデータセットの完了モデルの評価結果は次のとおりです。

モデル
忠実度
応答の関連性

gpt-3.5-turbo

0.9714

0.9087

gpt-3.5-turbo-1106

0.9671

0.9105

これらの結果に基づいて、最新の gpt-3.5-turbo はより因果整合性のある結果を生成しますが、古いバージョンでは特定のプロンプトに合った結果が生成されます。このチュートリアルでは、完了モデルとして gpt-3.5-turbo を使用します。

Tip

メトリクスのどちらかを選択をしたくない場合は、重み合計を使用して連結メトリクスを作成するか、評価に使用されるプロンプトをカスタマイズすることを検討してください。

最もパフォーマンスの高いモデルを使用して、RAMアプリケーションの全体的なパフォーマンスを評価します。

from ragas.metrics import answer_similarity, answer_correctness
data = {"question": [], "ground_truth": [], "answer": []}
data["question"] = QUESTIONS
data["ground_truth"] = GROUND_TRUTH
# Use the best embedding model from the retriever evaluation
retriever = get_retriever("text-embedding-3-small", 2)
# Use the best completion model from the generator evaluation
rag_chain = get_rag_chain(retriever, "gpt-3.5-turbo")
for question in tqdm(QUESTIONS):
data["answer"].append(rag_chain.invoke(question))
dataset = Dataset.from_dict(data)
run_config = RunConfig(max_workers=4, max_wait=180)
result = evaluate(
dataset=dataset,
metrics=[answer_similarity, answer_correctness],
run_config=run_config,
raise_exceptions=False,
)
print(f"Overall metrics: {result}")

この評価は、RG チェーンがサンプルデータセットに対して0.8873 の応答類似性と0.5922 の応答正確性を生成することを示しています。

結果をさらに調査するには、結果を pandas データフレームに変換し、低スコアの回答をフィルタリングします。

result_df = result.to_pandas()
result_df[result_df["answer_correctness"] < 0.7]

視覚的な分析用に、質問とメトリクスのヒートマップを作成します。

import seaborn as sns
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 8))
sns.heatmap(
result_df[1:10].set_index("question")[["answer_similarity", "answer_correctness"]],
annot=True,
cmap="flare",
)
plt.show()

上記のコードは、次のヒートマップを出力します。

RAGアプリケーションのパフォーマンスを可視化するヒートマップ

RGアプリケーションのパフォーマンスを可視化するヒートマップ

低スコアの結果を調べると、次の結果が見つかる場合があります。

  • 評価データセット内の一部のフィールドの結果が誤っています。 LM で生成された応答は正しいですが、証明機関の結果と一致しないため、スコアが低くなります。

  • 一部のデータ処理の結果は完全な文ですが、 LM で生成された応答は 1 つの単語または数字で表されます。

これらの結果は、LM 評価を特権チェックし、正確な評価データセットを管理することの重要性を強調します。

評価は 1 回限りのイベントであっては なりません 。システム内のコンポーネントを変更するたびに、その変更を評価して、パフォーマンスにどのように影響かを評価してください。アプリケーションが本番環境になると、パフォーマンスをリアルタイムでモニターし、変更を検出します。

Charts を使用して、 LMアプリケーションのパフォーマンスを監視します。評価結果と追跡したいフィードバックメトリクスを Atlasコレクションに書き込みます。

from datetime import datetime
result["timestamp"] = datetime.now()
collection = db["metrics"]
collection.insert_one(result)

このコードは評価結果に timestampフィールドを追加し、それを ragas_evalsデータベース内の metricsコレクションに書込みます。 Atlas のドキュメントは次のようになります。

{
"answer_similarity": 0.8873,
"answer_correctness": 0.5922,
"timestamp": "2024-04-07T23:27:30.655+00:00"
}

MongoDB Charts で ダッシュボードを作成 し、一定期間にわたるメトリクスを視覚化します。チャートとダッシュボードの作成方法については、「 Chartsの構築 」を参照してください。

このチュートリアルでは、 RAGASフレームワークとMongoDB Atlasを使用して RAGアプリケーションを評価する方法を学習しました。検索 用の埋め込みモデルと、生成用の完了モデルを比較し、アプリケーションの全体的なパフォーマンスを測定しました。また、 MongoDB Charts を使用して、一定の期間パフォーマンスを追跡する方法も学びます。

MongoDBを使用して RG アプリケーションを構築する方法の詳細については、次のリソースを参照してください。

戻る

自然言語クエリ