Сравнение структурированного вывода популярных провайдеров LLM — OpenAI, Gemini, Anthropic, Mistral и AWS Bedrock
Незначительно отличающиеся API требуют особого подхода.
Вот сравнение поддержки структурированного вывода (получение надежного JSON) от популярных провайдеров LLM вместе с минимальными примерами на Python

Мы уже рассмотрели, как запросить структурированный вывод от LLM, хостящегося на Ollama. Когда JSON возвращается по сети, статья Валидация структурированного вывода LLM на Python, которая держит удар охватывает парсинг, проверки Pydantic, повторные попытки и тесты в вашем сервисе. Здесь мы разбираем, как запросить то же самое у других провайдеров.
Краткая матрица (TL;DR)
| Провайдер | Нативный «режим JSON» | Принуждение к схеме JSON | Типичный параметр | Примечания |
|---|---|---|---|---|
| OpenAI | Да | Да (первоклассная поддержка) | response_format={"type":"json_schema", ...} |
Работает через Responses API или Chat Completions; также поддерживает function calling. |
| Google Gemini | Да | Да (первоклассная поддержка) | response_schema= + response_mime_type="application/json" |
Возвращает строго валидированный JSON, когда задана схема. |
| Anthropic (Claude) | Косвенно | Да (через Tool Use со схемой JSON) | tools=[{input_schema=...}] + tool_choice |
Принуждает модель «вызывать» ваш инструмент, определенный схемой; возвращает аргументы, соответствующие схеме. |
| Mistral | Да | Частично (только JSON; без серверной схемы) | response_format={"type":"json_object"} |
Гарантирует JSON, но валидация против вашей схемы выполняется на клиенте. |
| AWS Bedrock (платформа) | Зависит от модели | Да (через Tool/Converse schema) | toolConfig.tools[].toolSpec.inputSchema |
Converse API в Bedrock валидирует вход инструмента против схемы JSON. |
Структурированный вывод LLM — Общая информация
Структурированный вывод LLM относится к способности больших языковых моделей (LLM) генерировать ответы, которые строго соответствуют предопределенному конкретному формату или структуре, а не произвольному тексту. Этот структурированный вывод может иметь форматы JSON, XML, таблицы или шаблоны, что делает данные машиночитаемыми, согласованными и легко разбираемыми программным обеспечением для использования в различных приложениях.
Структурированные выводы отличаются от традиционных выводов LLM, которые обычно генерируют открытые естественные языковые тексты. Вместо этого структурированные выводы принудительно применяют схему или формат, например, объекты JSON с определенными ключами и типами значений, или конкретные классы в выводе (например, ответы с множественным выбором, классы настроений или форматы строк базы данных). Этот подход повышает надежность, снижает количество ошибок и галлюцинаций, а также упрощает интеграцию в такие системы, как базы данных, API или рабочие процессы.
Генерация структурированных выводов в LLM часто включает такие техники, как:
- Указание подробных инструкций в промпте, чтобы направить модель на выработку вывода в желаемом формате.
- Использование инструментов валидации и парсинга, таких как Pydantic в Python, для обеспечения соответствия вывода схеме.
- В некоторых случаях принудительное применение ограничений декодирования на основе грамматики или конечных автоматов для обеспечения соответствия форматированию на уровне токенов.
Преимущества структурированного вывода LLM включают:
- Машиночитаемость и легкость интеграции.
- Снижение вариативности и ошибок.
- Повышение предсказуемости и проверяемости для задач, требующих последовательных форматов данных.
Сложности включают проектирование эффективных схем, обработку сложных вложенных данных и потенциальные ограничения в способностях к рассуждениям по сравнению с генерацией свободного текста.
В целом, структурированный вывод позволяет LLM быть более полезными в приложениях, требующих точных, форматированных данных, а не только текста, читаемого человеком.
Примеры структурированного вывода на Python
Все фрагменты извлекают информацию о событии в формате JSON: {title, date, location}. Замените ключи/модели по своему усмотрению.
1) OpenAI — Схема JSON (строгая)
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)
Функция Structured Outputs от OpenAI принудительно применяет эту схему на стороне сервера.
2) Google Gemini — Схема ответа + JSON MIME
import google.generativeai as genai
from google.genai import types
# Configure with your API key
# 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) # already valid JSON per schema
Gemini вернет строгий JSON, соответствующий response_schema.
3) Anthropic (Claude) — Использование инструментов со схемой JSON
from anthropic import Anthropic
import json
client = Anthropic()
tool = {
"name": "extract_event",
"description": "Return event details.",
"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"}, # force schema
messages=[{"role": "user", "content":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
)
# Claude will "call" the tool; grab the args (which match your schema)
tool_use = next(b for b in msg.content if b.type == "tool_use")
print(json.dumps(tool_use.input, indent=2))
У Claude нет общего переключателя «режим JSON»; вместо этого Tool Use с 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"} # guarantees valid JSON
)
data = json.loads(resp.choices[0].message.content)
print(data)
# Tip: validate `data` against your Pydantic/JSON Schema locally.
json_object от Mistral принудительно применяет структуру 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"}}, # force schema
messages=[{"role":"user","content":[{"text":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}]}],
)
# Pull toolUse content
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: определите инструмент (Tool) со схемой 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` from any provider
except ValidationError as e:
# handle / retry / ask model to fix with 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
- Как запросить структурированный вывод от LLM, хостящегося на Ollama
- Шпаргалка по Python