RAG評価フレームワーク「Ragas」の紹介

x facebook hatena

こんにちは、ARISE analyticsの和久田です。

私は業務でカスタマーサポート向けのAIエージェントの開発に携わっており、特にRAG部分の精度向上に取り組んでいます。その過程で、RAG評価フレームワークである「Ragas」を知りました。

本記事では、私が担当しているプロジェクトにRagasを導入した経験をもとに、Ragasの特徴や、実務で利用する際に気を付けるべきポイントについて紹介します。

 はじめに:RAGとは

近年、生成AIの企業導入が加速する中で、RAG(Retrieval-Augmented Generation:検索拡張生成)は注目される技術の1つとなっています。

RAGは、LLMによるテキスト生成(Generation)に外部情報の検索(Retrieve)を組み合わせて回答精度を高める技術です。ユーザーの質問に対して、関連情報を検索し、その情報をプロンプトに埋め込み、回答を生成します。これにより、LLMに知識がなくても外部の正確な情報を基に回答できます。

techblog_20260313_1

RAGにおける評価の重要性

RAGは、LLMのハルシネーションを抑制するために導入される技術です。しかし、RAGを導入しただけでハルシネーションが完全に解決されるわけではありません。RAGで検索された内容が適切な情報でなければ、結果としてハルシネーションが発生してしまいます。また、適切な情報が検索できたとしても、LLMがその情報を適切に扱えなければ、質問に対して不適切な回答をしてしまう可能性があります。

このような不適切な回答は、実務における信頼性の低下や法的・倫理的リスクの増大、さらには社会的な混乱を招くおそれがあります。したがって実務では、ハルシネーションの少ない高性能なRAGが求められており、その性能を客観的に測定・評価することが重要です。

 RAG評価の観点と手法 

評価観点

RAG評価観点は、大きく次の2つの軸があります。

  • 検索:入力に対して「正しく検索できているか」を評価する
  • 生成:検索された情報を基に「適切に回答を生成できているか」を評価する

これらをより具体化すると、次のような評価観点に分解できます。

  • 検索
    • 質問に対してどの程度正しい情報が検索できているか
    • 回答に必要な情報がどの程度網羅的に検索できているか
  • 生成
    • 回答内容は検索された情報にどれだけ忠実か
    • 検索されていない情報を回答にどの程度含めてしまっているか
    • 回答内容はどの程度正確か
    • 回答内容は質問内容とどの程度関連しているか

ここで挙げたもの以外にも、ユースケースに応じて様々な評価観点が存在します。

手動評価と自動評価

上記の評価指標を人間が評価しようとすると、

  • 評価者ごとに「正しさ」の基準がブレてしまう
  • 評価に膨大な時間がかかってしまう

といった問題が発生します。

(参考:実際にプロジェクトで人手による評価を実施した際、1件のテストケースを先ほどの6つの評価観点で評価するのに約1時間かかりました。10件のテストケースに対しては、単純計算で10時間かかることになります。)

この課題を解決するために、BLEUやROUGEといった統計的手法や、LLMによる評価(LLM-as-a-judge)といった自動評価手法が存在します。

BLEUなどの統計的手法は、RAG評価で使用されることはありますが、文脈を正確に捉えた評価としては限界があります。一方、LLMによる評価では、BLEUなどに比べて文脈を捉えたより正確な評価が可能です。

本記事では、LLMによるRAG評価が可能なフレームワークである「Ragas」について紹介していきます。

 RAG評価フレームワーク「Ragas」の概要 

Ragas」は、現在広く利用されているRAGの自動評価が可能なオープンソースのフレームワークです。主な特徴は次です。

  • 評価指標の網羅性:先述したRAG評価における評価観点も含めて、様々な評価観点を網羅しています
  • 評価の透明性:LLMによる評価時の判断根拠が取得可能です

先述した評価観点は、Ragasではそれぞれ次の評価指標として提供されています。

