LLM Provider 的 Tool Schema 差异处理方法(详解 OpenClaw 的 Schema 适配方案)

处理不同 LLM Provider 的 Tool Schema 差异,靠的不是”写一个万能格式”,而是三层适配:先用统一 Schema 定义工具,再按 Provider 翻译成原生格式,最后对不兼容的关键字做定点清理。OpenClaw 按这套思路落地:API 适配器负责协议层翻译,toolSchemaProfile 做 Schema 归一化,unsupportedToolSchemaKeywords 处理端点级缺口。

一、差异到底差在哪里

OpenAI 用 tools 参数配 JSON Schema,Anthropic 用 tooluse 块,Gemini 用 functiondeclarations。三家的格式看着相似,细节处处不同:

差异点 OpenAI Anthropic Gemini
声明方式 tools 数组内嵌 JSON Schema tools 数组内嵌自有描述结构 function_declarations
结果回传 tool role 消息 tool_result 独立消息对象 function_response
约束支持 标准 JSON Schema 关键字 部分关键字支持有限 递归 Schema 支持有限
嵌套层级 支持多层嵌套 嵌套深度受限 递归/深层嵌套受限

差异横跨参数格式、嵌套深度、特殊类型约束与结果回传四层,例如有的端点不接受 pattern、minLength,有的对 maxLength 阈值敏感。

二、处理差异的三条路线

第一条,逐 Provider 各写一套工具定义,最直接但重复维护。第二条,统一中间格式加适配器翻译,开发者只写一份 Schema,运行时按 Provider 转换,这是主流做法。第三条,请求出口统一清理不兼容关键字,作兜底。OpenClaw 三样都用,分工明确。

接一个新 Provider,按下面四步走:

  1. 在 providers 节点下声明 provider 路由(api、baseUrl、apiKey),挂上模型;
  2. 在模型的 compat 块里声明能力(supportsTools、contextWindow 等);
  3. 能力声明解决不了的格式差异,用 toolSchemaProfile 选归一化 profile;
  4. profile 覆盖不到的缺口,用 unsupportedToolSchemaKeywords 定点移除关键字。

三、OpenClaw 的三层适配

3.1 API 适配器:协议层翻译

models.providers.*.api 决定协议层怎么转换。openai-completions 走 /v1/chat/completions,anthropic-messages 走 Anthropic 消息协议,google-generative-ai 与 google-vertex 走 Gemini 系,bedrock-converse-stream 走 AWS Bedrock。部分端点还能开 requiresOpenAiAnthropicToolPayload,把 OpenAI 形状的工具调用显式转成 Anthropic 系 payload。

3.2 toolSchemaProfile:Schema 归一化

toolSchemaProfile 内置两个 profile:llamacpp 和 gemini。llamacpp 针对 llama-server 把工具参数编译成 GBNF 语法的场景,移除 pattern 以及 ≥2000 的 maxLength 值,覆盖 cron 工具的 65536 长度限制。内置的 llama-cpp、ollama、lmstudio provider 自动应用清理器,自定义端点必须显式声明。

3.3 unsupportedToolSchemaKeywords:关键字级精修

profile 是定点缓解,不是对所有 JSON Schema 约束的完整兼容。剩下的缺口交给 unsupportedToolSchemaKeywords:Schema 发出前移除端点拒绝的关键字。旧版本没有 profile 时的兜底写法:

compat: {
  unsupportedToolSchemaKeywords: [
    "pattern", "patternProperties", "format", "propertyNames",
    "uniqueItems", "contains", "minContains", "maxContains",
    "minLength", "maxLength"
  ]
}

与 profile 的区别:它无条件移除所有列出项,llamacpp profile 只动 ≥2000 的 maxLength,更精准。

四、一个可跑的配置示例

把本地 llama-server 接成自定义 provider,是最典型的 Schema 适配场景:

{
  agents: {
    defaults: { model: { primary: "my-llamacpp/qwen35" } }
  },
  models: {
    mode: "merge",
    providers: {
      "my-llamacpp": {
        baseUrl: "http://127.0.0.1:8080/v1",
        apiKey: "llamacpp-no-key",
        api: "openai-completions",
        models: [
          {
            id: "qwen35",
            name: "Qwen3.5 (llama-server)",
            contextWindow: 8192,
            maxTokens: 2048,
            compat: {
              supportsTools: true,
              toolSchemaProfile: "llamacpp"
            }
          }
        ]
      }
    }
  }
}

漏掉 toolSchemaProfile,qwen35 的 cron 工具可能因 pattern 或超长 maxLength 被 llama-server 拒掉;补一行就解决。

五、两个落地注意点

内置 provider 的 compat 由 provider 目录管理,别往 config 里抄,openclaw doctor –fix 会自动清掉匹配的遗留覆盖。能力判定按端点而非内置 provider ID:Moonshot 原生端点就在共享 openai-completions 传输上声明了 streaming usage 兼容。自建适配照同一条原则:compat 只声明你真实验证过的能力。

常见问题(FAQ)

Q1:统一 Schema 用哪种格式定义?

推荐 OpenAI-compatible JSON Schema 作统一格式,其余 Provider 由适配器翻译。

Q2:toolSchemaProfile 和 unsupportedToolSchemaKeywords 怎么分工?

profile 做定点归一化,保留可用约束;后者无条件移除关键字,作兜底。

Q3:自定义 Provider 必须写 compat 吗?

必须。能力声明决定工具开关与格式转换,漏写会导致工具调用失败。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
其AI的头像其AI普通用户

相关推荐

返回顶部