Hoàn thành bài "Lesson 4: Tool Calling and External Integrations" trước để mở khoá bài này.Đến bài trước

Giới thiệu

Trong môi trường sản xuất, hệ thống tác nhân gặp sự cố theo những cách bất ngờ. Mô hình ngừng có thể tưởng tượng ra một tên công cụ. Một API trả về 500. Người dùng yêu cầu một thứ nằm ngoài phạm vi của tác nhân. Một vòng lặp chạy mãi mãi vì mô hình tiếp tục gọi cùng một công cụ với cùng một đầu vào. Tất cả những điều này không mang tính lý thuyết — mỗi tác nhân hoạt động trong thời gian dài trải qua chúng.

Bài học này trình bày các mẫu làm cho tác nhân tin cậy: thử lại với backoff, xác thực đầu vào trước khi gọi công cụ, xác thực đầu ra sau phản hồi từ mô hình, cầu dao để dừng các vòng lặp bị vượt quá, và các phương án thay thế mềm khi mô hình đưa ra thứ mà bạn không thể phân tích được. Mục tiêu không phải làm cho tác nhân hoàn hảo — mà là làm cho các lỗi có thể dự đoán, được ghi nhật ký và có thể khôi phục.

Xác thực Đầu vào Trước khi Thực thi Công cụ

Trước khi bạn truyền bất kỳ thứ gì cho một công cụ bên ngoài, hãy xác thực nó. Lỗ hổng phổ biến nhất là tác nhân sinh ra đối số công cụ trông hợp ngữ pháp nhưng mang ý nghĩa vô nghĩa — một ngày tháng năm 9999, một ID người dùng không tồn tại, một truy vấn SQL thiếu điều khoản.

python
def get_user_orders(user_id: str, date_from: str, date_to: str) -> dict:
# Validate user_id is numeric and exists
if not user_id.isdigit() or not user_exists(user_id):
return {"error": "invalid_user_id", "message": f"User {user_id} not found"}
# Validate date format
try:
from datetime import datetime
datetime.strptime(date_from, "%Y-%m-%d")
datetime.strptime(date_to, "%Y-%m-%d")
except ValueError:
return {"error": "invalid_date", "message": "Dates must be YYYY-MM-DD"}
# Validate date range
if date_from > date_to:
return {"error": "invalid_range", "message": "date_from must be before date_to"}
# Now safe to call the actual tool
return query_orders(user_id, date_from, date_to)

Khi xác thực thất bại, trả về một đối tượng lỗi có cấu trúc — chứ không phải một ngoại lệ. Tác nhân đọc cái này và quyết định bước tiếp theo: hỏi người dùng để xin làm rõ, thử một phương pháp khác, hoặc từ chối một cách mềm mại.

Thử lại, Backoff và Cầu dao

Các sự cố nhất thời (lỗi thời gian mạng, lỗi 503, giới hạn tốc độ) xứng đáng được thử lại. Nhưng thử lại một cách ngây ngô sẽ làm mọi thứ tệ hơn — nếu dịch vụ ở phía dưới đang quá tải, cứ thử lại càng nhiều càng làm nó quá tải.

python
import time
import random
def call_with_retry(fn, max_attempts=3, base_delay=1.0):
for attempt in range(max_attempts):
try:
result = fn()
if attempt > 0:
log_recovery(attempt) # Log that retry succeeded
return result
except RetryableError as e:
if attempt == max_attempts - 1:
raise
delay = base_delay * (2 ** attempt) + random.uniform(0, 0.5)
log_retry_attempt(attempt, e, delay)
time.sleep(delay)

Backoff lũy thừa với jitter phân tán lưu lượng thử lại để bạn không đồng bộ tất cả các tác nhân thử lại vào cùng một thời điểm. Chỉ thử lại khi lỗi được phân loại là nhất thời — tuyệt đối không thử lại với 400 Bad Request, vì cùng đầu vào sẽ gây ra cùng lỗi mọi lần.

Ràsđứn kích hoạt tác động của cầu dao: nếu một công cụ đã gặp lỗi N lần liên tiếp, dừng gọi nó trong một khoảng nghỉ và thất bại nhanh chóng. Điều này bảo vệ bạn khỏi việc các tác nhân vòng lặp vào một dịch vụ chết.

