DIVX テックブログ

catch-img

【RAG評価】運用データを活用した評価データセットの作り方


目次[非表示]

  1. 1.はじめに
  2. 2.RAGの評価の必要性
  3. 3.RAGASについて
    1. 3.1.使用する評価指標
  4. 4.評価データセット作成
    1. 4.1.実装
      1. 4.1.1.1. ドキュメントの保存
      2. 4.1.2.2. RAGの実装
      3. 4.1.3.3. テストセット生成
      4. 4.1.4.4. 評価データセット作成
  5. 5.評価実行
  6. 6.まとめ
  7. 7.おわりに
  8. 8.お悩みご相談ください
  9. 9.参考文献

はじめに

こんにちは、AI基礎研究チームでエンジニアをしている飯倉です!

今回は、RAG(Retrieval-Augmented Generation)の評価方法についてご紹介します。
特に運用データを活用した評価データセットの作成方法に焦点を当てて解説します。

RAGの評価の必要性

AI技術は日々進化しており、RAGに関しても精度向上に向けた新手法が次々と登場しています。
しかし、これらの改善方法をただ導入するだけでは、その効果を実感することは難しいです。

そこで重要になるのが、RAGの性能を客観的かつ定量的に評価する方法です。評価を行うことで、どの改善策が実際に効果を発揮しているのかを明確に把握できます。

今回は、RAGの評価方法としてRAGASを紹介します。 RAGASを活用することで、RAGの性能を多角的に評価し、改善の方向性を見極めることが可能になります。

RAGASについて

RAGASは、RAGの性能を多面的に評価するための強力なツールです。RAGASを使用することで、生成された回答の質や関連性、忠実性などを体系的に測定できます。

評価を始めるには、評価対象のRAGと評価データセットを用意します。RAGASには複数の評価指標が用意されており、これらを組み合わせることで包括的な性能評価が可能です。

また、用意された評価指標の他に、指標を自作することも可能です。独自に評価したい内容がある場合は試してみると良いかもしれません。

使用する評価指標

今回使用する評価指標は以下の通りです:

  • コンテキスト精度(Context Precision)
    • 評価カテゴリ: 検索性能
    • スコア: 高い値が望ましい
    • 概要: コンテキスト精度は、取得したコンテキスト内の関連情報の割合を測定する指標です。 検索結果に含まれる有用な情報の比率を評価します。スコアが高いほど、無関係な情報が少なく、効率的に機能していることを示します。
  • コンテキスト再現率(Context Recall)
    • 評価カテゴリ: 検索性能
    • スコア: 高い値が望ましい
    • 概要: コンテキスト再現率は、必要な情報をどれだけ漏れなく取得できているかを測定する指標です。 重要な情報の取得漏れがないかを評価し、スコアが高いほど必要な情報を網羅できていることを示します。
  • コンテキストエンティティ再現率(Context Entities Recall)
    • 評価カテゴリ: 検索性能
    • スコア: 高い値が望ましい
    • 概要: コンテキストエンティティ再現率は、参照情報(reference)内のエンティティが取得コンテキストにどれだけ含まれているかを測定します。 特に事実に基づく応答で、重要なエンティティの取得漏れがないかを評価します。スコアが高いほど、必要なエンティティを確実に取得できていることを示します。
  • ノイズ感度(Noise Sensitivity)
    • 評価カテゴリ: 回答生成性能
    • スコア: 低い値が望ましい
    • 概要: ノイズ感度は、関連・非関連コンテキストが混在する際の誤った応答生成の頻度を測定します。 スコアが低いほど、ノイズに強く、正確な回答を生成できることを示します。
  • レスポンスの関連性(Response Relevancy)
    • 評価カテゴリ: 回答生成性能
    • スコア: 高い値が望ましい
    • 概要: レスポンスの関連性は、生成された応答がプロンプトにどれだけ適切に対応しているかを評価します。 スコアが高いほど、質問に的確に応答し、有用な情報を提供できていることを示します。
  • 忠実性(Faithfulness)
    • 評価カテゴリ: 回答生成性能
    • スコア: 高い値が望ましい
    • 概要: 忠実性は、生成された応答が提供コンテキストに対してどれだけ事実に基づいているかを測定します。 スコアが高いほど、回答の信頼性が高く、正確な情報を提供できていることを示します。

