一、怎么限制大模型的输出格式
使用提示工程(Prompt Engineering)
最简单直接的方法:在提示词(prompt)中明确要求输出格式(如 JSON、YAML、XML 等),并提供示例。例如:“请以以下 JSON 格式返回:…”,并附上具体字段定义和样例。
在提示词中加入示例结构或“输出格式规范“之类的段落,也能有效提高格式契合度。
优点:实现简单,无需额外训练或修改模型本身。
缺点:结构严格的格式(尤其 JSON)仍易出错,难以确保 100% 达标。
使用function call的方式
这种方式的核心思想是:让大模型不直接输出自然语言,而是通过“调用一个函数”返回结构化参数,这样你就可以用程序严格解析它的返回值,确保输出符合要求。
1.基本原理
大模型在生成内容时,本质是“预测文本”。如果你只给它自然语言指令,它的输出可能会跑偏(比如漏字段、多字段、错格式)。
Function Call 是在模型 API 层面增加的一种“协议”:
你定义一个函数(其实是一个结构化描述,告诉模型这个函数的参数和数据类型)
模型会输出一个 JSON 参数对象来“调用”这个函数
你拿到这个参数,就能保证它符合你定义的结构
举个简单例子:
functions = [` `{` `"name": "create_task",` `"description": "创建一个任务",` `"parameters": {` `"type": "object",` `"properties": {` `"title": {"type": "string", "description": "任务标题"},` `"priority": {"type": "integer", "description": "任务优先级,1为最高"},` `"due_date": {"type": "string", "format": "date"}` `},` `"required": ["title", "priority"]` `}` `}``]这样模型被约束只能“生成”出:
{` `"title": "写周报",` `"priority": 1,` `"due_date": "2025-08-15"``}而不会生成你没定义的字段,也不会乱写格式(比如用中文写“优先级一”)。
2. 流程
用 function call 限制输出的完整流程大致是这样:
2.1 定义函数 schema
用 JSON Schema(parameters)描述函数的参数类型、必填字段、值的格式。
2.2 调用模型并指定可用函数
在 API 请求里带上 functions(有的 API 叫 tools)。
2.3 模型决定调用哪个函数
如果你要求它必须调用某个函数,可以设置 function_call={“name”: “xxx”}
否则它也可能选择不调用
2.4 返回结果是结构化 JSON
模型会返回一个 function_call.arguments 字段,内容就是 JSON 字符串(符合你 schema)。
2.5 解析参数并执行逻辑
你在代码中 json.loads() 后就能直接用。
3. 为什么能限制输出格式
因为 function call 的参数必须符合你定义的 schema:
类型限制:string / integer / boolean / array / object
必填字段:required
值格式:format(如 date, email, uri)
枚举值:enum(固定值集合)
嵌套结构:字段可以是对象或数组
这就像给模型套了一个“JSON护栏”,不让它乱跑。
即便它生成错了,API 层面会尝试自动修正,或者直接抛错,让你捕获处理。
4. 注意事项
4.1 描述要足够清晰
字段含义、取值范围写清楚
不要模糊不清,否则模型会生成奇怪的值
4.2 字段名稳定性
尽量用英文小写+下划线
不要用中文字段名,否则模型容易生成错误
4.3 嵌套结构越复杂,模型越容易出错
- 尽量分层调用多个函数,而不是一次返回超级复杂的 JSON
4.4 有些 API 会自动做 JSON 修正
比如 OpenAI、DashScope 在 function call 里会帮你补全缺失字段、修正数据类型
但如果修不回来,会返回报错,你要在代码里做兜底
5. 一个完整示例(DashScope)
DashScope 支持 function call,比如:
import dashscope``from dashscope import Generation``dashscope.api_key = "xxx"``functions = [` `{` `"name": "create_task",` `"description": "创建一个任务",` `"parameters": {` `"type": "object",` `"properties": {` `"title": {"type": "string"},` `"priority": {"type": "integer"},` `"due_date": {"type": "string", "format": "date"}` `},` `"required": ["title", "priority"]` `}` `}``]``response = Generation.call(` `model="qwen-plus",` `prompt="帮我生成一个重要的任务,明天截止",` `functions=functions,` `function_call={"name": "create_task"}``)``print(response.output.choices[0].message["function_call"]["arguments"])好处:
保证返回的 arguments 是合法 JSON
结构固定,字段不会乱
方便直接 json.loads() 转成 Python dict 用
二、MCP和Function call的区别
mcp是通用协议层的标准化约定(更偏抽象的通用),function call是某大模型厂商特定的实现方式和特性(更偏具体实现)。
函数调用 (Function Calling):2023年,OpenAI等机构引入了函数调用机制,这是一个巨大的进步。开发者可以预先定义结构化的函数(如 getWeather(location)),模型在需要时,会输出一个标准化的JSON对象来“请求”调用这个函数,而不是模糊的自然语言指令。
概念对比表:
下面是获得天气的Function call工作流程示意图:
以及获得当前天气和当前时间的Function call具体实现:
import dashscope``from dashscope import Generation``from datetime import datetime``import random``import json``import requests``dashscope.api_key = "sk-xxxx"``# 定义工具列表,模型在选择使用哪个工具时会参考工具的name和description``tools = [` `# 工具1 获取当前时刻的时间` `{` `"type": "function",` `"function": {` `"name": "get_current_time",` `"description": "当你想知道现在的时间时非常有用。",` `"parameters": {} # 因为获取当前时间无需输入参数,因此parameters为空字典` `}` `},` `# 工具2 获取指定城市的天气` `{` `"type": "function",` `"function": {` `"name": "get_current_weather",` `"description": "当你想查询指定城市的天气时非常有用。",` `"parameters": { # 查询天气时需要提供位置,因此参数设置为location` `"type": "object",` `"properties": {` `"location": {` `"type": "string",` `"description": "城市或县区,比如北京市、杭州市、余杭区等。"` `}` `}` `},` `"required": [` `"location"` `]` `}` `}``]``# 基于外部网站的天气查询工具。返回结果示例:{"location": "\u5317\u4eac\u5e02", "weather": "clear sky", "temperature": 17.94}``def get_current_weather(location):` `api_key = "xxxx" # 替换为你自己的OpenWeatherMap API密钥,用我的也无所谓啦,反正免费。` `url = f"http://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}&units=metric"` `response = requests.get(url)` `if response.status_code == 200:` `data = response.json()` `weather = data["weather"][0]["description"]` `temp = data["main"]["temp"]` `return json.dumps({"location": location, "weather": weather, "temperature": temp})` `else:` `return json.dumps({"location": location, "error": "Unable to fetch weather data"})` `# 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“``def get_current_time():` `# 获取当前日期和时间` `current_datetime = datetime.now()` `# 格式化当前日期和时间` `formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')` `# 返回格式化后的当前时间` `return f"当前时间:{formatted_time}。"` `# 封装模型响应函数``def get_response(messages):` `response = Generation.call(` `model='qwen-plus',` `messages=messages,` `tools=tools,` `seed=random.randint(1, 10000), # 设置随机数种子seed,如果没有设置,则随机数种子默认为1234` `result_format='message' # 将输出设置为message形式` `)` `return response` `def call_with_messages():` `print('\n')` `messages = [` `{` `"content": input('请输入:'), # 提问示例:"现在几点了?" "一个小时后几点" "北京天气如何?"` `"role": "user"` `}` `]` `# 模型的第一轮调用` `first_response = get_response(messages)` `assistant_output = first_response.output.choices[0].message` `print(f"\n大模型第一轮输出信息:{first_response}\n")` `messages.append(assistant_output)` `if 'tool_calls' not in assistant_output: # 如果模型判断无需调用工具,则将assistant的回复直接打印出来,无需进行模型的第二轮调用` `print(f"最终答案:{assistant_output.content}")` `return` `# 如果模型选择的工具是get_current_weather` `elif assistant_output.tool_calls[0]['function']['name'] == 'get_current_weather':` `tool_info = {"name": "get_current_weather", "role":"tool"}` `# location = json.loads(assistant_output.tool_calls[0]['function']['arguments'])['properties']['location']['description']` `location = json.loads(assistant_output.tool_calls[0]['function']['arguments'])['location']` `# print(location)` `tool_info['content'] = get_current_weather(location)` `# 如果模型选择的工具是get_current_time` `elif assistant_output.tool_calls[0]['function']['name'] == 'get_current_time':` `tool_info = {"name": "get_current_time", "role":"tool"}` `tool_info['content'] = get_current_time()` `print(f"工具输出信息:{tool_info['content']}\n")` `messages.append(tool_info)` `# 模型的第二轮调用,对工具的输出进行总结` `second_response = get_response(messages)` `print(f"大模型第二轮输出信息:{second_response}\n")` `print(f"最终答案:{second_response.output.choices[0].message['content']}")` `if __name__ == '__main__':` `call_with_messages()读者福利:如果大家对大模型感兴趣,这套大模型学习资料一定对你有用
对于0基础小白入门:
如果你是零基础小白,想快速入门大模型是可以考虑的。
一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。
包括:大模型学习线路汇总、学习阶段,大模型实战案例,大模型学习视频,人工智能、机器学习、大模型书籍PDF。带你从零基础系统性的学好大模型!
😝一直在更新,更多的大模型学习和面试资料已经上传带到CSDN的官方了,有需要的朋友可以扫描下方二维码免费领取【保证100%免费】👇👇
👉AI大模型学习路线汇总👈
大模型学习路线图,整体分为7个大的阶段:(全套教程文末领取哈)
第一阶段:从大模型系统设计入手,讲解大模型的主要方法;
第二阶段:在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;
第三阶段:大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;
第四阶段:大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;
第五阶段:大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;
第六阶段:以SD多模态大模型为主,搭建了文生图小程序案例;
第七阶段:以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。
👉大模型实战案例👈
光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
👉大模型视频和PDF合集👈
观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;
• 能够利用大模型解决相关实际项目需求:大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;
• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能,学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;
• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力:大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。
👉获取方式:
😝一直在更新,更多的大模型学习和面试资料已经上传带到CSDN的官方了,有需要的朋友可以扫描下方二维码免费领取【保证100%免费】👇👇