Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 4 — Xử lý lỗi và retry khi gọi tool

Đã đọc 0/8 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Tool gọi ra thế giới thật, nên nó sẽ hỏng: API timeout, mạng rớt, rate limit, dữ liệu thiếu. Agent xịn không phải là agent không bao giờ gặp lỗi, mà là agent phục hồi được từ lỗi. Bài này dạy chiến lược retry và cách để model tự sửa. Nguyên tắc bao trùm: một lỗi được xử lý tốt là một lỗi biến thành thông tin — hoặc để hệ thống retry, hoặc để model điều chỉnh, hoặc để người dùng biết chuyện gì xảy ra. Lỗi tệ nhất là lỗi bị nuốt im lặng.

Phân loại lỗi để xử lý đúng

Không phải lỗi nào cũng retry được. Phân loại trước:

  • Lỗi tạm thời (transient) — timeout, 503, rate limit 429, mạng chập chờn. → Retry được với backoff.
  • Lỗi đầu vào (client error) — tham số sai, 400, email không tồn tại. → Không retry; trả lỗi cho model để nó sửa tham số.
  • Lỗi nghiệp vụ — "đơn hàng đã hủy, không thể cập nhật". → Không retry; đây là kết quả hợp lệ, để model diễn giải cho người dùng.
Retry mù một lỗi 400 chỉ tốn thời gian và tiền — nó sẽ luôn 400.

Retry với exponential backoff

Với lỗi transient, chờ tăng dần và có jitter để tránh dồn tải:

import time, random

def call_with_retry(fn, *args, max_tries=3):
    for attempt in range(max_tries):
        try:
            return fn(*args)
        except TransientError as e:
            if attempt == max_tries - 1:
                raise
            wait = (2 ** attempt) + random.uniform(0, 0.5)  # 1s, 2s, 4s + jitter
            time.sleep(wait)

Để MODEL tự sửa: trả lỗi có cấu trúc

Đây là kỹ thuật mạnh nhất của tool-use. Với lỗi đầu vào, đừng crash — trả một message lỗi rõ ràng, gợi ý sửa về cho model. Model đọc và tự gọi lại đúng:

def dispatch(name, args):
    try:
        return {"ok": TOOLS[name]["fn"](**args)}
    except ValidationError as e:
        return {"error": "invalid_args",
                "message": f"Tham số sai: {e}. Hãy kiểm tra và gọi lại.",
                "retryable": False}
    except TransientError:
        return {"error": "temporary",
                "message": "Dịch vụ tạm gián đoạn, đã thử lại nhưng thất bại."}

Ví dụ: model gọi get_weather(city="Danang") nhưng registry dùng "Da Nang". Bạn trả {"error": "Không tìm thấy 'Danang'. Các thành phố hợp lệ: Da Nang, Ha Noi"}. Model đọc, gọi lại get_weather(city="Da Nang") và thành công. Bạn vừa cho model khả năng tự sửa.

Khung tư duy: cây quyết định khi lỗi

Lỗi xảy ra
 ├─ Transient? → retry backoff (tối đa N lần) → vẫn lỗi? báo model "tạm gián đoạn"
 ├─ Sai tham số? → trả lỗi mô tả + gợi ý → để MODEL gọi lại
 └─ Nghiệp vụ?  → trả kết quả hợp lệ → để MODEL diễn giải

Chống retry vô hạn ở tầng agent

Ngoài retry trong từng tool, đặt ngân sách toàn cục: tối đa số lần gọi tool, hoặc theo dõi cùng một tool call lặp lại. Nếu model gọi get_weather("X") ba lần với cùng lỗi, dừng và trả lời người dùng — đừng để nó lặp mãi.

if call_signature in seen and seen[call_signature] >= 2:
    return {"error": "Đã thử tool này nhiều lần không thành công, dừng lại."}

Checklist độ bền

  • [ ] Phân loại lỗi: transient / input / business.
  • [ ] Chỉ retry lỗi transient, có backoff + jitter.
  • [ ] Lỗi input trả message gợi ý sửa cho model.
  • [ ] Có timeout cho mọi lời gọi mạng.
  • [ ] Có ngân sách tool call toàn cục + phát hiện lặp.
  • [ ] Ghi log mọi lỗi kèm tham số (để debug sau).

Sai lầm thường gặp

  • Retry mọi loại lỗi. Retry một lỗi 400 chỉ đốt tiền; nó sẽ không bao giờ thành công.
  • Retry không backoff. Bắn lại ngay lập tức làm nặng thêm API đang quá tải, dễ bị ban.
  • Nuốt lỗi im lặng. except: pass khiến agent trả lời sai mà bạn không biết vì sao.
  • Không đặt timeout. Một API treo có thể khiến toàn bộ agent đứng vô thời hạn.
  • Trả lỗi kỹ thuật thô cho model. Stack trace dài làm model rối; hãy tóm gọn thành message hành động được.
  • Quên chống loop. Model kẹt trong vòng gọi-lỗi-gọi-lỗi sẽ cháy quota nếu không có trần.
Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi