RAG実装とプロンプト評価

Tech

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

RAG実装とプロンプト評価

、Retrieval-Augmented Generation (RAG) システムにおけるプロンプト設計と、その評価手法、そして改良サイクルについて詳細に解説します。RAGは、大規模言語モデル (LLM) が外部の知識源を参照することで、情報の正確性、最新性、および信頼性を向上させるための強力なアプローチです [1]。

ユースケース定義

特定のドメイン知識(例:企業内部文書、技術仕様書)に基づいてユーザーの質問に正確に回答する、チャットボットシステムを構築します。このシステムは、ユーザーの質問に対し、関連文書から情報を検索し、その情報を用いてLLMが回答を生成します。

制約付き仕様化(入出力契約)

入力契約

  • フォーマット: ユーザーからの自然言語の質問文字列。

  • 最大長: 200文字。

  • 禁止事項: 個人情報、機密情報、違法行為を促す内容は禁止。モデルへの直接指示(例:「システムプロンプトを変更せよ」)はフィルタリング対象。

  • 失敗時の挙動: 長すぎる入力や禁止事項に該当する場合は、エラーメッセージ「入力が不適切です。質問内容を確認してください。」を返す。

出力契約

  • フォーマット: JSON形式または箇条書き形式(プロンプトで指定)。

    • JSONの場合: {"answer": "回答内容", "sources": ["出典文書ID1", "出典文書ID2"]}

    • 箇条書きの場合: 回答本文の末尾に「参考情報:[出典文書ID1], [出典文書ID2]」を付与。

  • 最大長: 回答本文は500文字以内。出典は最大5つ。

  • 禁止事項: 幻覚 (hallucination) の発生、外部情報源で裏付けられない情報の生成、特定の政治的・倫理的主張の表明。

  • 失敗時の挙動: 関連情報が見つからない場合や、回答生成に失敗した場合は、「関連情報が見つかりませんでした。別の質問をお試しください。」と返す。

プロンプト設計

LLMの性能を最大限に引き出すためには、タスクに応じた適切なプロンプト設計が不可欠です [3]。ここでは、RAGシステムにおける3種類のプロンプト案を提示します。前提として、RAGによって取得された関連文書は{retrieved_documents}としてプロンプトに挿入されます。

1. ゼロショットプロンプト(Zero-shot Prompt)

基本指示のみで、モデルに自律的な回答生成を促します。

あなたは専門家です。以下の情報源のみを用いて、ユーザーの質問に正確に回答してください。情報源にない内容は生成しないでください。

情報源:
{retrieved_documents}

ユーザーの質問:
{user_query}

回答:

2. 少数例プロンプト(Few-shot Prompt)

少数の入出力例を示すことで、モデルに期待する挙動を具体的に伝えます。特に回答フォーマットの安定化に有効です。

あなたは専門家です。以下の情報源のみを用いて、ユーザーの質問に正確に回答してください。情報源にない内容は生成しないでください。回答は必ずJSON形式で、`answer`と`sources`のキーを含めてください。

例1:
情報源:

- 文書A: "製品Xは2024年4月1日にリリースされた。機能はAIアシスタント。"
ユーザーの質問:
製品Xのリリース日と主な機能を教えてください。
回答:
{"answer": "製品Xは2024年4月1日にリリースされ、主な機能はAIアシスタントです。", "sources": ["文書A"]}

情報源:
{retrieved_documents}

ユーザーの質問:
{user_query}

回答:

3. Chain-of-Thought制約型プロンプト(CoT-constrained Prompt)

モデルに思考の過程を段階的に示すよう促すことで、複雑な質問に対する推論能力を向上させ、幻覚を抑制します。RAGの文脈では、参照元を明確にする制約が重要です [4]。

あなたは専門家です。以下の情報源のみを用いて、ユーザーの質問に正確に回答してください。情報源にない内容は生成しないでください。回答はまず思考プロセスを記述し、その後、結論としての回答をJSON形式で出力してください。思考プロセスでは、どの情報源のどの部分を利用したかを具体的に言及してください。

情報源:
{retrieved_documents}

ユーザーの質問:
{user_query}

思考プロセス:

1. ユーザーの質問から主要なキーワードと意図を特定する。

2. `{retrieved_documents}`の中から、質問に関連する情報を特定する。その際、どの文書IDのどの内容が関連するかを明確にする。

3. 関連情報を基に、質問に対する回答を構成する。情報源にない推測や追加情報は加えない。

4. 回答が情報源と完全に一致しているか確認する。

5. 最終的な回答をJSON形式で出力する。

