성찰 및 자기 비평 루프
자신의 출력을 평가하고 개선 제안을 생성하는 에이전트를 구축합니다.
성찰 및 자기 비평 루프은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
에이전트 자기 성찰이란 무엇인가?
자기 성찰은 에이전트가 방금 완료한 자체 출력을 사용자에게 반환하기 before 또는 바로 그 후에 평가하도록 요청하는 방식입니다. 에이전트가 스스로 비평가 역할을 합니다.
이는 전문가가 자신의 작업을 검토하는 방식과 비슷합니다. 초안 작성 → 비평 → 수정의 과정입니다. 이 루프를 에이전트에 추가하면 기반 모델을 변경하지 않고도 출력 품질을 향상하는 경우가 많습니다.
성찰 프롬프트 패턴
에이전트가 응답을 생성한 후, 구조화된 성찰 프롬프트와 함께 그 응답을 모델에 다시 입력하십시오. 그러면 모델이 약점을 식별하고 개선 방법을 제안합니다.
import anthropic
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
def reflect_on_response(task: str, response: str) -> str:
reflection_prompt = (
'You just completed the following task:\n\n'
f'TASK: {task}\n\n'
f'YOUR RESPONSE:\n{response}\n\n'
'Please reflect on your performance by answering:\n'
'1. What did you do well?\n'
'2. What could be improved?\n'
'3. What would you do differently if you had to redo this?\n'
'Be specific and honest.'
)
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content': reflection_prompt}]
)
return result.content[0].text구조화된 성찰 출력
구조화되지 않은 성찰 문장은 프로그래밍 방식으로 처리하기 어렵습니다. 점수와 실행 항목을 안정적으로 추출할 수 있도록 모델에 구조화된 JSON 성찰 결과를 생성하도록 요청하십시오.
STRUCTURED_REFLECTION_PROMPT = '''
Reflect on the task and response above. Return ONLY valid JSON:
{
"strengths": ["..."],
"weaknesses": ["..."],
"alternative_approach": "...",
"quality_score": 0.0,
"retry_recommended": false
}
quality_score: 0.0 (terrible) to 1.0 (excellent).
retry_recommended: true if quality_score < 0.6.
'''
import json
def structured_reflect(task: str, response: str, client) -> dict:
prompt = f'TASK: {task}\n\nRESPONSE: {response}\n\n{STRUCTURED_REFLECTION_PROMPT}'
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content': prompt}]
)
text = result.content[0].text.strip()
# strip markdown code fences if present
if text.startswith('```'):
text = text.split('```')[1].lstrip('json').strip()
return json.loads(text)
if __name__ == '__main__':
class FakeContent:
def __init__(self, text):
self.text = text
class FakeResponse:
def __init__(self, text):
self.content = [FakeContent(text)]
class FakeMessages:
def create(self, **kwargs):
return FakeResponse(
'{"strengths": ["clear"], "weaknesses": ["too long"], '
'"alternative_approach": "be more concise", '
'"quality_score": 0.7, "retry_recommended": false}'
)
class FakeClient:
def __init__(self):
self.messages = FakeMessages()
result = structured_reflect('Summarize the article', 'A very long response...', FakeClient())
print('quality_score:', result['quality_score'])
print('weaknesses:', result['weaknesses'])
자기 비평 루프: 낮은 점수에서 재시도
성찰 점수가 임계값보다 낮으면 성찰에서 얻은 약점과 대안적 접근 방식을 추가 맥락으로 사용하여 작업을 자동으로 다시 시도하십시오. 이렇게 하면 한 번의 에이전트 실행 안에서 피드백을 기반으로 개선하는 루프가 만들어집니다.
def agent_with_self_critique(task: str, client, max_retries: int = 2) -> str:
response = run_agent(task, client)
for attempt in range(max_retries):
reflection = structured_reflect(task, response, client)
print(f'Attempt {attempt+1} quality: {reflection["quality_score"]:.2f}')
if not reflection['retry_recommended']:
break
# Enrich the task with reflection insights
improved_task = (
f'{task}\n\n'
'Previous attempt weaknesses:\n'
+ '\n'.join(f'- {w}' for w in reflection['weaknesses'])
+ f'\n\nSuggested approach: {reflection["alternative_approach"]}'
)
response = run_agent(improved_task, client)
return response
def run_agent(task: str, client) -> str:
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=1024,
messages=[{'role': 'user', 'content': task}]
)
return result.content[0].text성찰을 위한 에피소드 메모리
한 번의 성찰은 한 번만 유용하지만, 저장된 성찰은 에피소드 메모리가 되어 에이전트가 여러 세션에 걸쳐 학습하도록 돕습니다. 각 성찰은 작업 맥락 + 발생한 일 + 에이전트가 배운 내용으로 구성된 하나의 에피소드입니다.
from datetime import datetime
from dataclasses import dataclass, asdict
from typing import Optional
@dataclass
class ReflectionEpisode:
episode_id: str
task_type: str # e.g. 'summarize', 'code_review', 'translate'
task_summary: str # short description (not full text)
quality_score: float
strengths: list
weaknesses: list
alternative_approach: str
timestamp: str = ''
def __post_init__(self):
if not self.timestamp:
self.timestamp = datetime.utcnow().isoformat()
def to_dict(self) -> dict:
return asdict(self)
# Example
episode = ReflectionEpisode(
episode_id='ep_001',
task_type='summarize',
task_summary='Summarize a 5-page financial report',
quality_score=0.55,
strengths=['Identified key figures'],
weaknesses=['Too verbose', 'Missed conclusion'],
alternative_approach='Lead with the executive summary first'
)
print(episode.to_dict())성찰을 영구적으로 저장하기
성찰 에피소드를 JSON 파일이나 데이터베이스에 영구적으로 저장하십시오. 시작할 때 같은 작업 유형의 최근 에피소드를 불러와 맥락으로 주입하면 에이전트가 과거의 자체 수행에서 학습합니다.
import json
import os
MEMORY_FILE = 'agent_episodic_memory.json'
def save_episode(episode: ReflectionEpisode):
episodes = load_all_episodes()
episodes.append(episode.to_dict())
with open(MEMORY_FILE, 'w') as f:
json.dump(episodes, f, indent=2)
def load_all_episodes() -> list:
if not os.path.exists(MEMORY_FILE):
return []
with open(MEMORY_FILE) as f:
return json.load(f)
def load_recent_episodes(task_type: str, n: int = 3) -> list:
all_ep = load_all_episodes()
matching = [e for e in all_ep if e['task_type'] == task_type]
# Sort by timestamp descending, take most recent n
matching.sort(key=lambda e: e['timestamp'], reverse=True)
return matching[:n]과거 성찰을 맥락으로 주입하기
작업을 시작하기 전에 해당 작업 유형의 가장 최근 에피소드 성찰을 가져와 시스템 프롬프트에 포함하십시오. 그러면 에이전트는 지난번에 어떤 실수를 했는지 알고 이를 사전에 방지할 수 있습니다.
def build_system_prompt_with_memory(task_type: str) -> str:
base = 'You are a helpful AI assistant. Complete the task carefully.'
episodes = load_recent_episodes(task_type, n=3)
if not episodes:
return base
memory_block = '\n\nYour recent performance on similar tasks:\n'
for ep in episodes:
memory_block += (
f'- Score {ep["quality_score"]:.2f}: '
f'Weaknesses: {ep["weaknesses"]}. '
f'Better approach: {ep["alternative_approach"]}\n'
)
memory_block += '\nApply these lessons to your current response.'
return base + memory_block
# Before each task:
system_prompt = build_system_prompt_with_memory('summarize')
print(system_prompt[:300])도구 사용에 대한 성찰
도구를 사용하는 에이전트에서는 성찰이 더욱 유용합니다. 에이전트가 도구 호출 전략을 성찰할 수 있기 때문입니다. 올바른 도구를 올바른 순서로, 올바른 매개변수와 함께 사용했는지 확인할 수 있습니다.
TOOL_REFLECTION_PROMPT = '''
You completed a multi-step task using tools. Reflect on your tool usage:
Tool call log:
{tool_log}
Final result: {result}
Answer:
1. Were all tool calls necessary?
2. Were there redundant or incorrect calls?
3. What is the optimal tool sequence for this task type?
Return JSON:
{{
"redundant_calls": [],
"incorrect_calls": [],
"optimal_sequence": [],
"efficiency_score": 0.0
}}
'''
def reflect_on_tool_use(tool_log: list, result: str, client) -> dict:
import json
log_str = json.dumps(tool_log, indent=2)
prompt = TOOL_REFLECTION_PROMPT.format(
tool_log=log_str, result=result
)
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content': prompt}]
)
return json.loads(response.content[0].text)
if __name__ == '__main__':
class FakeContent:
def __init__(self, text):
self.text = text
class FakeResponse:
def __init__(self, text):
self.content = [FakeContent(text)]
class FakeMessages:
def create(self, **kwargs):
return FakeResponse(
'{"redundant_calls": ["search(x)"], "incorrect_calls": [], '
'"optimal_sequence": ["search", "summarize"], "efficiency_score": 0.8}'
)
class FakeClient:
def __init__(self):
self.messages = FakeMessages()
tool_log = [{'tool': 'search', 'args': {'q': 'x'}}, {'tool': 'search', 'args': {'q': 'x'}}]
reflection = reflect_on_tool_use(tool_log, 'Found the answer', FakeClient())
print('Efficiency score:', reflection['efficiency_score'])
print('Redundant calls:', reflection['redundant_calls'])
에피소드 메모리의 감쇠와 정리
세상이 변하거나 모델이 업데이트되면 오래된 성찰은 낡은 내용이 됩니다. 감쇠를 구현하여 최근 에피소드에 더 큰 가중치를 부여하고, 임계값보다 오래되었거나 품질 점수가 매우 낮은 에피소드를 정리하십시오. 이러한 에피소드는 이상치였을 수 있습니다.
from datetime import datetime, timedelta
def prune_old_episodes(
episodes: list,
max_age_days: int = 30,
min_quality: float = 0.0
) -> list:
cutoff = datetime.utcnow() - timedelta(days=max_age_days)
kept = []
for ep in episodes:
ep_time = datetime.fromisoformat(ep['timestamp'])
if ep_time >= cutoff and ep['quality_score'] >= min_quality:
kept.append(ep)
return kept
def weighted_episodes(episodes: list) -> list:
now = datetime.utcnow()
for ep in episodes:
age_days = (now - datetime.fromisoformat(ep['timestamp'])).days
# Recency weight: 1.0 today, halves every 7 days
ep['weight'] = 0.5 ** (age_days / 7)
return sorted(episodes, key=lambda e: e['weight'], reverse=True)
if __name__ == '__main__':
now = datetime.utcnow()
episodes = [
{'timestamp': (now - timedelta(days=2)).isoformat(), 'quality_score': 0.9, 'content': 'recent good episode'},
{'timestamp': (now - timedelta(days=45)).isoformat(), 'quality_score': 0.8, 'content': 'old episode'},
{'timestamp': (now - timedelta(days=10)).isoformat(), 'quality_score': 0.3, 'content': 'low quality episode'},
]
kept = prune_old_episodes(episodes, max_age_days=30, min_quality=0.5)
print(f'Kept {len(kept)} of {len(episodes)} episodes after pruning')
for ep in weighted_episodes(kept):
print(f" weight={ep['weight']:.3f} content={ep['content']}")
성찰 효과 측정
첫 시도와 최종(성찰 후) 시도의 품질 점수를 비교하여 자기 비평이 실제로 결과를 개선하는지 추적하십시오. 개선 폭이 작거나 오히려 낮아진다면 성찰 프롬프트를 조정해야 할 수 있습니다.
def measure_reflection_gain(run_log: list) -> dict:
"""
run_log: list of dicts with keys 'attempt', 'quality_score'
e.g. [{'attempt': 1, 'quality_score': 0.55}, {'attempt': 2, 'quality_score': 0.78}]
"""
if not run_log:
return {}
first_score = run_log[0]['quality_score']
best_score = max(r['quality_score'] for r in run_log)
final_score = run_log[-1]['quality_score']
return {
'first_attempt_score': first_score,
'final_score': final_score,
'best_score': best_score,
'absolute_gain': final_score - first_score,
'relative_gain_pct': ((final_score - first_score) / max(first_score, 0.001)) * 100,
'retries': len(run_log) - 1
}
log = [
{'attempt': 1, 'quality_score': 0.55},
{'attempt': 2, 'quality_score': 0.78}
]
print(measure_reflection_gain(log))성찰 루프의 안전장치
제한이 없으면 성찰 루프가 무한히 실행될 수 있습니다. 항상 최대 재시도 횟수, 조기 종료를 위한 최소 점수 임계값, 시간 예산을 적용하십시오. 루프의 동작을 감사할 수 있도록 모든 성찰을 로그에 기록하십시오.
import time
def safe_reflection_loop(
task: str,
client,
max_retries: int = 3,
quality_target: float = 0.75,
time_budget_seconds: float = 30.0
) -> dict:
start = time.time()
response = run_agent(task, client)
run_log = []
for attempt in range(max_retries + 1):
if time.time() - start > time_budget_seconds:
print('Time budget exceeded, returning best result')
break
reflection = structured_reflect(task, response, client)
run_log.append({'attempt': attempt + 1,
'quality_score': reflection['quality_score']})
if reflection['quality_score'] >= quality_target:
print(f'Quality target reached at attempt {attempt + 1}')
break
if attempt < max_retries:
response = run_agent(task + '\n' + reflection['alternative_approach'], client)
return {'response': response, 'run_log': run_log,
'gain': measure_reflection_gain(run_log)}지식 확인
성찰 에피소드를 에피소드 메모리로 저장하는 가장 큰 이점은 무엇입니까?
요약: 성찰 및 자기 비평 루프
훌륭합니다! 이 수업에서 다룬 내용은 다음과 같습니다.
- 성찰 프롬프트: 강점, 약점, 품질 점수, 재시도 플래그가 포함된 구조화된 JSON
- 자기 비평 루프: 낮은 점수에서 재시도하고 성찰 정보를 추가하여 작업을 보강함
- 에피소드 메모리: 작업 유형별로 타임스탬프가 기록된 에피소드로 성찰을 저장함
- 메모리 주입: 매번 실행하기 전에 최근 에피소드를 시스템 프롬프트로 불러옴
- 안전장치: 최대 재시도 횟수, 시간 예산, 품질 목표 달성 시 조기 종료
다음 주제에서는 성공하거나 실패한 실행 경로를 활용하여 더 깊이 자기 개선하는 방법을 알아봅니다.
자주 묻는 질문
“성찰 및 자기 비평 루프” 강의는 무료인가요?
네 — “성찰 및 자기 비평 루프” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
“성찰 및 자기 비평 루프”에서 뭘 배우나요?
자신의 출력을 평가하고 개선 제안을 생성하는 에이전트를 구축합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Agents을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“성찰 및 자기 비평 루프” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 피드백 수집 및 저장
- 성찰 및 자기 비평 루프
- 궤적 기반 자기 개선
- 자기 개선이 잘못될 때