Получение строгого JSON
Когда ответ модели нужен не человеку, а коду, он должен быть машиночитаемым — обычно это JSON.
Структурированный вывод — режим, в котором модель обязана вернуть данные в заданном формате (JSON по схеме), а не свободный текст.
Зачем строгий JSON
Если LLM извлекает из письма имя, email и сумму, вам нужен объект {"name": ..., "email": ..., "amount": ...}, который код тут же распарсит. Свободный текст «Имя клиента — Иван, почта...» придётся разбирать регулярками — хрупко и ненадёжно.
Способ 1: попросить в промпте (слабый)
Самый простой путь — попросить в системном промпте: «верни только JSON по схеме». Работает, но не гарантирует: модель может добавить пояснение, обернуть в Markdown-блок ```json, ошибиться в кавычках. Поэтому ответ всё равно надо валидировать.
system = (
"Извлеки данные из текста. Верни ТОЛЬКО JSON-объект с полями "
"name (строка), email (строка), amount (число). Без пояснений и markdown."
)
Способ 2: structured outputs / схема (надёжный)
Провайдеры дают режим, гарантирующий валидный JSON по JSON-схеме. У Anthropic это output_config.format со схемой, у OpenAI — response_format с JSON-схемой. Модель физически не может отступить от структуры.
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=512,
messages=[{"role": "user", "content": "Иван, [email protected], заказ на 1500."}],
output_config={
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"amount": {"type": "number"}
},
"required": ["name", "email", "amount"],
"additionalProperties": False
}
}
},
)
Способ 3: инструмент со схемой
Ещё один приём — определить «инструмент» с нужной схемой входа и заставить модель его «вызвать»: аргументы вызова и будут вашим структурированным объектом. Это мост к следующему уроку про tool use.
Валидация — всё равно обязательна
Даже с гарантированным форматом проверяйте ответ перед использованием: схема может не описывать все ограничения (диапазоны, бизнес-правила), а при свободном промпте парсинг тем более может упасть.
Валидация JSON по схеме полей (запускаемо)
Простой валидатор: парсим строку и проверяем наличие и типы полей — чистый Python:
import json
# Строка, которую вернула модель
model_text = '{"name": "Иван", "age": 30, "city": "Москва"}'
REQUIRED = {"name": str, "age": int, "city": str}
def validate(text, required):
try:
data = json.loads(text)
except json.JSONDecodeError as e:
return None, f"не JSON: {e}"
for key, typ in required.items():
if key not in data:
return None, f"нет поля {key}"
if not isinstance(data[key], typ):
return None, f"поле {key} должно быть {typ.__name__}"
return data, None
data, err = validate(model_text, REQUIRED)
if err:
print("Ошибка валидации:", err)
else:
print("Валидно. Имя:", data["name"], "| Возраст:", data["age"])
# Плохой случай: возраст строкой
bad, err = validate('{"name": "Иван", "age": "тридцать"}', REQUIRED)
print("Плохой ввод ->", err)
Вывод:
Валидно. Имя: Иван | Возраст: 30 Плохой ввод -> поле age должно быть int
Итог
- Для кода нужен машиночитаемый ответ — обычно строгий JSON.
- Просьба в промпте не гарантирует формат;
output_config.format/response_formatсо схемой — гарантирует. - Валидируйте ответ всегда: формат не покрывает бизнес-ограничения.