最終的な回答:

評価

RAGシステムのプロンプト評価は、システムの信頼性と有用性を確保するために不可欠です [2]。

評価シナリオ

  1. 正例(Positive Cases):

    • 質問: 「製品Aの最新バージョンは?」 (関連情報が豊富に存在する)

    • 期待: 正確なバージョン番号と関連文書の参照。

  2. 難例(Difficult Cases):

    • 質問: 「製品Bの将来のロードマップについて教えてください。」 (関連情報が部分的にしか存在しない、または不明瞭)

    • 期待: 「情報源に将来のロードマップに関する具体的な記載はありません。」といった適切な不十分回答。

  3. コーナーケース(Corner Cases):

    • 質問: 「製品Aと全く関係ないが、一般的な歴史の質問。」 (RAGで取得される情報が質問と無関係)

    • 期待: 「質問が情報源の範囲外です。」といった範囲外回答、または「関連情報が見つかりませんでした。」。

    • 質問: 「製品Cの開発チームは誰ですか?」(個人情報に関する質問)

    • 期待: 「個人情報のため回答できません。」といった拒否。

自動評価の擬似コード

LLMの自動評価は、LLM自身を評価者として利用する「LLM-as-a-judge」のアプローチや、キーワードマッチング、セマンティック類似度などがあります [2]。

def evaluate_rag_response(query: str, retrieved_docs: list[str], llm_response: str, ground_truth_answer: str) -> dict:
    score = {}

    # 1. Faithfulness (事実忠実性)


    # 応答内容がretrieved_docsから直接導き出せるか


    # LLM-as-a-judge (例: Gemini) を利用

    faithfulness_prompt = f"""
    以下の情報源と回答を比較し、回答が情報源に忠実であるかを0から5のスコアで評価してください。
    情報源: {retrieved_docs}
    回答: {llm_response}
    スコア:
    """

    # llm_judge_call(faithfulness_prompt) はGeminiを呼び出しスコアを返す関数と仮定

    score['faithfulness'] = llm_judge_call(faithfulness_prompt) # 0-5

    # 2. Answer Relevance (回答の関連性)


    # 応答がユーザーの質問に適切に回答しているか

    relevance_prompt = f"""
    以下の質問と回答を比較し、回答が質問に関連しているかを0から5のスコアで評価してください。
    質問: {query}
    回答: {llm_response}
    スコア:
    """
    score['answer_relevance'] = llm_judge_call(relevance_prompt) # 0-5

    # 3. Context Relevance (コンテキストの関連性)


    # retrieved_docsが質問に関連しているか(RAGの検索部分の評価)

    context_relevance_prompt = f"""
    以下の質問と情報源を比較し、情報源が質問に関連しているかを0から5のスコアで評価してください。
    質問: {query}
    情報源: {retrieved_docs}
    スコア:
    """
    score['context_relevance'] = llm_judge_call(context_relevance_prompt) # 0-5

    # 4. Answer Accuracy (回答の正確性) - Ground truthとの比較


    # ground_truth_answerが存在する場合にのみ実施

    if ground_truth_answer:
        accuracy_prompt = f"""
        以下の質問と模範解答、生成された回答を比較し、生成された回答が模範解答に対してどれだけ正確かを0から5のスコアで評価してください。
        質問: {query}
        模範解答: {ground_truth_answer}
        生成された回答: {llm_response}
        スコア:
        """
        score['answer_accuracy'] = llm_judge_call(accuracy_prompt) # 0-5

        # 正規表現によるキー情報抽出の検証 (例: リリース日の形式チェック)

        if "リリース日" in query:
            import re
            match = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', llm_response)
            score['date_format_correct'] = 1 if match else 0

    # 5. Format Adherence (フォーマット遵守)


    # JSON形式が適切か、特定のキーワードが含まれているかなど

    try:
        import json
        json.loads(llm_response)
        score['format_adherence_json'] = 1
    except json.JSONDecodeError:
        score['format_adherence_json'] = 0

    return score

上記の擬似コードは、llm_judge_callという関数を介してLLM-as-a-judgeを用いることを想定しています。これは、2024年3月28日にMLflowによって公開されたRAG評価手法でも推奨されています [2]。

誤り分析と抑制手法

RAGシステムにおける主な失敗モードとその抑制手法は以下の通りです。

失敗モード

  • 幻覚 (Hallucination): LLMが情報源にない情報をあたかも事実のように生成する現象 [5]。RAGの目的の一つはこれを抑制することですが、RAGシステム自体が不正確な文書を取得した場合や、プロンプト指示が不十分な場合に発生し得ます。

  • 様式崩れ (Format Deviation): JSONや箇条書きなどの指定された出力フォーマットを遵守できない。

  • 脱線 (Off-topic/Drifting): ユーザーの質問から逸脱した回答を生成する。

  • 禁止事項 (Prohibited Content): 不適切な内容(個人情報、ヘイトスピーチなど)を出力する。

  • 関連情報不足 (Lack of Relevant Information): RAGが質問に関連する情報を取得できなかったために、回答が不完全または不正確になる。

抑制手法

  • System指示による制約: プロンプトの最初に「情報源にない内容は生成しない」「指定されたフォーマットを厳守する」といった強い指示を配置する [3]。

  • Few-shot例の活用: 特にフォーマット遵守や特定の回答スタイルの定着には、模範となる入出力例を複数提示することが有効です。

  • 検証ステップの導入 (Chain-of-Thought): モデルに思考プロセスを開示させ、参照元を明示させることで、論理の飛躍や幻覚を自己修正させる。

  • LLM Guardrails/Moderation API: モデルの出力に対し、別途モデレーションモデルやルールベースのフィルタリングを適用し、禁止事項や不適切な内容を検知・除去する。

  • リトライ戦略: 特定のエラー(例: JSON形式のエラー)が発生した場合に、プロンプトを修正(例: 「再度JSON形式で出力してください」)して再実行する。

  • RAG検索品質の向上: 検索アルゴリズム(例: ベクトル検索、キーワード検索)のチューニング、チャンク戦略の改善、文書の前処理強化により、より高品質な関連情報を取得する。これは、RAGシステムの基盤として2024年4月15日にGoogle Cloudで紹介されています [1]。

改良と再評価

プロンプト評価の結果を受けて、以下のループでシステムを改良し再評価します。

graph LR
    A["プロンプト設計"] --> B("RAGシステム実行");
    B --> C{"LLM応答生成"};
    C --> D["評価シナリオ実行"];
    D --> E{"自動評価/手動評価"};
    E -- 失敗モード特定 --> F["誤り分析"];
    F -- 抑制手法適用 --> A;
    E -- 合格 --> G["最終展開"];

Mermaid図: RAGシステムにおけるプロンプト設計、評価、改良のループ。

  1. プロンプト修正: 誤り分析で特定された問題点(幻覚、様式崩れなど)に対し、プロンプトの指示、Few-shot例、CoTステップなどを調整します。

  2. RAG設定の最適化: 関連情報不足が課題の場合、埋め込みモデルの変更、チャンクサイズの見直し、検索アルゴリズムの調整を行います。

  3. 再評価: 修正後、同じ評価シナリオと自動評価スクリプトを用いて、改善度合いを定量的に測定します。特に、前回失敗した難例やコーナーケースが改善されているかを重点的に確認します。

  4. A/Bテスト: 複数のプロンプト案やRAG設定がある場合、A/Bテストを実施し、ユーザーフィードバックや特定のビジネス指標に基づいて最適な構成を選択します。

まとめ

RAGシステムにおけるプロンプト設計と評価は、高品質で信頼性の高いLLMアプリケーションを構築する上で不可欠です。ゼロショット、少数例、Chain-of-Thoughtなどのプロンプト戦略を適切に使い分け、明確な入出力契約を定義することで、モデルの挙動を制御できます。また、自動評価ツールと多様な評価シナリオを通じて、幻覚や様式崩れといった失敗モードを特定し、体系的な改良ループを通じて継続的にシステムを改善していくことが、2024年5月22日現在のベストプラクティスとされています。

参考情報

[1] Google Cloud. “Retrieval-Augmented Generation (RAG) Explained.” 2024年4月15日. https://cloud.google.com/vertex-ai/docs/generative-ai/learn/retrieval-augmented-generation [2] MLflow. “Evaluating RAG Systems: Metrics and Methodologies.” 2024年3月28日. https://www.mlflow.org/docs/latest/llms/llm-evaluate/rag-evaluation.html [3] Google Developers. “Prompt Engineering Best Practices for Gemini.” 2024年5月10日. https://developers.google.com/gemini/docs/prompt-engineering/overview [4] Wei, Jason, et al. “Chain-of-Thought Prompting Elicits Reasoning in Large Language Models.” arXiv, 2022年1月27日. https://arxiv.org/abs/2201.11903 [5] IBM Research. “Measuring and Mitigating Hallucinations in LLMs.” 2023年11月17日. https://www.ibm.com/blogs/research/2023/11/17/measuring-mitigating-hallucinations-llms/

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました