Mengesan dan Memutuskan Gelung Tanpa Penghujung
Pengawal lelaran maksimum, pengesanan tindakan berulang dan pemutus litar gelung.
Mengesan dan Memutuskan Gelung Tanpa Penghujung ialah pelajaran Ejen AI percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Ejen AI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Ancaman Gelung Tanpa Kesudahan
Ejen yang berada dalam gelung tanpa kesudahan membazirkan token, menyekat sumber dan tidak menghasilkan hasil yang berguna. Dalam persekitaran pengeluaran, keadaan ini secara langsung bermakna pembaziran wang dan kekecewaan pengguna.
Tiga mekanisme bekerjasama untuk menghalang gelung tanpa kesudahan: had bilangan lelaran maksimum, pengesanan tindakan berulang dan had masa.
Perlindungan 1: Had Bilangan Lelaran Maksimum
Perlindungan yang paling mudah dan penting ialah had langkah yang tetap. Setiap gelung ejen mesti mempunyainya. Apabila had dicapai, ejen sama ada mengembalikan jawapan semasa terbaiknya atau mesej 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
}Perlindungan 2: Mengesan Tindakan Berulang
Tindakan berulang ialah ciri utama gelung tanpa kesudahan. Jejaki sejarah pasangan (nama alat, argumen). Jika pasangan yang sama muncul lebih daripada N kali, ejen tersekat — hentikan gelung dan suntik mesej ralat.
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}Menjejak Tindakan Berulang dalam Tetingkap
Daripada menjejak kiraan sepanjang masa, kesan pengulangan dalam tetingkap gelongsor yang mengandungi N langkah terakhir. Kaedah ini mengesan gelung yang berubah sedikit tetapi berulang dalam kitaran 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 detectedPerlindungan 3: Had Masa Sebenar dengan signal.alarm
Pada sistem Unix, signal.alarm() mencetuskan SIGALRM selepas bilangan saat yang ditetapkan. Ini memberikan had masa yang tetap walaupun gelung ejen tersekat dalam panggilan alat yang perlahan.
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)Had Masa dengan threading.Timer untuk Semua Platform
threading.Timer berfungsi pada semua platform termasuk Windows. Tetapkan bendera selepas tempoh had masa — gelung ejen menyemak bendera itu dan keluar jika bendera telah ditetapkan.
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}Had Masa Tak Segerak dengan asyncio.wait_for
Dalam seni bina ejen tak segerak, gunakan asyncio.wait_for(coroutine, timeout=N). Fungsi ini mencetuskan asyncio.TimeoutError jika rutin bersama tidak selesai dalam tempoh saat yang ditetapkan.
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))Menyuntik Arahan Keluar ke dalam Sejarah
Apabila gelung dikesan, jangan hanya menghentikannya secara senyap. Suntik mesej sistem ke dalam sejarah perbualan yang menerangkan perkara yang berlaku dan meminta ejen membuat kesimpulan. Ini memberi LLM peluang untuk menghasilkan jawapan 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'])
Pengelogan Apabila Gelung Diputuskan
Sentiasa rekodkan apabila perlindungan gelung dicetuskan. Ini menghasilkan rekod tentang kekerapan dan sebab ejen tersekat — data yang amat berguna untuk menambah baik arahan anda dan pelaksanaan alat.
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-tiga Perlindungan
Ejen dalam persekitaran pengeluaran patut menggabungkan ketiga-tiga perlindungan: bilangan lelaran maksimum (wajib), pengesanan ulangan (mengesan kitaran) dan had masa (mengendalikan panggilan alat yang menyekat). Kesemuanya menjadikan gelung sangat teguh.
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 Perlindungan Gelung dengan Ujian Unit
Tulis ujian unit khusus untuk perlindungan gelung anda. Cipta ejen olok-olok yang sentiasa memanggil alat yang sama dan sahkan bahawa perlindungan tersebut mengesannya dalam bilangan langkah yang dijangka.
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')Semakan Pengetahuan: Mengesan Gelung Tanpa Kesudahan
Uji pemahaman anda tentang teknik mengesan dan memutuskan gelung tanpa kesudahan.
Imbas Kembali: Mengesan dan Memutuskan Gelung Tanpa Kesudahan
Anda kini boleh melindungi ejen daripada gelung tanpa kesudahan dengan tiga perlindungan yang saling melengkapi:
- Bilangan lelaran maksimum: Had langkah tetap yang wajib ada dalam setiap gelung ejen
- Pengesanan ulangan: Kira nilai cincang bagi pasangan (alat, argumen) dan hentikan gelung apabila pasangan itu dilihat lebih daripada N kali
- Had masa:
signal.alarm()pada Unix,threading.Timermerentas platform danasyncio.wait_for()untuk operasi tak segerak - Suntikan arahan keluar: Beri ejen peluang untuk membuat kesimpulan sebelum dihentikan secara paksa
- Sentiasa rekodkan apabila perlindungan dicetuskan — data ini bernilai untuk menambah baik arahan
Pelajari Ejen AI dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 60
- Pelajaran
- 239
Soalan Lazim
Adakah pelajaran “Mengesan dan Memutuskan Gelung Tanpa Penghujung” percuma?
Ya — teks penuh “Mengesan dan Memutuskan Gelung Tanpa Penghujung” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Ejen AI, tingkat taraf kepada CoddyKit PRO. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Mengesan dan Memutuskan Gelung Tanpa Penghujung”?
Pengawal lelaran maksimum, pengesanan tindakan berulang dan pemutus litar gelung. Anda berlatih Ejen AI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Ejen AI?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Ejen AI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.
Berapa lamakah pelajaran “Mengesan dan Memutuskan Gelung Tanpa Penghujung” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Ejen AI ini?
Ya. Setiap pelajaran Ejen AI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Kegagalan Gelung Ejen yang Lazim
- Pengelogan Jejak untuk Langkah Ejen
- Mengesan dan Memutuskan Gelung Tanpa Penghujung
- Teknik Penyahpepijatan Langkah demi Langkah