Loopar för reflektion och självkritik
Agenter som utvärderar sina egna resultat och genererar förbättringsförslag.
Loopar för reflektion och självkritik är en gratis lektion i AI-agenter på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för AI-agenter, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i AI-agenter innehåller totalt 4 lektioner.
Vad är agentens självreflektion?
Självreflektion innebär att be agenten utvärdera sin egen just avslutade output innan den returneras till användaren eller omedelbart efteråt. Agenten fungerar som sin egen kritiker.
Detta liknar hur experter granskar sitt arbete: utkast → kritik → revidering. Genom att lägga till denna loop i agenter förbättras ofta outputkvaliteten utan ändringar i den underliggande modellen.
Mönstret för en reflektionsprompt
Efter att agenten har skapat ett svar skickar Ni tillbaka svaret till modellen tillsammans med en strukturerad reflektionsprompt. Modellen identifierar då svagheter och föreslår förbättringar.
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].textStrukturerad reflektionsoutput
Ostrukturerad reflektionstext är svår att bearbeta programmatiskt. Be modellen skapa en strukturerad JSON-reflektion så att Ni på ett tillförlitligt sätt kan extrahera poäng och åtgärdspunkter.
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'])
Självkritikloop: försök igen vid låg poäng
När reflektionspoängen hamnar under en tröskel försöker Ni automatiskt utföra uppgiften igen, med svagheterna och det alternativa tillvägagångssättet från reflektionen som ytterligare kontext. Detta skapar en återkopplingsdriven förbättringsloop inom en enda agentkörning.
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].textEpisodiskt minne för reflektioner
En enskild reflektion är användbar en gång; lagrade reflektioner blir ett episodiskt minne som hjälper agenten att lära sig mellan sessioner. Varje reflektion är en episod: uppgiftens kontext + vad som hände + vad agenten lärde sig.
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())Lagra reflektioner permanent
Spara reflektionsepisoder i en JSON-fil eller databas. Läs vid uppstart in de senaste episoderna för samma uppgiftstyp och lägg in dem som kontext — agenten lär sig av sin tidigare prestation.
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]Lägg in tidigare reflektioner som kontext
Innan en uppgift påbörjas hämtar Ni de senaste episodiska reflektionerna för den uppgiftstypen och inkluderar dem i systemprompten. Agenten vet då vilka misstag den gjorde förra gången och kan undvika dem proaktivt.
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])Reflektion över användning av verktyg
Reflektioner är ännu mer värdefulla för agenter som använder verktyg, eftersom agenten kan reflektera över sin strategi för verktygsanrop: använde den rätt verktyg, i rätt ordning och med rätt parametrar?
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'])
Föråldrande och gallring av episodiskt minne
Gamla reflektioner blir inaktuella om omvärlden förändras eller modellen uppdateras. Implementera föråldrande: ge nya episoder större vikt och gallra episoder som är äldre än en viss tröskel eller har mycket låga kvalitetspoäng (de kan ha varit avvikande fall).
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']}")
Mät reflektions effektivitet
Följ upp om självkritiken faktiskt förbättrar resultaten genom att jämföra kvalitetspoängen för de första försöken med de slutliga försöken efter reflektionen. Om förbättringen är liten eller negativ kan reflektionsprompten behöva justeras.
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))Skyddsåtgärder för reflektionsloopen
Utan begränsningar kan en reflektionsloop köras i all oändlighet. Ange alltid: ett maximalt antal nya försök, en minsta poängtröskel för tidigt avslut och en tidsbudget. Logga alla reflektioner så att Ni kan granska loopens beteende.
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)}Kunskapskontroll
Vilken är den främsta fördelen med att lagra reflektionsepisoder som episodiskt minne?
Sammanfattning: reflektions- och självkritikloopar
Utmärkt! Här är vad Ni har gått igenom i den här lektionen:
- Reflektionsprompt: strukturerad JSON med styrkor, svagheter, kvalitetspoäng och flagga för nytt försök
- Självkritikloop: nytt försök vid låg poäng, där uppgiften berikas med insikter från reflektionen
- Episodiskt minne: reflektioner lagras som tidsstämplade episoder per uppgiftstyp
- Injektion av minne: senaste episoder läses in i systemprompten före varje körning
- Skyddsåtgärder: maximalt antal nya försök, tidsbudget och tidigt avslut när kvalitetsmålet är uppnått
Nästa steg: hur Ni kan använda lyckade och misslyckade körningsförlopp för djupare självförbättring.
Lär dig AI-agenter med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 60
- Lektioner
- 239
Vanliga frågor
Är lektionen ”Loopar för reflektion och självkritik” gratis?
Ja – hela texten till ”Loopar för reflektion och självkritik” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i AI-agenter, kan Ni uppgradera till CoddyKit PRO. Kursen i AI-agenter innehåller totalt 4 lektioner.
Vad lär jag mig i ”Loopar för reflektion och självkritik”?
Agenter som utvärderar sina egna resultat och genererar förbättringsförslag. Ni övar på AI-agenter med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig AI-agenter?
Du behöver inga förkunskaper. Utbildningen i AI-agenter på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Loopar för reflektion och självkritik”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här AI-agenter-lektionen?
Ja. Varje AI-agenter-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Insamling och lagring av feedback
- Loopar för reflektion och självkritik
- Självförbättring baserad på handlingsförlopp
- När självförbättring går fel