核心要点
能说清差异:OpenAI / Anthropic / Gemini / 国产模型的函数定义字段名、支持的 JSON Schema 子集、并行调用能力各不相同
能说清行为差异:强制调用(tool_choice / 强制某工具)与流式 tool_call 的增量格式、参数拼接方式不一致
能给统一抽象:定义内部 Tool 模型(名称、描述、参数 Schema、handler),再为每个 Provider 写转换层做 schema 映射与解析归一
能讲降级与兜底:对不支持 function calling 的模型回退到「提示词描述工具 + 结构化解析」,或直接用 LiteLLM 等网关统一接口
标准回答
差异在哪里
不同 Provider 的工具调用协议并不互通。字段结构不同:OpenAI 用 tools[{type:'function', function:{name, parameters}}],Anthropic 用 tools[{name, input_schema}],Gemini 用 function_declarations,国产模型(通义、文心、智谱等)多兼容 OpenAI 风格但细节有出入。Schema 子集不同:各家只支持 JSON Schema 的一部分,对 $ref、oneOf、嵌套深度、枚举的支持度不一。行为能力不同:是否支持并行多工具调用、强制调用(tool_choice 的取值与语义)、以及流式返回时 tool_call 的增量片段格式都不一样。
适配方案:统一抽象 + 转换层
工程上的标准做法是加一层抽象隔离差异。先定义一个内部统一的 Tool 模型——工具名、自然语言描述、参数 JSON Schema、以及执行 handler,业务代码只面向它编写。再为每个 Provider 实现一个转换层(Adapter),负责三件事:Schema 映射(把内部定义翻译成各家字段格式)、能力降级(目标模型不支持的特性如并行调用、复杂 Schema,做拆分或简化)、解析归一(把各家返回的 tool_call、流式增量统一解析成内部的「工具调用请求」对象,再分发执行)。
网关与兜底
不想自己维护转换层时,可用 LiteLLM、OpenRouter 或 Vercel AI SDK 这类网关/SDK,它们已抽象出统一的 tools 接口,一处定义多家可用。对完全不支持 function calling 的模型,回退到「提示工程」路线:在 prompt 里用文字描述可用工具与调用格式,要求模型输出约定的 JSON,再用解析器(配合 JSON 修复与 Schema 校验、失败重试)把文本还原成结构化调用。无论哪条路,都要对解析失败、幻觉出不存在的工具、参数不合法做防御性校验。
常见误区
⚠️ 常见踩坑
误区一:直接把某一家(常是 OpenAI)的 tools 结构透传给所有 Provider,遇到 Anthropic 的 input_schema 或 Gemini 的 function_declarations 就报错。误区二:忽略流式差异,按非流式逻辑拼 tool_call,结果增量片段拼接错乱、参数 JSON 截断。适配层必须同时覆盖请求构造与响应(含流式)解析两端。
追问
追问 1:某个模型不支持并行工具调用,但业务需要,怎么处理?
追问 2:流式输出下如何稳妥地解析工具调用?
追问 3:统一抽象之后,如何保证各 Provider 的实际表现一致?
抽象只统一了接口,不保证语义一致,必须用评测兜底。建一套覆盖典型工具调用场景的回归集,对每个接入的模型跑同样用例,统计工具选择准确率、参数正确率、解析成功率与延迟成本。据此为不同模型配置默认参数(如是否启用强制调用、是否走提示词回退),并在切换或新增模型时重新评测,避免「能调通」但效果回退。
🔗 相似问题
同一考点的不同问法,面试官可能换着问,一起刷更稳
没找到想看的面试题?把你想看的告诉我们 →
延伸学习
按主题分类的相关资源,便于系统复习