🔧 Tool Calling & Function Execution
Tools là "tay chân" của AI Agents, cho phép chúng tương tác với thế giới bên ngoài. Bài này sẽ cover cách build và sử dụng tools hiệu quả.
Tool Calling là gì?
Definition
Tool Calling (hay Function Calling) là khả năng của LLM để:
- Nhận biết khi nào cần sử dụng tool
- Chọn tool phù hợp
- Generate đúng arguments
- Process kết quả từ tool
Diagram
graph LR
U[User Query] --> L[LLM]
L --> D{Need Tool?}
D -->|Yes| T[Tool Call]
T --> E[Execute]
E --> R[Result]
R --> L
D -->|No| A[Direct Answer]
L --> AOpenAI Function Calling
OpenAI models hỗ trợ native function calling:
Python
1from openai import OpenAI23client = OpenAI()45# Define 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",12 "parameters": {13 "type": "object",14 "properties": {15 "city": {16 "type": "string",17 "description": "Tên thành phố"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]3031# Call with tools32response = client.chat.completions.create(33 model="gpt-4o",34 messages=[{"role": "user", "content": "Thời tiết Hà Nội thế nào?"}],35 tools=tools,36 tool_choice="auto" # Tự động quyết định37)3839# Check if tool was called40if response.choices[0].message.tool_calls:41 tool_call = response.choices[0].message.tool_calls[0]42 print(f"Function: {tool_call.function.name}")43 print(f"Arguments: {tool_call.function.arguments}")LangChain Tools
LangChain cung cấp cách đơn giản hơn để define tools:
Method 1: @tool decorator
Python
1from langchain.tools import tool23@tool4def search_web(query: str) -> str:5 """6 Tìm kiếm thông tin trên web.7 8 Args:9 query: Từ khóa tìm kiếm10 11 Returns:12 Kết quả tìm kiếm13 """14 # Implementation15 return f"Results for: {query}"1617@tool18def calculate(expression: str) -> str:19 """20 Tính toán biểu thức toán học.21 22 Args:23 expression: Biểu thức (ví dụ: "2 + 2 * 3")24 25 Returns:26 Kết quả27 """28 try:29 return str(eval(expression))30 except:31 return "Error: Invalid expression"Method 2: StructuredTool
Cho complex inputs:
Python
1from langchain.tools import StructuredTool2from pydantic import BaseModel, Field34class EmailInput(BaseModel):5 to: str = Field(description="Email người nhận")6 subject: str = Field(description="Tiêu đề email")7 body: str = Field(description="Nội dung email")8 cc: list[str] | None = Field(default=None, description="CC list")910def send_email(to: str, subject: str, body: str, cc: list[str] = None) -> str:11 """Gửi email"""12 # Implementation13 return f"Email sent to {to}"1415email_tool = StructuredTool.from_function(16 func=send_email,17 name="send_email",18 description="Gửi email đến người nhận",19 args_schema=EmailInput20)Method 3: BaseTool class
Full control:
Python
1from langchain.tools import BaseTool2from pydantic import BaseModel, Field3from typing import Type45class DatabaseQueryInput(BaseModel):6 query: str = Field(description="SQL query")7 database: str = Field(default="main", description="Database name")89class DatabaseQueryTool(BaseTool):10 name: str = "query_database"11 description: str = "Execute SQL query on database"12 args_schema: Type[BaseModel] = DatabaseQueryInput13 14 def _run(self, query: str, database: str = "main") -> str:15 """Execute the query"""16 # Implement database query17 return f"Query executed on {database}"18 19 async def _arun(self, query: str, database: str = "main") -> str:20 """Async version"""21 return self._run(query, database)Built-in Tools
LangChain cung cấp nhiều tools sẵn có:
Python
1# Search2from langchain_community.tools import DuckDuckGoSearchRun3search = DuckDuckGoSearchRun()45# Wikipedia6from langchain_community.tools import WikipediaQueryRun7from langchain_community.utilities import WikipediaAPIWrapper8wiki = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())910# Python REPL11from langchain_experimental.tools import PythonREPLTool12python_repl = PythonREPLTool()1314# File operations15from langchain_community.tools import ReadFileTool, WriteFileTool16read_file = ReadFileTool()17write_file = WriteFileTool()1819# Requests20from langchain_community.tools import RequestsGetTool21requests_tool = RequestsGetTool()Tool Selection Strategies
Automatic Selection
LLM tự chọn tool:
Python
1from langchain.agents import create_tool_calling_agent, AgentExecutor2from langchain_openai import ChatOpenAI34llm = ChatOpenAI(model="gpt-4o")56tools = [search, calculate, get_weather]78agent = create_tool_calling_agent(llm, tools, prompt)9executor = AgentExecutor(agent=agent, tools=tools)1011# LLM tự quyết định dùng tool nào12result = executor.invoke({"input": "Thời tiết Tokyo và tính 100 USD sang JPY"})Force Specific Tool
Bắt buộc dùng tool cụ thể:
Python
1response = llm.invoke(2 messages,3 tools=tools,4 tool_choice={"type": "function", "function": {"name": "get_weather"}}5)Require Any Tool
Bắt buộc phải dùng ít nhất 1 tool:
Python
1response = llm.invoke(2 messages,3 tools=tools,4 tool_choice="required"5)Parallel Tool Calls
Gọi nhiều tools cùng lúc:
Python
1@tool2def get_stock_price(symbol: str) -> str:3 """Lấy giá cổ phiếu"""4 # API call5 return f"{symbol}: $150"67# Query cần multiple tools8query = "Giá của AAPL, GOOGL và MSFT là bao nhiêu?"910# GPT-4 sẽ generate parallel tool calls11response = llm.invoke([HumanMessage(query)], tools=[get_stock_price])1213# Response có thể chứa multiple tool calls14for tool_call in response.tool_calls:15 print(f"Calling {tool_call['name']} with {tool_call['args']}")Error Handling
Graceful Failures
Python
1@tool2def risky_operation(data: str) -> str:3 """Operation có thể fail"""4 try:5 result = process(data)6 return f"Success: {result}"7 except ValidationError as e:8 return f"Validation error: {e}. Please check input format."9 except TimeoutError:10 return "Operation timed out. Please try again later."11 except Exception as e:12 return f"Unexpected error: {e}. Please contact support."Retries
Python
1from tenacity import retry, stop_after_attempt, wait_exponential23@tool4@retry(5 stop=stop_after_attempt(3),6 wait=wait_exponential(min=1, max=10)7)8def api_call(endpoint: str) -> str:9 """Call external API với retry"""10 response = requests.get(endpoint, timeout=5)11 response.raise_for_status()12 return response.json()Tool Validation
Validate inputs trước khi execute:
Python
1from pydantic import BaseModel, Field, validator23class SQLQueryInput(BaseModel):4 query: str = Field(description="SQL query to execute")5 6 @validator('query')7 def validate_query(cls, v):8 # Prevent SQL injection9 dangerous_keywords = ['DROP', 'DELETE', 'TRUNCATE', 'UPDATE']10 for keyword in dangerous_keywords:11 if keyword in v.upper():12 raise ValueError(f"Dangerous keyword '{keyword}' not allowed")13 return v1415@tool(args_schema=SQLQueryInput)16def safe_sql_query(query: str) -> str:17 """Execute safe SQL query"""18 # Only SELECT queries allowed19 return execute_query(query)Async Tools
Cho better performance:
Python
1import aiohttp23@tool4async def async_search(query: str) -> str:5 """Async web search"""6 async with aiohttp.ClientSession() as session:7 async with session.get(f"https://api.search.com?q={query}") as response:8 return await response.text()910# Use with async agent11result = await agent_executor.ainvoke({"input": "Search for Python tutorials"})Bài tập thực hành
Hands-on Exercise
Build một bộ tools cho E-commerce Agent:
- search_products(query, category, max_price): Tìm sản phẩm
- get_product_details(product_id): Chi tiết sản phẩm
- check_inventory(product_id): Kiểm tra tồn kho
- add_to_cart(product_id, quantity): Thêm vào giỏ
- calculate_shipping(address): Tính phí ship
Test với agent:
- "Tìm laptop gaming dưới 20 triệu"
- "Thêm sản phẩm ABC123 vào giỏ"
- "Tính phí ship về Hà Nội"
Python
1# Starter code2from langchain.tools import tool3from pydantic import BaseModel, Field45class ProductSearchInput(BaseModel):6 query: str = Field(description="Từ khóa tìm kiếm")7 category: str | None = Field(default=None, description="Danh mục")8 max_price: float | None = Field(default=None, description="Giá tối đa")910@tool(args_schema=ProductSearchInput)11def search_products(query: str, category: str = None, max_price: float = None) -> str:12 """Tìm kiếm sản phẩm"""13 # TODO: Implement14 pass1516# TODO: Add more toolsTiếp theo
Trong bài tiếp theo, chúng ta sẽ học về Memory Systems - cách giúp agents nhớ context và conversations.