評価データセット作成

RAGASで評価を行うためには、評価データセットが必要です。
評価データセットには以下のパラメータが含まれ、各評価指標ごとに必要なパラメータが異なります。

  • user_input(ユーザー入力): ユーザーからの質問やリクエスト。
  • retrieved_contexts(取得されたコンテキスト): RAGがユーザー入力に基づいて検索・取得した関連情報。
  • response(モデルの応答): RAGで生成した回答。
  • reference(期待する回答): 正確かつ理想的な回答例。

以下はLLMを利用しない評価方法で使用されるパラメータです。データセット生成時にセットされますが、今回は使用しません。

  • reference_contexts(期待するコンテキスト)

評価指標ごとの必要なパラメータは、以下のようになっています。

評価指標と必要パラメータの表

今回はRAG運用後の評価を想定して、ベクトルDB(データベース)に保存された情報から、評価データセットを生成してみます。

実装

では実際の処理を実装していきます。

使用する技術や環境

  • 実行環境:Google Colaboratory
  • 使用モデル:
    • gpt-4o-mini
    • gpt-4o(評価に使用)
    • text-embedding-3-large
  • ベクトルDB:ChromaDB
  • ライブラリ:
    • langchain: 0.3.13
    • ragas: 0.2.8

その前に準備として、ベクトルDBへ保存する情報を用意します。
情報は社内のルールと想定してAIに生成してもらいました。以下がその内容になります。

※ 以下はAIによって生成された架空の社内ルールで、実際の企業におけるルールではありません。