観点のカテゴリ 評価観点 Ragasで提供されている評価指標
 検索  質問に対してどのくらい正しい情報が検索できたか  Context Precision 
 検索  回答に必要な情報がどのくらい網羅的に検索できたか  Context Recall 
 生成  回答内容は検索された情報に忠実か  Faithfulness 
 生成  検索されていない情報を回答に含めていないか  Noise Sensitivity 
 生成  回答内容は正確か  Answer Correctness 
 生成   回答内容は質問内容と関連するか   Answer Relevancy 

 ※公式ドキュメントの情報が古かったり、バージョンによって記載内容が異なることがあります。最新バージョンである0.4.xで使用可能な評価指標はこちらに整理されています。 

 RagasによるRAG評価の流れ 

ここからは、Ragasを使ってRAGを評価する流れを実装例とともに解説し、Ragasが内部でどのように判断してスコアを出しているかを理由付きで詳しく見ていきます。

今回は、au公式HPの情報を登録したシンプルなRAGシステムを用意しました。
このRAGシステムに対して、検索の評価指標であるContext PrecisionContext Recallを用いてRagasによる自動評価を行います。

評価指標の説明

まず、Ragasの評価に必要なデータを整理します。 

user_input  ユーザーがRAGシステムに入力する質問文 
context  LLMが回答生成に使用する情報 
response  user_inputに対して、LLMが生成した回答 
reference  user_inputに対する回答の正解データ 

次に、Context PrecisionとContext Recallを説明します。

 Context Precision

評価内容  user_inputに対して有用なcontextが上位に検索できているか 
計算方法

1.LLMが、各contextがreferenceと関連するかを判定する

2.(関連あるcontextのprecision@kの合計) / (関連あるcontextの数)を計算する

入出力データ

・入力データ:user_input、context、reference

・出力データ:0~1。1に近いほど良い

Context Recall

評価内容  responseを生成するのに必要な情報が、検索されたcontextにどれだけ含まれているか 
計算方法

1.LLMが、referenceを主張ごとに分解する

2.LLMが、各主張がcontextに含まれているかを判定する

3.(contextに含まれる主張の数) / (主張の合計数)を計算する

入出力データ 

・入力データ:user_input、context、reference 

・出力データ:0~1。1に近いほど良い

 今回は、Context Precisionの計算方法1ステップ目と、Context Recallの計算方法2ステップ目のLLM判定結果を判定理由付きで詳細に確認します。

評価用テストケース

評価用テストケースは次を使用します。

テストケースNo. 質問内容 備考
1 au PAYの一時停止の操作方法を知りたい  ベクトルDBに関連情報が存在する質問 
2  Pontaポイントの概要   ベクトルDBに関連情報が存在しない質問 

 ベクトルDBに登録するデータはau公式HPにある次のページとします。 

 テストケースNo.    質問内容   備考 
1 au PAY/au PAYプリペイドカードの一時停止の操作方法に関するFAQ  https://www.au.com/support/faq/details/00/0000/000024/pg00002424/  
2 au PAYの利用上限額に関するFAQ  https://www.au.com/support/faq/details/00/0000/000002/pg00000236/  
3 au PAYプリペイドカードが利用可能なお店に関するFAQ  https://www.au.com/support/faq/details/00/0000/000001/pg00000123/  
4 au PAYプリペイドカード利用時の注意点に関するFAQ  https://www.au.com/support/faq/details/00/0000/000002/pg00000232/  
5 au PAYプリペイドカードとau PAYの違いに関するFAQ https://www.au.com/support/faq/details/00/0000/000002/pg00000275/  

(登録データは、テキスト化したものを固定文字数でチャンキングしてベクトルDBに登録します)
正解データは、au公式HPの「よくある質問」の内容を参考に作成しました。


評価コードの実装例 

今回はバージョン0.4.3で実装します。バージョンによって仕様が異なるため注意してください。
まず、Ragasで評価を実施するための評価用データセットをcsvファイル形式で作成します。

