生成AI入門 2026.04.19
Claude API プロンプト設計完全ガイド【2026年版】5つのテクニックとコード実装
テクニック1:XMLタグで構造化する(Claude固有の強み)
# xml_structured_prompt.py
# ClaudeはXMLタグによる構造化を得意とする
import anthropic
import os
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
# ❌ 非構造化(情報が混在して解釈が曖昧になりやすい)
bad_prompt = """
あなたはシニアエンジニアです。以下のコードのバグを修正してください。
コードはPythonで書かれています。エラーはZeroDivisionErrorです。
def calc(x, y): return x / y
修正後のコードとその説明をお願いします。
"""
# ✅ XML構造化(セクションが明確でClaudeが正確に解釈)
good_prompt = """
<role>シニアPythonエンジニア</role>
<task>以下のコードのバグを修正して、修正後のコードと説明を返してください</task>
<context>
<language>Python 3.11</language>
<error>ZeroDivisionError: division by zero</error>
</context>
<code>
def calc(x, y):
return x / y
</code>
<output_format>
1. 修正後のコード(コードブロック)
2. バグの原因(1-2文)
3. 修正方法の説明(1-2文)
</output_format>
"""
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=512,
messages=[{"role": "user", "content": good_prompt}]
)
print(response.content[0].text)
テクニック2:Chain of Thought(段階的推論)
# chain_of_thought.py
# 複雑な問題はステップバイステップで考えさせる
# ❌ 直接答えを求める(複雑な問題では精度が落ちる)
direct = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=64,
messages=[{"role": "user", "content": "1001人のスタジアムに3/7の確率で左利きの人がいる。左利きの人数は?"}]
)
# ✅ Chain of Thought(推論を明示させる)
cot = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=256,
messages=[{"role": "user", "content": """
1001人のスタジアムに3/7の確率で左利きの人がいる。左利きの人数は?
ステップバイステップで計算して、最後に答えを出してください。
<thinking>
1. 計算式: ...
2. 計算: ...
3. 答え: ...
</thinking>
"""}]
)
print("直接:", direct.content[0].text)
print("CoT:", cot.content[0].text)
テクニック3:システムプロンプトのキャッシュ(コスト90%削減)
# cached_system_prompt.py
# 長いシステムプロンプトを毎回送るコストをキャッシュで削減
SYSTEM_PROMPT = """
あなたは株式会社〇〇のカスタマーサポートAIです。
# 会社情報
- 設立: 2020年
- 本社: 東京都渋谷区
- 主要製品: クラウド型在庫管理システム
# 回答ポリシー
- 常に丁寧な日本語で回答する
- 技術的な質問は詳しく、料金に関する質問は料金ページに誘導する
- 回答できない場合は「担当者にお繋ぎします」と伝える
# よくある質問と回答
Q: 無料トライアルはありますか?
A: はい、30日間の無料トライアルを提供しています。
Q: 導入期間はどのくらいですか?
A: 通常2週間〜1ヶ月程度です。
...
""" # 実際は数千字になることが多い
def answer_question(question: str) -> str:
response = client.messages.create(
model="claude-haiku-4-5-20251001", # カスタマーサポートはHaikuが低コスト
max_tokens=256,
system=[{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"} # ← これでキャッシュ有効
}],
messages=[{"role": "user", "content": question}]
)
usage = response.usage
cache_hit = getattr(usage, "cache_read_input_tokens", 0)
if cache_hit > 0:
print(f"キャッシュヒット: {cache_hit}トークン節約")
return response.content[0].text
# 2回目以降はシステムプロンプトのトークンが90%割引になる
answer_question("料金はいくらですか?")
answer_question("導入サポートはありますか?")
テクニック4:Few-Shotで出力フォーマットを固定する
# few_shot_format.py
# 例を見せることで、出力形式を厳密にコントロールする
FEW_SHOT_PROMPT = """
製品レビューを以下のJSON形式で分析してください。
<examples>
入力: "配送が遅かったけど、商品は良かった。また買います"
出力: {"sentiment": "positive", "rating": 4, "aspects": {"delivery": "negative", "product": "positive"}, "intent": "repurchase"}
入力: "全然使えない。返品します"
出力: {"sentiment": "negative", "rating": 1, "aspects": {"usability": "negative"}, "intent": "return"}
</examples>
分析するレビュー:
{review}
JSONのみを出力してください。説明は不要です。
"""
import json
def analyze_review(review: str) -> dict:
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=128,
messages=[{"role": "user", "content": FEW_SHOT_PROMPT.format(review=review)}]
)
return json.loads(response.content[0].text)
result = analyze_review("思ったより小さかったけど品質は◎。リピートします!")
print(result)
# {"sentiment": "positive", "rating": 4, "aspects": {"size": "negative", "quality": "positive"}, "intent": "repurchase"}
テクニック5:プレフィリングで出力を誘導する
# prefilling.py
# assistantの最初の数文字を指定して、出力形式を強制する
def extract_json_only(text: str) -> dict:
"""JSONのみを確実に出力させる(コードブロックなし)"""
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=256,
messages=[
{"role": "user", "content": f"以下のテキストを解析してJSONで出力してください: {text}"},
{"role": "assistant", "content": "{"}, # ← プレフィリング: JSONで始まることを強制
]
)
# "{" + Claudeの続き = 完全なJSON
return json.loads("{" + response.content[0].text)
# もっと強力な使い方: 特定のフィールドを先に入れる
def force_field(text: str) -> dict:
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=128,
messages=[
{"role": "user", "content": f"商品名を抽出してJSONで返してください: {text}"},
{"role": "assistant", "content": '{"product_name": "'}, # フィールド名を指定
]
)
# 不完全なJSONを補完
return {"product_name": response.content[0].text.split('"')[0]}
あわせて読みたい
- プロンプトとは?Claude・ChatGPTで質問の質を上げる5つのコツ
- Claude Sonnet APIコスト完全解説|トークン計算・バッチ割引・月額試算
- Claude 200Kトークンの実用ガイド|コスト計算・大規模処理コード