Сравнение структурированного вывода у популярных провайдеров 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; также возможно использование вызова функций. |
| 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 |
API Converse в Bedrock валидирует входные данные инструмента по схеме JSON. |
Структурированный вывод LLM — Общая информация
Структурированный вывод LLM относится к способности больших языковых моделей (LLM) генерировать ответы, которые строго соответствуют заранее заданному формату или структуре, а не просто произвольный текст. Этот структурированный вывод может быть в форматах, таких как JSON, XML, таблицы или шаблоны, что делает данные машиночитаемыми, последовательными и легко парсируемыми программным обеспечением для использования в различных приложениях.
Структурированные выводы отличаются от традиционных выводов LLM, которые обычно генерируют открытый естественный язык. Вместо этого структурированные выводы принудительно применяют схему или формат, такую как JSON-объекты с определенными ключами и типами значений, или определенные классы в выводе (например, ответы с множественным выбором, классы тональности или форматы строк базы данных). Этот подход повышает надежность, снижает ошибки и галлюцинации, а также упрощает интеграцию в системы, такие как базы данных, API или рабочие процессы.
Генерация структурированных выводов в LLM часто включает такие методы, как:
- Указание подробных инструкций в промпте, чтобы направить модель к созданию вывода в желаемом формате.
- Использование инструментов валидации и разбора, таких как Pydantic в Python, чтобы убедиться, что вывод соответствует схеме.
- Иногда принудительное соблюдение ограничений декодирования на основе грамматики или конечных автоматов для обеспечения соответствия токенов формату.
Преимущества структурированных выводов 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)
Функция 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) — Использование инструментов (Tool Use) со схемой 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
- AWS SAM + AWS SQS + Python PowerTools
- Сравнение производительности AWS lambda: JavaScript vs Python vs Golang