user_input reference
Pontaポイントの概要 

Pontaポイントについてですね。

Pontaポイントは全国のPonta提携店やネットサービスで、ご利用金額に応じて「ためる」・「つかう」ことができる共通ポイントです。

Pontaポイントの貯め方、使い方などの詳細は以下のページをご確認ください。

▽Pontaポイント

https://kddi-l.jp/qNm?openExternalBrowser=1

※ポイントの加算/反映はサービスによってお時間がかかる場合があります

また、au IDとPonta会員IDを連携することで、ポイントを利用できる場所が広がります。
au IDとPonta会員IDの連携については、以下のページをご確認ください。

▽au IDとPonta会員IDを連携したい

https://kddi-l.jp/bjp?openExternalBrowser=1

au PAYの一時停止の操作方法を知りたい

au PAY(コード支払い)の一時停止/一時停止解除手順についてですね。

一時停止/一時停止解除は、au PAY サイトからお手続きができます。

■操作手順
①「au PAY利用設定」ページにアクセスし、au IDでログイン
②「au PAY」のスイッチを押下し、一時停止/一時停止解除を切り替え
③「設定」を選択

▽au PAY 利用設定

https://aupay.auone.jp/menu/lock_set.html?state=confirm&openExternalBrowser=1

※ご注意事項※
・一時停止にする場合はスイッチをオフ(灰色)、解除する場合はオン(緑色)にしてください
・「au PAY」を停止にした場合、au PAY プリペイドカードもご利用できなくなります

 このcsvファイルをdatasetsフォルダ配下に格納し、読み込みます。 

from ragas import Dataset
# csvファイルの読み込み
dataset_loaded = Dataset.load(
    name="{csvファイル名}",
    backend="local/csv",
    root_dir="{datasetsフォルダからのパス}",
)
    

 LLM評価器を設定します。今回は評価者LLMにGPT-5.1を使用します。 

from dotenv import load_dotenv
from metrics_with_reason import ContextPrecisionWithReason, ContextRecallWithReason
from openai import AsyncOpenAI
from ragas.llms import llm_factory
# 環境変数の読み込み
load_dotenv()
# 評価者LLMの設定
client = AsyncOpenAI()
llm = llm_factory("gpt-5.1", client=client)
# Ragasの潜在的なバグがあり、モデル名に"."が含まれている場合は
# max_tokens → max_completion_tokensへの変換を手動で行う必要がある
llm.model_args["max_completion_tokens"] = llm.model_args.pop("max_tokens", 1024)
llm.model_args["temperature"] = 0.0
# 評価指標の設定
precision_metric = ContextPrecisionWithReason(llm=llm)
recall_metric = ContextRecallWithReason(llm=llm)
    

RagasでContext PrecisionとContext Recallを算出する際、内部で評価理由を取得していますが出力されていません。そのため、Ragasのメソッドをオーバーライドして評価値を出力するよう修正します。

class ContextPrecisionWithReason(ContextPrecision):
    async def ascore(self, user_input, reference, retrieved_contexts) -> MetricResult:
        #######################
        # Ragasの既存の処理
        #######################
        for idx, context in enumerate(retrieved_contexts):
            input_data = ContextPrecisionInput(
                question=user_input, context=context, answer=reference
            )
            prompt_string = self.prompt.to_string(input_data)
            result = await self.llm.agenerate(prompt_string, ContextPrecisionOutput)
            verdicts.append(result.verdict)

            # context_index, verdict, reasonを出力するよう追加実装
            items.append(
                {
                    "context_index": idx,
                    "verdict": result.verdict,
                    "reason": result.reason,
                }
            )
            
        score = self._calculate_average_precision(verdicts)
        reason_json = json.dumps(items, ensure_ascii=False)
        return MetricResult(value=float(score), reason=reason_json)


