AIコーディング 2026.07.14

メタプロンプティング実装ガイド|LLMの出力を自動改善する3つの手法【Python・LangChain 2026年版】

タグ:メタプロンプティング / LangChain / プロンプト最適化 / LLM / 自動改善

メタプロンプティングとは

LLM自身にプロンプトを評価・改善させる手法です。人間が試行錯誤してプロンプトを修正する代わりに、「プロンプト改善専用のLLM」を用意し、自動的に最適なプロンプトを生成します。

通常のプロンプト設計(手作業):
  人間 → プロンプト作成 → LLM実行 → 結果確認 → 手動修正 → 繰り返し

メタプロンプティング(自動化):
  ユーザー → 初期プロンプト → 評価LLM → 改善プロンプト → 本体LLM → 出力

環境セットアップ

# 2026年版の正しいパッケージ名でインストール
pip install langchain langchain-anthropic langchain-openai anthropic openai

パターン1: プロンプト評価→改善案生成

# meta_prompt_basic.py
# Claude Haikuで評価し、Claude Sonnetで本処理(コスト最適化)

import anthropic
import os

haiku = anthropic.Anthropic()  # 評価用(安い)
sonnet = anthropic.Anthropic()  # 本処理用

def evaluate_prompt(prompt: str, task_description: str) -> str:
    """Claude HaikuでプロンプトのKPIを評価する"""
    response = haiku.messages.create(
        model="claude-haiku-4-5-20251001",  # 入力$0.80/1M(評価用)
        max_tokens=512,
        messages=[{"role": "user", "content": f"""
以下のプロンプトを評価して改善案を出してください。

タスク: {task_description}
プロンプト: {prompt}

問題点と改善後のプロンプトをJSON形式で出力:
{{"issues": ["問題1", "問題2"], "improved_prompt": "改善後のプロンプト"}}
"""}]
    )
    return response.content[0].text

def run_with_improved_prompt(improved_prompt: str, user_input: str) -> str:
    """Claude Sonnetで改善済みプロンプトを実行する"""
    response = sonnet.messages.create(
        model="claude-sonnet-4-5",  # 入力$3/1M(本処理)
        max_tokens=1024,
        system=improved_prompt,
        messages=[{"role": "user", "content": user_input}]
    )
    return response.content[0].text

# 使用例
import json

original_prompt = "ユーザーの質問に答えてください"
task = "カスタマーサポートチャットボット"

evaluation = evaluate_prompt(original_prompt, task)
data = json.loads(evaluation)

print(f"問題点: {data['issues']}")
print(f"改善後: {data['improved_prompt']}")

answer = run_with_improved_prompt(data['improved_prompt'], "返品の方法を教えてください")
print(f"\n回答: {answer}")

パターン2: LangChainでのメタプロンプトチェーン

# meta_prompt_chain.py
# LangChainで評価→改善→実行のパイプラインを構築

from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# モデルの役割分担でコストを最適化
evaluator_llm = ChatAnthropic(model="claude-haiku-4-5-20251001")   # 評価(安い)
executor_llm = ChatAnthropic(model="claude-sonnet-4-5")             # 実行(高品質)

# 1. 評価チェーン
evaluate_prompt = ChatPromptTemplate.from_template("""
以下のプロンプトを分析し、より良い版を生成してください。

元のプロンプト: {original_prompt}
タスク: {task}

改善されたプロンプト(プロンプト本文のみ出力):
""")
evaluate_chain = evaluate_prompt | evaluator_llm | StrOutputParser()

# 2. 実行チェーン
execute_prompt = ChatPromptTemplate.from_messages([
    ("system", "{improved_prompt}"),
    ("human", "{user_input}")
])
execute_chain = execute_prompt | executor_llm | StrOutputParser()

def meta_prompt_pipeline(task: str, original_prompt: str, user_input: str) -> dict:
    """評価→改善→実行のパイプラインを実行する"""
    improved = evaluate_chain.invoke({
        "original_prompt": original_prompt,
        "task": task
    })
    
    result = execute_chain.invoke({
        "improved_prompt": improved,
        "user_input": user_input
    })
    
    return {
        "original": original_prompt,
        "improved": improved,
        "output": result
    }

result = meta_prompt_pipeline(
    task="コードレビューアシスタント",
    original_prompt="コードを見てください",
    user_input="def add(a, b): return a + b"
)
print(f"改善前: {result['original']}")
print(f"改善後: {result['improved'][:200]}")
print(f"出力: {result['output'][:300]}")

パターン3: エラー自動修正ループ

# auto_fix_loop.py
# LLMのエラー出力を検出して自動修正する

import anthropic
import json

client = anthropic.Anthropic()

def ask_structured(prompt: str, schema_hint: str) -> dict | None:
    """JSON出力を求め、失敗したら自動修正する"""
    max_retries = 3
    
    for attempt in range(max_retries):
        response = client.messages.create(
            model="claude-haiku-4-5-20251001",
            max_tokens=512,
            messages=[{"role": "user", "content": f"""
{prompt}

必ず以下のJSON形式で出力してください:
{schema_hint}
"""}]
        )
        
        text = response.content[0].text
        
        try:
            # JSONとしてパース
            return json.loads(text)
        except json.JSONDecodeError as e:
            if attempt == max_retries - 1:
                return None
            
            # 修正プロンプトを自動生成(メタプロンプト)
            fix_response = client.messages.create(
                model="claude-haiku-4-5-20251001",
                max_tokens=512,
                messages=[{"role": "user", "content": f"""
以下の出力をJSON形式に修正してください。
エラー: {e}
元の出力: {text}

修正済みJSON(コードブロックなし):
"""}]
            )
            text = fix_response.content[0].text
            try:
                return json.loads(text)
            except:
                continue

# 使用例
result = ask_structured(
    prompt="Pythonの人気ライブラリをトップ3教えてください",
    schema_hint='{"libraries": [{"name": "ライブラリ名", "use_case": "用途"}]}'
)
if result:
    for lib in result["libraries"]:
        print(f"- {lib['name']}: {lib['use_case']}")

コスト比較:モデル選択の影響

# cost_comparison.py

MODELS = {
    "claude-haiku-4-5-20251001": (0.80, 4.00, "評価・修正用(最安)"),
    "claude-sonnet-4-5": (3.00, 15.00, "本処理用(高品質)"),
    "claude-opus-5": (15.00, 75.00, "最高精度が必要な場合"),
}

def cycle_cost(eval_model: str, exec_model: str, cycles_per_day: int = 100) -> dict:
    """メタプロンプトサイクルの月間コストを計算する"""
    # 評価サイクル(入力2000 + 出力500トークン)
    ei, eo = MODELS[eval_model][:2]
    eval_cost = (2000 * ei + 500 * eo) / 1_000_000
    
    # 実行サイクル(入力3000 + 出力1000トークン)
    xi, xo = MODELS[exec_model][:2]
    exec_cost = (3000 * xi + 1000 * xo) / 1_000_000
    
    daily = (eval_cost + exec_cost) * cycles_per_day
    return {"daily_usd": round(daily, 3), "monthly_usd": round(daily * 30, 1)}

print("推奨: Haiku評価 + Sonnet実行:")
r = cycle_cost("claude-haiku-4-5-20251001", "claude-sonnet-4-5", 100)
print(f"  日${r['daily_usd']} / 月${r['monthly_usd']}")

あわせて読みたい

参考ソース