LLMにおけるFew-Shot/In-Context Learningプロンプト設計ガイド

Tech

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

LLMにおけるFew-Shot/In-Context Learningプロンプト設計ガイド

大規模言語モデル(LLM)のFew-Shot/In-Context Learning(ICL)は、モデルが少数の例から新しいタスクを学習し、適応する能力を指します。この能力を最大限に引き出すためには、プロンプトの設計が極めて重要です。本ガイドでは、プロンプト設計の具体的な手順、評価方法、および失敗モードへの対処法を解説します。

1. ユースケース定義:ニュース記事の感情分類

ここでは、ニュース記事の本文からその記事の感情(Positive, Negative, Neutral)を分類するタスクをユースケースとして定義します。これは、顧客フィードバック分析、SNS投稿のセンチメント分析など、多くのビジネスシナリオに応用可能です。

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

LLMとの明確な契約を定義することで、予測可能性と信頼性を向上させます。

入力契約

  • 形式: テキスト形式

  • 内容: 分類対象のニュース記事の本文

  • 前提: 記事は日本語で記述されていること。

出力契約

  • 形式: JSON形式

  • 内容: 以下の構造を持つJSONオブジェクト

    {
      "sentiment": "positive" | "negative" | "neutral" | "unknown",
      "reason": "分類の根拠となる記事内の記述や推論過程"
    }
    
  • 失敗時の挙動: モデルが感情を明確に判断できない場合、"sentiment": "unknown" を返し、"reason" にその旨を具体的に記述する。

  • 禁止事項:

    • JSON形式以外の出力。

    • 記事内容に存在しない事実(幻覚)に基づいた理由の生成。

    • 不適切な言葉や偏見を含む出力。

    • 指定された感情カテゴリ以外の生成。

3. プロンプト設計

ここでは、異なる戦略に基づく3種類のプロンプト案を提示します。

3.1. プロンプト案1:ゼロショットプロンプト

基本的な指示のみで構成され、例を含まないプロンプトです。汎用性は高いですが、複雑なタスクや曖昧な指示では性能が不安定になる可能性があります。

あなたはニュース記事の感情を分析するAIアシスタントです。
以下のニュース記事を読み、その感情を「positive」「negative」「neutral」のいずれかに分類し、その根拠を簡潔に示してください。
感情を明確に判断できない場合は、「unknown」としてください。
出力はJSON形式で、`sentiment`と`reason`のキーを含めてください。

ニュース記事:
{{ニュース記事本文}}

3.2. プロンプト案2:少数例(Few-Shot)プロンプト

いくつかの具体例を示すことで、モデルにタスクの意図と期待される出力形式を学習させます。特に複雑な出力形式やニュアンスが重要なタスクで有効です。

あなたはニュース記事の感情を分析するAIアシスタントです。
以下のニュース記事を読み、その感情を「positive」「negative」「neutral」のいずれかに分類し、その根拠を簡潔に示してください。
感情を明確に判断できない場合は、「unknown」としてください。
出力はJSON形式で、`sentiment`と`reason`のキーを含めてください。

例1:
ニュース記事: 最新の調査により、〇〇企業の売上が前年比20%増を達成しました。市場シェアも拡大しており、今後の成長が期待されます。
出力:
```json
{
  "sentiment": "positive",
  "reason": "売上増加と市場シェア拡大というポジティブな情報が示されており、今後の成長への期待感が記述されているため。"
}

例2: ニュース記事: 〇〇地域で発生した大規模停電は、3日間にわたり住民生活に甚大な影響を与えました。復旧作業は難航し、経済的損失も懸念されています。 出力:

{
  "sentiment": "negative",
  "reason": "大規模停電による住民生活への甚大な影響、復旧作業の難航、経済的損失への懸念というネガティブな情報が示されているため。"
}

例3: ニュース記事: 〇〇市議会は昨日、来年度の予算案を巡り長時間にわたる議論を行いました。最終的な採決は来週に持ち越されました。 出力:

{
  "sentiment": "neutral",
  "reason": "予算案に関する議論と採決の延期という事実が述べられており、感情的な評価を伴わない客観的な情報であるため。"
}

ニュース記事: {{ニュース記事本文}}

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

少数例プロンプトに加えて、例ごとに推論過程(思考の連鎖)を示すことで、モデルにタスク解決のステップを学習させます。複雑な推論を必要とするタスクや、出力の透明性が求められる場合に特に有効です。

```text
あなたはニュース記事の感情を分析するAIアシスタントです。
以下のニュース記事を読み、感情を「positive」「negative」「neutral」のいずれかに分類し、その根拠を簡潔に示してください。
感情を明確に判断できない場合は、「unknown」としてください。
出力はJSON形式で、`sentiment`と`reason`のキーを含めてください。
推論の過程を「思考:」として記述してから、最終的なJSONを出力してください。

例1:
ニュース記事: 最新の調査により、〇〇企業の売上が前年比20%増を達成しました。市場シェアも拡大しており、今後の成長が期待されます。
思考: この記事では「売上20%増」「市場シェア拡大」「今後の成長が期待される」といった、企業にとって非常に好ましい状況が具体的に記述されている。全体として前向きな内容である。
出力:
```json
{
  "sentiment": "positive",
  "reason": "売上増加と市場シェア拡大というポジティブな情報が示されており、今後の成長への期待感が記述されているため。"
}

例2: ニュース記事: 〇〇地域で発生した大規模停電は、3日間にわたり住民生活に甚大な影響を与えました。復旧作業は難航し、経済的損失も懸念されています。 思考: この記事では「大規模停電」「甚大な影響」「復旧作業は難航」「経済的損失も懸念」といった、非常に深刻で否定的な出来事とその影響が記述されている。全体として否定的な内容である。 出力:

{
  "sentiment": "negative",
  "reason": "大規模停電による住民生活への甚大な影響、復旧作業の難航、経済的損失への懸念というネガティブな情報が示されているため。"
}

ニュース記事: {{ニュース記事本文}}

## 4. 評価

プロンプトの性能を客観的に評価するためのシナリオと自動評価の擬似コードを示します。

### 4.1. 評価シナリオ

*   **正例**: 明確な感情を持つ記事。

    *   例: 「新製品が記録的な売上を達成し、株価も急上昇。」

*   **難例**: 感情が曖昧または複合的、あるいは中立的な記事。

    *   例: 「景気回復の兆しが見られる一方で、一部産業では依然として厳しい状況が続く。」

    *   例: 「A国とB国の首脳会談が行われ、両国間の協力関係について意見交換がなされた。」

*   **コーナーケース**: プロンプトの制約を試すようなケース。

    *   例: 非常に短い記事や、ほとんど情報を含まない記事。

    *   例: 感情的表現がほとんどない専門技術記事。

    *   例: 禁止されている感情カテゴリを想起させるような記事。

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

自動評価は、出力の形式準拠、感情の正確性、理由の妥当性を確認します。

```python
import json
import re

def evaluate_sentiment_output(llm_output: str, expected_sentiment: str, article_text: str) -> dict:
    """
    LLMの感情分類出力と期待値を比較し、評価結果を返します。
    """
    evaluation_result = {
        "format_error": False,
        "sentiment_correct": False,
        "reason_plausible": False,
        "score": 0, # -1:フォーマットエラー, 0:不正解, 1:部分正解, 2:正解
        "details": []
    }

    try:
        output_json = json.loads(llm_output)
        if not isinstance(output_json, dict):
            raise ValueError("出力がJSONオブジェクトではありません。")

        sentiment = output_json.get("sentiment")
        reason = output_json.get("reason")

        if sentiment is None or reason is None:
            raise ValueError("必須キー('sentiment', 'reason')が見つかりません。")

        # 感情の正確性チェック

        if sentiment == expected_sentiment:
            evaluation_result["sentiment_correct"] = True
            evaluation_result["score"] += 1
        else:
            evaluation_result["details"].append(f"感情が不一致: 期待値 '{expected_sentiment}', モデル出力 '{sentiment}'")

        # 理由の妥当性チェック(簡略化された例)


        # 実際にはより高度なNLP技術やキーワードマッチング、モデルベースの評価が必要

        if expected_sentiment == "positive" and re.search(r'(増加|成長|成功|改善)', reason) and re.search(r'(好調|良好)', article_text):
            evaluation_result["reason_plausible"] = True
        elif expected_sentiment == "negative" and re.search(r'(減少|悪化|損失|問題)', reason) and re.search(r'(停滞|困難)', article_text):
            evaluation_result["reason_plausible"] = True
        elif expected_sentiment == "neutral" and re.search(r'(報告|議論|言及|事実)', reason) and not re.search(r'(増加|減少|成功|失敗|喜び|悲しみ)', article_text):
            evaluation_result["reason_plausible"] = True
        elif sentiment == "unknown" and re.search(r'(不明|判断不可|情報不足)', reason):
            evaluation_result["reason_plausible"] = True # unknownの場合の理由の妥当性

        if evaluation_result["sentiment_correct"] and evaluation_result["reason_plausible"]:
            evaluation_result["score"] += 1
        elif evaluation_result["sentiment_correct"] and not evaluation_result["reason_plausible"]:
             evaluation_result["details"].append("感情は正しいが、理由の妥当性に疑問。")
        elif not evaluation_result["sentiment_correct"] and evaluation_result["reason_plausible"]:
             evaluation_result["details"].append("感情は誤っているが、理由は記事に沿っている可能性あり。")

    except (json.JSONDecodeError, ValueError) as e:
        evaluation_result["format_error"] = True
        evaluation_result["score"] = -1
        evaluation_result["details"].append(f"JSONフォーマットエラー: {e}")

    return evaluation_result

# 採点ルーブリック例:


# -1: JSON形式エラー、必須キー欠落


#  0: 感情分類が不正解


#  1: 感情分類は正解だが、理由が不適切または不明確


#  2: 感情分類が正解かつ、理由が適切で妥当

5. 誤り分析と改良

LLMの出力に誤りがあった場合、その原因を特定し、プロンプトを改良する必要があります。

5.1. 失敗モード

  • 幻覚(Hallucination): 記事にない情報を根拠として提示する。

    • 例: 「〇〇企業は競合他社を買収したためポジティブ」と出力するが、記事には買収の事実がない。
  • 様式崩れ: JSON形式以外の出力や、指定されたキー以外の情報を含める。

    • 例: テキストのみを返す、"感情" のようにキー名を間違える。
  • 脱線: タスクの指示から逸脱し、要約や別の情報を提供する。

    • 例: 感情分類ではなく、記事の要約だけを返す。
  • 禁止事項の違反: 不適切な言葉や偏見を含む出力。

    • 例: 記事の内容を批判的に論評するなど、中立性を欠いた出力。
  • 感情分類の誤り: 記事の感情と異なる分類を行う。

    • 例: 明らかにネガティブな記事を「neutral」と分類する。
  • 理由の不十分さ: 感情分類は正しいが、その根拠が抽象的すぎる、または記事内の具体的な記述に結びついていない。

5.2. 抑制手法

失敗モード 抑制手法(プロンプト設計) 抑制手法(後処理/システム)
幻覚 思考:ステップで根拠を明示させる
記事の内容に厳密に基づいてください」と指示
外部知識を使わないでください」と明示
出力されたreasonを記事本文と照合する検証ステップ
様式崩れ 明確な出力フォーマット指示と例示
systemプロンプトで厳格なフォーマット要求
出力JSONのパースとスキーマ検証
失敗時のリトライ戦略(フォーマットエラーの場合、再度モデルに修正指示)
脱線 タスクの目的を明瞭に定義
他の情報や意見を含めないでください」と指示
出力内容がタスク目的から逸脱していないかキーワードでチェック
禁止事項 systemプロンプトで「中立的かつ客観的に」「倫理的ガイドラインを遵守し」と指示 出力フィルタリング(不適切表現検出)
人によるレビュー
感情分類誤り 少数例/CoTで判断基準を具体的に示す
曖昧なケースでのunknownの使用を促進
多数決(アンサンブル)評価
教師データとのF1スコア計算
理由の不十分さ 思考:ステップで詳細な推論を要求
記事内の具体的な箇所を引用して根拠を示してください
理由のキーワードと記事本文のキーワード共起分析
人による理由の妥当性評価

6. 改良と再評価のループ

プロンプトエンジニアリングは反復的なプロセスです。上記の手法を通じてプロンプトを改良し、再度評価シナリオを用いてその効果を測定します。

graph TD
    A["プロンプト生成"] --> B("LLM実行");
    B --> C{"出力結果"};
    C --> D["評価"];
    D --> E{"失敗分析"};
    E -- 課題特定 --> F["プロンプト改良"];
    F --> A;

グラフの説明:

  • プロンプト生成: 新しいプロンプトを作成するか、既存のプロンプトを調整します。

  • LLM実行: 設計したプロンプトをLLMに適用し、出力を生成させます。

  • 出力結果: LLMから得られた生の結果です。

  • 評価: 定義された評価シナリオと自動評価スクリプトを用いて、出力結果の品質を測定します。

  • 失敗分析: 評価結果に基づいて、なぜモデルが失敗したのか(例:幻覚、様式崩れ)を特定します。

  • プロンプト改良: 失敗モードの抑制手法などを参考に、プロンプトに修正を加えます。

  • このループを繰り返すことで、プロンプトの性能を継続的に向上させます。

7. まとめ

Few-Shot/In-Context Learningのプロンプト設計は、明確な入出力契約の定義、戦略的なプロンプト構成(ゼロショット、少数例、CoT)、体系的な評価、そして失敗モードへの対応と継続的な改良のループが成功の鍵です。特に、JSONのような構造化出力の強制、推論過程の明示(CoT)、そして出力検証の組み合わせは、LLMの信頼性と実用性を大幅に向上させます。本ガイドで示した手法は、様々なタスクにおいて高品質なLLMアプリケーションを構築するための基盤となるでしょう。

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

コメント

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