Function Calling 深度指南:原理、实现与多模型对比实测
Function Calling函数调用是大模型应用开发中最核心的功能之一。它让 AI 不再只是一个聊天机器人而是能够调用外部工具、获取实时数据、执行具体操作的智能助手。这篇文章我会从原理到实现再到多模型对比全方位讲清楚 Function Calling。测试用的是一个 OpenAI 兼容的聚合平台97AIPRO方便切换不同模型做对比。一、Function Calling 是什么简单说Function Calling 就是让大模型学会使用工具。你给模型描述一组可用的函数工具模型会根据用户的问题智能判断需不需要调用工具调用哪个工具传入什么参数然后你在代码中执行这个函数把结果返回给模型模型再根据结果生成最终的自然语言回答。整个流程是这样的用户提问 → 模型判断是否调用函数 → 是 → 返回函数名和参数↓代码执行函数↓结果返回给模型↓模型生成最终回答二、典型应用场景Function Calling 的应用场景非常广实时数据查询天气、股票、新闻、航班计算与分析数学运算、数据分析、统计操作系统发邮件、创建日历、操作数据库第三方服务地图导航、翻译、搜索企业内部查库存、查订单、审批流程Agent 系统多步骤任务规划与执行可以说任何需要 AI 和外部世界交互的场景都离不开 Function Calling。三、基础实现我们用 Python 来演示基于 OpenAI 兼容接口我用的是 97AIPRO其他兼容平台也一样。3.1 定义函数首先你需要用 JSON Schema 格式描述你的函数tools [{“type”: “function”,“function”: {“name”: “get_weather”,“description”: “获取指定城市的天气信息”,“parameters”: {“type”: “object”,“properties”: {“city”: {“type”: “string”,“description”: “城市名称如北京、上海、深圳”},“date”: {“type”: “string”,“description”: “日期格式为 YYYY-MM-DD默认为今天”}},“required”: [“city”]}}}]最佳实践函数的 description 要写清楚这个函数是做什么的、什么时候该用。参数的 description 也要详细这样模型才能正确理解和提取。3.2 第一次调用让模型判断from openai import OpenAIimport jsonclient OpenAI(api_key“your_api_key”,base_url“https://api.97aipro.com/v1”)messages [{“role”: “user”, “content”: “北京今天天气怎么样”}]response client.chat.completions.create(model“gpt-4o”,messagesmessages,toolstools,tool_choice“auto”)response_message response.choices[0].message3.3 检查是否需要调用函数if response_message.tool_calls:print(“模型决定调用函数”)for tool_call in response_message.tool_calls:print(f函数名{tool_call.function.name}“)print(f参数{tool_call.function.arguments}”)else:print(“模型直接回答”, response_message.content)运行结果大概是模型决定调用函数函数名get_weather参数{“city”:“北京”,“date”:“2024-01-15”}模型智能地识别出需要调用天气函数并且正确提取了参数。四、完整的函数调用流程上面只是第一步完整的流程需要多轮交互def get_weather(city, dateNone):“”“模拟获取天气的函数实际项目中调用真实 API”“”return f{city}{date or ‘今天’}的天气晴温度 25°C湿度 60%微风第一步用户提问messages [{“role”: “user”, “content”: “北京今天天气怎么样适合出门吗”}]第二步模型判断是否调用函数response client.chat.completions.create(model“gpt-4o”,messagesmessages,toolstools,tool_choice“auto”)response_message response.choices[0].messagemessages.append(response_message) # 把模型回复加入历史第三步执行函数if response_message.tool_calls:for tool_call in response_message.tool_calls:function_name tool_call.function.namefunction_args json.loads(tool_call.function.arguments)# 根据函数名分发执行 if function_name get_weather: function_response get_weather(**function_args) else: function_response f未知函数{function_name} # 把函数结果加入对话历史 messages.append({ tool_call_id: tool_call.id, role: tool, name: function_name, content: function_response })第四步把结果返回给模型生成最终回答second_response client.chat.completions.create(model“gpt-4o”,messagesmessages)print(second_response.choices[0].message.content)这样就完成了一次完整的函数调用流程。五、多函数场景实际项目中通常不止一个函数我们来看看多函数的情况tools [{“type”: “function”,“function”: {“name”: “get_weather”,“description”: “获取指定城市的天气信息”,“parameters”: {“type”: “object”,“properties”: {“city”: {“type”: “string”, “description”: “城市名称”},“date”: {“type”: “string”, “description”: “日期YYYY-MM-DD”}},“required”: [“city”]}}},{“type”: “function”,“function”: {“name”: “calculator”,“description”: “执行数学计算支持加减乘除和复杂表达式”,“parameters”: {“type”: “object”,“properties”: {“expression”: {“type”: “string”, “description”: “数学表达式如 ‘123 * 456’”}},“required”: [“expression”]}}},{“type”: “function”,“function”: {“name”: “search_news”,“description”: “搜索最新新闻”,“parameters”: {“type”: “object”,“properties”: {“keyword”: {“type”: “string”, “description”: “搜索关键词”},“count”: {“type”: “integer”, “description”: “返回结果数量默认5”}},“required”: [“keyword”]}}}]模型会根据用户的问题智能选择最合适的函数。比如“北京天气” → 调用 get_weather“12345 * 67890 等于多少” → 调用 calculator“今天有什么科技新闻” → 调用 search_news经验分享函数数量建议控制在 5-10 个以内。给的函数太多模型容易混淆选错函数的概率会增加。如果函数很多建议先做一层分类或者用 RAG 检索相关函数。六、多模型对比实测用聚合平台的好处就是切换模型方便。我分别用 GPT-4o 和 Claude 3.5 Sonnet 做了几个测试场景测试 1简单函数调用问题“北京今天天气怎么样”模型结果GPT-4o✅ 正确调用 get_weather参数 city北京Claude 3.5 Sonnet✅ 正确调用 get_weather参数 city北京测试 2多参数提取问题“帮我查一下 2024 年 1 月 20 号上海的天气”模型结果GPT-4o✅ 正确提取 city上海, date2024-01-20Claude 3.5 Sonnet✅ 正确提取 city上海, date2024-01-20测试 3多函数选择问题“帮我算一下 12345 * 67890 等于多少”模型结果GPT-4o✅ 正确选择 calculator 函数Claude 3.5 Sonnet✅ 正确选择 calculator 函数测试 4不需要调用的情况问题“你好介绍一下你自己”模型结果GPT-4o✅ 直接回答没有调用函数Claude 3.5 Sonnet✅ 直接回答没有调用函数测试 5复杂推理 多轮调用问题“北京今天天气怎么样如果下雨的话帮我推荐几个室内活动”模型结果GPT-4o✅ 先调用天气再根据结果推荐Claude 3.5 Sonnet✅ 先调用天气再根据结果推荐测试 6参数格式校验问题“查一下 2024/1/15 北京天气”日期格式不标准模型结果GPT-4o✅ 自动转换为 YYYY-MM-DD 格式Claude 3.5 Sonnet✅ 自动转换为 YYYY-MM-DD 格式结论两个模型在 Function Calling 方面表现都很不错基础场景完全够用。GPT-4o 在复杂场景下稍微稳定一些Claude 3.5 Sonnet 也完全能满足大多数需求。大家可以根据价格和场景选择。七、最佳实践分享一些实际项目中总结的经验7.1 函数设计函数名要清晰见名知意不要用缩写description 要详细说清楚做什么的、什么时候用、什么时候不用参数要明确每个参数都要有 description枚举值要列出来返回值要结构化尽量返回 JSON 或结构化数据方便模型理解7.2 错误处理参数校验不要完全信任模型传的参数一定要做校验异常捕获函数执行可能失败要做好异常处理友好的错误信息函数失败时返回清晰的错误描述方便模型理解和重试超时控制给函数调用设置超时时间避免卡住7.3 性能优化并行调用如果多个函数之间没有依赖可以并行执行缓存结果相同参数的调用可以缓存减少重复计算控制函数数量不要一次给太多函数影响模型判断准确率流式输出支持流式的话用户体验更好八、常见问题Q: 模型会乱调用函数吗A: 一般不会但偶尔会有。建议做好参数校验和异常处理并且设置合理的函数描述减少误调用概率。Q: 支持同时调用多个函数吗A: 支持GPT-4o 等模型支持 parallel tool calls可以一次返回多个函数调用。Q: 函数调用算 token 吗A: 算的函数定义和参数都会算输入 token。所以函数描述尽量简洁但准确。Q: 怎么调试 Function CallingA: 建议把每一步的输入输出都打日志方便排查问题。也可以用平台的调试工具。九、总结Function Calling 是大模型从能聊天到能做事的关键一步掌握它能让你的 AI 应用能力提升一个档次。核心要点理解原理模型判断 → 执行函数 → 返回结果 → 生成回答函数设计要清晰好的描述是成功的一半做好错误处理不要完全信任模型的输出多模型对比不同模型各有优劣根据场景选择如果你需要做多模型对比测试建议用 OpenAI 兼容的聚合平台切换模型只改一行代码测试效率高很多。我用的 97AIPRO 还不错支持支付宝充值国内访问也稳定大家可以试试。