46.4kデモを予約するログイン無料で始める

メトリクス主導のRAG開発

Jul 05, 20243 min read

先日のZilliz Unstructured Data Meetupでのプレゼンテーションで、RagasのメンテナであるJithin JamesとShahul Esは、RAG(Retrieval Augmented Generation)システムを評価するためのメトリクス駆動型開発の活用に関する洞察を共有した。開発者は、より良いパフォーマンスのために、評価結果に基づいてシステムを微調整することができます。

講演の中で、Jithin氏とShahul氏は、RAGシステム評価の理論的基礎と実践的応用の両方について議論しました。彼らは、評価コードの背後にある理論を理解することで、その機能についてより深い洞察が得られることを説明した。続いて、類似検索やAIアプリケーションの効率性で知られるオープンソースの主要なベクトルデータベースであるMilvusを搭載した実際のRAGシステムを用いて、評価プロセスを実演した。

より詳細な理解については、watch the replay of the meetup talk.をご覧ください。

RAG システムのパフォーマンスを評価する方法

Shahul氏は、RagasがRAGシステムによって生成された答えの真実性をどのように計算するかについて触れた。これは非常に重要な評価指標です。答えはエンドユーザーが見るものだからです。 少しゆっくり、深く掘り下げてみましょう。Ragasは以下の式を使って答えの真実性を計算します:

