Function calling案例
bash
from openai import OpenAI
import json
# ========================
# 配置部分
# ========================
API_KEY = "sk-......"
API_BASE = "https://api.deepseek.com/v1"
# 初始化 v2 Client
client = OpenAI(api_key=API_KEY, base_url=API_BASE)
# 1. 定义工具 (使用最新的 tools 格式)
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"]
}
}
}
]
# 2. 构建初始对话
messages = [
{"role": "system", "content": "你是一个智能助手。请调用天气工具回答问题。"},
{"role": "user", "content": "请告诉我北京的天气"}
]
try:
# 第一次调用:模型判断是否需要调用工具
response = client.chat.completions.create(
model="deepseek-chat", # 注意:R1 (reasoner) 目前不支持 tools
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
# 检查是否有工具调用请求
if message.tool_calls:
# 必须:先将模型的 tool_calls 消息加入对话历史
messages.append(message)
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
# 模拟本地函数执行
if func_name == "get_weather":
city = func_args.get("city")
result = f"{city} 的天气是 25°C,晴天。" # 实际应对接天气API
print(f"本地执行函数: {func_name} | 参数: {func_args}")
# 必须:将函数结果回传,角色为 'tool',并带上 tool_call_id
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
# 第二次调用:模型根据函数结果生成自然语言回答
final_response = client.chat.completions.create(
model="deepseek-chat",
messages=messages
)
print("-" * 30)
print("最终回答:", final_response.choices[0].message.content)
else:
print("模型没有发起工具调用,回复内容为:", message.content)
except Exception as e:
print("发生错误:", e)
思考:
- Function calling要解决的问题:
- 模型无法与外部数据源交互
- 模型没有执行的能力,不能帮助用户执行实际任务,比如运行程序,发邮件,上传文件等。
- Function calling=后端+LLM。
- 后端调用本地封装的方法。用户的提问不是直接给大模型的。
- 后端能够执行任务,但是不够"聪明"。大模型虽然"聪明",但是没有执行能力。
- Function calling会不会超出token的限制?
- Function Calling 的输入(messages + 函数 schema + 历史上下文)都算 token。
- 如果函数 schema 很复杂,或者多轮历史消息很多,可能超出模型的上下文上限。
- 模型覆盖有限,开发生态不统一
- 并不是所有模型都原生支持 Function Calling(如 DeepSeek R1 系列就不支持)。
- 不同模型对 schema、参数类型、返回格式的支持不统一。
