工具调用机制
约 1307 字大约 4 分钟
Agent虾学智能体入门
2026-03-08
工具调用机制(Function Calling)
本系列第四篇,深入讲解智能体的工具调用机制,包括 Function Calling 原理与实践。
什么是 Function Calling?
Function Calling(函数调用)是让 LLM 能够调用外部工具和 API 的机制。通过它,智能体可以:
- 查询实时数据(天气、股票、新闻)
- 执行计算和数据处理
- 访问数据库和文件系统
- 调用第三方服务
核心流程
用户请求 → LLM 判断需要工具 → 生成函数调用 → 执行函数 → 返回结果 → LLM 整合回复OpenAI Function Calling
工具定义格式
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如:北京、上海"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位"
}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "search_web",
"description": "搜索互联网获取信息",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词"
},
"num_results": {
"type": "integer",
"description": "返回结果数量",
"default": 5
}
},
"required": ["query"]
}
}
}
]完整调用示例
from openai import OpenAI
import json
client = OpenAI()
# 定义工具函数
def get_weather(city: str, unit: str = "celsius") -> dict:
"""模拟天气 API"""
weather_data = {
"北京": {"temp": 25, "condition": "晴"},
"上海": {"temp": 28, "condition": "多云"},
"深圳": {"temp": 30, "condition": "雷阵雨"}
}
data = weather_data.get(city, {"temp": 20, "condition": "未知"})
if unit == "fahrenheit":
data["temp"] = data["temp"] * 9/5 + 32
return {
"city": city,
"temperature": data["temp"],
"condition": data["condition"],
"unit": unit
}
def search_web(query: str, num_results: int = 5) -> list:
"""模拟搜索 API"""
return [
{"title": f"结果 {i+1}: {query}", "url": f"https://example.com/{i}"}
for i in range(num_results)
]
# 工具映射
available_functions = {
"get_weather": get_weather,
"search_web": search_web
}
def run_conversation(user_message: str) -> str:
"""运行带工具调用的对话"""
messages = [{"role": "user", "content": user_message}]
# 第一次调用:LLM 可能决定调用工具
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
tools=tools,
tool_choice="auto"
)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# 如果有工具调用
if tool_calls:
# 添加助手消息到历史
messages.append(response_message)
# 执行每个工具调用
for tool_call in tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"[调用工具] {function_name}({function_args})")
# 执行函数
function_response = available_functions[function_name](**function_args)
# 添加工具结果到消息历史
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(function_response, ensure_ascii=False)
})
# 第二次调用:LLM 整合结果生成回复
second_response = client.chat.completions.create(
model="gpt-4",
messages=messages
)
return second_response.choices[0].message.content
# 没有工具调用,直接返回
return response_message.content
# 使用示例
result = run_conversation("北京和上海今天天气怎么样?")
print(result)Claude Tool Use
Claude 的工具调用方式略有不同:
import anthropic
client = anthropic.Anthropic()
# 定义工具
tools = [
{
"name": "get_weather",
"description": "获取城市天气",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
]
def run_claude_with_tools(user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=messages
)
# 检查是否有工具调用
if response.stop_reason == "tool_use":
# 找到工具调用块
tool_use = next(
block for block in response.content
if block.type == "tool_use"
)
# 执行工具
if tool_use.name == "get_weather":
result = get_weather(**tool_use.input)
# 添加助手响应和工具结果
messages.append({"role": "assistant", "content": response.content})
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": json.dumps(result)
}]
})
else:
# 没有工具调用,返回结果
return response.content[0].text
# 使用
result = run_claude_with_tools("北京天气怎么样?")
print(result)工具设计最佳实践
1. 清晰的工具描述
# ❌ 不好的描述
{
"name": "search",
"description": "搜索"
}
# ✅ 好的描述
{
"name": "search_web",
"description": "搜索互联网获取最新信息。当用户询问实时新闻、当前事件或你不确定的信息时使用此工具。",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词,使用简洁准确的关键词"
}
},
"required": ["query"]
}
}2. 合理的参数设计
{
"name": "book_flight",
"parameters": {
"type": "object",
"properties": {
"from_city": {
"type": "string",
"description": "出发城市"
},
"to_city": {
"type": "string",
"description": "目的城市"
},
"date": {
"type": "string",
"format": "date",
"description": "出发日期,格式:YYYY-MM-DD"
},
"passengers": {
"type": "integer",
"description": "乘客数量",
"default": 1,
"minimum": 1,
"maximum": 9
}
},
"required": ["from_city", "to_city", "date"]
}
}3. 错误处理
def safe_tool_call(tool_func, **kwargs):
"""安全的工具调用包装"""
try:
result = tool_func(**kwargs)
return {
"success": True,
"data": result
}
except Exception as e:
return {
"success": False,
"error": str(e),
"message": f"工具调用失败:{e}"
}
# 在 Agent 中处理错误结果
def process_tool_result(result: dict) -> str:
if not result.get("success"):
return f"抱歉,操作失败:{result.get('message')}"
return json.dumps(result.get("data"))工具链(Tool Chaining)
当需要多个工具配合时,可以实现工具链:
class ToolChain:
"""工具链执行器"""
def __init__(self, tools: dict):
self.tools = tools
self.execution_history = []
def execute_chain(self, tool_calls: list) -> list:
"""执行工具链"""
results = []
for call in tool_calls:
tool_name = call["name"]
tool_args = call["args"]
# 支持使用前一个工具的结果作为输入
if "use_previous_result" in tool_args:
if results:
tool_args["input"] = results[-1]
result = self.tools[tool_name](**tool_args)
results.append(result)
self.execution_history.append({
"tool": tool_name,
"args": tool_args,
"result": result
})
return results
# 示例:搜索 → 提取 → 总结
chain = ToolChain({
"search": search_web,
"extract": extract_content,
"summarize": summarize_text
})
results = chain.execute_chain([
{"name": "search", "args": {"query": "AI Agent 最新进展"}},
{"name": "extract", "args": {"use_previous_result": True}},
{"name": "summarize", "args": {"use_previous_result": True, "max_length": 200}}
])常见工具类型
| 类型 | 示例工具 | 用途 |
|---|---|---|
| 搜索 | Google Search, Bing | 获取实时信息 |
| 计算 | Calculator, Code Interpreter | 数学计算、代码执行 |
| 数据库 | SQL Query, MongoDB | 数据查询 |
| 文件 | Read/Write File | 文件操作 |
| API | HTTP Request | 调用外部服务 |
| 代码 | Python REPL, Bash | 代码执行 |
小结
- Function Calling 让 LLM 能够调用外部工具,极大扩展了智能体的能力
- 工具定义要清晰、参数要合理,便于 LLM 正确理解和使用
- 工具链可以实现复杂的多步骤任务
下一篇
任务规划 - 学习如何分解和规划复杂任务