AIコーディング 2026.04.23
Claude Codeでプロンプト自動A/BテストするPythonコード【5分実装】
プロンプトA/Bテストの仕組み
Step 1: テストしたいプロンプトバリエーションを定義
Step 2: 各プロンプトを同じテストケースで実行(並列)
Step 3: 結果を自動スコアリングして最優秀プロンプトを選定
基本実装(シングルテスト)
# prompt_ab_test.py
# 複数プロンプトを自動A/Bテストして最優秀を選ぶ
import anthropic
from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass
from typing import Callable
client = anthropic.Anthropic()
@dataclass
class TestResult:
prompt_name: str
score: float
answer: str
cost_usd: float
def run_prompt(
prompt_template: str,
test_input: str,
model: str = "claude-haiku-4-5-20251001"
) -> tuple[str, float]:
"""プロンプトテンプレートにテスト入力を埋め込んで実行する"""
full_prompt = prompt_template.format(input=test_input)
response = client.messages.create(
model=model,
max_tokens=512,
messages=[{"role": "user", "content": full_prompt}]
)
inp = response.usage.input_tokens
out = response.usage.output_tokens
cost = (inp * 0.80 + out * 4.00) / 1_000_000 # Haiku料金
return response.content[0].text, cost
def evaluate_response(answer: str, expected_keywords: list[str]) -> float:
"""回答をキーワード含有率でスコアリングする(0.0〜1.0)"""
found = sum(1 for kw in expected_keywords if kw.lower() in answer.lower())
return found / len(expected_keywords) if expected_keywords else 0.5
def ab_test(
prompt_variants: dict[str, str],
test_cases: list[dict],
evaluator: Callable = None
) -> list[TestResult]:
"""複数プロンプトを全テストケースで並列実行してスコア比較する"""
results = {name: [] for name in prompt_variants}
def test_one(args):
name, template, case = args
answer, cost = run_prompt(template, case["input"])
if evaluator:
score = evaluator(answer, case.get("keywords", []))
else:
score = len(answer) / 500 # デフォルト: 文字数ベースのスコア
return name, score, answer, cost
# 全プロンプト×全テストケースを並列実行
tasks = [
(name, template, case)
for name, template in prompt_variants.items()
for case in test_cases
]
with ThreadPoolExecutor(max_workers=5) as executor:
for name, score, answer, cost in executor.map(test_one, tasks):
results[name].append((score, answer, cost))
# 集計してTestResultを作成
summary = []
for name, data in results.items():
avg_score = sum(d[0] for d in data) / len(data)
total_cost = sum(d[2] for d in data)
summary.append(TestResult(name, avg_score, data[0][1], total_cost))
return sorted(summary, key=lambda r: r.score, reverse=True)
# 使用例
PROMPTS = {
"A_simple": "以下を3行で要約してください:\n\n{input}",
"B_structured": "以下の文章を要約してください。\n要点: 3行以内\n数値: 具体的な数字を含める\n\n{input}",
"C_expert": "あなたはプロの編集者です。以下を簡潔に要約してください(200文字以内):\n\n{input}",
}
TEST_CASES = [
{"input": "AI市場は2026年に1兆ドルを超えると予測されている...", "keywords": ["AI", "兆"]},
{"input": "Anthropicは2025年に30億ドルの資金調達を行った...", "keywords": ["Anthropic", "億"]},
]
results = ab_test(PROMPTS, TEST_CASES, evaluator=evaluate_response)
print("\n=== A/Bテスト結果 ===")
for i, r in enumerate(results):
print(f"#{i+1} [{r.prompt_name}] スコア: {r.score:.2f} | コスト: ${r.cost_usd:.5f}")
print(f"\n最優秀プロンプト: {results[0].prompt_name}")
Batches APIで大規模A/Bテスト(50%オフ)
# batch_ab_test.py
# Batches APIで全パターンを一括送信してコストを半額にする
def batch_ab_test(prompt_variants: dict[str, str], test_cases: list[dict]) -> str:
"""Batches API(50%オフ)で全プロンプト×全テストケースを一括実行"""
requests = []
for prompt_name, template in prompt_variants.items():
for i, case in enumerate(test_cases):
full_prompt = template.format(input=case["input"])
requests.append({
"custom_id": f"{prompt_name}_case{i}",
"params": {
"model": "claude-haiku-4-5-20251001",
"max_tokens": 256,
"messages": [{"role": "user", "content": full_prompt}]
}
})
batch = client.messages.batches.create(requests=requests)
total_tests = len(requests)
estimated_cost = total_tests * 0.000002 * 0.5 # Haiku×Batches
print(f"A/Bテスト開始: {len(prompt_variants)}パターン×{len(test_cases)}テストケース")
print(f"合計{total_tests}リクエスト | 推定コスト: ${estimated_cost:.5f} (50%オフ適用)")
print(f"Batch ID: {batch.id} (結果は~1時間後に取得可能)")
return batch.id
batch_id = batch_ab_test(PROMPTS, TEST_CASES)