<h1 class="wp-block-heading">LLMの思考連鎖プロンプティング設計と評価</h1>
<h2 class="wp-block-heading">1. ユースケース定義</h2>
<p>本稿では、顧客サポートにおけるFAQからの問い合わせ対応を自動化するLLMプロンプトの設計と評価に焦点を当てます。特に、単に回答を提示するだけでなく、なぜその回答に至ったのかの「思考プロセス」を明示することで、ユーザーの信頼性向上と提供情報の透明性を確保することを目指します。LLMは、ユーザーからの自然言語クエリと関連するFAQリストを受け取り、FAQのみを根拠とした適切な回答と、その導出過程を生成します。</p>
<h2 class="wp-block-heading">2. 制約付き仕様化</h2>
<p>LLMの出力は以下の制約に従う必要があります。</p>
<ul class="wp-block-list">
<li><strong>出力形式</strong>: JSONオブジェクトとして、<code>thought_process</code> (文字列) と <code>final_answer</code> (文字列) の2つのキーを持つこと。</li>
<li><strong>根拠の明確化</strong>: <code>final_answer</code>は、提供された<code>faq_data</code>内の情報のみを根拠とすること。<code>thought_process</code>内でその根拠を明示すること。</li>
<li><strong>思考プロセスのステップ</strong>: <code>thought_process</code>は以下の論理的ステップを順に含むこと。
<ol>
<li>質問の意図分析</li>
<li>関連FAQの特定</li>
<li>回答の生成と根拠の提示</li>
</ol></li>
<li><strong>最終回答の文字数</strong>: <code>final_answer</code>は100文字以上200文字以下とすること。</li>
<li><strong>禁止事項</strong>: 「推測」「AIによる判断」「不明」「私にはわかりません」といった表現、感情的な言葉、ユーザーの個人情報を要求する行為は禁止。</li>
</ul>
<h2 class="wp-block-heading">3. 入出力契約</h2>
<h3 class="wp-block-heading">入力</h3>
<ul class="wp-block-list">
<li><code>user_query</code>: <code>string</code> – 顧客からの質問。</li>
<li><code>faq_data</code>: <code>array<string></code> – ユーザーの質問に関連すると想定されるFAQテキストのリスト。</li>
</ul>
<h3 class="wp-block-heading">成功時の出力</h3>
<p><code>JSON string</code> – 上記「制約付き仕様化」で定義された形式のJSONオブジェクト。
例: <code>{"thought_process": "...", "final_answer": "..."}</code></p>
<h3 class="wp-block-heading">失敗時の挙動</h3>
<ul class="wp-block-list">
<li><strong>FORMAT_ERROR</strong>: 出力JSON形式が不正、または必須キーが不足している場合。
<code>{"error_type": "FORMAT_ERROR", "message": "出力JSON形式が不正です。"}</code></li>
<li><strong>HALLUCINATION_ERROR</strong>: 提供されたFAQデータに基づかない情報が含まれている場合。
<code>{"error_type": "HALLUCINATION_ERROR", "message": "提供されたFAQデータに基づかない情報が含まれています。"}</code></li>
<li><strong>PROHIBITED_TERM_ERROR</strong>: 禁止された表現が含まれている場合。
<code>{"error_type": "PROHIBITED_TERM_ERROR", "message": "禁止された表現が含まれています。"}</code></li>
<li><strong>LENGTH_ERROR</strong>: <code>final_answer</code>の文字数が指定範囲外の場合。
<code>{"error_type": "LENGTH_ERROR", "message": "最終回答の文字数が範囲外です。"}</code></li>
<li><strong>GENERIC_ERROR</strong>: その他予期せぬエラーの場合。
<code>{"error_type": "GENERIC_ERROR", "message": "処理中にエラーが発生しました。"}</code></li>
</ul>
<h3 class="wp-block-heading">禁止事項</h3>
<p>LLMの出力において、以下の表現や行動は厳しく禁止されます。
「推測」「AIによる判断」「不明」「私にはわかりません」、過度な丁寧語/不快な表現、ユーザーの個人情報を聞き出すような質問。</p>
<h2 class="wp-block-heading">4. プロンプト設計(最低3種)</h2>
<h3 class="wp-block-heading">4.1. ゼロショットプロンプト</h3>
<pre data-enlighter-language="generic">あなたは顧客サポートアシスタントです。以下のFAQデータからユーザーの質問に回答し、その思考プロセスと最終回答をJSON形式で出力してください。
回答はFAQデータのみを根拠とし、他の情報源は参照しないでください。
思考プロセスには「質問の意図分析」「関連FAQの特定」「回答の生成と根拠の提示」のステップを含めてください。
最終回答は100文字以上200文字以下にしてください。
「推測」「AIによる判断」「不明」といった表現は禁止です。
---
ユーザーの質問: {user_query}
FAQデータ: {faq_data}
---
出力JSON:
</pre>
<h3 class="wp-block-heading">4.2. 少数例プロンプト</h3>
<pre data-enlighter-language="generic">あなたは顧客サポートアシスタントです。以下のFAQデータからユーザーの質問に回答し、その思考プロセスと最終回答をJSON形式で出力してください。
回答はFAQデータのみを根拠とし、他の情報源は参照しないでください。
思考プロセスには「質問の意図分析」「関連FAQの特定」「回答の生成と根拠の提示」のステップを含めてください。
最終回答は100文字以上200文字以下にしてください。
「推測」「AIによる判断」「不明」といった表現は禁止です。
---
例1:
ユーザーの質問: 配送状況を確認するにはどうすればいいですか?
FAQデータ: ["配送状況は、マイページの注文履歴からご確認いただけます。", "ご注文番号が必要です。"]
出力JSON:
{
"thought_process": "1.質問の意図分析: ユーザーは配送状況の確認方法を知りたい。 2.関連FAQの特定: 「マイページの注文履歴からご確認いただけます。」と「ご注文番号が必要です。」が関連。 3.回答の生成と根拠の提示: これらの情報をもとに、具体的な手順と必要な情報をまとめる。",
"final_answer": "配送状況は、弊社のウェブサイトのマイページにある注文履歴からご確認いただけます。ご確認の際には、ご注文番号が必要となりますので、お手元にご準備ください。"
}
---
ユーザーの質問: {user_query}
FAQデータ: {faq_data}
---
出力JSON:
</pre>
<h3 class="wp-block-heading">4.3. Chain-of-Thought制約型プロンプト</h3>
<pre data-enlighter-language="generic">system:
あなたは顧客サポートアシスタントです。以下の指示に厳密に従い、JSON形式で思考プロセスと最終回答を出力してください。
1. **質問の意図分析**: ユーザーの質問の核心を特定します。
2. **関連FAQの特定**: 提供されたFAQデータの中から、質問に最も関連する情報を選択し、その内容を簡潔にまとめます。
3. **回答の生成と根拠の提示**: 特定したFAQ情報のみを根拠として、ユーザーの質問に対する最終回答を生成します。その際、FAQからの具体的な引用や言い換えを用いて根拠を明示してください。
最終回答は100文字以上200文字以下とし、指定されたFAQデータのみを根拠としてください。
「推測」「AIによる判断」「不明」「私にはわかりません」といった表現は一切禁止です。
user:
ユーザーの質問: {user_query}
FAQデータ: {faq_data}
assistant:
出力JSON:
</pre>
<h2 class="wp-block-heading">5. 評価シナリオ</h2>
<h3 class="wp-block-heading">5.1. 正例 (Simple Case)</h3>
<ul class="wp-block-list">
<li><strong>ユーザーの質問</strong>: “注文履歴はどこで確認できますか?”</li>
<li><strong>FAQデータ</strong>: <code>["ご注文履歴は、マイページの『注文履歴を見る』からご確認いただけます。"]</code></li>
<li><strong>期待する応答</strong>: JSONフォーマットで、FAQに基づいた正確な回答と、規定の思考ステップを含むプロセス。</li>
</ul>
<h3 class="wp-block-heading">5.2. 難例 (Complex Case)</h3>
<ul class="wp-block-list">
<li><strong>ユーザーの質問</strong>: “製品保証と修理について教えてください。”</li>
<li><strong>FAQデータ</strong>: <code>["製品保証期間は購入日から1年間です。", "保証期間内の自然故障は無償修理の対象です。", "お客様の過失による破損は保証期間内でも有償修理となります。", "保証期間外の修理はすべて有償です。", "修理受付は弊社ウェブサイトのサポートページから可能です。"]</code></li>
<li><strong>期待する応答</strong>: 複数のFAQ情報を統合し、条件分岐(保証期間内外、故障原因)を考慮した回答と、明確な思考プロセス。</li>
</ul>
<h3 class="wp-block-heading">5.3. コーナーケース (No Relevant FAQ)</h3>
<ul class="wp-block-list">
<li><strong>ユーザーの質問</strong>: “私の個人情報が外部に漏洩していないか確認したいのですが。”</li>
<li><strong>FAQデータ</strong>: <code>["弊社は家電製品の販売を専門としております。", "個人情報の取り扱いについてはプライバシーポリシーをご確認ください。プライバシーポリシーはウェブサイト下部にリンクがあります。"]</code></li>
<li><strong>期待する応答</strong>: 提供されたFAQが直接的な回答を含まない場合でも、適切に関連情報(プライバシーポリシーの確認)を提示し、幻覚や「不明」を避ける応答。</li>
</ul>
<h2 class="wp-block-heading">6. 自動評価の擬似コード</h2>
<pre data-enlighter-language="generic">import json
import re
def evaluate_llm_response(response_json_str: str, user_query: str, faq_data: list[str]) -> tuple[int, list[str]]:
"""
LLMの応答を評価する関数。
Args:
response_json_str: LLMからの出力JSON文字列。
user_query: ユーザーの質問。
faq_data: 評価に使用されたFAQデータのリスト。
Returns:
tuple[int, list[str]]: 採点スコアとフィードバックメッセージのリスト。
"""
score = 0
feedback = []
faq_data_str = " ".join(faq_data)
prohibited_terms = ["推測", "AIによる判断", "不明", "私にはわかりません", "感情的"] # 例
# 1. JSONフォーマットチェック (20点)
try:
response = json.loads(response_json_str)
if not isinstance(response, dict) or "thought_process" not in response or "final_answer" not in response:
feedback.append("FORMAT_ERROR: 必須キー(thought_process, final_answer)が不足しています。")
return 0, feedback # 重大なエラーは早期終了
score += 20
except json.JSONDecodeError:
feedback.append("FORMAT_ERROR: JSON形式が不正です。")
return 0, feedback
thought_process = response.get("thought_process", "")
final_answer = response.get("final_answer", "")
# 2. 思考プロセスの論理性とステップ遵守 (30点)
# 思考ステップのキーワードと順序チェック
cot_steps = ["質問の意図分析", "関連FAQの特定", "回答の生成と根拠の提示"]
step_found_flags = [step in thought_process for step in cot_steps]
if all(step_found_flags) and \
thought_process.find(cot_steps[0]) < thought_process.find(cot_steps[1]) < thought_process.find(cot_steps[2]):
score += 30
else:
feedback.append("THOUGHT_PROCESS_ERROR: 思考ステップの不足、または順序が不正です。")
# 3. 最終回答の正確性・根拠 (30点)
# 回答がFAQデータ内の情報に基づいているか簡易的にチェック(高度な評価にはNLIが必要)
# FAQ内のキーワードが回答に含まれているか、幻覚がないか
is_accurate_and_based_on_faq = False
if any(re.search(r'\b' + re.escape(word) + r'\b', final_answer, re.IGNORECASE) for faq_item in faq_data for word in faq_item.split() if len(word) > 2):
is_accurate_and_based_on_faq = True
score += 20 # 部分的にFAQに基づいている
# 禁止語句がないか、幻覚がないかのより厳密なチェック (より洗練されたNLIが必要だが、ここではキーワードマッチ)
hallucination_detected = False
for word in final_answer.split():
if len(word) > 2 and not any(word in faq_item for faq_item in faq_data) and word not in user_query.split():
# 回答中の単語がFAQにも質問にもない場合、幻覚の可能性あり(簡易判定)
hallucination_detected = True
break
if not hallucination_detected:
score += 10 # 幻覚がない
else:
feedback.append("HALLUCINATION_ERROR: 回答がFAQデータに基づかない可能性があります。")
# 4. 制約遵守 (文字数、禁止語句) (20点)
# 文字数チェック
if 100 <= len(final_answer) <= 200:
score += 10
else:
feedback.append(f"LENGTH_ERROR: 最終回答の文字数({len(final_answer)}字)が範囲外です。")
# 禁止語句チェック
if not any(term in final_answer or term in thought_process for term in prohibited_terms):
score += 10
else:
feedback.append("PROHIBITED_TERM_ERROR: 禁止された表現が含まれています。")
return score, feedback
# --- 採点ルーブリック ---
# 1. JSONフォーマット完全性: 20点
# 2. 思考プロセスの論理性とステップ遵守 (CoT): 30点
# 3. 最終回答の正確性 (FAQとの一致、非幻覚): 30点 (正確性20点, 非幻覚10点)
# 4. 制約遵守 (文字数、禁止語句): 20点 (文字数10点, 禁止語句10点)
# 合計: 100点
</pre>
<h2 class="wp-block-heading">7. プロンプト→モデル→評価→改良のループ</h2>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["プロンプト設計"] --> B("LLMモデル")
B --> C{"LLM出力"}
C --> D["評価ツール: 自動評価コード"]
D -- 採点 & フィードバック --> E{"評価結果"}
E -- 低スコア/失敗モード検出 --> F["誤り分析"]
F -- 改善案 --> A
E -- 高スコア/合格 --> G["完了/デプロイ"]
</pre></div>
<h2 class="wp-block-heading">8. 失敗モードと抑制手法</h2>
<h3 class="wp-block-heading">8.1. 幻覚 (Hallucination)</h3>
<ul class="wp-block-list">
<li><strong>失敗モード</strong>: 提供されたFAQに存在しない情報を生成したり、事実と異なる内容を述べる。</li>
<li><strong>抑制手法</strong>:
<ul>
<li><strong>System指示</strong>: 「提供されたFAQ情報のみを根拠とし、それ以外の情報は一切追加しないでください。」と強く指示。</li>
<li><strong>検証ステップ</strong>: 生成された回答中の固有表現やキーワードが、入力のFAQデータセット内に存在するかをキーワードマッチ、NLI (Natural Language Inference) モデル、または埋め込みベースの類似度計算で検証。</li>
<li><strong>リトライ戦略</strong>: 検証で幻覚が検出された場合、「提供されたFAQ情報のみを使用して回答を修正してください。幻覚が検出されました。」と追加の指示を与えて再生成を促す。</li>
</ul></li>
</ul>
<h3 class="wp-block-heading">8.2. 様式崩れ (Format Deviation)</h3>
<ul class="wp-block-list">
<li><strong>失敗モード</strong>: JSON形式が不正になる、思考連鎖の指定されたステップが欠落する、順序が狂う。</li>
<li><strong>抑制手法</strong>:
<ul>
<li><strong>System指示</strong>: 「出力は厳密にJSON形式を遵守し、<code>thought_process</code>と<code>final_answer</code>キーを含めてください。また、<code>thought_process</code>は指定されたステップ(質問分析、FAQ特定、回答生成)をこの順序で含めてください。」と明確かつ詳細に指示。</li>
<li><strong>検証ステップ</strong>: Pythonの<code>json.loads()</code>でJSON構造をチェックし、正規表現やキーワードマッチで思考プロセスのステップの存在と順序を検証。パーシングエラーを即座に検出。</li>
<li><strong>リトライ戦略</strong>: 「出力JSON形式が不正です。正しいJSON形式で再度生成してください。」または「思考プロセスのステップが不足しています。指定されたステップを全て含めてください。」と具体的に指示して再生成。</li>
</ul></li>
</ul>
<h3 class="wp-block-heading">8.3. 脱線 (Topic Drifting)</h3>
<ul class="wp-block-list">
<li><strong>失敗モード</strong>: ユーザーの質問やFAQの範囲から逸脱した、無関係な内容を生成する。</li>
<li><strong>抑制手法</strong>:
<ul>
<li><strong>System指示</strong>: 「ユーザーの質問と提供されたFAQデータに厳密に基づいた回答のみを生成してください。関連性のない話題には触れないでください。」と関連性の維持を強調。</li>
<li><strong>検証ステップ</strong>: ユーザーの質問と生成された回答、およびFAQデータとのコサイン類似度(BERTなどの埋め込みを使用)を計算し、閾値以下であれば脱線と判断。</li>
<li><strong>リトライ戦略</strong>: 「回答がユーザーの質問から逸脱しています。質問に焦点を当てて再度回答を生成してください。」と指示。</li>
</ul></li>
</ul>
<h3 class="wp-block-heading">8.4. 禁止事項違反 (Prohibited Content)</h3>
<ul class="wp-block-list">
<li><strong>失敗モード</strong>: 指定された禁止語句(例:「AIの判断」「不明」)を使用したり、不適切な表現を用いる。</li>
<li><strong>抑制手法</strong>:
<ul>
<li><strong>System指示</strong>: 「以下の表現は絶対に使用しないでください: [禁止語句リスト]」と、禁止語句のリストを明示。</li>
<li><strong>検証ステップ</strong>: 生成されたテキスト全体に対して、禁止語句リストとの正規表現マッチングを実行し、違反を検出。</li>
<li><strong>リトライ戦略</strong>: 「禁止された表現が検出されました。これらの表現を使用せずに回答を修正してください。」と明確に指示し、修正版の生成を促す。</li>
</ul></li>
</ul>
<h2 class="wp-block-heading">9. まとめ</h2>
<p>本稿では、LLMの思考連鎖プロンプティングを用いた顧客サポートのFAQ応答システムについて、プロンプト設計、厳格な入出力契約、自動評価手法、そして失敗モードとその抑制策を詳細に記述しました。特に、思考プロセスを明示することで信頼性を高めるCoTプロンプティングの有効性と、厳密な評価基準の重要性を示しました。これらの手法を組み合わせることで、LLMの出力をより制御し、期待される品質と信頼性を実現することが可能です。今後の課題としては、より複雑な推論を必要とするシナリオへのCoT適用、評価の自動化における精度向上(特に幻覚検出)、およびリアルタイムシステムにおけるリトライ戦略の最適化が挙げられます。</p>
LLMの思考連鎖プロンプティング設計と評価
1. ユースケース定義
本稿では、顧客サポートにおけるFAQからの問い合わせ対応を自動化するLLMプロンプトの設計と評価に焦点を当てます。特に、単に回答を提示するだけでなく、なぜその回答に至ったのかの「思考プロセス」を明示することで、ユーザーの信頼性向上と提供情報の透明性を確保することを目指します。LLMは、ユーザーからの自然言語クエリと関連するFAQリストを受け取り、FAQのみを根拠とした適切な回答と、その導出過程を生成します。
2. 制約付き仕様化
LLMの出力は以下の制約に従う必要があります。
- 出力形式: JSONオブジェクトとして、
thought_process
(文字列) と final_answer
(文字列) の2つのキーを持つこと。
- 根拠の明確化:
final_answer
は、提供されたfaq_data
内の情報のみを根拠とすること。thought_process
内でその根拠を明示すること。
- 思考プロセスのステップ:
thought_process
は以下の論理的ステップを順に含むこと。
- 質問の意図分析
- 関連FAQの特定
- 回答の生成と根拠の提示
- 最終回答の文字数:
final_answer
は100文字以上200文字以下とすること。
- 禁止事項: 「推測」「AIによる判断」「不明」「私にはわかりません」といった表現、感情的な言葉、ユーザーの個人情報を要求する行為は禁止。
3. 入出力契約
入力
user_query
: string
– 顧客からの質問。
faq_data
: array<string>
– ユーザーの質問に関連すると想定されるFAQテキストのリスト。
成功時の出力
JSON string
– 上記「制約付き仕様化」で定義された形式のJSONオブジェクト。
例: {"thought_process": "...", "final_answer": "..."}
失敗時の挙動
- FORMAT_ERROR: 出力JSON形式が不正、または必須キーが不足している場合。
{"error_type": "FORMAT_ERROR", "message": "出力JSON形式が不正です。"}
- HALLUCINATION_ERROR: 提供されたFAQデータに基づかない情報が含まれている場合。
{"error_type": "HALLUCINATION_ERROR", "message": "提供されたFAQデータに基づかない情報が含まれています。"}
- PROHIBITED_TERM_ERROR: 禁止された表現が含まれている場合。
{"error_type": "PROHIBITED_TERM_ERROR", "message": "禁止された表現が含まれています。"}
- LENGTH_ERROR:
final_answer
の文字数が指定範囲外の場合。
{"error_type": "LENGTH_ERROR", "message": "最終回答の文字数が範囲外です。"}
- GENERIC_ERROR: その他予期せぬエラーの場合。
{"error_type": "GENERIC_ERROR", "message": "処理中にエラーが発生しました。"}
禁止事項
LLMの出力において、以下の表現や行動は厳しく禁止されます。
「推測」「AIによる判断」「不明」「私にはわかりません」、過度な丁寧語/不快な表現、ユーザーの個人情報を聞き出すような質問。
4. プロンプト設計(最低3種)
4.1. ゼロショットプロンプト
あなたは顧客サポートアシスタントです。以下のFAQデータからユーザーの質問に回答し、その思考プロセスと最終回答をJSON形式で出力してください。
回答はFAQデータのみを根拠とし、他の情報源は参照しないでください。
思考プロセスには「質問の意図分析」「関連FAQの特定」「回答の生成と根拠の提示」のステップを含めてください。
最終回答は100文字以上200文字以下にしてください。
「推測」「AIによる判断」「不明」といった表現は禁止です。
---
ユーザーの質問: {user_query}
FAQデータ: {faq_data}
---
出力JSON:
4.2. 少数例プロンプト
あなたは顧客サポートアシスタントです。以下のFAQデータからユーザーの質問に回答し、その思考プロセスと最終回答をJSON形式で出力してください。
回答はFAQデータのみを根拠とし、他の情報源は参照しないでください。
思考プロセスには「質問の意図分析」「関連FAQの特定」「回答の生成と根拠の提示」のステップを含めてください。
最終回答は100文字以上200文字以下にしてください。
「推測」「AIによる判断」「不明」といった表現は禁止です。
---
例1:
ユーザーの質問: 配送状況を確認するにはどうすればいいですか?
FAQデータ: ["配送状況は、マイページの注文履歴からご確認いただけます。", "ご注文番号が必要です。"]
出力JSON:
{
"thought_process": "1.質問の意図分析: ユーザーは配送状況の確認方法を知りたい。 2.関連FAQの特定: 「マイページの注文履歴からご確認いただけます。」と「ご注文番号が必要です。」が関連。 3.回答の生成と根拠の提示: これらの情報をもとに、具体的な手順と必要な情報をまとめる。",
"final_answer": "配送状況は、弊社のウェブサイトのマイページにある注文履歴からご確認いただけます。ご確認の際には、ご注文番号が必要となりますので、お手元にご準備ください。"
}
---
ユーザーの質問: {user_query}
FAQデータ: {faq_data}
---
出力JSON:
4.3. Chain-of-Thought制約型プロンプト
system:
あなたは顧客サポートアシスタントです。以下の指示に厳密に従い、JSON形式で思考プロセスと最終回答を出力してください。
1. **質問の意図分析**: ユーザーの質問の核心を特定します。
2. **関連FAQの特定**: 提供されたFAQデータの中から、質問に最も関連する情報を選択し、その内容を簡潔にまとめます。
3. **回答の生成と根拠の提示**: 特定したFAQ情報のみを根拠として、ユーザーの質問に対する最終回答を生成します。その際、FAQからの具体的な引用や言い換えを用いて根拠を明示してください。
最終回答は100文字以上200文字以下とし、指定されたFAQデータのみを根拠としてください。
「推測」「AIによる判断」「不明」「私にはわかりません」といった表現は一切禁止です。
user:
ユーザーの質問: {user_query}
FAQデータ: {faq_data}
assistant:
出力JSON:
5. 評価シナリオ
5.1. 正例 (Simple Case)
- ユーザーの質問: “注文履歴はどこで確認できますか?”
- FAQデータ:
["ご注文履歴は、マイページの『注文履歴を見る』からご確認いただけます。"]
- 期待する応答: JSONフォーマットで、FAQに基づいた正確な回答と、規定の思考ステップを含むプロセス。
5.2. 難例 (Complex Case)
- ユーザーの質問: “製品保証と修理について教えてください。”
- FAQデータ:
["製品保証期間は購入日から1年間です。", "保証期間内の自然故障は無償修理の対象です。", "お客様の過失による破損は保証期間内でも有償修理となります。", "保証期間外の修理はすべて有償です。", "修理受付は弊社ウェブサイトのサポートページから可能です。"]
- 期待する応答: 複数のFAQ情報を統合し、条件分岐(保証期間内外、故障原因)を考慮した回答と、明確な思考プロセス。
5.3. コーナーケース (No Relevant FAQ)
- ユーザーの質問: “私の個人情報が外部に漏洩していないか確認したいのですが。”
- FAQデータ:
["弊社は家電製品の販売を専門としております。", "個人情報の取り扱いについてはプライバシーポリシーをご確認ください。プライバシーポリシーはウェブサイト下部にリンクがあります。"]
- 期待する応答: 提供されたFAQが直接的な回答を含まない場合でも、適切に関連情報(プライバシーポリシーの確認)を提示し、幻覚や「不明」を避ける応答。
6. 自動評価の擬似コード
import json
import re
def evaluate_llm_response(response_json_str: str, user_query: str, faq_data: list[str]) -> tuple[int, list[str]]:
"""
LLMの応答を評価する関数。
Args:
response_json_str: LLMからの出力JSON文字列。
user_query: ユーザーの質問。
faq_data: 評価に使用されたFAQデータのリスト。
Returns:
tuple[int, list[str]]: 採点スコアとフィードバックメッセージのリスト。
"""
score = 0
feedback = []
faq_data_str = " ".join(faq_data)
prohibited_terms = ["推測", "AIによる判断", "不明", "私にはわかりません", "感情的"] # 例
# 1. JSONフォーマットチェック (20点)
try:
response = json.loads(response_json_str)
if not isinstance(response, dict) or "thought_process" not in response or "final_answer" not in response:
feedback.append("FORMAT_ERROR: 必須キー(thought_process, final_answer)が不足しています。")
return 0, feedback # 重大なエラーは早期終了
score += 20
except json.JSONDecodeError:
feedback.append("FORMAT_ERROR: JSON形式が不正です。")
return 0, feedback
thought_process = response.get("thought_process", "")
final_answer = response.get("final_answer", "")
# 2. 思考プロセスの論理性とステップ遵守 (30点)
# 思考ステップのキーワードと順序チェック
cot_steps = ["質問の意図分析", "関連FAQの特定", "回答の生成と根拠の提示"]
step_found_flags = [step in thought_process for step in cot_steps]
if all(step_found_flags) and \
thought_process.find(cot_steps[0]) < thought_process.find(cot_steps[1]) < thought_process.find(cot_steps[2]):
score += 30
else:
feedback.append("THOUGHT_PROCESS_ERROR: 思考ステップの不足、または順序が不正です。")
# 3. 最終回答の正確性・根拠 (30点)
# 回答がFAQデータ内の情報に基づいているか簡易的にチェック(高度な評価にはNLIが必要)
# FAQ内のキーワードが回答に含まれているか、幻覚がないか
is_accurate_and_based_on_faq = False
if any(re.search(r'\b' + re.escape(word) + r'\b', final_answer, re.IGNORECASE) for faq_item in faq_data for word in faq_item.split() if len(word) > 2):
is_accurate_and_based_on_faq = True
score += 20 # 部分的にFAQに基づいている
# 禁止語句がないか、幻覚がないかのより厳密なチェック (より洗練されたNLIが必要だが、ここではキーワードマッチ)
hallucination_detected = False
for word in final_answer.split():
if len(word) > 2 and not any(word in faq_item for faq_item in faq_data) and word not in user_query.split():
# 回答中の単語がFAQにも質問にもない場合、幻覚の可能性あり(簡易判定)
hallucination_detected = True
break
if not hallucination_detected:
score += 10 # 幻覚がない
else:
feedback.append("HALLUCINATION_ERROR: 回答がFAQデータに基づかない可能性があります。")
# 4. 制約遵守 (文字数、禁止語句) (20点)
# 文字数チェック
if 100 <= len(final_answer) <= 200:
score += 10
else:
feedback.append(f"LENGTH_ERROR: 最終回答の文字数({len(final_answer)}字)が範囲外です。")
# 禁止語句チェック
if not any(term in final_answer or term in thought_process for term in prohibited_terms):
score += 10
else:
feedback.append("PROHIBITED_TERM_ERROR: 禁止された表現が含まれています。")
return score, feedback
# --- 採点ルーブリック ---
# 1. JSONフォーマット完全性: 20点
# 2. 思考プロセスの論理性とステップ遵守 (CoT): 30点
# 3. 最終回答の正確性 (FAQとの一致、非幻覚): 30点 (正確性20点, 非幻覚10点)
# 4. 制約遵守 (文字数、禁止語句): 20点 (文字数10点, 禁止語句10点)
# 合計: 100点
7. プロンプト→モデル→評価→改良のループ
graph TD
A["プロンプト設計"] --> B("LLMモデル")
B --> C{"LLM出力"}
C --> D["評価ツール: 自動評価コード"]
D -- 採点 & フィードバック --> E{"評価結果"}
E -- 低スコア/失敗モード検出 --> F["誤り分析"]
F -- 改善案 --> A
E -- 高スコア/合格 --> G["完了/デプロイ"]
8. 失敗モードと抑制手法
8.1. 幻覚 (Hallucination)
- 失敗モード: 提供されたFAQに存在しない情報を生成したり、事実と異なる内容を述べる。
- 抑制手法:
- System指示: 「提供されたFAQ情報のみを根拠とし、それ以外の情報は一切追加しないでください。」と強く指示。
- 検証ステップ: 生成された回答中の固有表現やキーワードが、入力のFAQデータセット内に存在するかをキーワードマッチ、NLI (Natural Language Inference) モデル、または埋め込みベースの類似度計算で検証。
- リトライ戦略: 検証で幻覚が検出された場合、「提供されたFAQ情報のみを使用して回答を修正してください。幻覚が検出されました。」と追加の指示を与えて再生成を促す。
8.2. 様式崩れ (Format Deviation)
- 失敗モード: JSON形式が不正になる、思考連鎖の指定されたステップが欠落する、順序が狂う。
- 抑制手法:
- System指示: 「出力は厳密にJSON形式を遵守し、
thought_process
とfinal_answer
キーを含めてください。また、thought_process
は指定されたステップ(質問分析、FAQ特定、回答生成)をこの順序で含めてください。」と明確かつ詳細に指示。
- 検証ステップ: Pythonの
json.loads()
でJSON構造をチェックし、正規表現やキーワードマッチで思考プロセスのステップの存在と順序を検証。パーシングエラーを即座に検出。
- リトライ戦略: 「出力JSON形式が不正です。正しいJSON形式で再度生成してください。」または「思考プロセスのステップが不足しています。指定されたステップを全て含めてください。」と具体的に指示して再生成。
8.3. 脱線 (Topic Drifting)
- 失敗モード: ユーザーの質問やFAQの範囲から逸脱した、無関係な内容を生成する。
- 抑制手法:
- System指示: 「ユーザーの質問と提供されたFAQデータに厳密に基づいた回答のみを生成してください。関連性のない話題には触れないでください。」と関連性の維持を強調。
- 検証ステップ: ユーザーの質問と生成された回答、およびFAQデータとのコサイン類似度(BERTなどの埋め込みを使用)を計算し、閾値以下であれば脱線と判断。
- リトライ戦略: 「回答がユーザーの質問から逸脱しています。質問に焦点を当てて再度回答を生成してください。」と指示。
8.4. 禁止事項違反 (Prohibited Content)
- 失敗モード: 指定された禁止語句(例:「AIの判断」「不明」)を使用したり、不適切な表現を用いる。
- 抑制手法:
- System指示: 「以下の表現は絶対に使用しないでください: [禁止語句リスト]」と、禁止語句のリストを明示。
- 検証ステップ: 生成されたテキスト全体に対して、禁止語句リストとの正規表現マッチングを実行し、違反を検出。
- リトライ戦略: 「禁止された表現が検出されました。これらの表現を使用せずに回答を修正してください。」と明確に指示し、修正版の生成を促す。
9. まとめ
本稿では、LLMの思考連鎖プロンプティングを用いた顧客サポートのFAQ応答システムについて、プロンプト設計、厳格な入出力契約、自動評価手法、そして失敗モードとその抑制策を詳細に記述しました。特に、思考プロセスを明示することで信頼性を高めるCoTプロンプティングの有効性と、厳密な評価基準の重要性を示しました。これらの手法を組み合わせることで、LLMの出力をより制御し、期待される品質と信頼性を実現することが可能です。今後の課題としては、より複雑な推論を必要とするシナリオへのCoT適用、評価の自動化における精度向上(特に幻覚検出)、およびリアルタイムシステムにおけるリトライ戦略の最適化が挙げられます。
コメント