การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์
การจัดหมวดหมู่ความล้มเหลวอย่างเป็นระบบ: ข้อผิดพลาดของโมเดล เครื่องมือ ข้อมูล และตรรกะ
การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์ เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
อนุกรมวิธานความล้มเหลวของเอเจนต์
ความล้มเหลวของเอเจนต์แบ่งเป็นสี่ประเภท:
- ข้อผิดพลาดของโมเดล: LLM เรียกใช้เครื่องมือผิดรายการหรือสร้าง output ที่ไม่ถูกต้อง
- ข้อผิดพลาดของเครื่องมือ: ส่วนเชื่อมต่อโปรแกรมประยุกต์ภายนอกล้มเหลวหรือส่งคืนข้อมูลที่ไม่คาดคิด
- ข้อผิดพลาดของข้อมูล: input ไม่ถูกต้อง (รูปแบบผิด ฟิลด์หายไป หรือชนิดข้อมูลไม่คาดคิด)
- ข้อผิดพลาดทางตรรกะ: Step ถูกต้องแต่เรียงลำดับผิดหรืออาศัยข้อสมมติที่ไม่ถูกต้อง
ข้อผิดพลาดของโมเดล: การเรียกใช้เครื่องมือผิดรายการ
ข้อผิดพลาดของโมเดลเกิดขึ้นเมื่อ LLM เลือกเครื่องมือผิด ส่งอาร์กิวเมนต์ไม่ถูกต้อง หรือสร้าง JSON ที่มีรูปแบบผิดพลาด สาเหตุที่พบบ่อยมักมาจากคำอธิบายเครื่องมือไม่ชัดเจนหรือพรอมต์กำกวม
import openai
import json
client = openai.OpenAI(api_key='sk-...')
def detect_model_errors(response) -> list:
errors = []
message = response.choices[0].message
if message.tool_calls:
for tc in message.tool_calls:
tool_name = tc.function.name
try:
args = json.loads(tc.function.arguments)
except json.JSONDecodeError as e:
errors.append({
'type': 'model_error',
'subtype': 'malformed_tool_args',
'tool': tool_name,
'raw_args': tc.function.arguments,
'parse_error': str(e)
})
continue
# Validate required arguments
expected_tools = {
'search_web': ['query'],
'send_email': ['to', 'subject', 'body'],
'create_task': ['title']
}
required = expected_tools.get(tool_name, [])
missing = [r for r in required if r not in args]
if missing:
errors.append({
'type': 'model_error',
'subtype': 'missing_required_args',
'tool': tool_name,
'missing': missing
})
return errors
print('Model error detection function defined')ข้อผิดพลาดของเครื่องมือ: ความล้มเหลวของส่วนเชื่อมต่อโปรแกรมประยุกต์
ข้อผิดพลาดของเครื่องมือเกิดขึ้นเมื่อส่วนเชื่อมต่อโปรแกรมประยุกต์ภายนอกส่งคืน error (4xx, 5xx) หมดเวลา หรือส่งคืนข้อมูลในรูปแบบที่ไม่คาดคิด ให้บันทึก error ที่เกิดขึ้นจริง อาร์กิวเมนต์ของเครื่องมือ และการตอบกลับไว้เพื่อการวินิจฉัย
import httpx
from dataclasses import dataclass
from typing import Optional
@dataclass
class ToolError:
tool_name: str
error_type: str
status_code: Optional[int]
message: str
args_used: dict
retry_possible: bool
def classify_tool_error(tool_name: str, args: dict, exception: Exception) -> ToolError:
if isinstance(exception, httpx.TimeoutException):
return ToolError(
tool_name=tool_name,
error_type='timeout',
status_code=None,
message=str(exception),
args_used=args,
retry_possible=True # Retries are appropriate for timeouts
)
elif isinstance(exception, httpx.HTTPStatusError):
status = exception.response.status_code
retry = status >= 500 or status == 429 # Server errors and rate limits are retryable
return ToolError(
tool_name=tool_name,
error_type='http_error',
status_code=status,
message=exception.response.text[:200],
args_used=args,
retry_possible=retry
)
else:
return ToolError(
tool_name=tool_name,
error_type='unexpected_error',
status_code=None,
message=str(exception),
args_used=args,
retry_possible=False
)
print('Tool error classification defined')ข้อผิดพลาดของข้อมูล: การตรวจสอบ input
ข้อผิดพลาดของข้อมูลเกิดจาก input ที่ไม่ถูกต้องของเอเจนต์ เช่น ฟิลด์ที่จำเป็นหายไป ชนิดข้อมูลไม่ถูกต้อง หรือมีสตริงในตำแหน่งที่คาดว่าจะเป็นตัวเลข ตรวจสอบ input ที่จุดเริ่มต้นของเอเจนต์เพื่อค้นหาปัญหาเหล่านี้ตั้งแต่เนิ่น ๆ
from pydantic import BaseModel, validator, ValidationError
from typing import Optional
class EmailAgentInput(BaseModel):
email_id: str
action: str
user_id: int
priority: Optional[str] = 'normal'
@validator('action')
def action_must_be_valid(cls, v):
valid_actions = ['reply', 'forward', 'archive', 'summarize']
if v not in valid_actions:
raise ValueError(f'action must be one of {valid_actions}, got: {v}')
return v
@validator('email_id')
def email_id_not_empty(cls, v):
if not v.strip():
raise ValueError('email_id cannot be empty')
return v
def validate_agent_input(raw_input: dict) -> tuple:
try:
validated = EmailAgentInput(**raw_input)
return validated, None
except ValidationError as e:
return None, [
{'field': err['loc'][0], 'message': err['msg']}
for err in e.errors()
]
# Test with bad input
valid, errors = validate_agent_input({'email_id': '', 'action': 'delete', 'user_id': 'abc'})
if errors:
print('Data errors found:')
for err in errors:
print(f' {err["field"]}: {err["message"]}')ข้อผิดพลาดทางตรรกะ: ลำดับ Step ไม่ถูกต้อง
ข้อผิดพลาดทางตรรกะแก้ไขข้อบกพร่องได้ยากที่สุด เอเจนต์เรียกใช้เครื่องมือที่ถูกต้องด้วยอาร์กิวเมนต์ที่ถูกต้อง แต่เรียกใช้ผิดลำดับ ข้าม Step ที่จำเป็น หรือสร้างข้อสมมติที่ไม่ถูกต้องเกี่ยวกับ output ของ Step ก่อนหน้า
import logging
logger = logging.getLogger('agent.logic')
class AgentStepGuard:
'''
Enforces that steps execute in the required sequence.
'''
def __init__(self):
self.completed_steps = set()
self.STEP_DEPENDENCIES = {
'extract_action_items': ['read_email'],
'create_trello_card': ['extract_action_items'],
'send_slack_notification': ['create_trello_card']
}
def mark_complete(self, step_name: str):
self.completed_steps.add(step_name)
def can_run(self, step_name: str) -> tuple:
required = self.STEP_DEPENDENCIES.get(step_name, [])
missing = [r for r in required if r not in self.completed_steps]
if missing:
return False, f'Logic error: {step_name} requires {missing} to complete first'
return True, None
def assert_can_run(self, step_name: str):
ok, error = self.can_run(step_name)
if not ok:
logger.error(error)
raise RuntimeError(error)
guard = AgentStepGuard()
# Simulate trying to skip a step
try:
guard.assert_can_run('create_trello_card')
except RuntimeError as e:
print('Caught logic error:', e)
# Correct sequence
guard.mark_complete('read_email')
guard.mark_complete('extract_action_items')
guard.assert_can_run('create_trello_card') # Now allowed
print('Step sequence valid')การบันทึก Error แบบมีโครงสร้าง
บันทึก error ทุกครั้งพร้อมบริบทที่เพียงพอสำหรับการวิเคราะห์ภายหลัง ได้แก่ ประเภทของ error ลำดับการเรียกใช้ทั้งหมด input ของ Step และสถานะที่เกี่ยวข้องของเอเจนต์ในขณะที่เกิดความล้มเหลว
import logging
import traceback
import json
from datetime import datetime
logger = logging.getLogger('agent.errors')
def log_agent_error(error_type: str, step: str, inputs: dict, exception: Exception, agent_state: dict = None):
error_record = {
'timestamp': datetime.utcnow().isoformat(),
'error_type': error_type,
'step': step,
'exception_type': type(exception).__name__,
'exception_message': str(exception),
'traceback': traceback.format_exc(),
'inputs': inputs,
'agent_state': agent_state or {}
}
logger.error(json.dumps(error_record))
return error_record
# Example usage
try:
raise ValueError('Email ID not found in database')
except Exception as e:
record = log_agent_error(
error_type='data_error',
step='read_email',
inputs={'email_id': 'missing-id-123'},
exception=e,
agent_state={'user_id': 42, 'session_id': 'sess-abc'}
)
print('Error logged:', record['error_type'], '-', record['exception_message'])การตรวจสอบอัตรา Error
ติดตามอัตรา error แยกตาม Step และประเภทของ error เพื่อระบุปัญหาเชิงระบบ การพุ่งสูงขึ้นอย่างฉับพลันของ error จากโมเดลอาจบ่งชี้ว่าการเปลี่ยนพรอมต์ทำให้การเรียกใช้เครื่องมือเสียหาย ส่วนการพุ่งสูงขึ้นของ error จากเครื่องมืออาจบ่งชี้ว่าส่วนเชื่อมต่อโปรแกรมประยุกต์มีประสิทธิภาพลดลง
from collections import defaultdict
from datetime import datetime
class ErrorTracker:
def __init__(self):
self.errors = defaultdict(list)
def record(self, error_type: str, step: str):
key = f'{error_type}:{step}'
self.errors[key].append(datetime.utcnow())
def get_rates(self, window_minutes: int = 60) -> dict:
from datetime import timedelta
cutoff = datetime.utcnow() - timedelta(minutes=window_minutes)
rates = {}
for key, timestamps in self.errors.items():
recent = [ts for ts in timestamps if ts >= cutoff]
rates[key] = len(recent)
return dict(sorted(rates.items(), key=lambda x: x[1], reverse=True))
def has_spike(self, error_type: str, step: str, threshold: int = 5, window_minutes: int = 10) -> bool:
key = f'{error_type}:{step}'
rates = self.get_rates(window_minutes)
return rates.get(key, 0) >= threshold
tracker = ErrorTracker()
for _ in range(8):
tracker.record('tool_error', 'web_search')
tracker.record('model_error', 'intent_detection')
print('Error rates:', tracker.get_rates())
print('Spike detected:', tracker.has_spike('tool_error', 'web_search'))การแก้ไขข้อผิดพลาดของโมเดลด้วยการเล่นซ้ำ
เมื่อเกิดข้อผิดพลาดของโมเดล ให้เล่นซ้ำการเรียกใช้ LLM เดิมทุกประการด้วย input เดิม แล้วเปรียบเทียบ output กับสิ่งที่คาดไว้ เพิ่มคำสั่งที่เฉพาะเจาะจงยิ่งขึ้นในพรอมต์ระบบ หรือปรับปรุงคำอธิบายเครื่องมือเพื่อแก้ไขปัญหา
import openai
import json
client = openai.OpenAI(api_key='sk-...')
def save_failed_call(step_name: str, messages: list, tools: list, actual_response: str, expected_tool: str, filepath: str):
record = {
'step': step_name,
'messages': messages,
'tools': tools,
'actual_response': actual_response,
'expected_tool': expected_tool
}
with open(filepath, 'w') as f:
json.dump(record, f, indent=2)
print(f'Failed call saved to: {filepath}')
def replay_failed_call(filepath: str, improved_system_prompt: str = None) -> str:
with open(filepath) as f:
record = json.load(f)
messages = record['messages']
if improved_system_prompt:
# Replace system prompt
messages = [m if m['role'] != 'system' else {'role': 'system', 'content': improved_system_prompt}
for m in messages]
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
tools=record['tools']
)
return response.choices[0].message
print('Replay debugging functions defined')รายการตรวจสอบการวิเคราะห์สาเหตุราก
เมื่อเอเจนต์ล้มเหลว ให้ดำเนินการตามรายการตรวจสอบนี้อย่างเป็นระบบ:
- input ถูกต้องหรือไม่ (ข้อผิดพลาดของข้อมูล)
- มีส่วนเชื่อมต่อโปรแกรมประยุกต์ภายนอกใดส่งคืน error หรือไม่ (ข้อผิดพลาดของเครื่องมือ)
- LLM เรียกใช้เครื่องมือที่ถูกต้องหรือไม่ อาร์กิวเมนต์ถูกต้องหรือไม่ (ข้อผิดพลาดของโมเดล)
- Step ทำงานตามลำดับที่ถูกต้องหรือไม่ (ข้อผิดพลาดทางตรรกะ)
- พรอมต์มีบริบทเพียงพอหรือไม่ (ข้อผิดพลาดของโมเดล - บริบท)
def diagnose_failure(error_log: dict) -> dict:
diagnosis = {
'error_type': error_log.get('error_type'),
'root_cause': None,
'immediate_fix': None,
'long_term_fix': None
}
if error_log.get('error_type') == 'data_error':
diagnosis['root_cause'] = 'Invalid or missing input data'
diagnosis['immediate_fix'] = 'Return clear error to caller with field-level validation feedback'
diagnosis['long_term_fix'] = 'Add Pydantic validation at agent entry point'
elif error_log.get('error_type') == 'tool_error':
status = error_log.get('status_code')
if status == 429:
diagnosis['root_cause'] = 'Rate limit hit'
diagnosis['immediate_fix'] = 'Retry with exponential backoff'
diagnosis['long_term_fix'] = 'Add rate limiter to tool calls'
elif status and status >= 500:
diagnosis['root_cause'] = 'Upstream service degradation'
diagnosis['immediate_fix'] = 'Retry up to 3 times, then graceful degradation'
diagnosis['long_term_fix'] = 'Add circuit breaker pattern'
elif error_log.get('error_type') == 'model_error':
diagnosis['root_cause'] = 'LLM tool selection failure'
diagnosis['immediate_fix'] = 'Add explicit tool selection validation'
diagnosis['long_term_fix'] = 'Improve tool descriptions; add few-shot examples'
return diagnosis
result = diagnose_failure({'error_type': 'tool_error', 'status_code': 429})
print('Diagnosis:', result)การแจ้งเตือนความล้มเหลวร้ายแรง
ไม่ใช่ error ทุกประเภทที่ต้องดำเนินการทันที จัดประเภท error ตามระดับความรุนแรงและส่งการแจ้งเตือนไปยังปลายทางที่เหมาะสมตามประเภทนั้น ข้อผิดพลาดของข้อมูลที่ไม่สำคัญในกระบวนการที่ไม่สำคัญอาจบันทึกไว้ได้ ส่วนกระบวนการหลักที่เสียหายต้องแจ้งเตือนทันที
ERROR_SEVERITY = {
'data_error': 'low', # Bad input: log and return error to caller
'model_error': 'medium', # LLM misbehavior: investigate, may need prompt fix
'tool_error': 'medium', # API failure: may self-recover with retry
'logic_error': 'high' # Sequencing bug: needs code fix immediately
}
def route_alert(error_type: str, step: str, message: str, is_core_flow: bool = False):
severity = ERROR_SEVERITY.get(error_type, 'medium')
if is_core_flow:
severity = 'high'
if severity == 'high':
print(f'[PAGERDUTY] CRITICAL: {error_type} in {step}: {message}')
# Call PagerDuty API here
elif severity == 'medium':
print(f'[SLACK] WARNING: {error_type} in {step}: {message}')
# Call Slack API here
else:
print(f'[LOG] INFO: {error_type} in {step}: {message}')
route_alert('logic_error', 'create_trello_card', 'Prerequisites not met', is_core_flow=True)
route_alert('data_error', 'parse_input', 'Missing optional field', is_core_flow=False)แม่แบบการวิเคราะห์ภายหลังเหตุการณ์
สำหรับความล้มเหลวที่สำคัญของเอเจนต์ ให้เขียนการวิเคราะห์ภายหลังเหตุการณ์ที่ดีควรประกอบด้วย ลำดับเหตุการณ์ สาเหตุราก ผลกระทบ สิ่งที่ดำเนินการได้ดี สิ่งที่ผิดพลาด และรายการดำเนินการเพื่อป้องกันไม่ให้เกิดซ้ำ
def generate_post_mortem(failure_data: dict) -> str:
return f'''
## Post-Mortem: {failure_data.get("title", "Agent Failure")}
**Date**: {failure_data.get("date")}
**Duration**: {failure_data.get("duration_minutes")} minutes
**Impact**: {failure_data.get("impact")}
### Timeline
{chr(10).join(failure_data.get("timeline", []))}
### Root Cause
{failure_data.get("root_cause")}
### Contributing Factors
{chr(10).join(failure_data.get("contributing_factors", []))}
### Action Items
{chr(10).join([f"- [ ] {item}" for item in failure_data.get("action_items", [])])}
'''.strip()
post_mortem_data = {
'title': 'Email Pipeline Failure - Wrong Trello List',
'date': '2025-01-15',
'duration_minutes': 45,
'impact': '200 emails processed but Trello cards created in wrong list',
'timeline': ['09:00 - Pipeline started', '09:15 - First error logged', '09:45 - Fixed and redeployed'],
'root_cause': 'Logic error: TRELLO_LIST_ID env var defaulted to staging value in production',
'contributing_factors': ['- Missing config validation at startup', '- No alert on wrong list ID'],
'action_items': ['Add config validation on startup', 'Alert if list_id changes unexpectedly']
}
print(generate_post_mortem(post_mortem_data))แบบทดสอบความเข้าใจ: การวิเคราะห์สาเหตุที่แท้จริง
ทดสอบความเข้าใจของคุณเกี่ยวกับการวิเคราะห์สาเหตุที่แท้จริงของความล้มเหลวของเอเจนต์
สรุปการแก้ไขข้อบกพร่อง
การวิเคราะห์สาเหตุที่แท้จริงอย่างเป็นระบบสำหรับความล้มเหลวของเอเจนต์ใช้การจัดหมวดหมู่ 4 ประเภท ได้แก่ ข้อผิดพลาดจากโมเดล (ปัญหาการตัดสินใจของ LLM) ข้อผิดพลาดจากเครื่องมือ (ความล้มเหลวของส่วนเชื่อมต่อโปรแกรมประยุกต์) ข้อผิดพลาดจากข้อมูล (อินพุตไม่ถูกต้อง) และข้อผิดพลาดทางตรรกะ (ข้อบกพร่องด้านลำดับการทำงาน) ควรใช้ร่วมกับการบันทึกเหตุการณ์อย่างมีโครงสร้าง การติดตามอัตราข้อผิดพลาด การแก้ไขข้อบกพร่องด้วยการเล่นเหตุการณ์ซ้ำสำหรับข้อผิดพลาดจากโมเดล และการทบทวนหลังเหตุการณ์สำหรับความล้มเหลวที่สำคัญ
คำถามที่พบบ่อย
บทเรียน “การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์”
การจัดหมวดหมู่ความล้มเหลวอย่างเป็นระบบ: ข้อผิดพลาดของโมเดล เครื่องมือ ข้อมูล และตรรกะ คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การวิเคราะห์ร่องรอยด้วย LangSmith และ Langfuse
- การวิเคราะห์โทเคนและต้นทุนแยกตามขั้นตอน
- การระบุขั้นตอนที่ช้าและมีค่าใช้จ่ายสูง
- การวิเคราะห์สาเหตุรากของความล้มเหลวของเอเจนต์