LLMプロンプト評価指標と改善ループ

Tech

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

LLMプロンプト評価指標と改善ループ

大規模言語モデル(LLM)の活用において、プロンプトの品質はモデルの応答性能を決定づける重要な要素です。本記事では、効果的なLLMプロンプトの設計、評価指標、そして継続的な改善ループについて解説します。

1. ユースケース定義:顧客サポート問い合わせの自動分類と要約

、顧客サポートに寄せられる自由記述の問い合わせ内容を、特定のカテゴリに分類し、かつ簡潔に要約するタスクをユースケースとして定義します。これにより、オペレーターは迅速に問い合わせ内容を把握し、適切な対応を準備できます。

入力例: 「先週購入したスマートフォンの充電器が動作しません。注文番号はABC12345です。交換を希望します。」

期待出力例:

{
  "category": "製品不具合",
  "summary": "注文ABC12345のスマートフォン充電器が動作せず、交換を希望している。",
  "severity": "高"
}

2. 制約付き仕様化:入出力契約と失敗時の挙動

プロンプトとモデル間の明確な契約は、安定したLLMアプリケーションを構築する上で不可欠です。

入力契約

  • フォーマット: 顧客からの自由記述テキスト。最大1000トークン。

  • 前提条件: テキストは日本語であり、個人を特定する機密情報(住所、電話番号、クレジットカード番号など)は含まれないものとする。

出力契約

  • フォーマット: 常にJSON形式で { "category": "...", "summary": "...", "severity": "..." } を出力する。

    • category: 事前に定義されたカテゴリリスト(例: “製品不具合”, “注文関連”, “技術サポート”, “その他”)のいずれか。

    • summary: 元の問い合わせ内容を100字以内で簡潔に要約。

    • severity: “低”, “中”, “高” のいずれか。

  • 失敗時の挙動:

    • JSON形式に従わない場合は空のJSON {} を出力。

    • カテゴリが特定できない場合は "category": "その他" を出力。

    • 要約が困難な場合は "summary": "要約不可" を出力。

禁止事項

  • 顧客からの問い合わせ内容をそのまま出力すること。

  • 問い合わせ内容に存在しない情報を生成すること(幻覚)。

  • モデル自身の意見や判断を付加すること。

  • 出力JSONに指定されたキー以外の情報を追加すること。

3. プロンプト設計:3種のプロンプト案

以下に、顧客サポート問い合わせの分類と要約を行うための異なるアプローチのプロンプト案を提示します。

3.1. ゼロショットプロンプト

モデルが事前知識のみでタスクを実行する最も基本的な形式です。

あなたは顧客サポートアシスタントです。
以下の顧客からの問い合わせを、カテゴリ分類し、100字以内で要約し、重要度(低、中、高)を判定してください。
出力は以下のJSON形式に従い、カテゴリは「製品不具合」「注文関連」「技術サポート」「その他」のいずれかを選んでください。

問い合わせ: {{ユーザーの問い合わせ}}

JSON出力:

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

いくつかの例を示すことで、モデルにタスクの意図と期待される出力形式をより明確に伝えます。

あなたは顧客サポートアシスタントです。
以下の顧客からの問い合わせを、カテゴリ分類し、100字以内で要約し、重要度(低、中、高)を判定してください。
出力は以下のJSON形式に従い、カテゴリは「製品不具合」「注文関連」「技術サポート」「その他」のいずれかを選んでください。

---
問い合わせ: ログインできません。パスワードをリセットしたいのですが、手続きが分かりません。
JSON出力:
{"category": "技術サポート", "summary": "ログインできず、パスワードリセット方法について問い合わせている。", "severity": "中"}
---
問い合わせ: 先日注文した商品の配達が遅れています。追跡番号はXYZ98765です。いつ届きますか?
JSON出力:
{"category": "注文関連", "summary": "注文XYZ98765の商品の配達遅延について状況確認を依頼している。", "severity": "高"}
---
問い合わせ: 新しいキャンペーンについて詳しく知りたいです。
JSON出力:
{"category": "その他", "summary": "新しいキャンペーンについて詳細情報を求めている。", "severity": "低"}
---
問い合わせ: {{ユーザーの問い合わせ}}

JSON出力:

3.3. Chain-of-Thought(CoT)制約型プロンプト

