跨主流LLM提供商(OpenAI、Gemini、Anthropic、Mistral和AWS Bedrock)的结构化输出对比
略有不同的 API 需要特殊处理。
以下是结构化输出在主流大语言模型(LLM)提供商之间的对比,以及一些Python示例:
我们已经查看了如何从在Ollama上托管的LLM请求结构化输出。在这里,我们将回顾如何从其他提供商请求相同的输出。
TL;DR 矩阵
提供商 | 本机“JSON模式” | JSON 模式强制执行 | 典型旋钮 | 备注 |
---|---|---|---|---|
OpenAI | 是 | 是(第一类) | response_format={"type":"json_schema", ...} |
通过响应API或聊天完成实现;也可以进行函数调用。 |
Google Gemini | 是 | 是(第一类) | response_schema= + response_mime_type="application/json" |
设置模式后返回严格验证的JSON。 |
Anthropic (Claude) | 间接 | 是(通过工具使用与JSON模式) | tools=[{input_schema=...}] + tool_choice |
强制模型“调用”您定义的模式工具;生成符合模式的参数。 |
Mistral | 是 | 部分(仅JSON;无服务器端模式) | response_format={"type":"json_object"} |
确保JSON,但您需在客户端验证模式。 |
AWS Bedrock(平台) | 根据模型而定 | 是(通过工具/Converse模式) | toolConfig.tools[].toolSpec.inputSchema |
Bedrock的Converse API根据JSON模式验证工具输入。 |
LLM结构化输出 - 一般信息
LLM结构化输出指的是大型语言模型(LLMs)生成响应的能力,这些响应严格遵循预定义的特定格式或结构,而不是生成自由形式的文本。这种结构化输出可以是JSON、XML、表格或模板等格式,使数据可被机器读取、保持一致,并且易于软件解析,以便在各种应用中使用。
结构化输出与传统的LLM输出不同,后者通常生成开放式的自然语言文本。相反,结构化输出强制执行模式或格式,例如具有定义键和值类型的JSON对象,或输出中的特定类(例如多项选择答案、情感类别或数据库行格式)。这种方法提高了可靠性,减少了错误和幻觉,并简化了与数据库、API或工作流程等系统的集成。
LLM中结构化输出的生成通常涉及以下技术:
- 指定详细的提示指令,以指导模型以所需格式生成输出。
- 使用验证和解析工具,如Python中的Pydantic,以确保输出与模式匹配。
- 有时根据语法或有限状态机强制解码约束,以确保在格式上的标记级合规性。
结构化LLM输出的优点包括:
- 机器可读性和易于集成。
- 减少变异性与错误。
- 对需要一致数据格式的任务提高可预测性和可验证性。
挑战包括设计有效的模式、处理复杂的嵌套数据,以及与自由形式文本生成相比可能存在的推理能力限制。
总体而言,结构化输出使LLM在需要精确格式化数据的应用中更加有用,而不仅仅是人类可读的文本。
结构化输出 Python 示例
所有代码片段都提取事件信息为JSON:{title, date, location}
。您可以根据需要替换键/模型。
1) OpenAI — JSON Schema(严格)
from openai import OpenAI
import json
client = OpenAI()
schema = {
"name": "Event",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string", "description": "YYYY-MM-DD"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
},
"strict": True
}
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}
],
response_format={"type": "json_schema", "json_schema": schema},
)
data = json.loads(resp.choices[0].message.content)
print(data)
OpenAI的结构化输出功能在服务器端强制执行此模式。
2) Google Gemini — 响应模式 + JSON MIME
import google.generativeai as genai
from google.genai import types
# 使用您的API密钥进行配置
# genai.configure(api_key="your-api-key")
schema = types.Schema(
type=types.Type.OBJECT,
properties={
"title": types.Schema(type=types.Type.STRING),
"date": types.Schema(type=types.Type.STRING),
"location": types.Schema(type=types.Type.STRING),
},
required=["title", "date", "location"],
additional_properties=False,
)
resp = genai.generate_content(
model="gemini-2.0-flash",
contents="Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'",
generation_config=genai.GenerationConfig(
response_mime_type="application/json",
response_schema=schema,
),
)
print(resp.text) # 已经是符合模式的JSON
Gemini将返回严格符合response_schema
的JSON。
3) Anthropic (Claude) — 工具使用与JSON模式
from anthropic import Anthropic
import json
client = Anthropic()
tool = {
"name": "extract_event",
"description": "返回事件详情。",
"input_schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
}
}
msg = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=256,
tools=[tool],
tool_choice={"type": "tool", "name": "extract_event"}, # 强制使用模式
messages=[{"role": "user", "content":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
)
# Claude将“调用”工具;获取参数(符合您的模式)
tool_use = next(b for b in msg.content if b.type == "tool_use")
print(json.dumps(tool_use.input, indent=2))
Claude没有通用的“JSON模式”开关;相反,工具使用与**input_schema
**为您提供验证过的、符合模式的参数(您可以强制使用它)。
4) Mistral — JSON模式(客户端验证)
from mistralai import Mistral
import json
client = Mistral()
resp = client.chat.complete(
model="mistral-large-latest",
messages=[{"role":"user","content":
"Return JSON with keys title, date (YYYY-MM-DD), location for: "
"'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
response_format={"type": "json_object"} # 保证有效JSON
)
data = json.loads(resp.choices[0].message.content)
print(data)
# 提示:使用Pydantic/JSON Schema在本地验证`data`。
Mistral的json_object
强制执行JSON形状(不是您的精确模式)——在客户端进行验证。
5) AWS Bedrock — Converse API 工具模式(模型无关)
import boto3, json
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0"
tools = [{
"toolSpec": {
"name": "extract_event",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title","date","location"],
"additionalProperties": False
}
}
}
}]
resp = bedrock.converse(
modelId=model_id,
toolConfig={"tools": tools},
toolChoice={"tool": {"name": "extract_event"}}, # 强制使用模式
messages=[{"role":"user","content":[{"text":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}]}],
)
# 提取toolUse内容
tool_use = next(
c["toolUse"] for c in resp["output"]["message"]["content"] if "toolUse" in c
)
print(json.dumps(tool_use["input"], indent=2))
Bedrock根据您的JSON模式验证工具输入,并且许多托管模型(例如Claude)通过Converse支持它。
实用指南和验证
- 如果您想要最强的服务器端保证: 使用OpenAI结构化输出或Gemini响应模式。
- 如果您已经在使用Claude/Bedrock: 定义一个带有JSON模式的工具并强制使用它;将工具的参数读取为您的类型对象。
- 如果您使用Mistral: 启用
json_object
并在本地进行验证(例如使用Pydantic)。
验证模式(适用于所有)
from pydantic import BaseModel, ValidationError
class Event(BaseModel):
title: str
date: str
location: str
try:
event = Event.model_validate(data) # `data`来自任何提供商
except ValidationError as e:
# 处理/重试/让模型修复,使用e.errors()
print(e)
有用的链接
- https://platform.openai.com/docs/guides/structured-outputs
- https://ai.google.dev/gemini-api/docs/structured-output
- https://docs.mistral.ai/capabilities/structured-output/json_mode/
- https://aws.amazon.com/blogs/machine-learning/structured-data-response-with-amazon-bedrock-prompt-engineering-and-tool-use
- https://github.com/aws-samples/anthropic-on-aws/blob/main/complex-schema-tool-use/README.md
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html
- 如何从在Ollama上托管的LLM请求结构化输出
- Python速查表
- AWS SAM + AWS SQS + Python PowerTools
- AWS Lambda性能比较:JavaScript vs Python vs Golang