Mendeteksi dan Memutus Putaran Tak Berujung
Penjaga jumlah iterasi maksimum, deteksi tindakan berulang, dan pemutus sirkuit putaran.
Mendeteksi dan Memutus Putaran Tak Berujung adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.
Ancaman Perulangan Tak Berujung
Agen dalam perulangan tak berujung menghabiskan token, memblokir sumber daya, dan tidak menghasilkan keluaran yang berguna. Dalam produksi, hal ini secara langsung berarti pemborosan biaya dan frustrasi pengguna.
Tiga mekanisme bekerja sama untuk mencegah perulangan tak berujung: batas jumlah iterasi maksimum, deteksi tindakan berulang, dan batas waktu.
Pengaman 1: Batas Maksimum Iterasi
Pengaman yang paling sederhana dan penting adalah batas langkah yang tegas. Setiap perulangan agen harus memilikinya. Ketika batas tercapai, agen akan mengembalikan jawaban terbaiknya saat itu atau pesan kegagalan yang jelas.
MAX_ITERATIONS = 20
def run_agent(query: str) -> dict:
history = []
for step in range(1, MAX_ITERATIONS + 1):
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer'], 'steps': step}
result = execute_tool(action['tool'], action['args'])
history.append({'step': step, 'tool': action['tool'], 'result': result})
# Hard stop — max iterations reached
return {
'status': 'max_iterations_reached',
'answer': None,
'steps': MAX_ITERATIONS
}Pengaman 2: Mendeteksi Tindakan Berulang
Tindakan berulang merupakan ciri khas perulangan tak berujung. Lacak riwayat pasangan (nama alat, argumen). Jika pasangan yang sama muncul lebih dari N kali, agen berada dalam keadaan macet—hentikan perulangan dan sisipkan pesan kesalahan.
import hashlib
import json
def action_hash(tool_name: str, args: dict) -> str:
payload = json.dumps({'tool': tool_name, 'args': args}, sort_keys=True)
return hashlib.md5(payload.encode()).hexdigest()
def run_agent_with_repeat_detection(query: str) -> dict:
history = []
action_counts = {}
for step in range(1, 21):
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
key = action_hash(action['tool'], action['args'])
action_counts[key] = action_counts.get(key, 0) + 1
if action_counts[key] > 2: # seen this exact action more than twice
history.append({
'role': 'system',
'content': f'You have called {action["tool"]} with the same arguments {action_counts[key]} times. '
f'This approach is not working. Try a completely different strategy or state what you know so far.'
})
continue
result = execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
return {'status': 'loop_detected', 'answer': None}Melacak Tindakan Berulang dalam Jendela
Alih-alih melacak jumlah sepanjang waktu, deteksi pengulangan dalam jendela geser yang mencakup N langkah terakhir. Cara ini menangkap perulangan yang sedikit berubah, tetapi berulang dalam periode singkat.
from collections import deque
def is_cycling(recent_actions: deque, window: int = 6) -> bool:
if len(recent_actions) < window:
return False
# Check if the last window/2 actions repeat the first window/2
half = window // 2
first_half = list(recent_actions)[:half]
second_half = list(recent_actions)[half:window]
return first_half == second_half
# In the agent loop:
# recent_actions = deque(maxlen=6)
# recent_actions.append(action_hash(tool, args))
# if is_cycling(recent_actions):
# print('Cycling detected — breaking loop')
# break
recent = deque(['a', 'b', 'a', 'b'], maxlen=6)
print(is_cycling(recent, window=4)) # True — cycling detectedPengaman 3: Batas Waktu Nyata dengan signal.alarm
Pada sistem Unix, signal.alarm() menimbulkan SIGALRM setelah jumlah detik tertentu. Ini memberikan batas waktu tegas, bahkan jika perulangan agen terblokir dalam pemanggilan alat yang lambat.
import signal
class AgentTimeout(Exception):
pass
def timeout_handler(signum, frame):
raise AgentTimeout('Agent exceeded time limit')
def run_agent_with_signal_timeout(query: str, timeout_seconds: int = 60) -> dict:
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(timeout_seconds) # set the alarm
try:
result = run_core_agent_loop(query)
signal.alarm(0) # cancel the alarm on success
return result
except AgentTimeout:
signal.alarm(0)
return {'status': 'timeout', 'answer': None}
except Exception as e:
signal.alarm(0)
raise
# Note: signal.alarm is Unix-only (Linux/Mac)Batas Waktu dengan threading.Timer (Lintas Platform)
threading.Timer berfungsi di semua platform, termasuk Windows. Atur sebuah penanda setelah periode batas waktu—perulangan agen memeriksa penanda tersebut dan keluar jika penanda telah diatur.
import threading
def run_agent_with_timer_timeout(query: str, timeout_seconds: int = 60) -> dict:
timed_out = threading.Event()
def set_timeout():
timed_out.set()
timer = threading.Timer(timeout_seconds, set_timeout)
timer.start()
history = []
try:
for step in range(1, 21):
if timed_out.is_set():
return {'status': 'timeout', 'answer': None, 'steps': step}
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
result = execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
finally:
timer.cancel() # always cancel if done before timeout
return {'status': 'max_steps', 'answer': None}Batas Waktu Asinkron dengan asyncio.wait_for
Dalam arsitektur agen asinkron, gunakan asyncio.wait_for(coroutine, timeout=N). Fungsi tersebut menimbulkan asyncio.TimeoutError jika coroutine tidak selesai dalam jumlah detik yang ditentukan.
import asyncio
async def run_async_agent(query: str) -> dict:
history = []
for step in range(1, 21):
action = await async_decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
result = await async_execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
return {'status': 'max_steps', 'answer': None}
async def run_with_timeout(query: str, timeout: float = 60.0) -> dict:
try:
return await asyncio.wait_for(run_async_agent(query), timeout=timeout)
except asyncio.TimeoutError:
return {'status': 'timeout', 'answer': None}
# asyncio.run(run_with_timeout('What is Python?', timeout=30.0))Menyisipkan Instruksi Keluar ke Riwayat
Ketika perulangan terdeteksi, jangan hanya menghentikannya secara diam-diam. Sisipkan pesan sistem ke dalam riwayat percakapan yang menjelaskan apa yang terjadi dan meminta agen menyimpulkan. Ini memberi LLM kesempatan untuk menghasilkan jawaban akhir sebelum dihentikan.
def inject_loop_escape(history: list, step: int, reason: str):
message = (
f'[SYSTEM] You have been running for {step} steps. Reason: {reason}. '
f'You MUST now provide a FINAL_ANSWER based on what you have found so far, '
f'even if the information is incomplete. Do not call any more tools.'
)
history.append({'role': 'system', 'content': message})
# In the agent loop, when approaching the limit:
# if step >= MAX_ITERATIONS - 2:
# inject_loop_escape(history, step, 'approaching max iteration limit')
# Or when a repeat is detected:
# if action_counts[key] > 2:
# inject_loop_escape(history, step, 'repeated action detected')
if __name__ == '__main__':
demo_history = []
inject_loop_escape(demo_history, step=18, reason='approaching max iteration limit')
print(demo_history[-1]['content'])
Mencatat Saat Perulangan Dihentikan
Selalu catat saat pengaman perulangan terpicu. Ini membuat catatan tentang seberapa sering dan mengapa agen mengalami kemacetan—data yang sangat berharga untuk menyempurnakan perintah dan penerapan alat Anda.
import logging
logger = logging.getLogger('agent_guard')
def check_and_break_loop(step: int, action_counts: dict, current_key: str) -> bool:
count = action_counts.get(current_key, 0)
if count > 2:
logger.warning(
f'Infinite loop detected at step {step}. '
f'Action hash {current_key[:8]} seen {count} times. '
f'Breaking loop.'
)
return True # signal to break
if step >= 18: # approaching limit
logger.warning(
f'Approaching max iterations at step {step}. '
f'Injecting escape prompt.'
)
return False
if __name__ == '__main__':
import sys
logging.basicConfig(level=logging.WARNING, format='%(message)s', stream=sys.stdout)
demo_counts = {'search:{"q": "weather"}': 3}
check_and_break_loop(step=10, action_counts=demo_counts, current_key='search:{"q": "weather"}')
Menggabungkan Ketiga Pengaman
Agen produksi harus menggabungkan ketiga pengaman: jumlah iterasi maksimum (wajib), deteksi pengulangan (menangkap siklus), dan batas waktu (menangkap pemanggilan alat yang memblokir). Secara bersama-sama, ketiganya membuat perulangan sangat tangguh.
import threading
import hashlib
import json
def run_production_agent(query: str) -> dict:
MAX_STEPS = 20
TIMEOUT_SEC = 120
timed_out = threading.Event()
timer = threading.Timer(TIMEOUT_SEC, timed_out.set)
timer.start()
history = []
action_counts = {}
try:
for step in range(1, MAX_STEPS + 1):
if timed_out.is_set():
return {'status': 'timeout'}
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
key = hashlib.md5(json.dumps(action, sort_keys=True).encode()).hexdigest()
action_counts[key] = action_counts.get(key, 0) + 1
if action_counts[key] > 2:
inject_loop_escape(history, step, 'repeat detected')
continue
result = execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
finally:
timer.cancel()
return {'status': 'max_steps'}Menguji Pengaman Perulangan dengan Pengujian Unit
Tulislah pengujian unit khusus untuk pengaman perulangan Anda. Buat agen tiruan yang selalu memanggil alat yang sama dan verifikasi bahwa pengaman mendeteksinya dalam jumlah langkah yang diharapkan.
from unittest.mock import MagicMock
def test_repeat_detection_breaks_loop():
# Create a mock that always returns the same action
always_same_action = MagicMock(return_value={
'type': 'tool',
'tool': 'search_web',
'args': {'query': 'same query'}
})
always_success = MagicMock(return_value='some result')
result = run_agent_with_repeat_detection(
query='test',
decide_action=always_same_action,
execute_tool=always_success
)
# Should stop due to loop detection, not run all 20 steps
assert result['status'] in ('loop_detected', 'max_iterations_reached')
# Should not have run all 20 steps (loop should be detected by step 6-7)
print('Loop guard test passed')Uji Pemahaman: Mendeteksi Perulangan Tak Berujung
Uji pemahaman Anda tentang teknik mendeteksi dan menghentikan perulangan tak berujung.
Ringkasan: Mendeteksi dan Menghentikan Perulangan Tak Berujung
Sekarang Anda dapat melindungi agen dari perulangan tak berujung dengan tiga pengaman yang saling melengkapi:
- Jumlah iterasi maksimum: batas langkah tegas yang wajib ada dalam setiap perulangan agen
- Deteksi pengulangan: buat hash pasangan (alat, argumen) dan hentikan perulangan jika pasangan tersebut terlihat lebih dari N kali
- Batas waktu:
signal.alarm()di Unix,threading.Timerlintas platform, danasyncio.wait_for()untuk proses asinkron - Penyisipan jalan keluar: beri agen kesempatan untuk menyimpulkan sebelum dihentikan secara paksa
- Selalu catat saat pengaman terpicu—catatan ini merupakan data berharga untuk menyempurnakan perintah
Belajar AI Agents dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 60
- Pelajaran
- 239
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Mendeteksi dan Memutus Putaran Tak Berujung” gratis?
Ya — teks lengkap “Mendeteksi dan Memutus Putaran Tak Berujung” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Mendeteksi dan Memutus Putaran Tak Berujung”?
Penjaga jumlah iterasi maksimum, deteksi tindakan berulang, dan pemutus sirkuit putaran. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Agents?
Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Mendeteksi dan Memutus Putaran Tak Berujung” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?
Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Kegagalan Umum dalam Putaran Agen
- Pencatatan Jejak untuk Langkah Agen
- Mendeteksi dan Memutus Putaran Tak Berujung
- Teknik Debugging Langkah demi Langkah