python
class CircuitBreaker:
def __init__(self, failure_threshold=5, cooldown_seconds=60):
self.failures = 0
self.threshold = failure_threshold
self.cooldown = cooldown_seconds
self.open_until = 0
def call(self, fn):
if time.time() < self.open_until:
raise CircuitOpenError(f"Circuit open until {self.open_until}")
try:
result = fn()
self.failures = 0
return result
except Exception:
self.failures += 1
if self.failures >= self.threshold:
self.open_until = time.time() + self.cooldown
raise
Máy trạng thái cho cầu dao vòng lặp hiển thị các biến đổi đóng -> mở -> bán mở

Xác thực đầu ra mô hình và Xử lý vòng lặp

Mô hình đôi khi sẽ sản sinh đầu ra không phù hợp với sơ đồ mong đợi của bạn — một blob JSON thiếu trường bắt buộc, một lời gọi công cụ với tham số ở sai kiểu, một “gọi hàm” thực chất là một câu ngôn ngữ tự nhiên bị ảo giác. Bạn cần một lớp giữ lại để bắt được điều này.

python
def parse_agent_response(raw: str) -> AgentAction:
try:
parsed = json.loads(raw)
except json.JSONDecodeError:
return AgentAction.recover("Model returned non-JSON output")
if "tool" not in parsed or "arguments" not in parsed:
return AgentAction.recover("Missing tool or arguments field")
if parsed["tool"] not in ALLOWED_TOOLS:
return AgentAction.reject(f"Model tried to call unknown tool: {parsed['tool']}")
return AgentAction.execute(parsed["tool"], parsed["arguments"])

Phát hiện vòng lặp cũng quan trọng như vậy. Theo dõi N cặp (công cụ, tham số) cuối cùng. Nếu cùng cặp lặp lại nhiều hơn M lần, ngắt bỏ tác nhân và đưa ra lỗi cho người dùng — chẳng hạn "Tôi có vẻ đang lặp lại bước giống nhau." Nếu không có lớp bảo vệ này, một mô hình bị nhầm có thể mất hàng nghìn token để gọi cùng một công cụ như một điểm chết vô tận.

Sự giảm độ tin cậy nhẹ nhàng và lỗi hiển thị cho người dùng

Khi tác nhân không thể hoàn thành một nhiệm vụ, phản hồi cho người dùng nên cụ thể và có thể hành động. "Đã xảy ra lỗi" là vô dụng. "Tôi không thể lấy được đơn hàng của bạn vì dịch vụ đơn hàng tạm thời không sẵn có. Vui lòng thử lại sau một phút, hoặc tôi có thể hiển thị tóm tắt tài khoản của bạn" cho người dùng biết chuyện gì đã xảy ra và đề nghị tùy chọn thay thế.

Xây dựng chuỗi dự phòng: nếu công cụ chính thất bại, thử công cụ phụ đơn giản hơn (ví dụ, dữ liệu được lưu cache thay vì dữ liệu sống, hoặc một lượt gọi LLM khác với phạm vi nhỏ hơn). Nếu mọi thứ đều thất bại, trả về phản hồi cuối cùng giải thích giới hạn một cách thành thật. Tuyệt đối không tự ý làm giả dữ liệu để che đậy một cuộc gọi công cụ bị thiếu — người dùng sẽ nhận ra và niềm tin sẽ mất đi.

Tóm tắt

Những tác nhân đáng tin cậy được xây dựng từ nhiều lớp xác thực, thử lại và xử lý thất bại một cách tao nhã. Xác thực input trước công cụ, thử lại các lỗi tạm thời với backoff lũy thừa và jitter, dùng cầu dao để ngăn vòng lặp quá độ, xác thực đầu ra mô hình với một sơ đồ nghiêm ngặt, phát hiện hành động lặp lại để ngăn vòng lặp vô hạn, và luôn cho người dùng một câu trả lời cụ thể và trung thực khi mọi thứ gặp sự cố. Các mẫu trong bài học này áp dụng cho dù bạn đang xây dựng với LangChain, sự phối hợp tùy chỉnh, hoặc bất kỳ khung công tác nào cho tác nhân — khung có thể xử lý một số cái này cho bạn, nhưng bạn vẫn nên hiểu những gì đang diễn ra ở phía dưới.

Luyện tập sau buổi học

Bài kiểm tra cuối bài

Ôn lại kiến thức, thử sức và nhận góp ý cho bài làm.

0/1
Đã trả lời · 0/1
Lesson 5: Xử lý lỗi và Độ tin cậy trong Hệ thống Tác vụ