本記事はLLMを活用したアプリケーション開発におけるプロンプト設計と評価の実践ガイドです。
LLMプロンプト設計と評価実践ガイド:効果的な対話システム構築に向けて
本稿では、LLM(大規模言語モデル)を活用したアプリケーション開発における、プロンプトの設計から評価、そして改良に至るまでの一連のプロセスを解説します。特に、具体的なユースケースを想定し、制約付きの仕様化、多様なプロンプト設計、自動評価手法、そして失敗モードへの対策に焦点を当てます。
ユースケース定義
本ガイドでは、「顧客からの製品問い合わせをAIが初期対応し、適切な部門へのルーティングと初回応答のドラフト生成を自動化するシステム」をユースケースとして定義します。このシステムは、顧客体験の向上と社内業務効率化を目指します。
制約付き仕様化
LLMの出力を実用的なものにするためには、明確な入出力契約と制約を設けることが不可欠です。
入出力契約
入力形式:
顧客からの問い合わせテキスト。
最大文字数: 500文字。
言語: 日本語。
出力形式:
JSON形式。以下のキーを持つオブジェクトを厳守する。
{ "department": "部門名", "summary": "問い合わせ要約", "draft_response": "初回応答ドラフト" }departmentの値は必ず以下のいずれかに限定する: “技術サポート”, “営業”, “経理”, “その他”。summaryは入力テキストの主要な内容を簡潔に20〜50字でまとめる。draft_responseは敬語を用いた丁寧な言葉遣いで、初回応答として適切な内容(50〜100字程度)を生成する。
失敗時の挙動:
JSONパースエラーを防ぐため、常に有効なJSON形式で出力する。
問い合わせ内容が不明確、または判断が困難な場合は、
departmentを “その他” とし、draft_responseには「恐れ入りますが、詳細を伺わせていただくため、改めてお問い合わせください。」といった旨を記載する。出力の生成に失敗した場合(例: モデルが応答しない)、空のJSON
{}ではなく、エラーメッセージを含む固定JSON(例:{"error": "internal_server_error"})を返す。
禁止事項:
顧客の個人情報(氏名、電話番号、メールアドレスなど)を出力に含めない。
不適切な表現、ヘイトスピーチ、差別的な内容を生成しない。
誤った情報や存在しない製品情報などを生成しない。
プロンプト設計
以下に、異なるアプローチによる3種類のプロンプト案を提示します。
1. ゼロショットプロンプト
モデルにタスクの例をほとんど示さず、指示のみで期待する出力を促します。
あなたは弊社の顧客対応アシスタントです。
顧客からの問い合わせ内容を分析し、以下のJSON形式で応答してください。
出力形式の厳守:
```json
{
"department": "部門名",
"summary": "問い合わせ要約",
"draft_response": "初回応答ドラフト"
}
```
"department"は"技術サポート", "営業", "経理", "その他"のいずれかです。
"summary"は20〜50字で、"draft_response"は50〜100字で生成してください。
個人情報や不適切な内容は含めないでください。
問い合わせ:
{{問い合わせテキスト}}
2. 少数例(Few-shot)プロンプト
いくつかの入力例とその期待される出力例を提示することで、モデルにタスクのパターンを学習させます。
あなたは弊社の顧客対応アシスタントです。
顧客からの問い合わせ内容を分析し、以下のJSON形式で応答してください。
いくつかの例を参考にしてください。
出力形式の厳守:
```json
{
"department": "部門名",
"summary": "問い合わせ要約",
"draft_response": "初回応答ドラフト"
}
```
"department"は"技術サポート", "営業", "経理", "その他"のいずれかです。
"summary"は20〜50字で、"draft_response"は50〜100字で生成してください。
個人情報や不適切な内容は含めないでください。
例1:
問い合わせ:
製品Aの最新バージョンで発生しているバグについて教えてください。
出力:
```json
{
"department": "技術サポート",
"summary": "製品Aの最新バージョンにおけるバグに関する問い合わせ",
"draft_response": "製品Aのバグに関するお問い合わせありがとうございます。担当部署にて詳細を確認し、改めてご連絡いたしますので、恐れ入りますが今しばらくお待ちください。"
}
```
例2:
問い合わせ:
新製品Bの導入を検討していますが、見積もりをお願いできますか?
出力:
```json
{
"department": "営業",
"summary": "新製品Bの導入検討と見積もり依頼",
"draft_response": "新製品Bにご興味をお持ちいただきありがとうございます。見積もりについて承りました。担当営業より追ってご連絡させていただきますので、少々お待ちください。"
}
```
問い合わせ:
{{問い合わせテキスト}}
3. Chain-of-Thought(CoT)制約型プロンプト
モデルに直接答えを出すのではなく、段階的な思考プロセスを経てから最終出力を生成するよう促します。これにより、複雑なタスクでの精度向上や、モデルの「思考」の透明化が期待できます。
あなたは弊社の顧客対応アシスタントです。
顧客からの問い合わせ内容を分析し、以下のステップで思考してからJSON形式で応答してください。
ステップ1: 問い合わせの意図を簡潔に要約し、考えられる部門をリストアップする。
ステップ2: 最も適切な部門を一つ選択し、その理由を述べる。
ステップ3: 顧客への初回応答ドラフトの主要なポイントを箇条書きでまとめる。
ステップ4: 上記の思考プロセスに基づき、最終的なJSON形式の出力を生成する。
出力形式の厳守:
```json
{
"department": "部門名",
"summary": "問い合わせ要約",
"draft_response": "初回応答ドラフト"
}
```
"department"は"技術サポート", "営業", "経理", "その他"のいずれかです。
"summary"は20〜50字で、"draft_response"は50〜100字で生成してください。
個人情報や不適切な内容は含めないでください。
問い合わせ:
{{問い合わせテキスト}}
評価
プロンプトの効果を客観的に測るためには、体系的な評価プロセスが必要です。
評価シナリオ
モデルの様々な挙動をテストするため、以下のシナリオを考案します。
- 正例: 明確な意図を持つ問い合わせ。
- 「製品Cの請求書が届かないのですが、確認をお願いできますでしょうか。」
- 「ウェブサイトのログインパスワードを忘れました。リセット方法を教えてください。」
- 難例: 複数の部門に関連する可能性のある問い合わせや、曖昧な表現。
- 「製品Dの機能について聞きたいのですが、同時に契約プランの見直しも検討しています。」
- 「最近、システムが遅い気がします。何が原因でしょうか?」
- コーナーケース: 特殊なケースや、モデルが誤動作しやすい状況。
- 短すぎる/長すぎる問い合わせ: 「遅い」
- 誤字脱字が多い問い合わせ: 「さいしんのぷろだくとについぇ」
- 個人情報を含む問い合わせ: 「私の名前は山田太郎で、電話番号は090-XXXX-XXXXです。…」
自動評価(Python実装例)
Pythonを想定した自動評価のコードを以下に示します。
import json
import re
def evaluate_llm_output(llm_output_text: str, original_query: str) -> dict:
"""
LLMの出力を評価する関数。
"""
results = {
"json_parseable": False,
"department_valid": False,
"summary_length_valid": False,
"response_length_valid": False,
"no_pii_detected": True,
"overall_score": 0
}
try:
output_json = json.loads(llm_output_text)
results["json_parseable"] = True
except json.JSONDecodeError:
return results
required_keys = ["department", "summary", "draft_response"]
if all(key in output_json for key in required_keys):
valid_departments = ["技術サポート", "営業", "経理", "その他"]
if output_json["department"] in valid_departments:
results["department_valid"] = True
summary_len = len(output_json.get("summary", ""))
if 20 <= summary_len <= 50:
results["summary_length_valid"] = True
response_len = len(output_json.get("draft_response", ""))
if 50 <= response_len <= 100:
results["response_length_valid"] = True
pii_patterns = [
r'\d{3}-\d{4}-\d{4}',
r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}',
r'山田太郎|田中花子'
]
combined_text = output_json.get("summary", "") + output_json.get("draft_response", "")
for pattern in pii_patterns:
if re.search(pattern, combined_text):
results["no_pii_detected"] = False
break
score = 0
if results["json_parseable"]: score += 20
if results["department_valid"]: score += 20
if results["summary_length_valid"]: score += 10
if results["response_length_valid"]: score += 10
if results["no_pii_detected"]: score += 20
results["overall_score"] = score
return results
プロンプト改良のループ
プロンプトの設計と評価は、一度きりの作業ではなく、継続的なループとして実施されます。
graph TD
A["要求定義・ユースケース定義"] --> P["プロンプト設計"];
P -- |プロンプトを適用| --> M[LLM];
M -- |JSON出力| --> E["評価システム"];
E -- |評価結果を生成| --> R["評価レポート"];
R -- |改善点を特定| --> A_prime["分析と改良"];
A_prime -- |プロンプトを修正| --> P;
失敗モードと抑制手法
LLMは強力ですが、完璧ではありません。特定の状況下で望ましくない出力を生成する「失敗モード」を理解し、その抑制策を講じることが重要です。
| 失敗モード | 説明 | 抑制手法 |
|---|---|---|
| 幻覚 (Hallucination) | 事実に基づかない情報を生成する。 | CoTによる思考プロセスの明示要求、外部データソース(RAGなど)との連携、出力に対するファクトチェックステップの導入。 |
| 様式崩れ | 指定されたJSON形式や文字数制限などを守れない。 | Systemプロンプトでの厳密なフォーマット指示、少数例の提示、出力後のバリデーション(正規表現、JSONスキーマ)、モデルのリトライ戦略。 |
| 脱線 (Off-topic) | 指示されたタスクや役割から逸脱し、無関係な情報を生成する。 | Systemプロンプトでの役割とタスクの明確な定義、CoTによる思考制約、入力フィルタリング、出力フィルタリング。 |
| 禁止事項の生成 | 個人情報、不適切な表現、ヘイトスピーチなどを出力に含めてしまう。 | Systemプロンプトでの明確な禁止事項の指示、出力に対するキーワードフィルタリング、固有表現認識(NER)による個人情報マスキング、安全性分類モデルによる出力チェック。 |
まとめ
本記事では、LLMプロンプトの設計から評価、改良に至る実践的なプロセスを解説しました。LLMの能力を最大限に引き出し、ビジネス要件に合致するAIアプリケーションを構築するためには、単にプロンプトを記述するだけでなく、入出力の明確な契約定義、多角的な評価、そして失敗モードへの対策が不可欠です。これらの手法を継続的に適用することで、より堅牢で信頼性の高いLLMシステムを構築できるでしょう。
この記事の更新履歴
この記事は、生成AIを活用した自動レビュー・更新フローにより内容を見直し、必要な修正を反映しています。
2026年9月16日
- 変更HTML直接記述となっていたプロンプト例の表示をWordPress標準のコードブロック構造に修正しました。
- 削除まとめ部分に混入していた不要な読点を削除し、プレースホルダー表現を修正しました。

