导读:本期聚焦于Robin创作的《Function Calling参数总出错?如何用JSON Schema严格定义与校验》,敬请观看详情。Function Calling 的参数错误往往不是模型突然变笨,而是参数约束没有被准确描述。当大模型需要调用工具时,它本质上是根据自然语言说明和参数定义来生成 JSON 对象,如果只告诉它“提取用户信息”,却没有给出每个字段的类型、是否必填、取值范围,返回结果就很容易出现少字段、多字段、类型不符等问题。JSON Schema 的价值就在于此:把模糊描述变成可校验的结构化契约。严格设置 type、properties、required、additionalProperties 和 enum 等约束后,模型生成错误参数的概率会明显下降。再配合服务端 JSON Schema 校验与错误回传重试,可以形成闭环,让 Function Calling 在业务中更加可靠。本文从参数错误成因、Schema 设计要点、校验实现和常见修复技巧几个方面展开。

Function Calling 的参数错误通常不是模型能力不足,而是参数契约没有被严格描述。大模型在生成工具调用参数时,本质上是在输出一段需要被 JSON 解析器接受的文本,如果开发者只给了一个简单的描述,比如“返回城市和日期”,模型可能会返回字段名不一致、类型错误、多余字段或缺少必填项。这样的参数一进入业务函数就会抛异常,甚至造成静默数据错误。解决思路是把自然语言约束升级为 JSON Schema,并且在服务端做二次校验,让错误能够被及时发现和纠正。

Function Calling参数总出错?如何用JSON Schema严格定义与校验

为什么 Function Calling 参数容易出错?

Function Calling 并不是传统编程中的函数调用。模型不会直接执行函数,而是根据你在 tools 或 functions 中给出的说明,生成一个 JSON 格式的 arguments 字符串。这个字符串随后由框架解析并交给你的业务函数。这个过程的本质是文本生成,而不是类型安全的参数传递。模型在生成 token 时会受到训练数据、上下文和随机采样影响,因此即使提示词清晰,也可能出现字段缺失、类型不匹配、枚举值越界等问题。

更麻烦的是,很多开发者在定义工具时只写了简单的 description,没有给出严格的参数结构。例如获取天气的函数只说明“查询某地天气”,模型可能返回 { "city": "北京", "date": "明天" },而你的函数签名却需要 latitude、longitude 和 unit。当这些字段对不上时,运行时就会报 KeyError、TypeError 或 API 参数错误。要降低这种概率,就需要把接口契约显式化,让模型知道每个字段的约束,而不是依赖它猜测。

用 JSON Schema 严格定义参数:核心字段与实践

JSON Schema 是描述 JSON 数据结构的标准。在 Function Calling 中,它可以作为参数模板,告诉模型目标 JSON 应该有哪些属性、每个属性是什么类型、哪些必填、是否允许额外字段。几个关键字段包括 typepropertiesrequiredadditionalPropertiesitemsenumdescription

以查询天气为例,假设业务函数要求传入 location 对象,包含 latitudelongitude 两个数值,以及一个可选的 unit 字符串,只能是 celsius 或 fahrenheit。严格的 Schema 可以这样定义:

{
  "type": "object",
  "properties": {
    "location": {
      "type": "object",
      "description": "目标位置的经纬度坐标",
      "properties": {
        "latitude": {
          "type": "number",
          "description": "纬度,范围 -90 到 90"
        },
        "longitude": {
          "type": "number",
          "description": "经度,范围 -180 到 180"
        }
      },
      "required": ["latitude", "longitude"],
      "additionalProperties": false
    },
    "unit": {
      "type": "string",
      "enum": ["celsius", "fahrenheit"],
      "description": "温度单位,默认 celsius"
    }
  },
  "required": ["location"],
  "additionalProperties": false
}

这里 additionalProperties: false 的作用很大。它明确禁止模型在对象里添加未定义字段。很多真实场景中,模型会自作主张添加 citycountry 等字段,虽然看起来无害,但下游严格反序列化时会报错。通过 required 声明必填字段,则可以让模型意识到哪些字段没有生成就属于失败结果。

此外,enum 对枚举值非常有效。与其在描述中写“单位只能是摄氏度或华氏度”,不如直接用 enum 约束。模型在面对明确枚举时会优先选择其中之一,而不是生成 celcius 这种拼写错误。限制数值字段类型为 number 而不是 string,也能减少 "23.5"23.5 混用的问题。

