# LLM Function Calling 实战:让 AI 大模型调用外部工具
## 背景介绍
大语言模型很强大,这没错。但它有个天然的缺陷:训练数据会过时。一个 2024 年训练出来的模型,不可能知道 2025 年发生了什么。它也做不到查数据库、调用 API、执行代码这些实事。
这就是 Function Calling 要解决的问题。通过这项技术,LLM 可以识别用户意图,然后去调用你提前写好的外部函数。查天气、查股票、做计算、操作数据库——这些都能让 AI 帮你完成。
现在主流的 LLM 都支持 Function Calling:OpenAI、Anthropic、Google,还有国内的通义千问、文心一言。本文用 OpenAI GPT-4o 来演示。
## 问题描述
实际开发中经常遇到这种情况:用户问”今天北京天气怎么样”,AI 应该调用天气 API 返回真实数据,而不是根据训练数据瞎猜。传统的做法是在 prompt 里写一堆”你是一个天气查询助手”,效果不稳定,还容易产生幻觉。
另一个例子是让 AI 执行具体操作。比如用户说”把这条记录存到数据库里”,AI 需要真的去操作数据库,而不是回复一句”好的,我会把记录存进去”。
Function Calling 的做法是:开发者先定义好函数,LLM 根据用户说的话判断要不要调用、调用哪个、传什么参数,然后把结果整合到回复里。整个过程是透明的,开发者完全可控。
## 详细步骤
### 第一步:定义工具函数
先告诉 LLM 你有哪些函数可以用。每个函数需要包含:
– 函数名称
– 函数描述(让 LLM 知道什么情况下该调用这个函数)
– 参数模式(用 JSON Schema 定义)
天气查询函数的例子:
“`python
functions = [
{
“type”: “function”,
“function”: {
“name”: “get_weather”,
“description”: “获取指定城市的天气信息,包括温度、湿度、风力等”,
“parameters”: {
“type”: “object”,
“properties”: {
“city”: {
“type”: “string”,
“description”: “城市名称,如北京、上海、深圳”
},
“unit”: {
“type”: “string”,
“enum”: [“celsius”, “fahrenheit”],
“description”: “温度单位,默认为摄氏度”
}
},
“required”: [“city”]
}
}
}
]
“`
### 第二步:发送请求并处理响应
调用 OpenAI API 时,把函数定义一起发送:
“`python
from openai import OpenAI
client = OpenAI(api_key=”your-api-key”)
response = client.chat.completions.create(
model=”gpt-4o”,
messages=[
{“role”: “user”, “content”: “北京今天天气怎么样?”}
],
tools=functions,
tool_choice=”auto”
)
assistant_message = response.choices[0].message
# 检查 LLM 是否决定调用函数
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f”调用函数: {function_name}”)
print(f”参数: {function_args}”)
“`
### 第三步:执行函数并返回结果
LLM 决定调用函数后,执行实际逻辑,然后把结果传回去:
“`python
import json
# 函数的实际实现
def get_weather(city, unit=”celsius”):
“””模拟天气查询 API”””
weather_data = {
“北京”: {“temp”: 22, “humidity”: 45, “wind”: “东北风3级”, “condition”: “晴”},
“上海”: {“temp”: 25, “humidity”: 60, “wind”: “东南风2级”, “condition”: “多云”},
“深圳”: {“temp”: 28, “humidity”: 75, “wind”: “南风2级”, “condition”: “雷阵雨”}
}
if city in weather_data:
data = weather_data[city]
if unit == “fahrenheit”:
data[“temp”] = data[“temp”] * 9/5 + 32
unit_str = “°F”
else:
unit_str = “°C”
return {
“city”: city,
“temperature”: f”{data[temp]}{unit_str}”,
“humidity”: f”{data[humidity]}%”,
“wind”: data[“wind”],
“condition”: data[“condition”]
}
else:
return {“error”: f”未找到城市 {city} 的天气数据”}
# 执行函数调用
tool_call = assistant_message.tool_calls[0]
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
if function_name == “get_weather”:
result = get_weather(**function_args)
# 把结果返回给模型,让它生成最终回复
final_response = client.chat.completions.create(
model=”gpt-4o”,
messages=[
{“role”: “user”, “content”: “北京今天天气怎么样?”},
assistant_message,
{
“role”: “tool”,
“tool_call_id”: tool_call.id,
“content”: json.dumps(result)
}
]
)
print(final_response.choices[0].message.content)
“`
## 完整代码示例
一个完整的多函数调用示例:
“`python
import json
from openai import OpenAI
client = OpenAI(api_key=”your-openai-api-key”)
# 定义三个工具函数
tools = [
{
“type”: “function”,
“function”: {
“name”: “get_weather”,
“description”: “获取指定城市的天气信息”,
“parameters”: {
“type”: “object”,
“properties”: {
“city”: {“type”: “string”, “description”: “城市名称”},
“unit”: {“type”: “string”, “enum”: [“celsius”, “fahrenheit”], “default”: “celsius”}
},
“required”: [“city”]
}
}
},
{
“type”: “function”,
“function”: {
“name”: “calculate”,
“description”: “执行数学计算,支持加减乘除和复杂表达式”,
“parameters”: {
“type”: “object”,
“properties”: {
“expression”: {“type”: “string”, “description”: “数学表达式,如 2+3*4”}
},
“required”: [“expression”]
}
}
},
{
“type”: “function”,
“function”: {
“name”: “search_wiki”,
“description”: “搜索维基百科获取准确的信息”,
“parameters”: {
“type”: “object”,
“properties”: {
“query”: {“type”: “string”, “description”: “搜索关键词”}
},
“required”: [“query”]
}
}
}
]
# 函数实现
functions = {
“get_weather”: lambda city, unit=”celsius”: {“city”: city, “temp”: 22, “condition”: “晴”},
“calculate”: lambda expression: {“result”: eval(expression)},
“search_wiki”: lambda query: {“title”: query, “snippet”: f”{query}是一个常见术语…”}
}
def chat_with_functions(user_message, conversation_history=None):
messages = conversation_history or []
messages.append({“role”: “user”, “content”: user_message})
# 第一次调用
response = client.chat.completions.create(
model=”gpt-4o”,
messages=messages,
tools=tools,
tool_choice=”auto”
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
# 处理函数调用
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f”\n[函数调用] {function_name}”)
print(f”[参数] {function_args}”)
if function_name in functions:
result = functions[function_name](**function_args)
print(f”[结果] {result}”)
messages.append({
“role”: “tool”,
“tool_call_id”: tool_call.id,
“content”: json.dumps(result)
})
# 第二次调用,获取最终回复
final_response = client.chat.completions.create(
model=”gpt-4o”,
messages=messages
)
final_message = final_response.choices[0].message.content
messages.append({“role”: “assistant”, “content”: final_message})
return final_message, messages
return assistant_message.content, messages
# 测试
print(“=” * 50)
print(“开始测试”)
print(“=” * 50)
response1, history1 = chat_with_functions(“北京今天天气怎么样?”)
print(f”\n[AI]: {response1}\n”)
response2, history2 = chat_with_functions(“帮我算一下 123 * 456″, history1)
print(f”\n[AI]: {response2}\n”)
response3, history3 = chat_with_functions(“这个数字的平方是多少?”, history2)
print(f”\n[AI]: {response3}\n”)
“`
## 运行结果
执行后得到:
“`
==================================================
开始测试
==================================================
[函数调用] get_weather
[参数] {“city”: “北京”, “unit”: “celsius”}
[结果] {“city”: “北京”, “temp”: 22, “condition”: “晴”}
[AI]: 北京今天天气晴朗,气温约22°C,适合外出。
[函数调用] calculate
[参数] {“expression”: “123*456”}
[结果] {“result”: 56088}
[AI]: 123 × 456 = 56088。
[AI]: 56088 的平方是 3148863744。
“`
第一次问天气,LLM 识别到需要调用 get_weather;第二次让它算乘法,它去调用 calculate;第三次问平方,它直接用了上次的计算结果继续算。整个过程很流畅。
## 总结
Function Calling 解决了 LLM 无法与外部世界交互的问题。关键点就三个:
第一,函数定义要清晰。名称、描述、参数 Schema 都要写明白,LLM 才能准确判断什么时候该调用。
第二,流程是”请求-判断-执行-返回”四步。开发者在每一步都能介入,完全可控。
第三,可以定义多个函数,LLM 会根据需求自动选择,甚至可以链式调用。
实际应用场景很多:AI 客服、智能家居、数据分析助手、企业内部知识库问答。AI Agent 现在很火,Function Calling 就是实现 Agent 工具调用能力的基础。
用的时候注意几点:函数描述要具体,避免 LLM 理解错;对返回值做好错误处理;敏感操作不要放进函数里;定期看调用日志,不断优化函数设计。
把这块搞明白,你做的 AI 应用就能真正”动”起来了。