モデルに思考プロセスを段階的に出力させることで、複雑な推論を促し、結果の透明性を高めます。さらに、JSON出力の前に具体的な制約を設けます。

あなたは顧客サポートアシスタントです。
以下の顧客からの問い合わせを、思考プロセスを経て、カテゴリ分類し、100字以内で要約し、重要度(低、中、高)を判定してください。

### 思考プロセス


1. 問い合わせ内容の主要な問題を特定する。

2. その問題がどのカテゴリ(「製品不具合」「注文関連」「技術サポート」「その他」)に最も合致するか判断する。

3. 問い合わせの緊急性や顧客への影響度を考慮し、重要度を決定する。

4. 主要な問題と要求事項を基に、100字以内で簡潔に要約を作成する。

### 制約


- 出力は必ず以下のJSON形式に従ってください。

- カテゴリは定義済みのリストから選択してください。

- 要約は問い合わせ内容に厳密に基づいてください。

- 幻覚を防ぐため、元の情報にない内容は追加しないでください。

問い合わせ: {{ユーザーの問い合わせ}}

思考プロセス:

4. 評価:シナリオと自動評価

プロンプトの性能を客観的に測定するために、多様な評価シナリオと自動評価手法を組み合わせます。

4.1. 評価シナリオ

  • 正例: 明確なカテゴリと内容を持つ、一般的な問い合わせ。

    • 例: 「購入したPCの電源が入りません。修理をお願いしたいです。」
  • 難例: 複数の解釈が可能な、曖昧な問い合わせ。

    • 例: 「なんかよくわからないけど、動きがおかしい。前は大丈夫だったのに。」
  • コーナーケース: 特殊な状況や、想定外の入力。

    • 例: 「御社の製品は最高です!もっと買いたいです!」(分類不要、要約も難しい)

    • 例: 誤字脱字が多い、非常に長い、または非常に短いテキスト。

4.2. 自動評価の擬似コード

自動評価は、事前に定義されたルールや基準に基づいて、モデルの出力がどれだけ期待値に近いかを数値化する手法です。

import json
import re

def evaluate_response(expected_output: dict, actual_output_str: str) -> dict:
    """
    LLMの応答を自動評価する擬似コード。
    """
    score = {"total": 0, "category_match": 0, "summary_length": 0, "severity_match": 0, "json_format": 0}
    feedback = []

    try:
        actual_output = json.loads(actual_output_str)
        score["json_format"] = 1
    except json.JSONDecodeError:
        feedback.append("JSON形式が不正です。")
        return {"score": score, "feedback": feedback}

    # 1. JSON形式のチェック (既に実施)


    # 2. カテゴリの評価

    if actual_output.get("category") == expected_output.get("category"):
        score["category_match"] = 1
    else:
        feedback.append(f"カテゴリ不一致: 期待 '{expected_output.get('category')}', 実際 '{actual_output.get('category')}'")

    # 3. 要約の評価(文字数、キーワードマッチ)

    actual_summary = actual_output.get("summary", "")
    if 0 < len(actual_summary) <= 100:
        score["summary_length"] = 1
    else:
        feedback.append(f"要約の文字数が範囲外です ({len(actual_summary)}字)。")

    # 例: キーワードマッチングによる要約内容の評価 (簡略化)


    # 実際には、セマンティック類似度や別のLLMによる評価がより堅牢

    expected_keywords = expected_output.get("keywords", []) # 事前に定義されたキーワード
    if all(keyword in actual_summary for keyword in expected_keywords):
        score["summary_keyword_match"] = 1
    else:
        feedback.append(f"要約に必須キーワードが含まれていません。")

    # 4. 重要度の評価

    if actual_output.get("severity") == expected_output.get("severity"):
        score["severity_match"] = 1
    else:
        feedback.append(f"重要度不一致: 期待 '{expected_output.get('severity')}', 実際 '{actual_output.get('severity')}'")

    # 総合スコア

    score["total"] = sum(v for k, v in score.items() if k != "total")
    return {"score": score, "feedback": feedback}

# --- 採点ルーブリック例 ---


# 1. JSON形式の準拠: 1点 (必須)


# 2. カテゴリの正確性: 1点


# 3. 要約の文字数 (1-100字): 1点


# 4. 要約のキーワード網羅性 (部分一致): 1点


# 5. 重要度の正確性: 1点


# 合計5点満点

5. 誤り分析と抑制手法

評価を通じて明らかになった失敗モードを分析し、適切な抑制手法を適用します。

5.1. 失敗モード

  • 幻覚(Hallucination): 問い合わせ内容に存在しない情報を生成してしまう。

    • 例: 「充電器が動作しません」という問い合わせに対し、「バッテリーも交換が必要です」と誤って追加する。
  • 様式崩れ(Format Deviation): 指定されたJSON形式に従わない出力。

    • 例: JSONが不完全、キー名が異なる、余計なテキストが含まれる。
  • 脱線(Topic Drifting): タスクの範囲を超えた無関係な情報を出力する。

    • 例: 製品の歴史や会社のビジョンについて語り始める。
  • 禁止事項違反(Prohibited Content): 入出力契約で禁止された内容(例: 問い合わせの原文そのまま出力、個人情報生成)を出力。

5.2. 抑制手法

  • System指示の強化: プロンプトのSystem部分で、モデルの役割、制約、禁止事項を明確かつ簡潔に指示します。特に、幻覚を防ぐために「提供された情報のみに基づいて回答せよ」といった指示が有効です。

  • 検証ステップ(Verification Step): モデルの出力後、別の小規模なモデルやルールベースのコードで出力内容を検証します。

    • 例: JSONスキーマバリデーション、キーワードの有無チェック、要約と元の文章の類似度チェック。
  • リトライ戦略(Retry Strategy): 検証ステップで出力が不正と判断された場合、異なるプロンプト(例: より厳格な制約を追加、失敗例を提示)で再試行する。

    • 例: 「あなたの出力はJSON形式ではありませんでした。再度JSON形式で出力してください。」
  • Few-shotの活用: 具体的な成功例を複数提示し、モデルに正しい出力パターンを学習させます。

  • Chain-of-Thoughtの導入: 推論プロセスを強制することで、誤った結論に至る可能性を減らします。

6. 改良と再評価:継続的な改善ループ

プロンプトの評価と誤り分析の結果に基づき、プロンプトを改良し、再び評価を行うことで、継続的な改善ループを確立します。

graph TD
    A["プロンプト設計"] -->|初期プロンプト| B("モデル実行")
    B -->|モデル応答| C{"評価"}
    C -->|評価結果| D["誤り分析"]
    D -->|洞察と改善案| E["プロンプト改良"]
    E -->|新プロンプト| B
    C -- 正確性低下を検出 --> F["アラートと再分析"]
    F -->|根本原因調査| D

ループのステップ:

  1. プロンプト設計: ゼロショット、少数例、CoTなど、様々な手法を用いてプロンプトを構築します。

  2. モデル実行: 設計したプロンプトをLLMに入力し、出力を生成させます。

  3. 評価: 自動評価ツールや必要に応じて人間によるレビューを用いて、モデルの応答を評価します。ここでは、カテゴリの正確性、要約の品質、JSONフォーマットの準拠などを指標とします。

  4. 誤り分析: 評価で明らかになった失敗モード(幻覚、様式崩れなど)の原因を特定します。特に、自動評価で低いスコアが出た難例やコーナーケースを詳細に分析します。

  5. プロンプト改良: 分析結果に基づき、Systemプロンプトの調整、Few-shot例の追加・修正、CoTステップの最適化、または検証ステップの強化といった具体的な改善策をプロンプトに適用します。

  6. 再評価: 改良されたプロンプトで再度モデルを実行し、その性能を評価します。このサイクルを繰り返すことで、プロンプトの品質は段階的に向上していきます。

この改善ループを継続的に回すことで、LLMアプリケーションはより堅牢で信頼性の高いものとなります。特に、新しいデータやユースケースの要件が変化する際には、このループがモデルの性能維持に不可欠です。

まとめ

LLMのプロンプトエンジニアリングは、単一のプロンプト作成で完結するものではなく、継続的な評価と改良を伴うプロセスです。本記事では、ユースケース定義から始まり、入出力契約による制約、ゼロショット・少数例・Chain-of-Thoughtといった具体的なプロンプト設計、そして自動評価による客観的な性能測定について解説しました。さらに、幻覚や様式崩れといった失敗モードへの対処法と、プロンプト・モデル・評価・改良からなる継続的な改善ループの重要性を示しました。これらの手法を体系的に適用することで、LLMの持つ可能性を最大限に引き出し、実用的なアプリケーションを構築することが可能になります。

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

コメント

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