🐧

RAGシステム評価の落とし穴と、改善への道標【RAGAS使用】

2024/12/20に公開

はじめに

この記事は、 any Product Team Advent Calendar 2024 の20日目の記事です。

https://qiita.com/advent-calendar/2024/anyinc

any株式会社でAIエンジニアをしているMatsu Shinと申します。

2024年は、LLM(大規模言語モデル)があらゆる領域で注目を集めました。なかでもRAG(Retrieval-Augmented Generation)と呼ばれる、「LLMに外部の情報源を参照させて文章を生成させる」技術は、様々なサービスで実用化されている手法です。

しかし、RAGシステムを実装しただけで終わりにせず、それをどう評価・改善していくかは、多くの現場で手探り状態です。

本記事では、RAGシステムの評価に焦点を当てます。評価で陥りがちな失敗パターンと、それらを踏まえたより良い評価システムの考え方をお伝えします。ここで紹介するアプローチは、any株式会社で提供するプロダクトでの知見にも基づいており、お読みいただく皆さんのサービス品質向上にも役立つはずです。

対象読者

  • RAG技術を使ったアプリケーション構築に関わるエンジニア・PMの方
  • LLMを活用したプロダクト運営に興味がある方

よくある落とし穴

RAG(Retrieval-Augmented Generation)システムは、「参照ドキュメント選択」と「回答生成」という2つのステップから成り立っています。ところが、評価の際によく起こりがちなミスがあります。

最終出力(回答)だけを見る

多くの場合、「出てきた回答が良い or 悪い」だけで評価しがちです。しかし、それだと「検索したドキュメント選びが悪かったのか?」それとも「回答生成がイマイチだったのか?」といった問題点が曖昧になります。

重要なことは、

  • 参照ドキュメント選択
  • 回答生成

の2つの手順を区別して評価することです。

Retrieval augmented generation (RAG) - LangChain

この図の 1 と 2 がそれぞれ、参照ドキュメントの選択と回答生成に対応しています

機械的な指標(数値)にだけ頼る

類似度の測定アルゴリズムや自動評価ツールなどによる、便利な定量指標は増えています。ですが残念ながら、それらの数値のみにより、いま相対しているRAGシステムのユーザーによる「使いやすさ」や「満足度」を説明できるケースは稀です。

そのため重要なのは、機械的な指標にのみ頼らずに、

  • LLMによる評価
  • 人間 (とくに実際にシステムを使用するユーザー) による評価

なども取り入れ、多面的な評価を実施する基盤を整えることです。

正しい評価のガイドライン

RAGシステムをうまく評価するコツは、前述の通り、「参照ドキュメント選択」と「回答生成」を分けて考え、それぞれを別個のシステムとして評価することです。ここでは例として、RAGシステムの評価ツールとして広く使用される Ragas を参照して進めます。

① 参照ドキュメント選択の評価

NonLLMでの評価

検索精度は数値化しやすく、古くより情報検索技術で確立された指標が広く使えます。例えば、機械学習の文脈でよく使用される、 Precision や Recall などの指標は、理解を得られやすいでしょう。

RAGシステムでは、「質問内容」と「引用してほしいドキュメント集」をまとめて、いわゆる「教師データ集」を用意し、実際に引用されたドキュメントとの一致率を自動で測定するような仕組みを作ると、改善効果を追いやすくなります。

たとえば Ragas に実装されている評価指標でいうと、以下のページの「Context Precision」や「Context Recall」の、 Non LLM Based の実装が、まずは明瞭で使いやすいと思います。

Context Precision with reference contexts

from ragas import SingleTurnSample
from ragas.metrics import NonLLMContextPrecisionWithReference

context_precision = NonLLMContextPrecisionWithReference()

sample = SingleTurnSample(
    retrieved_contexts=["エッフェル塔はパリにあります"], 
    reference_contexts=["パリはフランスの首都です", "エッフェル塔はパリで最も有名なものです"]
)

context_precision.single_turn_score(sample)
(実行結果)
0.9999999999

以上のコードでは、LLMの使用無しで、 Precision を測定してみました。

Precision とは、検索された結果の内容が、教師データの内容と意味的に近いか? (i.e. 余計な情報を引っ張ってきていないか?) の度合いを数値化したものです。結果は 0~1 の実数値で返されます。1に近いほど、内容に矛盾がなく、良い引用結果として捉えられ、「Precisionが高い」などと言ったりします。今回の結果もほぼ1なので、「Precisionが高い」ドキュメント検索ができた例と言えます。

今回のコードでは、 retrieved_contexts には検索された参照ドキュメントを、 reference_contexts には教師データとしての参照ドキュメントを、それぞれ文字列のリストで渡しています。内部では、渡された文字列の内容同士の距離 (詳細) を機械的に測定し、スコアを計算しています。

NonLLM評価を行う際の注意点は、

  • あくまでも個々の単語の意味同士の近さを測定してるのみなので、「話題は近いが内容が矛盾しているドキュメント」も高く評価される
  • ドキュメント同士の「完全一致」を判定することはないので、厳密に拾ってほしいドキュメントを決める必要がある場合は使えない
  • (言うまでもないが)教師データが必須で用意が面倒

あたりが考えられます。そのためこの評価指標1つに頼り切るのは危険ですが、コストも殆どかからず、直感的な理解もされやすい指標となるので、常に追っておくべき指標の1つと言えるでしょう。

LLMでの評価

以上をベースの指標として追いつつ、 LLM を用いた評価指標も取り入れ、同時に変化を追うことをおすすめします。

Context Precision 先ほどと同じく、Precisionを例に説明します。 LLM Based な評価の強みは以下のとおりです。

  • 話題だけでなく文脈が一致しているかを判定できるため、内容の矛盾なども判定でき、実際のユーザーの使用感と評価が一致しやすい
  • 教師データ無し (without reference) での評価も可能

どちらも非常に重要なポイントで、NonLLMでの機械的な評価の弱点を見事に補ってくれます。

Ragas では、先程のNonLLMでの評価とほとんど同じ使用感で評価結果を出力できます。ただしLLMを使用するため、このページの内容に従い、評価用LLMの設定を行う必要があります。

Context Precision without reference

# 評価用LLMの設定 例としてOpenAIを使用 OPENAI_API_KEYは個人で発行する必要あり
import os
os.environ["OPENAI_API_KEY"] = "*****"
from ragas.llms import LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper
from langchain_openai import ChatOpenAI
from langchain_openai import OpenAIEmbeddings
evaluator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-3.5-turbo"))

# LLMによるPrecisionの計算
from ragas import SingleTurnSample
from ragas.metrics import LLMContextPrecisionWithoutReference

context_precision = LLMContextPrecisionWithoutReference(llm=evaluator_llm)
sample = SingleTurnSample(
    user_input="エッフェル塔はどこにありますか?",
    response="エッフェル塔はパリにあります",
    retrieved_contexts=["エッフェル塔はパリで最も有名なものです"],
)

context_precision.single_turn_score(sample)
(実行結果)
0.9999999999

以上のコードでは、LLMを用いて、教師データなしのPrecisionの計算を実行しています。前半の評価用LLM (evaluator_llm) の設定が少しややこしいですが、そこ以外はNonLLMのときとほとんど同じで、結果も納得感があります。

LLMによる評価のデメリットは以下のとおりです。

  • LLMの使用に関わる諸々のコスト (金銭、実行時間、セキュリティ、アカウントや支払いの管理など、特に組織で大規模な開発となると色々と面倒) が発生
  • 結果の解釈・説明が感覚的になりがち
  • 結果の固定ができず、同じ入力でも実行ごとに結果が変化する

総じて、実際にプロジェクト等で導入して使っていくうえでは、予算確保やSecretsの管理など、気にしなければいけない領域が広がってしまう点で、一定のハードルが生まれます。また、厳密性や説明性がネックになり、評価結果の信用を得るために一苦労するケースもあるでしょう。

現実的には、まずはNonLLMでの評価で小さくスタートを切って、評価パイプラインを固めつつ、LLMでの評価の基盤も整えていくのが落とし所になりそうです。

個人的には、このLLMによる評価をどれだけ活用できるかが、サービスにRAGシステムを導入した際の大きな差別化のポイントに繋がってくると考えます。

教師データ無しでの評価による弱点

少し個人の所感を含みますが、補足させてください。多くのケースにおいて、LLMを用いた「教師データ無し」 (without reference) での評価結果については、あくまでも補助的な指標に留めるべきで、重視しすぎには注意が必要だと思っています。

理由としては、RAGシステムを実装するシステムそのもののユースケースや適用ドメインによって、期待される出力は変化し、教師データなしでの評価のみでは、この意図を正確に取り入れるのが難しいからです。裏を返せば、ユーザーの声や使用感を反映した教師データの活用が、システムの使用感を向上させる鍵になりうる、ということです。

