Zero-shot CoTの深掘りと応用

Tech

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

Zero-shot CoTの深掘りと応用

ユースケース定義

本稿では、Zero-shot CoT (Chain-of-Thought) プロンプティングを「多段階の論理推論を要する顧客問い合わせの自動分類と分析」に適用します。具体的には、技術サポート部門における顧客からの複雑な問い合わせテキストから、問題の特定、根本原因の推測、そして解決策の提案、最終的な分類と要約を自動で行うことを目的とします。これにより、一次対応の効率化と専門家へのエスカレーション判断の精度向上を目指します。

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

入力契約

  • フォーマット: 純粋なテキスト形式の顧客からの問い合わせメッセージ。

  • コンテンツ: ユーザーの課題、状況説明、質問などを含む。

  • 文字数: 10文字以上、2000文字以内を想定。

出力契約

  • フォーマット: 以下の構造を持つ厳密なJSON形式。

    {
      "問題特定": "具体的な問題の記述",
      "根本原因推測": "考えられる根本原因の推測",
      "解決策提案": "具体的な解決策の提案(技術的な解決策または情報提供)",
      "分類": "['技術問題', '料金関連', 'アカウント関連', 'その他']のいずれか",
      "要約": "問い合わせ内容と分析結果の簡潔な要約"
    }
    
  • 失敗時の挙動:

    • JSONパースエラー、キーの欠落、または値が空文字列の場合、モデルは「ERROR: JSON形式が不正です。」というメッセージを返す。

    • 推論ステップ(問題特定、根本原因推測、解決策提案)のいずれかが著しく不適切または欠落している場合、「ERROR: 分析が不十分です。」と返す。

  • 禁止事項:

    • 顧客の個人情報(氏名、住所、電話番号など)をJSON出力に含めること。

    • モデルが知識を持たない事項について「断定的な」解決策や原因を提示すること。

    • 不適切な言葉、差別的な表現、偏見を含む内容を出力すること。

プロンプト設計

以下に3種類のプロンプト案を提示します。

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

あなたは高度なカスタマーサポート分析AIです。以下の顧客からの問い合わせを分析し、「問題特定」「根本原因推測」「解決策提案」「分類」「要約」の5つの項目を厳密なJSON形式で出力してください。分類は['技術問題', '料金関連', 'アカウント関連', 'その他']のいずれかです。

問い合わせ:
{customer_query}

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

あなたは高度なカスタマーサポート分析AIです。以下の顧客からの問い合わせを分析し、「問題特定」「根本原因推測」「解決策提案」「分類」「要約」の5つの項目を厳密なJSON形式で出力してください。分類は['技術問題', '料金関連', 'アカウント関連', 'その他']のいずれかです。

例1:
問い合わせ:
先日購入した〇〇デバイスがインターネットに接続できません。Wi-Fiルーターは正常に動いていて、他のデバイスは接続できます。

出力:
```json
{
  "問題特定": "〇〇デバイスがWi-Fiに接続できない",
  "根本原因推測": "〇〇デバイス固有のネットワーク設定、ファームウェアの問題、または互換性の問題",
  "解決策提案": "〇〇デバイスのネットワーク設定のリセット、ファームウェアのアップデート確認、ルーターの再起動を試すよう案内。必要であればメーカーサポートへの連絡を推奨。",
  "分類": "技術問題",
  "要約": "〇〇デバイスのWi-Fi接続問題。設定リセットやファームウェア更新を推奨。"
}

例2: 問い合わせ: 今月の請求額が先月より2000円高いです。何か追加料金が発生しているのでしょうか?覚えがありません。

出力:

{
  "問題特定": "今月の請求額が先月より2000円高いことに対する疑問",
  "根本原因推測": "プラン変更、オプションサービスの追加、期間限定割引の終了、または誤請求の可能性",
  "解決策提案": "契約内容と請求履歴の詳細を確認するよう案内。必要であれば請求明細の確認と照合を提案。",
  "分類": "料金関連",
  "要約": "請求額増加に関する問い合わせ。契約内容と請求履歴の確認を推奨。"
}

問い合わせ: {customer_query}

### 3. Chain-of-Thought制約型プロンプト (Zero-shot CoT)

```text
あなたは高度なカスタマーサポート分析AIです。以下の顧客からの問い合わせを分析し、ステップバイステップで論理的に思考し、最終的な分析結果を厳密なJSON形式で出力してください。

思考プロセス:

1. まず、顧客の問い合わせから中心的な「問題」を明確に特定します。

2. 次に、特定された問題に基づいて「根本原因」として考えられるものを複数、可能性の順に推測します。

3. その推測された根本原因に対応する「解決策」を具体的に提案します。

