Product Management
Đăng nhập
ESC

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

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

Bài 3 — Thiết lập môi trường và đăng ký tool đầu tiên

Đã đọc 0/9 mục · còn khoảng 3 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.

Bài này bạn sẽ dựng một tool registry — nơi tập trung khai báo schema và hàm thực thi — rồi nối nó vào vòng lặp model. Đây là bộ khung tái sử dụng cho mọi agent về sau. Sau khi có registry, thêm một tool mới chỉ là viết một hàm và một schema, đăng ký vào bảng; phần vòng lặp và dispatcher không phải sửa. Đó chính là giá trị của việc tách lớp ngay từ đầu.

Bước 1 — Chuẩn bị môi trường

  • Cài SDK của nhà cung cấp (ví dụ Python): pip install openai hoặc pip install anthropic.
  • Đặt API key qua biến môi trường, không hardcode:
export LLM_API_KEY="sk-..."
  • Tạo file tools.py cho registry và agent.py cho vòng lặp.

Bước 2 — Viết hàm thực thi thật

Tách hàm nghiệp vụ khỏi phần LLM. Hàm nhận tham số Python thường, trả về dict:

def get_weather(city: str) -> dict:
    # Gọi API thật; ở đây mock cho gọn
    data = {"Da Nang": 31, "Ha Noi": 28}
    if city not in data:
        raise ValueError(f"Không có dữ liệu cho {city}")
    return {"city": city, "temp_c": data[city]}

Bước 3 — Đăng ký tool vào registry

Gom schema và hàm vào một chỗ, dùng chung name làm khóa:

TOOLS = {
    "get_weather": {
        "schema": {
            "name": "get_weather",
            "description": "Lấy nhiệt độ hiện tại của một thành phố VN.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string",
                             "description": "Tên thành phố, vd 'Da Nang'"}
                },
                "required": ["city"]
            }
        },
        "fn": get_weather
    }
}

def tool_schemas():
    return [t["schema"] for t in TOOLS.values()]

Bước 4 — Viết bộ dispatcher

Dispatcher tra registry theo name và gọi đúng hàm. Không bao giờ dùng eval trên tên model trả về — chỉ tra bảng cho phép:

def dispatch(name: str, args: dict) -> dict:
    if name not in TOOLS:                 # allowlist
        return {"error": f"Tool {name} không tồn tại"}
    try:
        return {"ok": TOOLS[name]["fn"](**args)}
    except Exception as e:
        return {"error": str(e)}          # lỗi -> trả về, không crash

Bước 5 — Nối vào vòng lặp model

def run(user_msg: str):
    messages = [{"role": "user", "content": user_msg}]
    for _ in range(6):                    # trần lặp, chống loop vô hạn
        resp = model.chat(messages, tools=tool_schemas())
        if not resp.tool_calls:
            return resp.content
        for call in resp.tool_calls:
            result = dispatch(call.name, call.args)
            messages.append(resp.as_message())
            messages.append({"role": "tool",
                             "tool_call_id": call.id,
                             "content": json.dumps(result)})
    return "Đã đạt giới hạn số bước."

Hai chi tiết sống còn: trần lặp (range(6)) chống loop vô hạn, và luôn gắn tool_call_id để model biết kết quả nào ứng với lời gọi nào. Con số 6 chỉ là mặc định an toàn — hãy chọn trần vừa đủ cho tác vụ phức tạp nhất mà agent phải làm, không hơn. Trần quá lớn làm mất tác dụng bảo vệ; trần quá nhỏ cắt ngang tác vụ hợp lệ.

Khung tư duy: tách 3 lớp

Giữ ba lớp này độc lập để dễ test và bảo trì:

  • Lớp nghiệp vụ (get_weather): thuần Python, test được không cần LLM.
  • Lớp registry/dispatch: ánh xạ name → hàm, validate, bắt lỗi.
  • Lớp vòng lặp agent: nói chuyện với model, quản lý messages.

Checklist trước khi chạy

  • [ ] API key nằm trong env, không trong code.
  • [ ] Dispatcher dùng allowlist, tuyệt đối không eval/getattr động.
  • [ ] Có trần số bước lặp.
  • [ ] Mỗi kết quả tool gắn đúng tool_call_id.
  • [ ] Hàm nghiệp vụ test được độc lập.

Sai lầm thường gặp

  • Dùng eval(name) hoặc globals()[name] để gọi hàm theo tên model đưa. Đây là lỗ hổng thực thi mã tùy ý. Luôn tra allowlist.
  • Quên trần lặp. Model có thể gọi tool liên tục và bạn cháy hết quota trong vài giây.
  • Gộp nghiệp vụ vào vòng lặp. Khi trộn code gọi API thời tiết với code nói chuyện model, bạn không test được gì cả.
  • Không serialize kết quả. Kết quả tool phải là chuỗi (thường JSON) khi gửi lại model; quên json.dumps gây lỗi.
  • Bỏ sót tool_call_id. Với nhiều tool call song song, thiếu id khiến model ghép sai kết quả.
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