class ContextRecallWithReason(ContextRecall):
    async def ascore(self, user_input, retrieved_contexts, reference) -> MetricResult:
        #######################
        # Ragasの既存の処理
        #######################
        attributions = [c.attributed for c in result.classifications]
        score = sum(attributions) / len(attributions) if attributions else np.nan

        # statement, attributed, reasonを出力するよう追加実装
        items = [
            {
                "statement": c.statement,
                "attributed": c.attributed,
                "reason": c.reason,
            }
            for c in result.classifications
        ]
        reason_json = json.dumps(items, ensure_ascii=False)
        return MetricResult(value=float(score), reason=reason_json)

    

 RAGシステムを実装します。FAISSインデックスが作成されている前提のコードになります。 

class RAGSystem:
    def __init__(self, index_dir: str = "faiss_index"):
        self.index_dir = index_dir
        self.embeddings = OpenAIEmbeddings()
        self.vectorstore = FAISS.load_local(
            self.index_dir,
            self.embeddings,
            allow_dangerous_deserialization=True,
        )

        self.llm = ChatOpenAI(model="gpt-4.1", temperature=0)
        # ベクトル検索結果を受け取り回答生成を行うチェーンの実装
        template = """以下のコンテキスト情報を基に質問に答えてください。
コンテキスト情報: {context}
質問: {question}
回答:"""
        prompt = ChatPromptTemplate.from_template(template)
        self._prompt_llm_chain = prompt | self.llm

    # RAGの実行
    def query(self, query):
        # ベクトル検索(検索件数は3件)
        source_documents = self.vectorstore.similarity_search_with_score(query, k=3)
        retrieved_contexts = [doc.page_content for doc, _ in source_documents]
        context = "\n\n".join(retrieved_contexts)
        # 回答生成
        result = self._prompt_llm_chain.invoke({"context": context, "question": query})
        answer = result.content

        return answer, retrieved_contexts
    

 評価を実行するための関数を定義し、評価を実行します。

from pydantic import BaseModel

# 自前のRAGシステムをインポート
from rag_system import RAGSystem

rag_system = RAGSystem()

# 評価結果の型定義
# ここで定義した項目をカラム名としたcsvファイルが自動で出力される
class EvalResult(BaseModel):
    user_input: str
    reference: str
    context_precision_value: float
    context_precision_reason: Optional[str] = None
    context_recall_value: float
    context_recall_reason: Optional[str] = None

# 評価実行関数の定義
@experiment(EvalResult)
async def run_evaluation(row):
    response, retrieved_contexts = await asyncio.to_thread(
        rag_system.query, row["user_input"]
    )
    precision_result = await precision_metric.ascore(
        user_input=row["user_input"],
        retrieved_contexts=retrieved_contexts,
        reference=row["reference"],
    )
    recall_result = await recall_metric.ascore(
        user_input=row["user_input"],
        retrieved_contexts=retrieved_contexts,
        reference=row["reference"],
    )
    return EvalResult(
        **row,
        context_precision_value=precision_result.value,
        context_precision_reason=precision_result.reason,
        context_recall_value=recall_result.value,
        context_recall_reason=recall_result.reason,
    )

# 評価の実行
await run_evaluation.arun(
    dataset_loaded, name=f"{datetime.now().strftime('%Y%m%d%H%M%S')}"
)
    

評価結果

各質問内容に対して次のような結果になりました。 

テストケースNo. 質問内容 Context Precision Context Recall
1  au PAYの一時停止の操作方法を知りたい   1.00  0.83
2  Pontaポイントの概要   0.00  0.00

テストケース1は、ベクトルDBに関連した情報が存在するためContext Precision、Context Recallともに最大値である1.00に近い値になっており、良い結果が得られています。

テストケース2は、ベクトルDBに関連した情報が存在しないためContext PrecisionとContext Recallがそれぞれ0.00になっています。

以下では、テストケース1に対してRagasでどのような評価が行われたか詳しく見ていきます。

ケース1 評価結果の詳細

Context Precisionの評価内

Context Precisionでは、user_input、context、referenceを確認して、「contextがuser_inputに対して有用か」を判断していきます。

下表はRagasが有用か判断した結果(理由付き)です。

No. context(最初の100字) user_inputに対して有用か Ragasが出力した判断理由
1  一時停止中は、au PAY 残高がもらえるキャンペーンの特典は受け取れなくなります。特典をお受け取りになった後に手続きください。
手順
目安時間:5分
ステップ数:4
ご準備ください
au ID/パスワード… 
1


コンテキストは、au PAYの一時停止と一時停止解除の正確な手順を説明しており、「au PAY利用設定」ページへのアクセス、au IDでのログイン、スイッチの切り替え、設定ボタンの確認、オン(緑色)とオフ(灰色)の状態についても詳述している。回答はこれらの手順と詳細を直接使用しているため、コンテキストは明らかに回答を導くのに有用だった。

2  【au PAY/au PAY プリペイドカード】利用を一時停止したい/一時停止を解除したい
au PAY アプリでの手続き方法
【au PAY/au PAY プリペイドカード】利用を一時停止したい/一時停止を解除したい
au PAY アプリのアカウント画面で、一時停止/解除のお手続きができます。… 
1  コンテキストは、「au PAY利用設定」ページへのアクセス、au IDでのログイン、スイッチの切り替え、スイッチの色の意味など、au PAYの一時停止と再開の手順を明確に説明している。回答はこれらの手順と詳細を直接使用しているため、コンテキストは明らかに回答を導くのに有用だった。 
3  【au PAY】利用上限額はいくらですか?
au PAY(コード支払い/ネット支払い/請求書支払い)
【au PAY】利用上限額はいくらですか?
au PAY(コード支払い/ネット支払い/請求書支払い)の利用上限額は、… 
0  コンテキストはau PAYとau PAYプリペイドカードの利用上限額のみを説明しており、一時停止の手順や方法については一切言及していない。提供された回答にある具体的な一時停止/解除の操作手順は、このコンテキストから導けない。 

 Context Precisionは、関連ないcontextが関連あるcontextよりも上位に検索されると評価値が下がります。今回のケースでは、関連ないcontextが3位、関連あるcontextが1位・2位のため評価値は下がりません。 

Context Recallの評価内容

Context Recallでは、referenceを「主張」という細かい文章に区切り、「主張がcontextに含まれているか」を判断していきます。

下表はRagasが含まれているか判断した結果(理由付き)です。

主張 主張がcontextに含まれているか Ragasが出力した判断理由

 au PAY(コード支払い)の一時停止/一時停止解除手順についてですね。 

1  コンテキストは、コード支払いを含むau PAYの一時停止と再開方法を説明するヘルプ記事であるため、この導入文はコンテキストと一致しており、コンテキストに基づいている。 
 一時停止/一時停止解除は、au PAY サイトからお手続きができます。  1  コンテキストには、au PAYサイト(「au PAY利用設定」ページ)で一時停止または解除の手続きができることが明示されており、この文と一致する。 
 ■操作手順  1  これは手順を紹介する見出しであり、コンテキストも手順として提示しているため、一貫性があり、コンテキストに基づいている。 
 ①「au PAY利用設定」ページにアクセスし、au IDでログイン  1 コンテキストには「「au PAY 利用設定」ページにアクセスし、au IDでログインします。」と記載されており、この手順と一致する。
 ②「au PAY」のスイッチを押下し、一時停止/一時停止解除を切り替え  1 コンテキストには、同じページで[au PAY]または[プリペイドカード]のスイッチをタップして一時停止と解除を切り替えることができると説明されており、この手順に対応する。 
 ③「設定」を選択  1 コンテキストには、スイッチの状態を確認して[設定]をタップするよう指示されており、この手順と一致する。 
 ▽au PAY 利用設定  1  これはau PAY設定ページのリンクのラベルであり、コンテキストにも「au PAY 利用設定」ページとして言及されている。 
   1 これはリンクの前に付ける装飾記号であり、コンテキストを超える事実的な内容を追加していない。 
 https://aupay.auone.jp/menu/lock_set.html?state=confirm&openExternalBrowser=1   0 コンテキストには「au PAY 利用設定」ページが存在し、「こちら」と記載されているが、この具体的なURLは提供されていないため、正確なリンクはコンテキストに基づいていない。 
 ※ご注意事項※  1 れは注意事項の見出しであり、コンテキストにも注意セクションがあるため、注意見出しの存在は一貫性があり、コンテキストに基づいている。 
・一時停止にする場合はスイッチをオフ(灰色)、解除する場合はオン(緑色)にしてください  1 コンテキストには「スイッチがオン(緑色)の場合は解除、オフ(灰色)の場合は一時停止されます。」と記載されており、この指示と一致する。
・「au PAY」を停止にした場合、au PAY プリペイドカードもご利用できなくなります 0 コンテキストには、一時停止中はau PAY(コード支払い)とau PAYプリペイドカードの両方が利用できなくなると記載されているが、au PAYのみを停止するとプリペイドカードも自動的に利用不可になるという因果関係は明示されていない。

実際に、referenceに記載されているURLはcontextに含まれないため、正しく評価できています。

最後の主張については、人間なら「含まれている」と判断するところですが、Ragasの判定は「含まれていない」でした。
原文では「一時停止中は~」と書かれており、「au PAYの一時停止中である」という前提が明記されていません。そのため、Ragasは「何が一時停止のときの話なのか」を正しく読み取れず、「含まれていない」と判断してしまったと思われます。

また、「≫」という記号単体で主張に分解するなど、主張への分解精度は課題があります。

Ragasを使って見えた『気づきポイント』

 Ragasを実際に利用してみて得られた気づきポイントをまとめます。 


Ragasの評価精度 

Ragasは、人間の評価感覚と概ね近い評価を行えることが確認できました。ベクトルDBに関連情報が含まれる場合は高評価、含まれない場合は低評価となり、直感的に理解しやすい評価結果が得られます。

一方で、主語や前提条件が省略されているなどで情報構造が崩れているケースや、言い回しが少し異なるケースでは、人間の評価とRagasの評価がズレることもありました。
また、「≫」のような記号やURL自体など、人間から見ると意味の薄い要素も1つの主張として評価されるため、違和感のある評価を行う場合があります。

自動評価の実用性と費用対効果

 Context PrecisionとContext RecallをLLMを使わず人手で評価した場合、1テストケースあたり約40分かかっていましたが、Ragasによる自動評価では1~2分程度まで短縮されました。コスト面でも、2ケースを2つの評価指標で評価した場合(GPT-5.1使用)の費用は約5円と低く、十分な費用対効果が得られると考えられます。  

 評価結果の扱い方 

 LLMによる評価であるため、評価のたびに結果がブレる可能性があります。より安定した評価を得るには、複数回評価を実行し、その平均値を取ることを推奨します。
また、評価値だけでなく、Ragasが提供する評価理由も確認し、評価が妥当かどうかを人間がレビューすることが重要です。 

 まとめ 

本記事では、RAG評価フレームワーク「Ragas」について、その概要と具体的な使用例を紹介しました。 Ragasは、RAGの評価作業を大幅に効率化できる有用なフレームワークです。

一方で、RagasはLLMによる自動評価に基づくため、評価結果がブレたり、人間の評価感覚とズレてしまうところもあります。
そのため、自動評価結果をそのまま活用せず、評価値の根拠をしっかり確認したうえで、評価の妥当性を人間がレビューすることが重要です。

 

ご質問・お問い合わせは
こちらよりお送りください
採用
ARISE analyticsとは

PAGE TOP