🎯 Mục tiêu bài học
Function Calling biến LLM từ "text generator" thành "agent" — có thể gọi APIs, query databases, và thực hiện actions.
Sau bài này, bạn sẽ:
✅ Hiểu Function Calling architecture ✅ Implement tools cho OpenAI & Claude ✅ Build AI agent với multiple tools ✅ Xử lý structured outputs
🔍 Function Calling Explained
1.1 Tại sao cần Function Calling?
1Without tools:2User: "Thời tiết Hà Nội hôm nay?"3AI: "Tôi không biết thời tiết hiện tại." ← Chỉ biết training data4 5With tools:6User: "Thời tiết Hà Nội hôm nay?"7AI: [calls get_weather("Hanoi")] → "Hà Nội hôm nay 28°C, nắng."1.2 Architecture
11. User sends message22. LLM decides which function to call (if any)33. LLM returns function name + arguments (JSON)44. YOUR CODE executes the function55. Function result sent back to LLM66. LLM generates final response using result1.3 Key Concept
1LLM KHÔNG thực sự chạy code.2LLM chỉ QUYẾT ĐỊNH gọi function nào + arguments.3CODE CỦA BẠN thực sự execute function.Checkpoint
Bạn đã hiểu kiến trúc Function Calling và vai trò của LLM vs code của bạn chưa?
💻 OpenAI Function Calling
2.1 Define Tools
1from openai import OpenAI23client = OpenAI()45# Define available tools6tools = [7 {8 "type": "function",9 "function": {10 "name": "get_weather",11 "description": "Lấy thông tin thời tiết hiện tại của một thành phố",12 "parameters": {13 "type": "object",14 "properties": {15 "city": {16 "type": "string",17 "description": "Tên thành phố, e.g. 'Hanoi', 'Ho Chi Minh City'"18 },19 "unit": {20 "type": "string",21 "enum": ["celsius", "fahrenheit"],22 "description": "Đơn vị nhiệt độ"23 }24 },25 "required": ["city"]26 }27 }28 },29 {30 "type": "function",31 "function": {32 "name": "search_products",33 "description": "Tìm kiếm sản phẩm trong database",34 "parameters": {35 "type": "object",36 "properties": {37 "query": {"type": "string", "description": "Search query"},38 "category": {"type": "string", "description": "Product category"},39 "max_price": {"type": "number", "description": "Maximum price in VND"}40 },41 "required": ["query"]42 }43 }44 }45]2.2 Implement Functions
1import json23# Your actual function implementations4def get_weather(city, unit="celsius"):5 """Simulate weather API call."""6 # In production: call real weather API7 weather_data = {8 "Hanoi": {"temp": 28, "condition": "Nắng", "humidity": 75},9 "Ho Chi Minh City": {"temp": 33, "condition": "Mưa rào", "humidity": 85},10 }11 data = weather_data.get(city, {"temp": 25, "condition": "Unknown", "humidity": 60})12 return json.dumps(data, ensure_ascii=False)1314def search_products(query, category=None, max_price=None):15 """Simulate product search."""16 products = [17 {"name": "Laptop Dell XPS 13", "price": 35000000, "category": "laptop"},18 {"name": "MacBook Air M3", "price": 28000000, "category": "laptop"},19 {"name": "iPhone 16 Pro", "price": 32000000, "category": "phone"},20 ]21 results = [p for p in products if query.lower() in p["name"].lower()]22 if max_price:23 results = [p for p in results if p["price"] <= max_price]24 return json.dumps(results, ensure_ascii=False)2526# Map function names to implementations27FUNCTIONS = {28 "get_weather": get_weather,29 "search_products": search_products,30}2.3 Complete Flow
1def chat_with_tools(user_message):2 messages = [3 {"role": "system", "content": "Bạn là shopping assistant. Trả lời bằng tiếng Việt."},4 {"role": "user", "content": user_message}5 ]6 7 # Step 1: First API call8 response = client.chat.completions.create(9 model="gpt-4-turbo",10 messages=messages,11 tools=tools,12 tool_choice="auto" # Let model decide13 )14 15 msg = response.choices[0].message16 17 # Step 2: Check if model wants to call functions18 if msg.tool_calls:19 messages.append(msg) # Add assistant's tool_calls message20 21 # Step 3: Execute each function22 for tool_call in msg.tool_calls:23 func_name = tool_call.function.name24 func_args = json.loads(tool_call.function.arguments)25 26 print(f"🔧 Calling {func_name}({func_args})")27 28 # Execute function29 result = FUNCTIONS[func_name](**func_args)30 31 # Add function result to messages32 messages.append({33 "role": "tool",34 "tool_call_id": tool_call.id,35 "content": result36 })37 38 # Step 4: Get final response with function results39 final_response = client.chat.completions.create(40 model="gpt-4-turbo",41 messages=messages,42 tools=tools43 )44 return final_response.choices[0].message.content45 46 # No function calls needed47 return msg.content4849# Test50print(chat_with_tools("Thời tiết Hà Nội thế nào?"))51print(chat_with_tools("Tìm laptop dưới 30 triệu"))52print(chat_with_tools("Hello!")) # No function call neededCheckpoint
Bạn đã thực hành implement function calling với OpenAI API chưa?
💻 Claude Tool Use
3.1 Define & Use Tools
1import anthropic23client = anthropic.Anthropic()45tools = [6 {7 "name": "get_weather",8 "description": "Lấy thông tin thời tiết hiện tại",9 "input_schema": {10 "type": "object",11 "properties": {12 "city": {"type": "string", "description": "Tên thành phố"}13 },14 "required": ["city"]15 }16 }17]1819response = client.messages.create(20 model="claude-3-5-sonnet-20241022",21 max_tokens=1024,22 tools=tools,23 messages=[{"role": "user", "content": "Thời tiết Hà Nội?"}]24)2526# Check for tool use27for block in response.content:28 if block.type == "tool_use":29 print(f"Tool: {block.name}, Input: {block.input}")30 31 # Execute and return result32 result = get_weather(**block.input)33 34 # Continue conversation with result35 final = client.messages.create(36 model="claude-3-5-sonnet-20241022",37 max_tokens=1024,38 tools=tools,39 messages=[40 {"role": "user", "content": "Thời tiết Hà Nội?"},41 {"role": "assistant", "content": response.content},42 {"role": "user", "content": [43 {"type": "tool_result", "tool_use_id": block.id, "content": result}44 ]}45 ]46 )47 print(final.content[0].text)Checkpoint
Bạn có thể implement tool use với Anthropic Claude API không?
📝 Structured Outputs
4.1 JSON Mode (OpenAI)
1response = client.chat.completions.create(2 model="gpt-4-turbo",3 messages=[{4 "role": "user",5 "content": "Phân tích sentiment của review: 'Sản phẩm tốt nhưng giao hàng chậm'"6 }],7 response_format={"type": "json_object"} # Force JSON8)910import json11result = json.loads(response.choices[0].message.content)12# {"sentiment": "mixed", "positive": ["sản phẩm tốt"], "negative": ["giao hàng chậm"]}4.2 Strict Structured Output
1from pydantic import BaseModel23class SentimentAnalysis(BaseModel):4 sentiment: str # positive, negative, mixed5 score: float # -1.0 to 1.06 positive_aspects: list[str]7 negative_aspects: list[str]8 summary: str910response = client.beta.chat.completions.parse(11 model="gpt-4-turbo",12 messages=[{13 "role": "user",14 "content": "Phân tích: 'Quán coffee đẹp, nhân viên thân thiện, nhưng giá hơi cao'"15 }],16 response_format=SentimentAnalysis17)1819result = response.choices[0].message.parsed20print(f"Sentiment: {result.sentiment}")21print(f"Score: {result.score}")22print(f"Positive: {result.positive_aspects}")Checkpoint
Bạn đã hiểu cách sử dụng JSON mode và Pydantic models cho structured output chưa?
🛠️ Build Multi-Tool Agent
5.1 Complete Agent
1import json2from datetime import datetime34# Define all tools5def get_current_time():6 return json.dumps({"time": datetime.now().strftime("%H:%M %d/%m/%Y")})78def calculate(expression):9 try:10 result = eval(expression) # Caution: sanitize in production!11 return json.dumps({"result": result})12 except:13 return json.dumps({"error": "Invalid expression"})1415def get_exchange_rate(from_currency, to_currency):16 rates = {"USD_VND": 25400, "EUR_VND": 27500, "JPY_VND": 168}17 key = f"{from_currency}_{to_currency}"18 rate = rates.get(key, None)19 return json.dumps({"rate": rate, "pair": key})2021TOOLS = {22 "get_current_time": get_current_time,23 "calculate": calculate,24 "get_exchange_rate": get_exchange_rate,25 "get_weather": get_weather,26 "search_products": search_products,27}2829tools_schema = [30 {"type": "function", "function": {31 "name": "get_current_time",32 "description": "Lấy thời gian hiện tại",33 "parameters": {"type": "object", "properties": {}}34 }},35 {"type": "function", "function": {36 "name": "calculate",37 "description": "Tính toán biểu thức toán học",38 "parameters": {"type": "object", "properties": {39 "expression": {"type": "string", "description": "Math expression, e.g. '2+2'"}40 }, "required": ["expression"]}41 }},42 {"type": "function", "function": {43 "name": "get_exchange_rate",44 "description": "Lấy tỷ giá ngoại tệ",45 "parameters": {"type": "object", "properties": {46 "from_currency": {"type": "string"},47 "to_currency": {"type": "string"}48 }, "required": ["from_currency", "to_currency"]}49 }},50 # ... add weather and products schemas51]5.2 Agent Loop
1def agent_loop(user_message, max_iterations=5):2 """Agent that can call multiple tools in sequence."""3 messages = [4 {"role": "system", "content": """5 Bạn là AI assistant có nhiều tools.6 Sử dụng tools khi cần thông tin real-time.7 Có thể gọi nhiều tools nếu cần.8 Trả lời bằng tiếng Việt.9 """},10 {"role": "user", "content": user_message}11 ]12 13 for i in range(max_iterations):14 response = client.chat.completions.create(15 model="gpt-4-turbo",16 messages=messages,17 tools=tools_schema,18 tool_choice="auto"19 )20 21 msg = response.choices[0].message22 23 if not msg.tool_calls:24 return msg.content # Final answer25 26 messages.append(msg)27 28 for tool_call in msg.tool_calls:29 func_name = tool_call.function.name30 func_args = json.loads(tool_call.function.arguments)31 32 print(f" 🔧 [{i+1}] {func_name}({func_args})")33 result = TOOLS[func_name](**func_args)34 35 messages.append({36 "role": "tool",37 "tool_call_id": tool_call.id,38 "content": result39 })40 41 return "Exceeded max iterations."4243# Test multi-tool queries44print(agent_loop("100 USD bằng bao nhiêu VND? Tính luôn 100 USD * 2"))45print(agent_loop("Bây giờ mấy giờ? Thời tiết HN thế nào?"))Checkpoint
Bạn đã xây dựng được agent loop với multiple tool calls chưa?
💻 Hands-on Lab
Lab 1: Personal Assistant Agent
Build agent với tools:
get_weather— Weather infocalculate— Math calculatorsearch_web— Simulated web searchtake_note— Save notes to fileget_notes— Retrieve saved notes
Lab 2: Data Analyst Agent
Build agent có thể:
- Load CSV file
- Run pandas queries
- Generate charts (matplotlib)
- Summarize findings
Lab 3: Customer Support Bot
Build chatbot có tools:
lookup_order— Tra cứu đơn hàngcheck_inventory— Kiểm tra tồn khocreate_ticket— Tạo support ticketget_faq— Tìm FAQ answers
Checkpoint
Bạn đã thực hành xây dựng Personal Assistant và Data Analyst agents chưa?
🎯 Tổng kết
📝 Quiz
-
LLM thực sự execute function không?
- Có, LLM chạy code trực tiếp
- Không, LLM chỉ quyết định gọi function nào
- Tùy model
- Chỉ với GPT-4
-
tool_choice="auto" nghĩa là?
- Luôn gọi tool
- Không bao giờ gọi tool
- LLM tự quyết định có gọi tool hay không
- Random
-
Structured output dùng response_format để?
- Giảm cost
- Force LLM trả về đúng JSON format
- Tăng speed
- Improve accuracy
Những điểm quan trọng
- Function Calling = LLM + Actions — Biến text model thành agent
- LLM decides, YOU execute — LLM chọn function, code chạy function
- Agent loop — Cho phép multiple tool calls liên tiếp
- Structured output — Pydantic models cho type-safe responses
- Tool design — Clear descriptions giúp LLM chọn đúng tool
Câu hỏi tự kiểm tra
- LLM có thực sự execute function không? Vai trò thực tế của LLM trong function calling là gì?
- Agent loop hoạt động như thế nào khi cần gọi nhiều tools liên tiếp?
- tool_choice parameter có các giá trị nào và ảnh hưởng thế nào đến hành vi của LLM?
- Structured output với Pydantic models giúp ích gì so với để LLM trả về free-form text?
🎉 Tuyệt vời! Bạn đã hoàn thành bài học Function Calling & Tool Use!
Tiếp theo: Chúng ta sẽ học cách quản lý tokens, chọn model phù hợp và tối ưu chi phí!
🚀 Bài tiếp theo
Cost Optimization — Quản lý tokens, chọn model phù hợp, và giảm chi phí!
