プロンプトの入出力契約と評価基準

Tech

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

プロンプトの入出力契約と評価基準

LLM(大規模言語モデル)を活用したアプリケーション開発において、プロンプトの品質はシステムの性能と信頼性に直結します。本記事では、プロンプトの入出力契約を明確に定義し、多様なプロンプト設計手法、適切な評価基準、および一般的な失敗モードとその抑制手法について解説します。

ユースケース定義

ここでは、ユーザーからの要求に基づき、特定のドキュメントを要約し、その要約文からキーワードを抽出するというユースケースを想定します。

ユースケース名: ドキュメント要約とキーワード抽出

目的: 長文のドキュメント(ニュース記事、技術文書など)を簡潔に要約し、その要約内容を最もよく表すキーワードを複数抽出する。

期待される価値: ユーザーはドキュメント全体を読まずに概要を把握し、主要な論点を迅速に識別できる。

入出力契約による制約付き仕様化

堅牢なプロンプトを設計するためには、LLMとの「契約」を明確に定義することが不可欠です。これにより、モデルの出力の一貫性を保ち、予測不能な挙動を最小限に抑えます。

入力契約

  • 入力形式: プレーンテキストまたはMarkdown形式のドキュメント。

  • 最大文字数: 10,000文字。これを超える場合はエラーを返却。

  • 言語: 日本語または英語。その他の言語はサポート対象外。

  • 禁止事項: 個人情報、機密情報、著作権侵害の可能性があるコンテンツ。

出力契約

  • 出力形式: JSON形式。以下の構造を厳守。

    {
      "summary": "要約されたテキスト(200字以内)",
      "keywords": ["キーワード1", "キーワード2", "キーワード3"]
    }
    
  • 要約の長さ: 200文字以内。

  • キーワードの数: 3〜5個。各キーワードは単語または短いフレーズ。

  • 言語: 入力言語と同じ。

  • 失敗時の挙動: 指定された文字数や形式を満たせない場合は、error フィールドを持つJSONを返す。

失敗時の挙動と禁止事項

  • フォーマット不遵守: 出力形式がJSONスキーマに違反した場合、または要約文字数・キーワード数制限に違反した場合は、呼び出し側でリトライするか、エラーとして処理する。

  • 幻覚(Hallucination): 要約内容が原文と著しく異なる、またはキーワードが原文に存在しない場合。

  • 禁止事項違反: 入力に含まれる禁止事項をモデルが処理しようとした場合、または出力に不適切なコンテンツが含まれた場合。

    • 挙動: {"error": "入力または出力がポリシーに違反しました。"} を返却。
  • タイムアウト: 指定時間内に応答がない場合、呼び出し側でタイムアウトエラーを処理。

プロンプト設計

ここでは、上記のユースケースに基づき、3種類のプロンプト案を提示します。

ゼロショットプロンプト

基本的な指示のみで、具体例を示さない形式です。

あなたはプロの要約・キーワード抽出アシスタントです。
以下のドキュメントを要約し、その要約から3つの主要キーワードを抽出してください。
出力はJSON形式で、`summary`と`keywords`の2つのキーを含めてください。
要約は200文字以内とします。

---
ドキュメント:
[ここにドキュメントの内容を挿入]
---

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

いくつかの入出力ペアの例を提供することで、モデルの理解を深める形式です。

あなたはプロの要約・キーワード抽出アシスタントです。
以下のドキュメントを要約し、その要約から3つの主要キーワードを抽出してください。
出力はJSON形式で、`summary`と`keywords`の2つのキーを含めてください。
要約は200文字以内とします。

---
入力例1:
ドキュメント:
「本日、株式会社ABCは最新のAI技術を搭載した新製品『スマートアシストX』を発表しました。この製品は、自然言語処理と画像認識を統合し、ユーザーの日常業務を大幅に効率化すると期待されています。初期ロットは来月よりオンラインストアで販売開始予定です。」
出力例1:
```json
{
  "summary": "株式会社ABCは、AI技術を搭載した新製品「スマートアシストX」を発表しました。自然言語処理と画像認識を統合し、業務効率化に貢献すると期待され、来月より販売開始予定です。",
  "keywords": ["スマートアシストX", "AI技術", "業務効率化"]
}

入力例2: ドキュメント:

[ここにドキュメントの内容を挿入]

### Chain-of-Thought制約型プロンプト

モデルに思考プロセスを段階的に出力させ、特定の思考ステップを強制することで、出力の信頼性と制御性を高めます。

```text
あなたはプロの要約・キーワード抽出アシスタントです。
以下の指示に従って、ドキュメントの要約とキーワード抽出を行ってください。

1. ドキュメントを注意深く読み、主要なテーマと論点を特定してください。

2. 主要なテーマと論点に基づき、200文字以内で要約を作成してください。

3. 作成した要約から、最も重要なキーワードを3つ抽出してください。

4. 最終結果をJSON形式で出力してください。`summary`と`keywords`の2つのキーを含めてください。

---
ドキュメント:
[ここにドキュメントの内容を挿入]
---

評価戦略

プロンプトの有効性を確認するためには、体系的な評価が不可欠です。

評価シナリオの設計

シナリオ名 タイプ 説明 期待される結果
正例(Normal Case) 正常系 一般的なニュース記事やブログ記事。 正確な要約と関連性の高いキーワード、正しいJSON形式。
難例(Complex Case) 境界条件/複雑 専門用語が多い技術文書、複数のテーマが混在する長文。 専門用語を適切に扱った要約、専門性の高いキーワード。
短文(Short Text) コーナーケース 数行程度の短いドキュメント。 短いが正確な要約、少ないキーワード(3個未満も許容)。
多言語(Multi-language) コーナーケース 日本語と英語以外の言語(例:中国語)の入力。 エラーメッセージ(入力言語外)。
禁止語句(Forbidden Word) セキュリティ 個人情報や差別表現を含む入力。 エラーメッセージ(ポリシー違反)。

自動評価の擬似コード

採点ルーブリック、正規表現、または関数評価を組み合わせることで、自動評価システムを構築できます。

import json
import re

def evaluate_llm_output(expected_json, actual_output_text, doc_content):
    score = 0
    feedback = []

    # 1. JSON形式の検証

    try:
        actual_output = json.loads(actual_output_text)
        if not isinstance(actual_output, dict):
            raise ValueError("出力は辞書型である必要があります。")
        score += 10
    except json.JSONDecodeError:
        feedback.append("出力が有効なJSONではありません。")
        return {"score": score, "feedback": feedback, "is_pass": False}
    except ValueError as e:
        feedback.append(f"JSON構造エラー: {e}")
        return {"score": score, "feedback": feedback, "is_pass": False}

    # 2. キーの存在と型の検証

    if "summary" in actual_output and isinstance(actual_output["summary"], str):
        score += 5
    else:
        feedback.append("`summary`キーが見つからないか、文字列ではありません。")

    if "keywords" in actual_output and isinstance(actual_output["keywords"], list):
        score += 5
    else:
        feedback.append("`keywords`キーが見つからないか、リストではありません。")

    if score < 20: # 基本的なJSON構造が満たされていない場合
        return {"score": score, "feedback": feedback, "is_pass": False}

    # 3. 要約の長さ検証 (200文字以内)

    if len(actual_output.get("summary", "")) <= 200:
        score += 10
    else:
        feedback.append(f"要約が200文字を超過しています ({len(actual_output.get('summary', ''))}文字)。")

    # 4. キーワードの数検証 (3〜5個)

    num_keywords = len(actual_output.get("keywords", []))
    if 3 <= num_keywords <= 5:
        score += 10
    else:
        feedback.append(f"キーワードの数が3〜5個の範囲外です ({num_keywords}個)。")

    # 5. キーワードの妥当性 (原文との関連性 - 簡易チェック)


    # 各キーワードが原文に登場するか、または意味的に関連するかを簡易的にチェック


    # (より高度な評価にはRAGや別のLLMが必要)

    keyword_relevance_score = 0
    for keyword in actual_output.get("keywords", []):
        if re.search(r'\b' + re.escape(keyword) + r'\b', doc_content, re.IGNORECASE):
            keyword_relevance_score += 2 # 原文に直接含まれる

        # else: 別のLLMで意味的関連性を評価するなど

    score += min(keyword_relevance_score, 10) # 最大10点

    # 6. 幻覚チェック (要約内容の正確性 - 簡易チェック)


    # 要約が原文の主要な固有名詞や数字を含んでいるかなど、簡易的な事実チェック


    # (より高度な評価にはRAGや別のLLMが必要)


    # ここでは、要約と原文の語彙類似度を計算するなどの簡略化された方法を想定


    # 例: 文書と要約間のTF-IDFコサイン類似度など

    summary_relevance_score = 0

    # 仮の実装: 要約が原文の特定の主要単語を含んでいれば加点

    if any(word in actual_output["summary"] for word in ["ABC", "スマートアシストX"]): # 検出すべき単語リストは別途定義
        summary_relevance_score += 5
    score += min(summary_relevance_score, 10) # 最大10点

    # 7. 禁止事項チェック

    if "ポリシー違反" in actual_output_text or "error" in actual_output:
        score -= 50 # 大きく減点
        feedback.append("出力にエラーまたはポリシー違反の兆候があります。")

    is_pass = (score >= 60) # 合格基準を定義

    return {"score": score, "feedback": feedback, "is_pass": is_pass, "parsed_output": actual_output}

# 採点ルーブリック:


# JSON形式: 10点


# summaryキーと型: 5点


# keywordsキーと型: 5点


# 要約の長さ: 10点


# キーワードの数: 10点


# キーワードの原文との関連性: 10点 (例: 1キーワードあたり2点、最大5キーワード)


# 要約の正確性 (幻覚防止): 10点 (例: 特定のキーワード検出、類似度など)


# 禁止事項違反: -50点


# 合計最大: 60点


# 合格基準: 60点以上

誤り分析と抑制手法

プロンプトの失敗モードを特定し、適切な抑制手法を適用することで、システムの信頼性を向上させます。

失敗モード

  1. 幻覚(Hallucination):

    • 説明: 事実に基づかない情報を生成する。要約が原文と異なる内容を含んだり、キーワードが原文に存在しなかったりする。
  2. 様式崩れ(Format Deviation):

    • 説明: 定義されたJSON形式や文字数制限、キーワード数制限に従わない。
  3. 脱線(Topic Drift):

    • 説明: ドキュメントの要約ではなく、関連性の低い一般論や別のテーマについて言及する。
  4. 禁止事項違反(Policy Violation):

    • 説明: 入力に個人情報や機密情報が含まれる場合に、それらを無意識に処理・出力してしまったり、不適切コンテンツを出力したりする。
  5. 不完全な出力(Incomplete Output):

    • 説明: モデルの応答が途中で途切れる、または指定されたすべての要素(summary, keywords)を含まない。

抑制手法

  1. System指示の強化:

    • 内容: プロンプトの先頭に、モデルの役割、厳守すべき制約、禁止事項を明記した system 指示を追加する。例えば、「あなたは中立的で客観的なアシスタントです。提供された情報のみに基づいて回答し、憶測で情報を追加しないでください。」
  2. 出力検証ステップ:

    • 内容: LLMの出力後に、別のプロンプトや外部ツールを用いて出力形式、内容の正確性、ポリシー準拠を検証する。上記の擬似コードのような自動評価をデプロイ前のテストだけでなく、実行時にも適用する。
  3. Few-shot例の充実:

    • 内容: 正しい入出力ペアの例を増やすことで、モデルが期待される挙動をより良く学習できるようにする。特に境界ケースや複雑なシナリオの例を含める。
  4. Chain-of-Thought(CoT)の導入と制約:

    • 内容: モデルに思考プロセスを段階的に出力させ、各ステップで制約を設けることで、論理的な飛躍や誤りを防ぐ。例えば、「まず主要なテーマを列挙し、次にそれらを統合して要約を作成し、最後に要約からキーワードを抽出する」といった具体的なステップを指示する。
  5. リトライ戦略:

    • 内容: 初回の出力が期待される形式を満たさなかったり、エラーを示したりした場合に、プロンプトを修正したり、温度(temperature)などのモデルパラメータを変更したりして再試行する。
  6. 安全フィルター(Safety Filter)の活用:

    • 内容: LLMの入出力に対して、不適切コンテンツや機密情報を検出・ブロックする専用のモジュールを導入する。

改良と再評価のループ

プロンプトの設計は一度で完結するものではなく、継続的な評価と改良のループを通じて品質を高めていくプロセスです。

graph TD
    A["要求定義・ユースケース定義"] --> |プロンプト要件定義| B{"入出力契約の設計"};
    B --> |契約に基づき作成| C["プロンプト設計・実装"];
    C --> |モデルに入力| D["LLMモデル実行"];
    D --> |モデル出力| E{"出力評価"};
    E --|評価基準に合致| F["本番デプロイ"];
    E --|評価基準に不合格| G["誤り分析と失敗モード特定"];
    G --> |原因特定・対策立案| H["抑制手法検討"];
    H --> |プロンプト改良| C;
    F --> |運用フィードバック| A;

このループでは、まず要求とユースケースを定義し、入出力契約を設計します。これに基づきプロンプトを設計・実装し、LLMに実行させます。その出力は定義された評価基準によって評価され、合格であればデプロイに進みます。不合格の場合、誤り分析を行い、失敗モードを特定します。その原因を基に抑制手法を検討し、プロンプトを改良して再度評価ループに戻ります。デプロイ後も運用フィードバックを収集し、初期の要求定義に反映させることで、システム全体の品質を継続的に向上させます。

まとめ

、LLMプロンプトの堅牢な設計と評価のために、入出力契約の重要性、多様なプロンプト設計手法、そして具体的な評価戦略と誤り分析・抑制手法を詳細に解説しました。プロンプトエンジニアリングは反復的なプロセスであり、入出力契約を明確にし、体系的な評価と継続的な改良のループを回すことが、高品質なLLMアプリケーション開発の鍵となります。ここで紹介した枠組みは、プロンプトの予測可能性と信頼性を高め、実用的なAIシステムを構築するための出発点となるでしょう。

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

コメント

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