4. 最後に、これらの分析結果全体を考慮し、問い合わせを['技術問題', '料金関連', 'アカウント関連', 'その他']のいずれかに「分類」し、全体の「要約」を作成します。

最終出力は、以下のJSON形式に従ってください。

```json
{
  "問題特定": "具体的な問題の記述",
  "根本原因推測": "考えられる根本原因の推測",
  "解決策提案": "具体的な解決策の提案(技術的な解決策または情報提供)",
  "分類": "['技術問題', '料金関連', 'アカウント関連', 'その他']のいずれか",
  "要約": "問い合わせ内容と分析結果の簡潔な要約"
}

問い合わせ: {customer_query}

## 評価シナリオと自動評価

### 評価シナリオ

1.  **正例**:

    *   入力: 「私のPCで〇〇ソフトウェアが起動できません。エラーコード1234が表示されます。再インストールは試しました。」

    *   期待出力: ソフトウェア固有のエラー、再インストール後の問題、具体的な解決策(ログ確認、互換性確認など)。分類は「技術問題」。

2.  **難例**:

    *   入力: 「最近サービスが遅く感じます。時々ログインもできなくなりますし、先月はなぜか請求額が高かったです。どうなっているんですか?」

    *   期待出力: 複数の問題(パフォーマンス低下、ログイン障害、料金増加)をそれぞれ特定し、根本原因を推測し、解決策を提案。分類は主要な問題に基づくか、複合的な記述。

3.  **コーナーケース**:

    *   入力: 「こんにちは、元気ですか?」

    *   期待出力: サービスに関する明確な問い合わせがないため、適切な分析は困難。分類は「その他」。または「ERROR: 分析が不十分です。」

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

```python
import json
import re

def evaluate_llm_output(output_text, expected_category, keywords_to_check=None):
    score = 0
    feedback = []

    # 1. JSON形式の検証 (出力契約)

    try:
        parsed_output = json.loads(output_text)
        score += 10 # JSONパース成功
    except json.JSONDecodeError:
        feedback.append("ERROR: JSON形式が不正です。")
        return 0, feedback, {}

    # 2. 必須キーの存在検証 (出力契約)

    required_keys = ["問題特定", "根本原因推測", "解決策提案", "分類", "要約"]
    if not all(key in parsed_output for key in required_keys):
        feedback.append("ERROR: 必須キーが不足しています。")
        return 0, feedback, parsed_output
    score += 10 # 全てのキーが存在

    # 3. '分類'の妥当性検証 (出力契約)

    valid_categories = ['技術問題', '料金関連', 'アカウント関連', 'その他']
    if parsed_output.get("分類") in valid_categories:
        score += 10
        if parsed_output.get("分類") == expected_category:
            score += 20 # 正しい分類
        else:
            feedback.append(f"警告: 分類が期待値と異なります。期待値: {expected_category}, 実際: {parsed_output.get('分類')}")
    else:
        feedback.append("ERROR: 分類が不正な値です。")
        score -= 10 # 不正な分類は減点

    # 4. 内容の妥当性 (キーワードチェックや文字列長)


    # 各項目が空でないかチェック

    for key in required_keys:
        if not parsed_output.get(key):
            feedback.append(f"警告: '{key}'が空です。")
            score -= 5

    # キーワードチェック (オプション)

    if keywords_to_check:
        for key, expected_kws in keywords_to_check.items():
            if key in parsed_output:
                found_count = 0
                for kw in expected_kws:
                    if re.search(re.escape(kw), parsed_output[key], re.IGNORECASE):
                        found_count += 1
                if found_count == len(expected_kws):
                    score += 10
                else:
                    feedback.append(f"警告: '{key}'に期待キーワードの一部または全てが見つかりません。")
                    score -= 5

    # 5. 禁止事項の簡易チェック (例: 個人情報、断定的な表現)


    # 簡単なパターンマッチングによる個人情報検出 (簡易版)

    if re.search(r'\d{3}[-.\s]?\d{4}[-.\s]?\d{4}|\w+@\w+\.\w+', output_text): # 電話番号/メールアドレス簡易検出
        feedback.append("ERROR: 個人情報が含まれている可能性があります。")
        score -= 50

    # 総合スコアとフィードバック

    if not feedback:
        feedback.append("出力は概ね良好です。")

    return max(0, score), feedback, parsed_output

# ルーブリック:


# JSONパース成功: +10点


# 全ての必須キーが存在: +10点


# 分類が有効なカテゴリ内: +10点


# 分類が期待値と一致: +20点


# 各項目が空でない: 各-5点 (最大-25点)


