- Authors

- Name
- Youngju Kim
- @fjvbn20031
- プロンプトエンジニアリングがまだ重要な理由
- 技術1:システムプロンプトの設計原則
- 技術2:Few-Shotプロンプティング
- 技術3:Chain-of-Thought(CoT)プロンプティング
- 技術4:構造化出力(Structured Output)
- 技術5:XMLタグによる構造化(Claude特効)
- 技術6:Role + Context + Constraintパターン
- プロンプトのバージョン管理:コードと同様に管理する
- モデル別最適化のヒント
- プロンプトデバッグの方法論
- まとめ:プロンプトエンジニアリングはエンジニアリング技術だ
プロンプトエンジニアリングがまだ重要な理由
「LLMが賢くなり過ぎて、プロンプトエンジニアリングはもう不要になるのでは?」
よく聞かれる質問です。答えは「いいえ」。その理由があります。
モデルの能力 × プロンプトの品質 = 出力の品質
最高のモデルでも悪いプロンプトを与えれば悪い結果になります。よく設計されたプロンプトは、同じモデルから20〜40%以上の性能差を生み出せます。タスク特化では、小さなモデルに優れたプロンプトを与えた結果が、大きなモデルに雑なプロンプトを与えた結果を上回ることもあります。
2025年も新しいモデルが登場し続けますが、優れたプロンプト作成スキルはモデルが変わっても使える移植可能な技術です。
技術1:システムプロンプトの設計原則
システムプロンプトはLLMの「設定値」です。多くの開発者がここを軽視します。
# 悪いシステムプロンプト(多くの人がこう始める)
bad_prompt = "You are a helpful assistant."
# 問題:曖昧すぎてモデルが何をすべきかわからない
# COSTARフレームワークを使った良いシステムプロンプト
good_prompt = """
## Role(役割)
あなたはTechCorpのシニア日本語カスタマーサービス専門家です。
## Context(文脈)
TechCorpはHR管理向けB2B SaaSソフトウェアを販売しています。
顧客は主に100〜5,000名規模の企業のHRマネージャーです。
## Objective(目標)
顧客の問題を解決し、製品に関する質問に答えます。
請求関連の問題はfinance@techcorp.comにエスカレーションしてください。
## Style(スタイル)
- 丁寧で温かみのある日本語
- 回答は200文字以内
- 必ずフォローアップの質問で締めくくる
## Tone(トーン)
プロフェッショナル、共感的、解決志向
## Audience(対象)
日本のHRマネージャー、多くは非技術系ユーザー
## Response Format(形式)
1. 問題を認識(「はい、[問題]についてお手伝いします」)
2. 解決策の提示(必要に応じてステップ別)
3. 締め:「他にお手伝いできることはございますか?」
"""
COSTARフレームワーク:Context、Objective、Style、Tone、Audience、Response Format。この6つを明示すると予測可能で一貫した結果が得られます。
技術2:Few-Shotプロンプティング
「言葉で説明するより例を見せる方が早い」という原則です。
# Zero-shot(例なし)
zero_shot = """
このレビューの感情を分類してください:「配送が遅すぎました」
"""
# 分類はできるが、出力形式や一貫性にばらつきが出ることがある
# Few-shot(例あり)
few_shot = """
レビューの感情を「ポジティブ」「ネガティブ」「ニュートラル」に分類してください。
レビュー:「本当に良い製品です!」→ ポジティブ
レビュー:「配送は少し遅かったですが製品には満足です」→ ニュートラル
レビュー:「完全に不良品です。返金したいです」→ ネガティブ
レビュー:「値段の割には普通です」→ ニュートラル
レビュー:「配送が遅すぎました」→ """
# 出力:ネガティブ(はるかに一貫性が高い)
Few-shotのポイント:
- 例の品質:典型的なケースを含める
- 多様性:エッジケースも見せる
- 数:通常3〜8件が最適(多ければ良いとは限らない)
- 順序:最後の例が出力に最も影響する(Recency Bias)
技術3:Chain-of-Thought(CoT)プロンプティング
「考える過程」を見せてもらうよう頼むと、複雑な推論能力が劇的に向上します。
# CoTなし(不安定な結果)
no_cot = """
電車が2時間で120km走り、その後3時間で180km走りました。
平均速度はいくつですか?
"""
# LLMが (120/2 + 180/3) / 2 = 60 と誤った方法で計算する可能性がある
# CoTあり(正確な結果)
with_cot = """
電車が2時間で120km走り、その後3時間で180km走りました。
平均速度はいくつですか?
ステップごとに考えてみましょう:
"""
# LLM:「総距離 = 120 + 180 = 300km
# 総時間 = 2 + 3 = 5時間
# 平均速度 = 300 / 5 = 60 km/h」
# 正解!
# Zero-shot CoT(最もシンプルな形)
zero_shot_cot = """
問題:[複雑な推論問題]
解答:ステップごとに考えてみましょう。
"""
機能する理由:LLMは自己回帰的にトークンを生成します。中間推論ステップをトークンとして生成することで、後続のトークンがその推論を「参照」でき、最終的な答えの精度が上がります。
注意:o1やo3などの推論モデルは内部的にCoTを実行します。これらのモデルには「ステップごとに考えて」ではなく、問題を明確に記述することに集中してください。
技術4:構造化出力(Structured Output)
プロダクションシステムでLLMの出力をパースする必要があるなら、必ず構造化出力を使いましょう。
import json
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
# 方法1:JSONモード(シンプルなケース)
response = client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[{
"role": "user",
"content": """
以下のテキストから製品情報を抽出してJSONで返してください:
「iPhone 15 Pro Max、256GB、スペースブラック、定価199,800円」
返却形式:{"name": ..., "storage": ..., "color": ..., "price_jpy": ...}
"""
}]
)
data = json.loads(response.choices[0].message.content)
# 方法2:Structured Outputs(型安全、より安定)
class ProductInfo(BaseModel):
name: str
storage: str
color: str
price_jpy: int
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[{
"role": "user",
"content": "iPhone 15 Pro Max、256GB、スペースブラック、定価199,800円"
}],
response_format=ProductInfo
)
product = response.choices[0].message.parsed
print(product.price_jpy) # 199800(int型を保証)
OpenAIのStructured OutputsはJSONスキーマへの100%準拠を保証します。パースエラーがなくなります。
技術5:XMLタグによる構造化(Claude特効)
Claudeは特にXMLタグで構造化されたプロンプトに良く反応します。AnthropicがClaudeの訓練にXML構造を多用したためと考えられます。
import anthropic
client = anthropic.Anthropic()
prompt = """
<task>
以下のドキュメントを要約してください。
</task>
<document>
[長いドキュメントの内容をここに]
</document>
<constraints>
- 最大3つの箇条書き
- 各箇条書き:1〜2文
- 実行可能なアイテムに集中
- 専門用語は平易な言葉に言い換える
</constraints>
<output_format>
以下のJSONで返してください:
{
"summary_bullets": ["...", "...", "..."],
"key_action": "最も重要な実行アイテム1つ"
}
</output_format>
"""
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
XMLタグを使うとLLMが各セクションの役割を明確に理解し、指示をより正確に守ります。このパターンはClaude以外のモデルでも効果的です。
技術6:Role + Context + Constraintパターン
最も汎用的で信頼性の高いプロダクションプロンプトパターンです。
def create_production_prompt(
role: str,
context: str,
task: str,
constraints: list[str],
output_format: str
) -> str:
constraints_text = "\n".join(f"- {c}" for c in constraints)
return f"""# Role(役割)
{role}
# Context(文脈)
{context}
# Task(タスク)
{task}
# Constraints(制約)
{constraints_text}
# Output Format(出力形式)
{output_format}"""
# 実際の使用例
prompt = create_production_prompt(
role="あなたはZ世代をターゲットにした10年キャリアの日本語コピーライターです。",
context="クライアント:スタートアップコーヒーブランド「BREW」。新製品コールドブリューの発売。",
task="Instagramキャプション3バリエーションを作成してください。",
constraints=[
"各キャプションは50文字以内",
"絵文字を1〜2個含める",
"価格やプロモーションの言及禁止",
"ハッシュタグは含めない"
],
output_format="JSON配列で返してください:['キャプション1', 'キャプション2', 'キャプション3']"
)
このパターンの利点:
- コードでプロンプトを動的に生成できる
- 各コンポーネントを独立して修正できる
- A/Bテストがしやすい
プロンプトのバージョン管理:コードと同様に管理する
プロダクションではプロンプトはコードです。バージョン管理が必要です。
# 悪い方法:ビジネスロジックにハードコード
def summarize(text):
prompt = f"要約してください:{text}" # 追跡不可能、テスト不可能
return call_llm(prompt)
# 良い方法:プロンプトをバージョン管理されたアーティファクトとして管理
class PromptManager:
def __init__(self):
self.prompts = {}
self.active_versions = {}
def register(self, name: str, version: str, template: str):
self.prompts[f"{name}_v{version}"] = template
def get(self, name: str, version: str = None) -> str:
v = version or self.active_versions.get(name, "1")
return self.prompts[f"{name}_v{v}"]
def set_active(self, name: str, version: str):
self.active_versions[name] = version
pm = PromptManager()
pm.register("summarize", "1", "要約してください:{text}")
pm.register("summarize", "2", "あなたはビジネスアナリストです。3行以内で要約:{text}")
pm.set_active("summarize", "2")
より体系的な管理にはLangSmithやPromptLayerを検討してください。プロンプトのバージョン管理、A/Bテスト、パフォーマンスモニタリングを統合して提供しています。
モデル別最適化のヒント
同じプロンプトが全てのモデルで同様に機能するわけではありません:
GPT-4o:
- 明確で直接的な指示を好む
- Markdown形式を良く守る
- 「あなたは[役割]です」スタイルに良く反応
Claude 3.5/3.7:
- XMLタグ構造に特に良く反応
- 長いシステムプロンプトを消化できる
- 強い制約(「必ず〜してください」「絶対に〜しないで」)に従順
Gemini:
- マルチモーダルコンテキストに強い
- 検索グラウンディング(grounding)が内蔵
オープンソース(Llama、Mistralなど):
- 各モデルの特定チャットテンプレートを必ず使用
- 商業モデルより指示追従が弱い場合がある
- より明示的で具体的な指示が必要
プロンプトデバッグの方法論
プロンプトが期待通りに動かないとき:
1. 温度(Temperature)を0に設定
→ 再現可能な結果で診断
2. 指示をより具体的に
→ 「うまく書いて」→「プロフェッショナルなトーン、能動態、50文字以内」
3. 出力例を追加(Few-shot)
→ 言葉での説明より例示が効果的
4. してはいけないことを明示
→ ネガティブ制約でエラーケースが減少
5. Chain-of-thoughtを追加
→ 「ステップごとに考えましょう」の一言が複雑な推論精度を大幅に向上
6. プロンプト長の最適化
→ 長ければ良いとは限らない。不要な部分を削除
まとめ:プロンプトエンジニアリングはエンジニアリング技術だ
プロンプトエンジニアリングは魔法ではありません。テスト・測定・反復というエンジニアリング的アプローチで改善する技術です。
実践的なアドバイス:
- シンプルに始めて段階的に改善:基本的なプロンプトから始め、問題が発生したら改善
- プロンプトをコードとして管理:バージョン管理、テスト、デプロイパイプラインを構築
- 定量的に評価:「良くなった気がする」ではなく測定可能な指標で判断
- モデルアップデートを監視:新モデルバージョンで既存プロンプトの動作が変わる可能性がある
良いプロンプトは良いコードのように、時間が経っても保守可能で、テスト可能で、変更に耐えられる設計であるべきです。