Thủ thuật
Hướng dẫn gọi công cụ trên OpenRouter: Viết code một lần, chạy đa mô hình chỉ với một dòng thay đổi
(giờ Việt Nam)
Tóm tắt AI
OpenRouter ra mắt hướng dẫn giúp lập trình viên sử dụng chung một cấu trúc code để gọi công cụ (tool calling) trên nhiều mô hình như Claude, GPT và các mô hình mã nguồn mở, chỉ cần thay đổi tên mô hình trong yêu cầu.
Bản dịch AI

Tool calling (gọi công cụ), hay còn gọi là function calling (gọi hàm), cho phép một mô hình yêu cầu một hàm thông qua định dạng JSON có cấu trúc. Mã nguồn của bạn sẽ thực thi hàm đó, trả về kết quả và mô hình sẽ sử dụng kết quả này để hoàn thiện câu trả lời. Mọi nhà cung cấp lớn đều hỗ trợ phiên bản này, nhưng hầu hết các hướng dẫn chỉ tập trung vào một nhà cung cấp duy nhất. Do đó, mã nguồn viết theo hướng dẫn của OpenAI sẽ cần phải viết lại khi bạn chuyển sang Claude. Với API của chúng tôi, bạn không cần viết lại bất cứ thứ gì. Bạn chỉ cần viết vòng lặp một lần, thay đổi chuỗi tên mô hình và giữ nguyên mã nguồn của công cụ.
Hướng dẫn này bao gồm toàn bộ vòng lặp: định nghĩa công cụ, gửi yêu cầu, đọc phản hồi tool_calls, thực thi hàm, trả về kết quả và nhận câu trả lời cuối cùng. Sau đó, bạn sẽ chạy cùng một đoạn mã đó với ba nhà cung cấp khác nhau chỉ bằng cách thay đổi một chuỗi ký tự.
Tài liệu về tool calling của chúng tôi liệt kê mọi trường dữ liệu. Hướng dẫn này sẽ trình bày toàn bộ quy trình từ đầu đến cuối.
Tóm tắt
Tool calling là gì và tại sao "function calling" lại là một?
Tool calling và function calling là hai tên gọi cho cùng một cơ chế. Bạn mô tả hàm cho mô hình bằng một lược đồ JSON (JSON schema) – một bản đặc tả văn bản về tên hàm và các đầu vào. Sau đó, mô hình có thể yêu cầu mã nguồn của bạn gọi hàm đó với các đối số cụ thể. Mã nguồn của bạn thực thi hàm, trả về kết quả và mô hình sử dụng kết quả đó để hoàn thiện câu trả lời.
OpenAI đã phổ biến tên gọi cũ hơn là "function calling". Hầu hết các API hiện nay đều gọi là "tool calling". Cả hai đều có nghĩa giống nhau. Bạn gửi trường tools, mô hình trả về tool_calls và chúng tôi chấp nhận một lược đồ tương thích với OpenAI cho cả Claude, GPT và Llama, vì vậy sự khác biệt về tên gọi không làm thay đổi mã nguồn của bạn. Hướng dẫn này sử dụng thuật ngữ "tool calling" xuyên suốt vì đó là tên gọi của các trường trong API. Bạn vẫn sẽ thấy "function calling" trong các tài liệu và SDK cũ hơn.
Vòng lặp này có bốn bước:
Tool calling so với việc mô hình "tự chạy" công cụ
Mô hình không bao giờ tự thực thi công cụ. Nó chỉ trả về một yêu cầu tool_calls, và ứng dụng của bạn mới là bên thực hiện việc thực thi đó.
Nó không tự gọi API thời tiết, không truy vấn cơ sở dữ liệu hay chạy mã nguồn của bạn. Nó chỉ gửi một yêu cầu có cấu trúc như get_weather(location="Paris") rồi dừng lại. Ứng dụng của bạn sẽ chạy hàm và quyết định những gì cần trả về. Bạn vẫn giữ quyền kiểm soát đối với các khóa bảo mật, tác dụng phụ (side effects) và xác thực dữ liệu. Mô hình chỉ quyết định khi nào cần đặt câu hỏi.
Định nghĩa một công cụ
Trước khi bắt đầu, bạn cần có tài khoản OpenRouter và một khóa API, bạn có thể tạo khóa này trong bảng điều khiển. Hãy xuất nó dưới dạng biến môi trường OPENROUTER_API_KEY để các ví dụ bên dưới có thể đọc được.
Bạn cũng cần một SDK: Python 3.10 trở lên với lệnh pip install openai, hoặc Node 22 trở lên với lệnh npm install openai. Không cần thêm bất cứ thứ gì khác. Hàm thời tiết trả về một giá trị cố định thay vì gọi một API thực tế, vì vậy khóa OpenRouter là khóa duy nhất bạn cần.
Hướng dẫn này sử dụng một công cụ duy nhất là get_weather(location, unit) trong mọi ví dụ. Hãy định nghĩa nó dưới dạng lược đồ JSON tương thích với OpenAI:
Tiếp theo, hãy viết hàm mà mô hình có thể yêu cầu. Một ứng dụng thực tế sẽ gọi đến một API thời tiết. Ví dụ này trả về một giá trị cố định để bạn không cần thêm khóa API thứ hai khi thực hành theo:
Bây giờ, hãy trỏ SDK vào endpoint của chúng tôi. Chúng tôi chấp nhận định dạng API của OpenAI, vì vậy nếu bạn đã sử dụng OpenAI SDK, bạn chỉ cần thay đổi base_url và khóa API:
Nếu bạn muốn xem yêu cầu thô trước khi kết nối với SDK, lệnh gọi đầu tiên tương tự trong cURL sẽ trông như thế này:
Vòng lặp yêu cầu/phản hồi trong mã nguồn
Hàm này đại diện cho toàn bộ vòng lặp và bạn sẽ không cần thay đổi nó nữa trong hướng dẫn này. Nó gửi các tin nhắn và công cụ, kiểm tra tool_calls, thực thi từng công cụ, đính kèm kết quả và yêu cầu mô hình đưa ra câu trả lời cuối cùng:
Đây là cùng một vòng lặp trong JavaScript/TypeScript cho Node 22+, sử dụng gói openai trỏ đến endpoint của chúng tôi:
Hãy thêm một lưu ý trước khi đưa mã này vào môi trường production: arguments là một chuỗi do mô hình tạo ra, không phải là một payload đã được xác thực. Đôi khi các mô hình trả về JSON không hợp lệ hoặc tự tạo ra các tham số mà lược đồ của bạn chưa từng khai báo. Hãy bao bọc quá trình phân tích (parse) trong các khối xử lý lỗi và kiểm tra các khóa (keys) so với lược đồ của bạn trước khi truyền chúng vào hàm. Các ví dụ ở đây bỏ qua bước này để mã nguồn ngắn gọn hơn.
Mọi nội dung bên dưới đều gọi run_tool_loop hoặc runToolLoop với các chuỗi tên mô hình khác nhau.
Chạy với Claude
Lần chạy đầu tiên chỉ cần tên mô hình. Hãy truyền vào một mô hình của Anthropic và cả bốn bước sẽ diễn ra trong một lần gọi run_tool_loop:
Lần gọi run_tool_loop đó đã thực hiện cả bốn bước và thực hiện hai yêu cầu API. Yêu cầu đầu tiên trả về một yêu cầu tool_calls. Mã nguồn của bạn đã chạy get_weather và đính kèm kết quả. Yêu cầu thứ hai trả về câu trả lời hoàn chỉnh.
Các slug (tên định danh) của mô hình có thể thay đổi giữa các bản phát hành, vì vậy hãy xác nhận chuỗi chính xác trên danh mục mô hình của chúng tôi trước khi sử dụng.
Đọc phản hồi
Tên hàm và các đối số nằm trong mảng tool_calls. Trong phản hồi đầu tiên, choices[0].message sẽ trông như thế này:
Có hai chi tiết quan trọng ở đây. Thứ nhất, arguments là một chuỗi đã mã hóa JSON, không phải là một đối tượng, vì vậy hãy phân tích nó bằng json.loads hoặc JSON.parse. Thứ hai, tool_calls là một mảng, vì vậy mã nguồn của bạn phải xử lý được nhiều hơn một lệnh gọi trong mỗi phản hồi.
Chạy với GPT
Lần chạy với Claude đã chứng minh vòng lặp hoạt động. Lần chạy tiếp theo cho thấy cùng một đoạn mã đó hoạt động trên một nhà cung cấp khác. Thay đổi duy nhất chỉ là một chuỗi ký tự:
Sự khác biệt duy nhất so với ví dụ của Claude là anthropic/claude-opus-4.8 chuyển thành openai/gpt-4o. Lược đồ công cụ, vòng lặp, quá trình phân tích và tin nhắn kết quả đều giữ nguyên, vì chúng tôi trả về cùng một định dạng tool_calls cho cả hai. Điều này đúng với bất kỳ mô hình nào hỗ trợ công cụ. Hãy kiểm tra khả năng hỗ trợ công cụ trước khi bạn chuyển đổi.
Chạy với một mô hình mã nguồn mở
Các mô hình độc quyền thường chia sẻ chung một định dạng, vì vậy một mô hình mã nguồn mở (open-weight) là một bài kiểm tra khắt khe hơn. Hãy thay đổi chuỗi tên mô hình một lần nữa:
Đó là ba nhà cung cấp trên cùng một cơ sở mã mà không cần viết lại bất cứ thứ gì. Mô hình mã nguồn mở trả về cấu trúc tool_calls giống hệt như Claude và GPT. Bạn có thể lưu tên mô hình trong cấu hình và thay đổi nó trong bộ định tuyến (router), bài kiểm tra hoặc cơ chế dự phòng mà không cần đụng đến mã nguồn công cụ của mình.
Các trường hợp đặc biệt và lưu ý
Vòng lặp trên bao phủ các trường hợp phổ biến. Có bốn yếu tố có thể làm hỏng nó trong môi trường production: gọi công cụ song song, streaming, các mô hình không hỗ trợ công cụ và việc kiểm soát thời điểm mô hình gọi công cụ.
Gọi công cụ song song
Bài viết được AI dịch và tổng hợp tự động từ OpenRouter: Announcements. Liên kết bài gốc ở phía trên. Dữ liệu đồng bộ qua API công khai được ghi nguồn tại AI HOT (canonical) ↗. AIHOT.vn luôn dẫn nguồn đầy đủ — nếu bạn thấy điểm cần chỉnh sửa, hãy gửi ý kiến tại trang phản hồi.