OpenAI Function Calling 教程
OpenAI Function Calling 让 GPT 模型能够调用外部函数,实现查询数据库、调用 API、执行计算等操作。本文介绍 Function Calling 的定义、调用流程和 Agent 构建方法。
Function Calling 原理
Function Calling 的工作流程:
- 开发者定义可用函数(名称、描述、参数 JSON Schema)
- GPT 分析用户请求,决定是否调用函数,并输出调用参数
- 开发者执行函数,将结果返回给 GPT
- GPT 根据函数结果生成最终回复
定义函数
from openai import OpenAI
client = OpenAI(
api_key="your-api-key",
base_url="https://claude4u.com/v1"
)
tools = [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "获取指定股票的当前价格和涨跌幅",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "股票代码,如 AAPL、GOOGL、600519"
},
"market": {
"type": "string",
"enum": ["US", "CN", "HK"],
"description": "市场,US=美股,CN=A股,HK=港股"
}
},
"required": ["symbol"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate_investment",
"description": "计算投资收益,包括本金、利率和时间",
"parameters": {
"type": "object",
"properties": {
"principal": {"type": "number", "description": "本金(元)"},
"annual_rate": {"type": "number", "description": "年化利率(%)"},
"years": {"type": "number", "description": "投资年限"}
},
"required": ["principal", "annual_rate", "years"]
}
}
}
]
处理函数调用
import json
def get_stock_price(symbol, market="US"):
"""模拟股票查询"""
prices = {
"AAPL": {"price": 198.50, "change": "+1.2%"},
"GOOGL": {"price": 175.30, "change": "-0.5%"},
"600519": {"price": 1685.00, "change": "+0.8%"}
}
return prices.get(symbol, {"price": 0, "change": "未知"})
def calculate_investment(principal, annual_rate, years):
"""计算复利收益"""
total = principal * (1 + annual_rate / 100) ** years
return {"total": round(total, 2), "profit": round(total - principal, 2)}
# 函数映射
function_map = {
"get_stock_price": get_stock_price,
"calculate_investment": calculate_investment
}
# 第一次调用
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "苹果股票现在多少钱?如果投10万美元,年化10%,5年后能有多少?"}],
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
# 处理工具调用
if message.tool_calls:
messages = [
{"role": "user", "content": "苹果股票现在多少钱?如果投10万美元,年化10%,5年后能有多少?"},
message
]
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
# 执行函数
result = function_map[func_name](**func_args)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})
# 第二次调用:让 GPT 基于函数结果生成回复
final_response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools
)
print(final_response.choices[0].message.content)
Node.js 示例
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'your-api-key',
baseURL: 'https://claude4u.com/v1'
});
const tools = [{
type: 'function',
function: {
name: 'search_products',
description: '搜索商品信息',
parameters: {
type: 'object',
properties: {
keyword: { type: 'string', description: '搜索关键词' },
max_price: { type: 'number', description: '最高价格' }
},
required: ['keyword']
}
}
}];
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: '帮我搜索500元以下的蓝牙耳机' }],
tools,
tool_choice: 'auto'
});
// 处理 tool_calls
const toolCalls = response.choices[0].message.tool_calls;
if (toolCalls) {
for (const call of toolCalls) {
console.log(`调用函数: ${call.function.name}`);
console.log(`参数: ${call.function.arguments}`);
}
}
构建循环 Agent
def run_agent(user_message, tools, function_map, max_iterations=10):
messages = [{"role": "user", "content": user_message}]
for _ in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message)
# 没有工具调用,返回最终回复
if not message.tool_calls:
return message.content
# 执行所有工具调用
for tool_call in message.tool_calls:
func = function_map[tool_call.function.name]
args = json.loads(tool_call.function.arguments)
result = func(**args)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})
return "Agent 达到最大迭代次数"
函数设计最佳实践
- 描述清晰:函数描述和参数说明要详细,GPT 依赖描述来决策
- 参数简洁:避免过多参数,必要参数用
required标记 - 使用 enum:有限选项用 enum 约束,提高准确率
- 错误处理:函数执行失败时返回清晰的错误信息
- 结果精简:返回必要数据即可,过多数据浪费 token
提示:通过 claude4u.com 轻舟 AI 中转服务使用 Function Calling,兼容 OpenAI 和 Claude 的工具调用格式,可以方便地在不同模型之间切换,对比效果选择最优方案。
注意:GPT 生成的函数参数可能不完全符合预期,务必在执行前做参数验证。不要让函数直接执行数据库删除等危险操作,应添加确认步骤。
轻舟 AI