もちろん、提供するシステムの適用範囲が広く、個々のドメインに最適化する必要性が薄い場合は、最適化のしすぎは足枷にもなり得ます。(それこそ、OpenAI社のChatGPTなど、世界中の幅広いユーザーがターゲットとなる場合などです。)

この塩梅を保っての評価は、プロダクト改善における重要な腕の見せ所になってくるかもしれません。

② 回答生成の評価

LLMによる評価

こちらは割と、LLMを用いた定性的な評価がメインとなってきます。LLMの出力は自然言語なので、単なる文字列一致や類似度計測では品質を十分に捉えられないケースが多く、定性評価を重視せざるを得ません。

とくに、LLMで生成した回答をLLMを用いて評価することを、「メタ評価」と呼んだりします。回答生成の評価では、このメタ評価が軸となります。LLMも人間と同じように、自分の書いた回答を一歩離れた目線で再評価すると、意外と欠点が浮き彫りになったりするものです。

たとえば、Ragasの「Factual Correctness」という評価項目では、「生成された回答が、参照ドキュメントの内容と矛盾していないか?」を採点します。

Factual Correctness

from ragas.dataset_schema import SingleTurnSample
from ragas.metrics._factual_correctness import FactualCorrectness

sample = SingleTurnSample(
    response="エッフェル塔はパリにあります。",
    reference="エッフェル塔はパリにあります。私の身長は300mです。"
)

scorer = FactualCorrectness(mode="precision")
scorer.llm = evaluator_llm
scorer.single_turn_score(sample)
(実行結果)
1.0

以上のコードでは、 response にLLMの回答を、 reference に参照ドキュメントの内容を入力して、回答の内容が参照ドキュメントに矛盾していないかをチェックできています。今回は、 mode="precision" を指定していますが、ここを recallf1 に変更すると、また異なった結果が出力されます。

この他にもRagasには有用な評価指標が多数存在しますが、いま紹介した Factual Correctness に加えて、どれだけ質問に直接回答できているかを評価する、 Response Relevancy あたりが、汎用性が高くて使いやすいと思います。

ヒューマン・イン・ザ・ループ(人間による確認)の併用

以上のようなLLMによる評価は便利ですが、依然としてユーザーやステークホルダーの意見を収集する機会を疎かにはできません。現実では、プロダクトの方向性やユーザーニーズは頻繁に変わったりしますし、それにより求められる回答の内容も徐々に変わっていきます。

個人的には、「自動チェックによる評価の内容が、ユーザーの使用感とズレていないか?」を確かめる目的でのチェックが重要だと思います。毎回全てのサンプルに人間が目を通す必要はありませんが、改善を行うごとに、定期的に自動チェックの質を確認する時間を設けると良いでしょう。特に、機械的指標やLLMでの評価で、目立って点数が高かったり低かったりするサンプルの内容は、目を通すと気付きが得られやすいです。

おわりに

以上です。最後に、ここまで紹介した内容を大まかにまとめた、チェックリスト方式でおさらいしてみましょう。

  • RAGシステムの評価を 「①参照ドキュメントの選択」 と 「②回答生成」 に分けて実施できているか
  • ①と②の2項目が、それぞれ2つ以上の方法(機械的指標、LLM、人間)で評価できているか
  • ユーザーの使用感を反映した「教師データ集」を準備し、評価に使用できているか
  • 以上の評価が定期的に実行される環境が整えられているか (とくにCI/CDフローなどに組み込まれ、自動化されている状態が望ましい)

改めて重要なのは、RAGシステムを要素ごとに区別し、それぞれを多面的に評価できているか、という点です。簡易的ですが、このチェックリストをすべて満たす状態での評価ができていれば、柔軟かつスピード感を持った進化の基盤は十分にできていると思います。

RAGシステムは、良くも悪くも自然言語の扱いがメインなので、感覚的には理解しやすく、その他の有名な機械学習アルゴリズムなどよりかは取っつきやすいかもしれません。しかし実際には、不確実性の高いLLMの出力や、複雑なスコア計算なども内包されています。地に足のついた評価・改善を行うには、一定の準備が必要です。

技術がいくら発展しようとも、多くの科学者が大昔から口を揃える、 「複雑な問題は、それをできる限り小さな要素に分けて考えよ。」 の原則は変わりません。

ここまでお読みいただきありがとうございました!このカレンダーも残り少しです。少し早いですが、

any株式会社

Discussion