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

Мы уже рассматривали, как запрашивать структурированный вывод от LLM, размещенного на Ollama. Здесь мы рассматриваем, как запросить то же самое от других поставщиков.
Краткая сводка
| Поставщик | Нативный режим “JSON” | Принудительное соблюдение схемы JSON | Типичный параметр | Примечания |
|---|---|---|---|---|
| OpenAI | Да | Да (первоклассный) | response_format={"type":"json_schema", ...} |
Работает через 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) | toolConfig.tools[].toolSpec.inputSchema |
API Converse Bedrock валидирует вход инструмента по схеме JSON. |
Структурированный вывод LLM - общая информация
Структурированный вывод LLM относится к способности больших языковых моделей (LLMs) генерировать ответы, которые строго соответствуют заранее определенному, конкретному формату или структуре, а не просто производить свободный текст. Такой структурированный вывод может быть в форматах 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": "Извлеките мероприятие из: 'PyData Sydney проходит 2025-11-03 в Дарлинг-Харборе.'"}
],
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
# Настройка с вашим 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="Извлеките мероприятие из: 'PyData Sydney проходит 2025-11-03 в Дарлинг-Харборе.'",
generation_config=genai.GenerationConfig(
response_mime_type="application/json",
response_schema=schema,
),
)
print(resp.text) # уже валидный JSON по схеме
Gemini вернет строгий JSON, соответствующий response_schema.
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":
"Извлеките мероприятие из: 'PyData Sydney проходит 2025-11-03 в Дарлинг-Харборе.'"}],
)
# 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”; вместо этого 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":
"Верните JSON с ключами title, date (YYYY-MM-DD), location для: "
"'PyData Sydney проходит 2025-11-03 в Дарлинг-Харборе.'"}],
response_format={"type": "json_object"} # гарантирует валидный JSON
)
data = json.loads(resp.choices[0].message.content)
print(data)
# Совет: валидируйте `data` по вашей схеме Pydantic/JSON Schema локально.
Режим json_object Mistral навязывает форму JSON (не вашу точную схему) — валидируйте на стороне клиента.
5) AWS Bedrock — Схема инструмента API Converse (независимо от модели)
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":
"Извлеките мероприятие из: 'PyData Sydney проходит 2025-11-03 в Дарлинг-Харборе.'"}]}],
)
# Получаем содержимое 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
- Как запросить структурированный вывод от LLM, размещенного на Ollama
- Шпаргалка по Python
- AWS SAM + AWS SQS + Python PowerTools
- Сравнение производительности AWS Lambda: JavaScript vs Python vs Golang