internal_data = """
# 勤務形態

## 就業時間
標準就業時間: 午前9時から午後6時(1時間の休憩含む)
フレックスタイム制度:
- コアタイム: 午前11時から午後3時
- フレキシブルタイム: 午前6時から午前11時、午後3時から午後10時
- 月間最低労働時間: 160時間

## リモートワーク
導入目的: 業務効率の向上と柔軟な働き方の提供
リモートワークガイドライン:
- 申請方法: 毎月初週に専用ポータルより申請
- 設備要件: 安定したインターネット回線、社給のデバイスリスト
- 通信費補助: 定期的な補助金額の支給条件


# オフィス利用

## 出入管理
- 社員証: 出社時は常に社員証を携行
- 来訪者対応: 事前登録システムにて来訪者情報を登録し、受付でバッジを受け取る
- 警備体制: 24時間体制で警備員が常駐
- オフィスの利用可能時間: 午前7時から午後10時

## 会議室利用
- 予約システム: オンラインツールを用いた予約手続きとキャンセル手続き
- 使用制限: 月一回の長時間予約もしくはプロジェクト単位での予約申請
- 清掃・点検: 使用後の現状復帰、定期的な清掃と設備点検のスケジュール

# 業務プロセス

## プロジェクト管理
- プロジェクト開始: 開始前にプロジェクト計画書の提出と承認が必要
- 進捗報告: 週次の進捗報告会を実施、テンプレートに沿った報告書の作成
- 評価制度: 各プロジェクト終了時に評価基準に基づくフィードバックの実施

## リスクリダクション
- リスクアセスメント: 定期的なリスクアセスメントと社内教育の実施
- 報告手順: リスク発生時の報告フローと必要情報の一覧
- 対応策: リスク軽減策および対応プロセスの文書化


# 福利厚生

## 健康管理
- 健康診断: 年1回の定期健康診断を実施、記録の管理とフォローアップ
- メンタルヘルスサポート: カウンセリングサービス提供と利用ガイド
- 健康促進プログラム: 定期的なフィットネスアクティビティ、健康情報配信

## 福利厚生制度
休暇制度:
- 年次有給休暇の取得推奨と残日数の管理
- 特別休暇(育児休暇、介護休暇等)の取得手続き
- その他福利厚生: 社員向け割引、提携店舗リスト

## キャリア開発
- 研修プログラム: 社内外の研修プログラムの紹介と参加方法
- キャリアパス: 個々のキャリア支援と年次評価面談
- 資格取得支援: 資格取得のための支援金制度と利用申請手続き


# 情報セキュリティ

## データ保護
- 情報管理ポリシー: 機密情報の取り扱いには常に最大限の注意を払い、社内規定に従う
- アクセス権限: 各従業員に必要最小限のアクセス権限を設定
- 暗号化: 機密データは必ず暗号化を施して保存し、送信時にも暗号化プロトコルの使用を義務化

## パスワード管理
- 更新頻度: パスワードは90日ごとに更新
- 複雑性要件: パスワードは大小文字、数字、記号を含む8文字以上
- 二要素認証: 外部からのアクセスには二要素認証を必須とする


# 環境保護と持続可能性

## 環境方針
- 資源の節約: 紙資源や電力量を最小限に抑えた業務の推進
- 廃棄物管理: 廃棄物の分別とリサイクルの徹底
- エネルギー効率: エネルギー効率の高い設備の導入と利用

## 持続可能性活動
- グリーンオフィス: 持続可能な資材の利用とエコな職場環境の維持
- 社員の啓発活動: 定期的な環境保護に関するワークショップの開催
- 地域社会貢献: 地域の環境保護活動への参加と支援


# 技術革新と改善活動

## イノベーション促進
- 提案制度: 社員からの業務改善や新技術導入の提案を奨励
- 賞賛と報酬: 優れた提案には報奨を贈呈
- 実験スペース: 新しい技術を試験するための専用スペースの提供

## 継続的改善プロセス
- PDCAサイクル: プロジェクトや業務プロセスにおけるPDCAサイクルの活用
- ベンチマーク分析: 業績のベンチマーク分析を行い、業務改善の機会を特定
- ファシリテーショングループ: 継続的改善活動を支援する専門グループの設置


# 社内コミュニケーション

## 電子メールポリシー
- 使用目的: 社内活動関連の連絡と顧客対応に限定
- 返信時間: 業務時間内であれば24時間以内に返信
- フォルダ管理: メールフォルダを使用して分類し、整理整頓を推奨

## 社内チャットツール
- 推奨ツール: 社内標準コミュニケーションツールを使用
- 使用マナー: 簡潔で明瞭なメッセージを心掛け、業務外の利用をしない
- ステータス管理: 業務時間外や集中業務中はステータスを更新


# クライアント対応

## 顧客サービス基準
- 応対方針: 礼儀正しく、迅速かつ正確なサービスを提供
- フィードバック収集: 顧客満足度調査と定期レビュー会議の実施
- 苦情対応: 苦情を受けた際は迅速な対応と報告を行う

## 契約管理
- 契約交渉: すべての交渉は法令遵守と倫理規範に基づく
- 契約書類管理: 専用クラウドでの電子管理と各部門での複製管理
- 見直しプロセス: 契約書は定期的に見直し、更新の必要性を確認


# 人材育成と評価制度

## 人材育成プログラム
- 新人研修: 入社後1ヶ月間の徹底した研修プログラム
- メンター制度: 新人社員や中途採用者にメンターを割り当て
- 継続学習: 年4回の専門スキルアップ研修の実施

## 業績評価システム
- 評価頻度: 半年毎に個人の業績評価を実施
- 評価基準: 目標達成度、協調性、業務改善提案の質
- フィードバック: 評価後にフィードバックセッションを行い、個別のキャリアプランを策定


# 社内イベントと文化

## 社内イベント
- 定期イベント: 半年に一度の全社ミーティングとチームビルディングアクティビティ
- 社内コンペティション: 年1回のイノベーションチャレンジ大会開催
- ボランティア活動: 年2回の地域貢献ボランティアイベント

## 企業文化
- 価値観の共有: 初日に企業理念および価値観研修を受講
- オープンなコミュニケーション: 定期的なタウンホールミーティングでの自由発言機会
- 多様性推進: 多様性委員会による定期活動と政策の見直し

"""