# 特定キーワードが検出された: +10点 (シナリオ依存)


# 個人情報検出: -50点

# 例:


# query = "私のPCで〇〇ソフトウェアが起動できません。エラーコード1234が表示されます。再インストールは試しました。"


# expected_output_json_str = """


# {


#   "問題特定": "〇〇ソフトウェア起動不可とエラーコード1234",


#   "根本原因推測": "ソフトウェアの破損、OSとの互換性問題、または特定のDLLファイルの欠損",


#   "解決策提案": "イベントログの確認、互換モードでの実行、システムの復元ポイントの利用を提案。",


#   "分類": "技術問題",


#   "要約": "〇〇ソフトウェアがエラー1234で起動しない。ログ確認や互換モード実行を推奨。"


# }


# """


# score, fb, parsed = evaluate_llm_output(expected_output_json_str, "技術問題", 


#                                          keywords_to_check={"問題特定": ["ソフトウェア起動不可", "エラーコード1234"]})


# print(f"Score: {score}, Feedback: {fb}")

プロンプト設計・評価・改良ループ

graph TD
    A["プロンプト設計"] -->|プロンプト定義| B("LLMモデル")
    B -->|モデル出力| C{"出力解析"}
    C -->|分析結果| D["評価指標定義"]
    D -->|評価基準| E["自動評価スクリプト"]
    E -->|評価レポート| F{"評価結果分析"}
    F -->|改善点特定| A

失敗モードと抑制手法

1. 幻覚 (Hallucination)

  • 発生モード: 存在しないエラーコードや、誤った解決策を自信満々に提示する。誤った根本原因を推測する。

  • 抑制手法:

    • System指示: 「事実に基づかない推測や断定は避けてください。不明な場合はその旨を明記してください。」

    • 検証ステップ: 参照情報源を明記させる、あるいは信頼できるナレッジベースとの照合ステップを後段に設ける。

    • リトライ戦略: 「不明な点は『確認が必要です』と記述し、具体的な推測は行わないでください」という制約を加え、再度生成を試みる。

2. 様式崩れ (Format Breakage)

  • 発生モード: JSON形式が不正になる(例: カンマ抜け、クォーテーションの誤り、キーの欠落)。

  • 抑制手法:

    • System指示: 「出力は厳密に指定されたJSON形式に従ってください。それ以外のテキストは一切含めないでください。」

    • 検証ステップ: 生成されたJSON出力をPythonのjson.loads()でパースし、スキーマバリデーションを行う。

    • リトライ戦略: パースに失敗した場合、エラーメッセージとともにプロンプトに「前回の出力はJSON形式が不正でした。再度、正しいJSON形式で出力してください。」と付加して再試行。

3. 脱線 (Off-topic / Task Deviation)

  • 発生モード: 問い合わせ内容とは無関係な情報を含めたり、指定されたタスク(問題特定、原因推測など)以外のことを話し始める。

  • 抑制手法:

    • System指示: 「与えられたタスクのみに集中し、余計な情報や挨拶は含めないでください。出力は純粋なJSONのみです。」

    • 検証ステップ: 出力された要約や各項目に、問い合わせ内容に直接関連しないキーワードが含まれていないかチェックする。

    • プロンプトの明確化: 各項目の説明をより具体的に記述し、何を答えるべきかを明確にする。

4. 禁止事項 (Prohibited Content)

  • 発生モード: 顧客の個人情報(入力に含まれる場合)を誤って出力に含めてしまう。不適切な言葉を使用する。

  • 抑制手法:

    • System指示: 「出力に個人情報(氏名、電話番号、メールアドレス等)を含めることを固く禁じます。不適切な言葉遣いは厳禁です。」

    • 検証ステップ: 出力テキストに対し、個人情報や不適切語のパターンマッチング、または専用のセキュリティフィルタリングAPIを適用する。

    • データ前処理: LLMへの入力前に、機密情報匿名化 (PII Redaction) を施す。

まとめ

、Zero-shot CoTを多段階の論理推論を要する顧客問い合わせ分析に適用する事例を通して、プロンプト設計、厳密な入出力契約の定義、自動評価シナリオ、そしてMermaidによる評価・改良ループを詳述しました。特にChain-of-Thought制約型プロンプトは、モデルに思考プロセスを明示させることで、複雑なタスクにおける推論能力と出力の信頼性を向上させる強力な手法です。また、幻覚や様式崩れといった典型的な失敗モードに対する具体的な抑制手法を導入することで、システムの安定性と安全性を高めることができます。これらの知見は、他の複雑なLLM応用タスクにも展開可能であり、より堅牢なLLMアプリケーション開発に貢献するでしょう。

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

コメント

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