図1- Ragasのanswer_truthfulnessメトリック計算式](https://assets.zilliz.com/Fig_1_Ragas_answer_truthfulness_metric_computation_formula_d691ad34df.png)

検索支援生成(RAG)システムにおける答えの正しさの計算

このプロセスには2つの主要なメトリクスが含まれる:事実的類似性と意味的類似性。これらのメトリクスは、グランドトゥルースと比較した生成された回答の品質と関連性を判断するのに役立ちます。

主なメトリクス

1.実際の類似性:* 2.

  • このメトリクスは、グランドトゥルースと生成された答えの間の事実情報の存在を比較することで、生成された答えの事実の正しさを測定します。

2.意味的類似度:*。

  • このメトリクスは、生成された回答がグランド・トゥルースと意味的にどれだけ類似しているかを測定し、生成された回答によって伝達される意味がグランド・トゥルースと一致することを保証します。

回答の正しさを計算するステップ

1.真陽性(TP)、偽陽性(FP)、偽陰性(FN)を特定する:

  • 真陽性(True Positives):** グラウンドトゥルースと生成された回答の両方に正しく存在する文。

  • 偽陽性(False Positives):** 生成された回答には存在するが、ground truthには存在しないステートメント。

  • 偽陰性:** グラウンド・トゥルースには存在するが、生成された答えには存在しないステートメント。

2.F1スコアを計算する:

  • F1スコアは精度と想起の平均であり、2つの間のバランスを提供する。F1スコアの計算式を図1に示す。

実例

ある真実の文章と生成された答えを考える:

  • アラン・チューリングはチューリング・マシンの概念を開発した。

  • 生成された答え:** "アラン・チューリングはチューリング・マシンと人工知能の概念を開発したことで知られている"

**ステップ1:TP、FP、FNを特定する。

  • 真陽性 (TP):**

    • "アラン・チューリングはチューリング・マシンの概念を開発した"
  • 偽陽性 (FP):**

    • "アラン・チューリングは人工知能を開発したことで知られている"
  • 偽陰性(FN):***。

    • なし(生成された答えには真実のすべての要素が含まれているため)。

ステップ2:F1スコアを計算する。

  • TP = 1

  • FP = 1

  • FN = 0

F1 = 1 / (1 + 0.5 * (1 + 0))

= 1 / 1.5

≈ 0.67

解釈<

  • 事実の類似性: 生成された答えは、グランド・トゥルースからの本質的な情報を含んでいるので、事実上正しい。

  • 意味的類似性: 生成された答えは、追加情報を含むものの、グランド・トゥルースとの意味的な整合性を維持します。

F1スコアは、精度と想起のバランスを取りながら、答えの正しさの尺度を提供するために、これらの側面を組み合わせます。この方法は、生成された答えが、事実のコンテンツと全体的な意味の両方において、グランドトゥルースとどの程度一致しているかを評価するのに役立ちます。

しかし、ボロシステムを評価するために使用できる指標は、回答の真実性だけではありません。他のメトリクスは、忠実度、答えの関連性、コンテキストのリコール、コンテキストの精度です。それでは、Mivusを利用したRAGシステムをどのように評価し、改善できるかを実際に見てみましょう。

Milvus搭載RAGシステムの評価と改善

RAGシステムを評価するための理論的基礎を理解したところで、Milvusベクトルデータベースを使用して構築された実用的なRAGの例に飛び込んでみましょう。RAGシステムのセットアップ、実装、評価について説明する。その結果に基づいて、どのようにシステムを改善できるかを検討する。

環境のセットアップ

まず、開発環境をセットアップする必要がある。そのためにまず、必要なライブラリをすべてインストールする:


pip install pymilvus[model] ragas langchain langchain_openai python-dotenv nest_asyncio pypdf langchain_community

それぞれのライブラリがコードの中でどのように使われるかを説明しよう: 1.1.Pymilvus[model]はMilvusへの接続、コレクションの作成、データの挿入、類似検索の実行を支援する。 2.Ragasは評価指標を提供し、合成テストセットを生成し、RAGパイプラインを評価する。 3.Langchain はドキュメントをロードし、チャンクに分割し、埋め込みとクエリのためにテキストデータを準備する。 4.Langchain_openaiはOpenAIモデルとのインターフェースを持ち、埋め込みデータを生成し、APIコールを使って質問に答える。 5.Python-dotenv は.envファイルから環境変数をロードし、APIキーのような機密情報を管理する。 6.Nest_asyncioは同期環境内でネストされた非同期操作を可能にする。特にJupiterノートブックを使っている場合に有効である。 7.Pypdf は PDF ドキュメントを読み込み、内容を抽出し、処理のためにテキストを準備する。 8.8. Langchain_community は追加のドキュメントローダーとコミュニティから提供されたリソースを統合するためのユーティリティを提供する。 ライブラリをインストールしたら、それらをコードにインポートし、APIキーを設定する:


インポート os

インポート pandas as pd

インポート nest_asyncio

インポート openai

from pymilvus import MilvusClient, model

from ragas import evaluate

from ragas.metrics import (

    忠実度

    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 データセット

# 環境変数をロードする

# nest_asyncioを適用して、ネストされたイベントループを許可する

nest_asyncio.apply()

# OpenAIのAPIキーを設定する

os.environ["OPENAI_API_KEY"] = "あなたのAPIキー"

クライアント = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

ライブラリやモジュールをコードにインポートすることで、それらの関数を呼び出して使うことができるようになります。OpenAI キーは、API 呼び出しの際に OpenAI に対して自分自身を認証するのに役立ちます。もし持っていなければ、OpenAI API page にアクセスして、生成してください。

ドキュメントの読み込みと準備

次に、ドキュメントを読み込んで、処理の準備をします:


# ディレクトリからPDF文書を読み込む

pdf_loader = DirectoryLoader("/content/data", loader_cls=PyPDFLoader)

documents = pdf_loader.load()

# 各文書がメタデータにファイル名を持つようにする

for document in documents:

    document.metadata['filename'] = document.metadata['source'

このコードは PyPDFLoader クラスを使用して、ディレクトリからPDFドキュメントをロードします。そして、DirectoryLoaderインスタンスを作成し、ドキュメントをロードし、各ドキュメントを繰り返し処理して、メタデータに filename 属性を追加します。これにより、各ドキュメントが適切に識別され、対応するファイル名で管理されるようになる。このステップはRAGシステムのナレッジベースを形成するので非常に重要である。この例ではPDFドキュメントを使用していますが、必要に応じて他のドキュメントタイプにも適用できます。

テストセットの生成

データをロードしたので、RAG システムを効果的に評価するために、多様なテスト問題セットが必要です。Ragas フレームワークを使用して、合成テストセットを生成します。


# テストセット生成のために OpenAI モデルを初期化する

generator_llm = ChatOpenAI(model="gpt-3.5-turbo-16k")

critic_llm = ChatOpenAI(model="gpt-4")

embeddings = OpenAIEmbeddings()

# テストセットジェネレータを作成する

generator = TestsetGenerator.from_langchain(

    generator_llm、

    critic_llm、

    埋め込み

)

# 10サンプルで合成テストセットを生成

testset = generator.generate_with_langchain_docs(documents, test_size=10, distributions={simple: 0.5, reasoning: 0.25, multi_context:0.25})

# テストセットをPandas DataFrameに変換する

testset_df = testset.to_pandas()

print(testset_df)

このコードは2つの言語モデル(テストセット生成用の gpt-3.5-turbo-16k と評価用の gpt-4 )と OpenAI からの埋め込みモデルを初期化する。そして、これらのモデルを用いて TestsetGenerator インスタンスを生成する。このジェネレータは、読み込まれた PDF 文書から、さまざまな種類の問題に対して指定された分布を持つ、10 サンプルの合成テストセットを生成します。このテストセットは、単純なクエリ、推論タスク、および複数のコンテキストを必要とする質問を処理する能力を含む、RAGシステムのパフォーマンスのさまざまな側面を評価するのに役立ちます。以下は生成されたテストセットの例です。

図2- Ragasを使って生成されたテストセット](https://assets.zilliz.com/Fig_2_Test_set_generated_using_Ragas_5f358eb210.png)

グランドトゥルースとは、与えられた質問に対する実際の答えのことである。私たちは後で、RAGシステムの出力がこれらのグランド・トゥルースにどれだけ近いかによって、私たちのRAGシステムがどの程度うまくいっているかを測定するためにこれを使用します。Shahulが講演で指摘しているように、Ragasを使って合成テストセットを生成しても、それをやみくもに使うことにはならない。必要なサンプルをフィルタリングして使用しなければならない。

テストセットを手に入れたので、Milvusを使った簡単なRAGシステムを構築し、上記のテストセットを使って評価してみよう。

Milvusのセットアップとドキュメントの埋め込み

それでは、Milvusベクトルデータベースをセットアップし、文書埋め込みを挿入してみましょう。Milvusがインストールされていることを確認してください。インストールされていない場合は、こちらのMilvusインストール総合ガイドを参照してください。


# Milvusインスタンスに接続する

milvus_client = MilvusClient(uri="http://localhost:19530")

# コレクション名の定義

コレクション名 = "pdf_collection"

# コレクションが既に存在する場合は削除する

if milvus_client.has_collection(collection_name):

    milvus_client.drop_collection(collection_name)

# 新しいコレクションを作成する

milvus_client.create_collection(

    コレクション名=コレクション名、

    dimension=768, # ベクトルの次元

    上書き=真

)

# 埋め込み関数を初期化する

embedding_fn = model.DefaultEmbeddingFunction()

# 文書のテキストを抽出し、埋め込みを生成する

expanded_docs = [doc.page_content for doc in documents] # ドキュメントテキストを抽出し、埋め込みを生成する。

expanded_vectors = embedding_fn.encode_documents(expanded_docs)

# 挿入するデータを準備する

expanded_data = [ 拡張されたデータ

    {"id": i, "vector": expanded_vectors[i], "text": expanded_docs[i], "subject":"pdf_documents"}。

    for i in range(len(expanded_vectors))

]

# 展開されたデータをコレクションに挿入する

milvus_client.insert(data=expanded_data, collection_name=collection_name)

上記のコードはMilvusインスタンスに接続し、ドキュメントベクトルを格納するためにpdf_collectionという名前のコレクションをセットアップする。コレクションが既に存在する場合は、それを削除し、ベクトル用に 768 の次元で再作成する。埋め込み関数を初期化し、読み込んだ文書からテキストを抽出し、埋め込みデータを生成する。そして、埋め込みと関連テキストを含むデータを準備し、このデータをMilvusコレクションに挿入する。このステップがMilvusの真骨頂であり、格納された埋め込みデータに対して高速かつ効率的な類似検索を行うことができます。これはRAGシステムの検索部分にとって非常に重要です。

類似検索の実行

あなたのドキュメントがMilvusでインデックス化され、あなたは今、私たちの質問に関連するコンテキストを取得するために類似検索を実行することができます:


# 検索パラメータを定義する

search_params = {"metric_type":"COSINE", "params":{"nprobe": 20}} # nprobeはより良い想起のため。  # より良いリコールを得るためにnprobe

# 検索を実行する

query_vectors = embedding_fn.encode_queries(testset_df['question'].tolist())

results = milvus_client.search(

    コレクション名=コレクション名、

    data=query_vectors、

    anns_field="vector", # ベクトルフィールド名を指定する。

    search_params=search_params、

    limit=3, # トップの検索結果の数

    output_fields=["id", "text"]。

)

上記のコードでは、cosine similarity と nprobe の値 20 を用いてMilvusコレクションの検索パラメータを設定しています。テストセットの質問をクエリベクターにエンコードし、pdf_collectionコレクションで検索を行い、各クエリに対して最も類似した上位3つのベクターを取得する。検索結果にはマッチした文書の ID と text が含まれる。

大規模な言語モデルを使った回答生成.

関連するコンテキストが取得されたので、言語モデルを使用して回答を生成することができます。今回は、GPT 3.5ターボを使用します。


# OpenAIを使って回答を生成する関数

def generate_answer(question, contexts):

    context_text = ".join(contexts)

    メッセージ = [

        {"role":"system", "content":「あなたは役に立つアシスタントです、}

        {"role":"user", "content": f "コンテキスト:{context_text}nn質問:{質問}回答:"}

    ]

    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()

# コンテキストを抽出し、OpenAIを使って回答を生成する

コンテキスト = []

アンサー = [].

for i, result in enumerate(results):

    コンテキスト = [match['entity']['text'] for match in result].

    context.append(コンテキスト)

    question = testset_df['question'].iloc[i].

    answer = generate_answer(question, context)

    answers.append(answer)

このコードでは、OpenAIの gpt-3.5-turbo モデルを使って、与えられた質問とコンテキストに基づいて答えを生成する generate_answer 関数を定義しています。APIコールのメッセージを準備し、コンテキストを連結し、モデルに問い合わせます。そして、生成された答えを抽出して返します。後続のループは検索結果を繰り返し、generate_answer関数を使用してテストセットの各質問の回答を生成し、コンテキストと回答をリストに格納します。答えを生成するループで使われる問題はテストセットで生成されたものと同じです。

RAGシステムが生成した解答と真実の解答があるので、RAGシステムがどの程度うまくいっているかを評価してみましょう。

RAGシステムの評価

最後に、先ほど説明したメトリクスを使ってRAGシステムのパフォーマンスを評価します:


# すべてのリストが同じ長さであることを確認する

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]。

アンサー = アンサー[:min_length] (最小長)

コンテキスト = contexts[:min_length]

# 正しいカラム名でデータセットを作成する

データ = {

    "question": 質問、

    "答え": 答え、

    "contexts": コンテキスト、

    "ground_truth": ground_truths

}

from datasets import データセット

# dictをデータセットに変換する

データセット = Dataset.from_pandas(pd.DataFrame(data))

# RAGAS を使って評価する

メトリクス = evaluate(

    dataset=dataset、

    メトリクス=[

        answer_correctness、

        context_precision、

        context_recall、

        忠実さ、

        answer_relevancy、

    ],

    raise_exceptions=False #非同期の問題を処理する

)

# 読みやすくするために結果をDataFrameに変換する

result_df = metrics.to_pandas()

print(result_df)

このコードでは、関連するリストをすべて同じ最小の長さに切り詰めることで、評価プロセスの一貫性を確保している。これにより、評価中にエラーを引き起こす可能性のある長さの不一致を防ぐことができます。次に、これらのトリミングされたリストで辞書を作成し、それをPandas DataFrameに変換し、Hugging Face Datasetに変換します。この構造化されたデータセットにより、RAGASフレームワークを使用した体系的な評価が可能になり、生成された回答をグランドトゥルースと比較することができます。評価メトリクス(答えの正しさ、文脈の精度、文脈の想起、忠実度、答えの関連性)は、RAGパイプラインの性能の評価を提供します。

以下の評価結果を見てください:

図3- Ragas RAGシステムの評価結果](https://assets.zilliz.com/Fig_3_Ragas_RAG_system_evaluation_results_dccebbe289.png)

私たちのRAGシステムのコンテキストの精度とリコールは優れており、回答の関連性は賞賛に値します。しかし、正解率はかなり低い。

検索側は、文脈の想起と精度が優れているため、良好です。つまり、生成の部分が回答の正しさに影響している可能性があると結論づけることができます。これを改善するには、GPT-4のようなより強力な回答生成モデルを使用することができます。

結論

検索支援生成(RAG)システムの評価と改善は、AI駆動型情報検索の領域において、微妙ではあるが不可欠なタスクである。Jithin James氏とShahul Es氏によって実証されたように、メトリクス主導のアプローチを活用することで、RAGシステムを体系的に改良し、正確で関連性が高く、信頼できる情報を確実に提供することができる。

このトピックの詳細については、YouTubeでトークのリプレイを見る.

その他のリソース

Updated on Jul 09, 2026