Někdy se model zasekne v neproduktivní smyčce. Naučte se to rozpoznat a řešit.
Typy loop problémů
1. Repetitive Output Loop
Model opakuje stejný text:
Assistant: Let me think about this...
Let me think about this...
Let me think about this...
Let me think about this...
Příčina: Temperature příliš nízká nebo corrupted context.
Řešení:
# Zvyšte temperature
response = client.messages.create(
model="claude-opus-4-5-20250101",
temperature=0.7, # Increase from 0
messages=[...]
)
2. Thinking Loop
Model v extended thinking krouží bez závěru:
<thinking>
Option A might work...
But option B is also good...
Actually, let me reconsider A...
But B has advantages...
Let me think about A again...
</thinking>
Příčina: Ambiguní zadání bez jasného kritéria pro rozhodnutí.
Řešení:
# Přidejte decision criteria
prompt = """
Choose between A and B.
Decision criteria (in priority order):
1. Performance > 100ms
2. Cost < $1
3. Simplicity
Make a definitive choice based on these criteria.
"""
3. Tool Calling Loop
Agent volá stejný nástroj opakovaně:
Tool: search_database("user")
Tool: search_database("user")
Tool: search_database("user")
Příčina: Tool vrací nedostatečný výsledek, model zkouší znovu.
Řešení:
class LoopDetector:
def __init__(self, max_same_calls=3):
self.history = []
self.max_same_calls = max_same_calls
def check(self, tool_name: str, tool_input: dict) -> bool:
call = (tool_name, str(tool_input))
self.history.append(call)
# Count same calls
same_count = sum(1 for c in self.history if c == call)
if same_count >= self.max_same_calls:
return False # Don't execute
return True
def get_suggestion(self) -> str:
return "I notice I'm repeating the same action. Let me try a different approach."
# V agent loop
if not loop_detector.check(tool.name, tool.input):
# Force different approach
messages.append({
"role": "user",
"content": loop_detector.get_suggestion()
})
Diagnostika
Detekce loop patterns
import re
from collections import Counter
def detect_repetition(text: str, min_length: int = 20) -> bool:
"""Detect if text contains repetitive patterns"""
# Split into chunks
chunks = [text[i:i+min_length] for i in range(0, len(text)-min_length, 10)]
# Count occurrences
counter = Counter(chunks)
# If any chunk appears >3 times, it's likely a loop
most_common = counter.most_common(1)
if most_common and most_common[0][1] > 3:
return True
return False
def detect_thinking_loop(thinking_text: str) -> bool:
"""Detect circular reasoning in thinking"""
patterns = [
r"let me (think|consider|reconsider)",
r"on (the other|second) hand",
r"but (wait|actually|however)"
]
total_backtracks = 0
for pattern in patterns:
matches = re.findall(pattern, thinking_text.lower())
total_backtracks += len(matches)
# Too many backtracks indicates circular reasoning
return total_backtracks > 10
Monitoring v reálném čase
class StreamingLoopDetector:
def __init__(self):
self.buffer = ""
self.chunk_hashes = []
def on_chunk(self, chunk: str):
self.buffer += chunk
# Hash each 50 char segment
if len(self.buffer) >= 50:
segment = self.buffer[-50:]
segment_hash = hash(segment)
if segment_hash in self.chunk_hashes[-10:]:
return "LOOP_DETECTED"
self.chunk_hashes.append(segment_hash)
return "OK"
Recovery strategie
Strategy 1: Hard Reset
async def recover_from_loop(original_prompt: str):
"""Start fresh with modified prompt"""
reset_prompt = f"""
{original_prompt}
IMPORTANT:
- Be direct and decisive
- Don't overthink or reconsider excessively
- Make a choice and commit to it
- If unsure, state your best guess with confidence level
"""
return await client.messages.create(
model="claude-opus-4-5-20250101",
messages=[{"role": "user", "content": reset_prompt}]
)
Strategy 2: Decomposition
async def break_down_task(stuck_prompt: str):
"""Break complex task into smaller steps"""
breakdown_prompt = f"""
I was trying to do this but got stuck:
{stuck_prompt}
Please break this down into 3-5 smaller, concrete steps.
For each step, give a specific action I can take.
"""
steps = await get_steps(breakdown_prompt)
results = []
for step in steps:
result = await client.messages.create(
messages=[{"role": "user", "content": step}]
)
results.append(result)
return combine_results(results)
Strategy 3: Timeout + Retry
import asyncio
async def with_timeout_retry(prompt: str, timeout: int = 30, retries: int = 3):
for attempt in range(retries):
try:
result = await asyncio.wait_for(
call_claude(prompt),
timeout=timeout
)
if not detect_repetition(result):
return result
# Retry with modified prompt
prompt += "\n\n(Note: Please provide a direct, non-repetitive response)"
except asyncio.TimeoutError:
print(f"Attempt {attempt + 1} timed out")
continue
raise LoopError("Failed to get non-looping response")
Rozpoznání a recovery z loop je klíčová skill pro práci s AI.