自己修正とリフレクティブプロンプティング
エージェントが元の目標に照らして自らの出力を見直し、不足や誤りを特定して、再試行前に修正済みの計画を生成するリフレクションステップを実装します
「自己修正とリフレクティブプロンプティング」はCoddyKit上の無料AI Engineering Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Engineering Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Engineering Academyコースには全4レッスンが含まれています。
内省的プロンプトとは
内省的プロンプトは、エージェントに最終確定前の出力を自ら評価させる手法です。回答を生成して終了するのではなく、エージェントは元の目的に照らして応答を見直し、不足や誤りを特定して、修正版を生成します。これは人間が自分の作業を校正する方法を模倣するもので、別の批評モデルを必要とせずに、複雑なタスクの出力品質を大きく向上させます。
内省と修正のループ
基本的な内省ループは、3つのステップで構成されます。まず初期応答を生成し、明確な基準に照らしてその応答を批評し、批評に基づいて修正します。このループは1回以上実行できます。批評によって満足できる品質だと判定されるか、最大修正回数に達するまで、各反復で応答を改善します。批評ステップ自体も、専用の内省プロンプトを使ったLLM呼び出しです。
async def reflect_and_revise(task: str, max_rounds: int = 2) -> str:
response = await generate_initial(task)
for round_num in range(max_rounds):
critique = await critique_response(task, response)
if critique.is_satisfactory:
break
response = await revise_response(task, response, critique.feedback)
return response効果的な批評プロンプトの作成
批評プロンプトでは、モデルに応答を単に「改善」するよう求めるのではなく、具体的な評価基準を指定する必要があります。確認すべき項目を具体的に列挙してください。すべての主張は正確か、質問のすべての部分に答えているか、抜けているステップはないか、不要な冗長表現はないか、といった項目です。チェックリスト項目を明示した批評プロンプトは、修正ステップがそのまま利用できる、実行可能なフィードバックを生成します。
CRITIQUE_PROMPT = '''
You are reviewing an AI-generated response to this task: {task}
Response to evaluate:
{response}
Check each criterion and provide specific feedback:
1. COMPLETENESS: Does it address all parts of the task?
2. ACCURACY: Are all factual claims correct?
3. CONCISENESS: Is there unnecessary padding or repetition?
4. FORMAT: Does it match the requested output format?
5. ACTIONABILITY: Can the user act on this response?
For each issue found, state exactly what to fix.
If the response is satisfactory on all criteria, say APPROVE.
'''批評応答の解析
批評の出力を Pydantic モデルとして構造化すると、修正するかどうかをプログラムで判断できます。is_satisfactory フィールドによってループを終了するかどうかを決定します。issues リストには、修正ステップで何を直すべきかが正確に示されます。severity フィールドを使うと、軽微な文体上の問題では修正を省略しつつ、事実誤認がある場合は必ず修正できます。
from pydantic import BaseModel
from typing import List, Literal
class Issue(BaseModel):
criterion: str
description: str
severity: Literal['critical', 'moderate', 'minor']
class Critique(BaseModel):
is_satisfactory: bool
issues: List[Issue]
overall_verdict: str
# is_satisfactory=True means no revision needed
# is_satisfactory=False means issues must be addressed修正プロンプト
修正プロンプトには、元のタスク、最初の応答、批評のフィードバックを渡します。批評で指摘された各問題に具体的に対処しつつ、元の応答の正しい部分は維持した改善版を生成するようモデルに依頼します。批評ですでに承認された内容をモデルが不必要に変更しないよう、必ず「only」という単語を含めてください。
def build_revision_prompt(task: str, response: str, critique: Critique) -> str:
issues_text = '\n'.join(
f'- [{i.severity.upper()}] {i.criterion}: {i.description}'
for i in critique.issues
)
return f'''
Original task: {task}
Your previous response:
{response}
Issues to fix:
{issues_text}
Write an improved response that fixes ONLY the issues listed above.
Do not change parts that were not flagged as problems.
'''コード生成における自己修正
自己修正は、コード生成で特に強力です。コードを生成した後、リンターまたは型チェッカーで検査し、エラー出力をモデルに返して修正を依頼します。これは実行に基づくリフレクションであり、別の LLM による判断ではなく客観的なツールからフィードバックを得るため、言語だけに基づく批評よりも信頼性が高くなります。
import subprocess
import sys
async def self_correct_code(task: str, max_rounds: int = 3) -> str:
code = await generate_code(task)
for _ in range(max_rounds):
# Write code to temp file and run mypy
with open('/tmp/agent_code.py', 'w') as f:
f.write(code)
result = subprocess.run(
[sys.executable, '-m', 'mypy', '/tmp/agent_code.py', '--ignore-missing-imports'],
capture_output=True, text=True
)
if result.returncode == 0:
break # No type errors
code = await fix_code(code, result.stdout + result.stderr)
return code過剰修正の回避
リフレクティブシステムでよくある失敗は過剰修正です。これは、別の問題を直そうとする中で、元の問題を悪化させてしまうことです。修正の範囲を制限して対策してください。修正プロンプトには、「指摘されていないものは何も変更しない」と明記します。また、差分チェックを使って修正版と元の応答を比較してください。修正版が大幅に異なる場合は何か問題が起きているため、元の応答を維持します。
from difflib import SequenceMatcher
def safe_revision(original: str, revised: str, max_change_ratio: float = 0.7) -> str:
similarity = SequenceMatcher(None, original, revised).ratio()
if similarity < (1 - max_change_ratio):
print(f'Revision changed too much (similarity: {similarity:.2f}). Keeping original.')
return original
return revised複数ステップのエージェントタスクにおけるリフレクション
複数ステップのエージェントでは、一連のステップを完了した後にリフレクションチェックポイントを追加します。たとえば、すべての調査を集め終えた後、最終レポートを書く前に実行します。エージェントは収集した情報を確認し、不足している点を特定して、追加の情報を集めるか処理を続行するかを判断します。このタスク途中のリフレクションにより、不完全または矛盾した証拠のまま統合ステップへ進むことを防げます。
async def research_with_reflection(question: str) -> str:
# Phase 1: gather evidence
evidence = await gather_evidence(question)
# Reflection checkpoint
assessment = await assess_evidence_completeness(question, evidence)
if not assessment.is_complete:
for gap in assessment.gaps:
more_evidence = await targeted_search(gap.search_query)
evidence.extend(more_evidence)
# Phase 2: synthesize
return await synthesize_answer(question, evidence)リフレクション結果のログ記録
批評のスコア、特定された問題、修正によって実際に問題が解消されたかどうかなど、すべてのリフレクションラウンドをログに記録します。このデータから、リフレクションプロンプトが有効かどうかを確認できます。修正版の応答で、批評が指摘した同じ問題が繰り返し再発する場合は、修正プロンプトが十分に具体的ではありません。ほとんどの批評が最初のラウンドで「APPROVE」と判定する場合は、初回生成の品質がすでに高く、リフレクションのオーバーヘッドがコストに見合わない可能性があります。
import structlog
log = structlog.get_logger()
def log_reflection_round(task_id: str, round_num: int, critique: Critique, action: str):
log.info(
'reflection_round',
task_id=task_id,
round=round_num,
is_satisfactory=critique.is_satisfactory,
issue_count=len(critique.issues),
critical_issues=sum(1 for i in critique.issues if i.severity == 'critical'),
action=action # 'approved', 'revised', 'max_rounds_reached'
)リフレクションを使用するタイミング
リフレクションには遅延とコストが伴います。2ラウンドのリフレクト・アンド・リバイズを行うと、そのタスクに対する LLM の呼び出し回数は少なくとも3倍になります。リフレクションは選択的に使用してください。実行されるコードや、重大なビジネス上の判断に関わる質問への回答など、高いリスクを伴う出力では必ず使用します。ユーザー向けの応答では必要に応じて使用し、ツールですぐに検証する内部の中間ステップでは使用しません。速度より品質が重要な場合は、このコストをかける価値があります。
# Reflection decision matrix:
# Task type: Use reflection?
# SQL query generation YES (run+verify)
# Final report writing YES (review before delivery)
# Tool argument prep NO (tool result verifies it)
# Short factual answer MAYBE (if accuracy is critical)
# Internal agent thought NO (intermediate, not final)
# Code generation YES (run linter/tests)
USE_REFLECTION = {'report', 'code', 'email', 'analysis'}リフレクションの有効性の測定
ランダムに選んだ50%のタスクにはリフレクションを適用し、残りの50%には適用せずに処理する A/B テストを実施して、リフレクションが実際に出力を改善しているかを測定します。その後、LLM の評価器で両方のグループを評価します。リフレクションを行ったグループのスコアが大幅に高く、その改善が追加の遅延とコストを上回るなら、リフレクションは効果を発揮しています。スコアが同程度なら、初回生成の品質がすでに十分高く、リフレクションは効果なくオーバーヘッドを増やしています。
async def reflection_ab_test(tasks: list) -> dict:
import random
results = {'with_reflection': [], 'without_reflection': []}
for task in tasks:
if random.random() < 0.5:
response = await reflect_and_revise(task, max_rounds=2)
group = 'with_reflection'
else:
response = await generate_initial(task)
group = 'without_reflection'
score = await judge(task, response)
results[group].append(score.overall)
return {
'mean_with': sum(results['with_reflection']) / len(results['with_reflection']),
'mean_without': sum(results['without_reflection']) / len(results['without_reflection'])
}理解度チェック
エージェントにおける自己修正とリフレクティブプロンプトについての理解度を確認します。
レッスンのまとめ
このレッスンでは、リフレクト・アンド・リバイズのループによってエージェントが自分の応答を批評して修正するため、出力品質が向上すること、具体的な批評ルーブリックによって曖昧な改善案ではなく実行可能なフィードバックが得られること、そしてリンターなどの客観的なツールを使った実行に基づくリフレクションがコード生成で特に強力であることを学びました。次は、エージェントのチェックポイント保存とタスクの再開を実装します。
よくある質問
「自己修正とリフレクティブプロンプティング」レッスンは無料ですか?
はい。「自己修正とリフレクティブプロンプティング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Engineering Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Engineering Academyコースには全4レッスンが含まれています。
「自己修正とリフレクティブプロンプティング」で何を学びますか?
エージェントが元の目標に照らして自らの出力を見直し、不足や誤りを特定して、再試行前に修正済みの計画を生成するリフレクションステップを実装します ブラウザで直接実行するハンズオンコードでAI Engineering Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Engineering Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Engineering Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「自己修正とリフレクティブプロンプティング」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Engineering Academyレッスンでコードを書いて実行できますか?
はい。すべてのAI Engineering Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- エージェントの失敗モードの分類
- 自己修正とリフレクティブプロンプティング
- チェックポイントとタスクの再開
- Human-in-the-Loopエスカレーション