Sử Dụng Tools & Function Calling
Cách agent gọi tools, function calling pattern, và tích hợp với OpenAI API
Tool Use Design Pattern
Tool Use là pattern quan trọng nhất trong AI Agents — cho phép LLM vượt ra ngoài việc generate text để thực sự tương tác với thế giới bên ngoài.
Khi Nào Cần Tool Use?
- Data Retrieval: Truy vấn database, search APIs, đọc files
- Code Execution: Chạy code, xử lý data
- Workflow Automation: Gửi email, tạo tickets, deploy
- Customer Support: Truy vấn CRM, knowledge base
Function Calling: Cơ Chế Hoạt Động
Function calling gồm 3 bước:
1. Định nghĩa functions (schema) → Gửi cho LLM
2. LLM quyết định function nào cần gọi + arguments
3. Code thực thi function → Trả kết quả về LLM
Bước 1: Định Nghĩa Tool Schema
import OpenAI from "openai";
const client = new OpenAI();
const tools: OpenAI.ChatCompletionTool[] = [
{
type: "function",
function: {
name: "get_current_time",
description: "Lấy thời gian hiện tại tại một thành phố",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "Tên thành phố, ví dụ: 'Ho Chi Minh City'"
}
},
required: ["location"]
}
}
}
];
Bước 2: LLM Quyết Định Gọi Tool
const messages: OpenAI.ChatCompletionMessageParam[] = [
{ role: "user", content: "Mấy giờ rồi ở Sài Gòn?" }
];
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages,
tools,
tool_choice: "auto" // LLM tự quyết định
});
// LLM trả về tool_calls thay vì text
const toolCalls = response.choices[0].message.tool_calls;
// → [{ function: { name: "get_current_time", arguments: '{"location":"Ho Chi Minh City"}' } }]
Bước 3: Thực Thi và Trả Kết Quả
// Implement actual function
function getCurrentTime(location: string): string {
const timezones: Record<string, string> = {
"ho chi minh city": "Asia/Ho_Chi_Minh",
"tokyo": "Asia/Tokyo",
"new york": "America/New_York"
};
const tz = timezones[location.toLowerCase()];
if (!tz) return JSON.stringify({ error: "Unknown location" });
const time = new Date().toLocaleString("vi-VN", { timeZone: tz });
return JSON.stringify({ location, current_time: time });
}
// Xử lý tool calls
if (toolCalls) {
// Thêm assistant message (chứa tool_calls)
messages.push(response.choices[0].message);
for (const call of toolCalls) {
const args = JSON.parse(call.function.arguments);
const result = getCurrentTime(args.location);
// Thêm tool result
messages.push({
role: "tool",
tool_call_id: call.id,
content: result
});
}
// Gọi LLM lần 2 với kết quả tool
const finalResponse = await client.chat.completions.create({
model: "gpt-4o-mini",
messages
});
console.log(finalResponse.choices[0].message.content);
// → "Hiện tại ở Sài Gòn là 15:30 chiều."
}
Tool Use Với Vercel AI SDK
Vercel AI SDK đơn giản hoá flow trên đáng kể:
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
const result = await generateText({
model: openai("gpt-4o-mini"),
tools: {
getCurrentTime: tool({
description: "Lấy thời gian hiện tại tại một thành phố",
parameters: z.object({
location: z.string().describe("Tên thành phố")
}),
execute: async ({ location }) => {
const time = new Date().toLocaleString("vi-VN", {
timeZone: "Asia/Ho_Chi_Minh"
});
return { location, current_time: time };
}
}),
searchWeb: tool({
description: "Tìm kiếm thông tin trên web",
parameters: z.object({
query: z.string().describe("Từ khoá tìm kiếm")
}),
execute: async ({ query }) => {
// Tích hợp search API
return { results: [`Kết quả cho: ${query}`] };
}
})
},
maxSteps: 5, // Agent loop tự động
prompt: "Mấy giờ rồi ở Sài Gòn?"
});
console.log(result.text);
// Vercel AI SDK tự handle tool calling loop!
So Sánh: Raw OpenAI vs Vercel AI SDK
| Aspect | OpenAI Raw | Vercel AI SDK |
|---|---|---|
| Tool definition | JSON Schema | Zod (type-safe) |
| Tool execution | Tự handle loop | Tự động (maxSteps) |
| Type safety | Không | Có (tự infer types) |
| Streaming | Tự implement | Built-in |
| Multi-provider | Chỉ OpenAI | OpenAI, Anthropic, Google… |
Nhiều Tools Cùng Lúc
Agent thông minh khi có nhiều tools sẽ tự chọn tool phù hợp:
const result = await generateText({
model: openai("gpt-4o-mini"),
tools: {
getWeather: tool({ /* ... */ }),
searchFlights: tool({ /* ... */ }),
bookHotel: tool({ /* ... */ }),
translateText: tool({ /* ... */ })
},
maxSteps: 10,
prompt: "Tìm cho tôi chuyến bay đi Tokyo tuần sau, thời tiết ra sao?"
// Agent sẽ tự gọi: searchFlights + getWeather
});
Best Practices
1. Mô Tả Tool Rõ Ràng
// ❌ Xấu
tool({ description: "Tìm kiếm" })
// ✅ Tốt
tool({
description: "Tìm kiếm sản phẩm trong database. Trả về danh sách sản phẩm kèm giá, mô tả, và rating."
})
2. Validate Input
parameters: z.object({
email: z.string().email("Email không hợp lệ"),
age: z.number().min(0).max(150),
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/)
})
3. Handle Errors Gracefully
execute: async ({ query }) => {
try {
const data = await fetchData(query);
return { success: true, data };
} catch (error) {
return {
success: false,
error: "Không thể truy vấn dữ liệu. Vui lòng thử lại."
};
}
}
Tổng Kết
- Function Calling là pattern nền tảng: Schema → LLM chọn tool → Execute → Return
- Vercel AI SDK đơn giản hoá tool use với Zod schemas và auto tool loop
- Mô tả tools rõ ràng, chi tiết để LLM chọn đúng tool
- Luôn validate input và handle errors gracefully