1. ドキュメントの保存

始めに先ほど用意した情報をベクトルDBへ登録します

from langchain_chroma import Chroma
from langchain_text_splitters import MarkdownHeaderTextSplitter
from langchain_openai import OpenAIEmbeddings


# 埋め込みモデルの準備
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")

# ベクトルDBの準備
chroma = Chroma(
    collection_name="vector_index",
    embedding_function=embeddings,
    collection_metadata={"hnsw:space": "cosine"},
)

# マークダウンヘッダーごとにドキュメントの分割
markdown_header_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=[("#", "#"), ("##", "##")], strip_headers=False
)

chunked_docs = markdown_header_splitter.split_text(internal_data)

# ドキュメントの登録
chroma.add_documents(documents=chunked_docs)


2. RAGの実装

RAGの処理を作成します。

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough


# ベクトルDBからドキュメント取得するリトリーバーの準備
retriever = chroma.as_retriever(
    search_type="similarity"
)

# モデルの準備
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)


# プロンプト作成
prompt_template = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "次の情報のみ使用して質問に答えてください。\n\n情報:\n{context}",
        ),
        ("human", "{input}"),
    ]
)


# 生成チェイン
generation_chain = RunnablePassthrough() | prompt_template | llm | StrOutputParser()

# リトリーバーチェイン
retrieve_chain = (lambda x: (x["input"])) | retriever

# RAGチェイン
rag_chain = RunnablePassthrough.assign(context=retrieve_chain).assign(
    answer=generation_chain
)

一度動作を確認してみます。

res = rag_chain.invoke({"input": "勤務時間は?"})
print(res["answer"])

標準就業時間は午前9時から午後6時までで、1時間の休憩が含まれています。
また、フレックスタイム制度があり、コアタイムは午前11時から午後3時まで、フレキシブルタイムは午前6時から午前11時、午後3時から午後10時までです。月間最低労働時間は160時間です。

問題なく動作していそうです。

3. テストセット生成

ベクトルDBから取得した情報をもとに、RAGASのテストセット生成機能を使用して作成します。
この生成機能では、以下のパラメータを含むテストセットを生成します。(この時点でretrieved_contextsとresponseパラメータは生成されません。)

  • user_input
  • reference
  • reference_contexts

テストセット生成に関する処理を準備していきます。

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from ragas.embeddings import LangchainEmbeddingsWrapper
from ragas.llms import LangchainLLMWrapper
from ragas.testset import TestsetGenerator
from ragas.testset.synthesizers.single_hop.specific import (
    SingleHopSpecificQuerySynthesizer,
)
from ragas.testset.persona import Persona
from ragas.testset.transforms.extractors.llm_based import NERExtractor
from ragas.testset.transforms.splitters import HeadlineSplitter


# テストセット生成に使用するモデル
generator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o-mini", temperature=1.0))
generator_embeddings = LangchainEmbeddingsWrapper(
    OpenAIEmbeddings(model="text-embedding-3-large")
)

# テストセット生成におけるペルソナの設定。
personas = [
    Persona(
        name="New Joinee",
        role_description="会社についてあまり知らないので、社内のルールを確認したい。",
    ),
]

# テストセットの生成に使用するクエリの準備
distribution = [
    (SingleHopSpecificQuerySynthesizer(llm=generator_llm), 1.0),
]
# クエリを日本語に変換
for query, _ in distribution:
    prompts = await query.adapt_prompts("japanese", llm=generator_llm)
    query.set_prompts(**prompts)

続いてテストセット生成に使用する情報を、ベクトルDBから取得します。 生成したい大まかなカテゴリーを指定して検索クエリとしました。

今回はドキュメントが少ないので、1つのリストにまとめています。
テストのカテゴリーやRAGの取得ドキュメント数を増やす場合は、カテゴリーごとにリストを分けた方が、生成内容の偏りを抑えられて良いかもしれません。

# 生成したいテストセットのカテゴリー
test_categories = [
    "勤務形態",
    "オフィス利用",
    "人材育成と評価制度",
]