服务端二次校验与错误回传重试

JSON Schema 定义只是第一层防线,它让模型输出更规范,但不能保证百分百正确。服务端在接收到 arguments 后,仍然必须进行真正的 JSON Schema 校验。校验的目的不是怀疑模型,而是找到那些会直接导致业务逻辑崩溃的坏参数,并给出可读的错误信息。

以 Python 为例,可以使用 jsonschema 库的 validate 方法。先定义相同的 schema,然后调用 json.loads 解析模型输出的 arguments,最后执行校验。如果出现问题,会抛出 ValidationError

import json
from jsonschema import validate, ValidationError

schema = {
    "type": "object",
    "properties": {
        "location": {
            "type": "object",
            "properties": {
                "latitude": {"type": "number"},
                "longitude": {"type": "number"}
            },
            "required": ["latitude", "longitude"],
            "additionalProperties": False
        },
        "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
        }
    },
    "required": ["location"],
    "additionalProperties": False
}

def safe_call_weather(arguments: str):
    try:
        params = json.loads(arguments)
        validate(instance=params, schema=schema)
        return call_real_weather_api(params)
    except json.JSONDecodeError as e:
        return {"error": "arguments is not valid json", "detail": str(e)}
    except ValidationError as e:
        return {"error": "schema validation failed", "detail": e.message}

上面的 validate 会根据 schema 检查类型、必填字段、枚举值和额外字段。捕获到 ValidationError 后,不应该只记录日志就结束,而应该把错误信息反馈给模型,让它重新生成。比如可以在下一次请求中追加一条 tool 消息,告诉模型:上次生成的参数违反了哪些约束,请根据错误信息重新生成。这种错误回传重试机制能显著提升 Function Calling 的成功率。

需要注意的是,重试不能无限进行。通常设置 2 到 3 次即可。如果模型连续失败,说明 schema 本身可能过于复杂,或者业务描述与函数签名不一致。此时应该简化嵌套结构、补充示例值,而不是继续提高重试上限。

def run_with_retry(user_query: str, max_retries: int = 3):
    messages = [{"role": "user", "content": user_query}]
    for attempt in range(max_retries):
        response = model.chat(messages=messages, tools=tools)
        tool_call = response.tool_calls[0]
        try:
            params = json.loads(tool_call.arguments)
            validate(instance=params, schema=schema)
            return call_real_weather_api(params)
        except (json.JSONDecodeError, ValidationError) as e:
            messages.append({
                "role": "assistant",
                "content": None,
                "tool_calls": [tool_call]
            })
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": f"参数错误:{e}。请根据 schema 重新生成。"
            })
    raise RuntimeError("Function calling failed after retries")

常见 Schema 设计与校验误区

很多参数错误不是模型不遵守约束,而是 Schema 本身设计不合理。例如把参数嵌套层级设计得过深。模型对深层嵌套对象的生成稳定性会下降,尤其是同时要求多个层级必填时。建议尽量将参数控制在两到三层以内,必要时拆成多个工具调用。另一个常见误区是只写 type 不写 required,模型会把所有字段都当作可选,导致关键参数缺失。

还有一个隐蔽问题是 additionalProperties 没有关闭。在某些框架中,模型看到历史示例后可能添加额外字段,例如把 latitude 写成 lat 的同时保留 lat。如果不禁止额外字段,这种偏差可能直接进入下游。开启 additionalProperties: false 后,误差会被暴露出来,反而更容易被修正。

对于枚举值,建议同时提供说明和示例。一个技巧是在 description 中写出目标 JSON 的完整示例,例如“示例:{"location":{"latitude":39.9042,"longitude":116.4074},"unit":"celsius"}”。模型看到示例后会明显更倾向于输出合法结构。当然,示例必须在语义上正确,否则会起到反效果。

Function Calling 的可靠性不是单纯靠模型能力提升就能解决的,更关键的是把约束前移到参数定义阶段,把校验落实到服务端执行阶段。JSON Schema 提供了一套通用且可验证的描述方式,配合错误回传重试,可以显著减少参数错误带来的业务故障。对于正在集成工具调用的项目来说,优先完善 Schema 往往比反复调整提示词更有效。

Function CallingJSON Schema参数校验修改时间:2026-08-22 16:40:13

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。