大模型支持 Function Calling(函数调用)和结构化输出,本质上是通过“底层模型训练”与“上层工程约束”相结合来实现的。
简单来说,就是先通过训练让模型“听得懂”工具并“学会”输出特定格式,再通过工程手段强制约束它“必须”输出完全合规的数据。
以下是具体的实现原理及举例说明:
🧠 1. 底层原理:模型训练与约束解码
- 指令微调(让模型“听得懂”):
开发者会使用大量包含“函数定义”和“调用参数”的合成数据对模型进行微调。这让模型学会理解人类的自然语言意图,并将其精准映射到预定义的函数名和参数上。 - 约束解码(让格式“绝对合规”):
这是确保 100% 可靠的核心黑科技。在模型生成文本(Token)的过程中,系统会根据预定义的JSON Schema(数据模式)实时介入,动态限制模型下一个能输出的字符。例如,当 Schema 规定某个字段必须是数字时,系统会直接屏蔽掉所有字母和符号的生成概率。这彻底杜绝了模型输出乱码、缺括号或字段拼写错误等常见问题。
💡 2. 举例说明:Function Calling(函数调用)
Function Calling 的核心是让大模型充当“路由”,它不直接执行代码,而是输出一个标准的 JSON 指令,告诉应用程序该调用哪个函数、传入什么参数。
场景举例:用户问“北京今天天气怎么样?”
第一步:开发者向大模型注册工具清单
在发起对话时,开发者会通过 API 的tools参数,向大模型描述当前可用的外部工具:
json
tools = [ { "type": "function", "function": { "name": "get_current_weather", // 函数名 "description": "查询指定城市的实时天气", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "城市名称,如北京、上海" } }, "required": ["location"] // 必填参数 } } } ]第二步:大模型输出结构化的调用指令
大模型理解用户意图后,不会直接瞎编天气,而是暂停生成回复,输出一个包含函数名和参数的结构化对象:
json
{ "tool_calls": [ { "id": "call_12345", "type": "function", "function": { "name": "get_current_weather", "arguments": "{ \"location\": \"北京\" }" // 提取出的参数 } } ] }第三步:应用程序执行并回填结果
你的程序捕获到这个指令,去调用真实的天气 API,拿到“北京今天是多云”的结果,再把这个结果作为一条新消息(role: "tool")喂回给大模型。大模型最终结合这个真实数据,生成自然语言回复:“北京今天天气多云,气温适宜。”
📝 3. 举例说明:结构化输出(JSON Mode)
结构化输出主要用于数据提取或固定格式回复,确保大模型返回的文本可以直接被代码解析,不需要复杂的正则清洗。
场景举例:从一段杂乱的文本中提取用户的姓名和年龄。
实现方式:
在调用大模型时,开启response_format参数,并在提示词中明确要求输出 JSON。
请求参数示例:
json
{ "model": "qwen-flash", "messages": [ { "role": "system", "content": "请从用户文本中提取姓名和年龄,并以JSON格式返回。" }, { "role": "user", "content": "大家好,我叫刘五,今年34岁,平时喜欢打篮球。" } ], "response_format": { "type": "json_object" } // 开启JSON结构化输出模式 }大模型的返回结果:
在约束解码的作用下,模型会严格输出合法的 JSON 字符串,不会包含任何“好的,这是你要的数据:”之类的废话或 Markdown 标记(如 ```json):
json
{ "姓名": "刘五", "年龄": 34 }总结:大模型之所以能支持这些能力,是因为它在训练时被教会了理解工具和格式化的规范,在推理时被工程手段(如约束解码)限制了输出格式,并通过“暂停-执行-回填”的交互机制实现了与外部世界的精准联动。