Penanganan Galat dalam Rantai Perintah
Validasi keluaran perantara dan pulihkan proses dari kegagalan rantai.
Penanganan Galat dalam Rantai Perintah adalah pelajaran AI Prompt Engineering gratis di CoddyKit. Ini adalah pelajaran 4 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 Prompt Engineering, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Prompt Engineering mencakup 4 pelajaran total.
Mengapa Rantai Gagal
Rantai perintah menimbulkan mode kegagalan baru yang tidak ada pada sistem dengan satu perintah. Setiap langkah dapat gagal dengan caranya sendiri, dan kegagalan tersebut terakumulasi—output Langkah 2 yang buruk merusak setiap langkah berikutnya.
Mode kegagalan yang umum:
- Model mengembalikan JSON yang formatnya tidak valid sehingga tidak dapat diurai
- Model salah memahami tugas dan menghasilkan output yang keliru secara makna
- Batas laju atau batas waktu API menyebabkan langkah gagal
- Jendela konteks terlampaui dalam rantai yang panjang
- Model mengarang data yang kemudian dianggap sebagai fakta oleh langkah-langkah berikutnya
Validasi Output Setelah Setiap Langkah
Garis pertahanan pertama adalah memvalidasi output segera setelah setiap langkah, sebelum meneruskannya ke langkah berikutnya. Jangan pernah berasumsi bahwa model mengembalikan apa yang Anda minta.
import json
def validate_json_output(raw_text, required_fields):
'Parse and validate that required fields are present in model output.'
try:
data = json.loads(raw_text.strip())
except json.JSONDecodeError as e:
raise ValueError(f'Invalid JSON: {e}. Raw: {raw_text[:200]}')
missing = [f for f in required_fields if f not in data]
if missing:
raise ValueError(f'Missing required fields: {missing}. Got: {list(data.keys())}')
return data
# Usage after a chain step
raw = '{"sentiment": "positive", "priority": "high"}'
validated = validate_json_output(raw, required_fields=['sentiment', 'priority'])
print('Valid:', validated)Logika Percobaan Ulang untuk Kegagalan Sementara
Kegagalan API—batas laju, batas waktu, dan kesalahan server—bersifat sementara. Terapkan logika percobaan ulang dengan jeda eksponensial untuk kegagalan tingkat jaringan:
import anthropic, time
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
def call_with_retry(prompt, max_retries=3, base_delay=1.0):
last_error = None
for attempt in range(max_retries):
try:
r = client.messages.create(
model='claude-opus-4-5', max_tokens=500,
messages=[{'role': 'user', 'content': prompt}]
)
return r.content[0].text
except anthropic.RateLimitError as e:
wait = base_delay * (2 ** attempt)
print(f'Rate limited. Waiting {wait}s before retry {attempt+1}/{max_retries}...')
time.sleep(wait)
last_error = e
except anthropic.APIError as e:
last_error = e
if attempt < max_retries - 1:
time.sleep(base_delay)
raise RuntimeError(f'All retries exhausted: {last_error}')Validasi Semantik
Beberapa kegagalan memiliki struktur yang valid tetapi maknanya salah—model mengembalikan JSON yang valid, tetapi dengan nilai yang keliru. Gunakan langkah validasi ringan untuk memeriksa ketepatan makna:
def semantic_validate(data, schema_rules):
'Apply semantic validation rules to parsed output.'
errors = []
for field, rules in schema_rules.items():
value = data.get(field)
if rules.get('required') and value is None:
errors.append(f'{field} is required but missing')
continue
if 'allowed_values' in rules and value not in rules['allowed_values']:
errors.append(f'{field} must be one of {rules["allowed_values"]}, got: {value}')
if 'min_length' in rules and isinstance(value, list) and len(value) < rules['min_length']:
errors.append(f'{field} must have at least {rules["min_length"]} items, got {len(value)}')
if errors:
raise ValueError('Semantic validation failed: ' + '; '.join(errors))
return data
rules = {'sentiment': {'allowed_values': ['positive', 'negative', 'mixed']}, 'issues': {'min_length': 1}}
data = {'sentiment': 'positive', 'issues': ['login bug']}
print(semantic_validate(data, rules))Perintah Cadangan
Jika suatu langkah gagal divalidasi setelah beberapa kali percobaan ulang, perintah cadangan dapat menghasilkan output yang lebih sederhana tetapi tetap dapat digunakan, alih-alih menghentikan seluruh rantai:
import json
def call_with_fallback(primary_prompt, fallback_prompt, required_fields):
# Try primary prompt
try:
raw = call_with_retry(primary_prompt)
return validate_json_output(raw, required_fields)
except (ValueError, RuntimeError) as e:
print(f'Primary prompt failed: {e}. Trying fallback...')
# Try simpler fallback prompt
try:
raw = call_with_retry(fallback_prompt)
return validate_json_output(raw, required_fields)
except (ValueError, RuntimeError) as e:
print(f'Fallback also failed: {e}. Returning safe default.')
# Return safe default — chain continues with minimal data
return {field: None for field in required_fields}
# Usage
primary = 'Analyze this review. Return JSON with 10 fields: {...}'
fallback = 'Classify this review. Return JSON: {"sentiment": "positive|negative|neutral"}'
result = call_with_fallback(primary, fallback, ['sentiment'])
print(result)Pemutus Sirkuit
Pemutus sirkuit mencegah rantai yang gagal membuang panggilan API. Setelah N kegagalan berturut-turut, pemutus ini membuka sirkuit dan segera mengembalikan kesalahan tanpa melakukan panggilan API lebih lanjut:
class CircuitBreaker:
def __init__(self, failure_threshold=3, recovery_timeout=60):
self.failure_count = 0
self.threshold = failure_threshold
self.state = 'closed' # closed = normal, open = blocking
self.opened_at = None
def call(self, fn, *args, **kwargs):
import time
if self.state == 'open':
elapsed = time.time() - self.opened_at
if elapsed > 60: # recovery_timeout
self.state = 'half-open'
else:
raise RuntimeError('Circuit open — skipping API call')
try:
result = fn(*args, **kwargs)
self.failure_count = 0
self.state = 'closed'
return result
except Exception as e:
self.failure_count += 1
if self.failure_count >= self.threshold:
self.state = 'open'
self.opened_at = time.time()
print(f'Circuit opened after {self.failure_count} failures.')
raise e
cb = CircuitBreaker(failure_threshold=3)
print('Circuit breaker initialized.')Membuat Titik Pemeriksaan pada Rantai Panjang
Untuk rantai dengan banyak langkah atau langkah yang mahal, gunakan titik pemeriksaan untuk menyimpan hasil perantara. Jika langkah yang lebih akhir gagal, lanjutkan dari titik pemeriksaan tersebut, bukan memulai ulang dari Langkah 1:
import json, os
CHECKPOINT_DIR = '/tmp/chain_checkpoints'
os.makedirs(CHECKPOINT_DIR, exist_ok=True)
def save_checkpoint(run_id, step_id, data):
path = os.path.join(CHECKPOINT_DIR, f'{run_id}_step{step_id}.json')
with open(path, 'w') as f:
json.dump(data, f)
print(f'Checkpoint saved: step {step_id}')
def load_checkpoint(run_id, step_id):
path = os.path.join(CHECKPOINT_DIR, f'{run_id}_step{step_id}.json')
if os.path.exists(path):
with open(path) as f:
return json.load(f)
return None
def run_with_checkpoints(run_id, input_data):
step1 = load_checkpoint(run_id, 1) or json.loads(call(f'Step 1 processing: {input_data}'))
save_checkpoint(run_id, 1, step1)
step2 = load_checkpoint(run_id, 2) or json.loads(call(f'Step 2 processing: {step1}'))
save_checkpoint(run_id, 2, step2)
return step2
print('Checkpointing system defined.')Degradasi yang Terkendali
Jika suatu langkah dalam rantai gagal dan tidak dapat dipulihkan, degradasi yang terkendali melanjutkan rantai dengan data sebagian, alih-alih menghentikannya sepenuhnya:
def process_with_degradation(tickets):
results = []
for ticket in tickets:
try:
# Full chain: extract -> classify -> respond
extracted = json.loads(call(f'Extract issue from ticket. Return JSON: {{"issue": str}}\n\n{ticket}'))
classified = json.loads(call(f'Classify priority. Return JSON: {{"priority": str}}\n\n{extracted["issue"]}'))
response = call(f'Draft response for {classified["priority"]} priority: {extracted["issue"]}')
results.append({'ticket': ticket, 'response': response, 'degraded': False})
except Exception as e:
print(f'Chain failed for ticket, using fallback: {e}')
# Fallback: simple direct response without classification
simple_response = call(f'Respond to this support ticket:\n{ticket}')
results.append({'ticket': ticket, 'response': simple_response, 'degraded': True})
return results
print('Graceful degradation pipeline defined.')Pencatatan Kesalahan Terstruktur
Catat kesalahan dengan konteks yang cukup untuk mendiagnosis langkah mana yang gagal, seperti apa inputnya, dan apa yang dikembalikan model:
import logging, traceback
from datetime import datetime
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('chain')
def logged_step(step_name, prompt, validator=None):
start = datetime.utcnow()
try:
raw = call_with_retry(prompt)
result = validator(raw) if validator else raw
logger.info(f'[{step_name}] SUCCESS in {(datetime.utcnow()-start).total_seconds():.2f}s')
return result
except Exception as e:
logger.error(f'[{step_name}] FAILED after {(datetime.utcnow()-start).total_seconds():.2f}s')
logger.error(f'[{step_name}] PROMPT: {prompt[:200]}')
logger.error(f'[{step_name}] ERROR: {traceback.format_exc()}')
raise
print('Structured error logging defined.')Menguji Skenario Kesalahan
Uji penanganan kesalahan Anda secara khusus dengan menyuntikkan kegagalan. Gunakan objek tiruan untuk menyimulasikan kesalahan API dan output yang formatnya tidak valid:
from unittest.mock import patch, MagicMock
def test_fallback_on_json_error():
with patch('__main__.call') as mock_call:
# First call returns malformed JSON, fallback returns valid JSON
mock_call.side_effect = [
'This is not JSON at all',
'{"sentiment": "positive"}'
]
result = call_with_fallback(
primary_prompt='Analyze review with 10 fields',
fallback_prompt='Just classify sentiment as JSON',
required_fields=['sentiment']
)
assert result['sentiment'] == 'positive'
print('PASS: fallback activated correctly on JSON parse error')
def test_circuit_breaker_opens():
cb = CircuitBreaker(failure_threshold=2)
for i in range(2):
try:
cb.call(lambda: (_ for _ in ()).throw(RuntimeError('API fail')))
except RuntimeError:
pass
assert cb.state == 'open'
print('PASS: circuit breaker opened after 2 failures')
print('Error handling tests defined.')Memantau Kesehatan Rantai dalam Produksi
Dalam lingkungan produksi, lacak metrik kesehatan rantai untuk mendeteksi penurunan kinerja sebelum disadari pengguna:
- Tingkat keberhasilan langkah: Persentase proses ketika setiap langkah berhasil pada percobaan pertama
- Tingkat aktivasi perintah cadangan: Seberapa sering perintah cadangan digunakan?
- Tingkat degradasi: Berapa bagian proses rantai yang selesai dalam mode terdegradasi?
- Latensi langkah: Lacak latensi p50/p95 per langkah—langkah yang lambat menunjukkan masalah kompleksitas perintah
- Tingkat kegagalan validasi: Tingkat yang tinggi menandakan bahwa perintah perlu disempurnakan
Pemeriksaan Cepat
Apa tujuan pemutus sirkuit dalam rantai perintah?
Penanganan Kesalahan dalam Rantai—Inti Pembelajaran
Penanganan kesalahan yang tangguh membedakan rantai purwarupa dari sistem produksi:
- Validasi output setiap langkah sebelum meneruskannya—jangan pernah berasumsi bahwa model mengembalikan data yang benar
- Lakukan percobaan ulang terhadap kegagalan API sementara dengan jeda eksponensial—batas laju dan batas waktu dapat dipulihkan
- Gunakan perintah cadangan untuk menghasilkan output yang lebih sederhana ketika perintah utama gagal dalam validasi semantik
- Pemutus sirkuit menghentikan pemborosan panggilan API setelah terjadi kegagalan berulang
- Buat titik pemeriksaan untuk langkah yang mahal agar rantai panjang dapat dilanjutkan setelah kegagalan pada langkah akhir
- Degradasi yang terkendali menjaga alur kerja tetap berjalan dengan data sebagian, alih-alih menghentikannya
- Lacak tingkat keberhasilan langkah, tingkat penggunaan perintah cadangan, dan tingkat degradasi dalam produksi
Belajar AI Prompt Engineering 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
- 53
- Pelajaran
- 199
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Penanganan Galat dalam Rantai Perintah” gratis?
Ya — teks lengkap “Penanganan Galat dalam Rantai Perintah” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Prompt Engineering, upgrade ke CoddyKit PRO. Kursus AI Prompt Engineering mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Penanganan Galat dalam Rantai Perintah”?
Validasi keluaran perantara dan pulihkan proses dari kegagalan rantai. Kamu berlatih AI Prompt Engineering 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 Prompt Engineering?
Tidak diperlukan pengalaman sebelumnya. AI Prompt Engineering 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 4 dari 4.
Berapa lama pelajaran “Penanganan Galat dalam Rantai Perintah” 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 Prompt Engineering ini?
Ya. Setiap pelajaran AI Prompt Engineering 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
- Apa Itu Rantai Perintah?
- Pola Keluaran-ke-Masukan
- Rantai Transformasi Berurutan
- Penanganan Galat dalam Rantai Perintah