# テストセット生成に使用するドキュメントを取得
retrieved_documents = []
for category in test_categories:
    documents = retriever.invoke(category)
    print(len(documents))
    retrieved_documents.extend(documents)

最後にテストセット生成を実行します。

# テストセットの生成
test_set = generator.generate_with_langchain_docs(
    documents=retrieved_documents,
    testset_size=5,
    query_distribution=distribution,
    transforms=transforms,
)

テストセットを出力してみましょう。

test_set.to_pandas()

テストセット出力結果

取得した情報をもとに、テストセットが作成されています。

4. 評価データセット作成

生成したテストセットのuser_inputを使用して、実際にRAGを実行します。
RAGの実行結果を、retrieved_contextsresponseに入れていきます。

# 評価データセットに変換。この時点ではretrieved_contextsとresponseが存在しない。
eval_dataset = test_set.to_evaluation_dataset()

# RAGを実行してresponseとretrieved_contextsを埋める。
for d in eval_dataset:
    input = d.user_input
    rag_result = rag_chain_with_source.invoke({"input": input})
    d.response = rag_result["answer"]
    d.retrieved_contexts = [doc.page_content for doc in rag_result["context"]]

評価データセットが出来上がったので出力してみます。

eval_dataset.to_pandas()

評価データセット出力結果

retrieved_contextsresponseが追加された評価データセットが出力されました。これでデータセット作成は完了です。

評価実行

作成した評価データセットを使用して、実際に評価を実行してみます。

from ragas.metrics import (
    ContextPrecision,
    ContextRecall,
    ContextEntityRecall,
    Faithfulness,
    ResponseRelevancy,
    NoiseSensitivity,
)
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from ragas.embeddings import LangchainEmbeddingsWrapper
from ragas.llms import LangchainLLMWrapper


# 評価器モデルの準備
evaluator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))
evaluator_embeddings = LangchainEmbeddingsWrapper(
    OpenAIEmbeddings(model="text-embedding-3-large")
)

# 評価指標の準備
metrics = [
    ContextPrecision(llm=evaluator_llm),
    ContextRecall(llm=evaluator_llm),
    ContextEntityRecall(llm=evaluator_llm),
    NoiseSensitivity(llm=evaluator_llm),
    ResponseRelevancy(llm=evaluator_llm, embeddings=evaluator_embeddings),
    Faithfulness(llm=evaluator_llm),
]


# 評価実行
eval_result = evaluate(eval_dataset, metrics)


評価結果のスコアを出力してみます。

評価結果の出力

ちゃんと評価できています。
スコアは概ね高いですが、Faithfulnessの値が低い結果がいくつか見受けられます。評価データセットの内容と照らし合わせると、与えられたコンテキスト以外の情報を使って回答していそうです。

今回の場合は保存したデータが少なく、回答に必要な情報が不足していることが原因と考えられます。

改善する場合は、「与えられたコンテキストで回答できない場合は、わかりませんと返すようプロンプトを設定する」や「より詳細な情報をベクトルDBに追加する」などの対策が考えられそうです。

まとめ

RAGの評価は、その性能を正確に把握し、継続的な改善を行うために非常に重要です。

RAGASを活用することで、多角的な評価指標を利用してRAGの強みと弱点を明確にすることができます。

また、運用しているデータを基に評価データセットを作成することで、実際の業務に即した評価を行うことが可能になります。
これにより、RAGの精度向上に向けた具体的な改善策を効果的に実施できます。

おわりに

今回紹介したRAGASを用いた評価方法と運用データを活用した評価データセットの作成方法が、皆様のRAGの改善にお役立ていただければ幸いです。

最後までお読みいただき、ありがとうございました。

お悩みご相談ください

  ご相談フォーム | 株式会社divx(ディブエックス) DIVXのご相談フォームページです。 株式会社divx(ディブエックス)

参考文献

RAGAS公式ドキュメント

お気軽にご相談ください


ご不明な点はお気軽に
お問い合わせください

サービス資料や
お役立ち資料はこちら

DIVXブログ

テックブログ タグ一覧

人気記事ランキング

関連記事

GoTopイメージ