Почему валидация JSON Schema необходима для выходных данных LLM
Техническое руководство, объясняющее, почему синтаксически корректного JSON от больших языковых моделей (LLM) недостаточно для производственных систем и как JSON Schema обеспечивает необходимые структурные и типовые гарантии.
В этом материале
Короткий ответ
Разберите ответ модели и проверьте полученный объект по явно заданной схеме до использования. Разбор JSON подтверждает читаемость формата, но не наличие нужных полей и не типы приложения. Используйте required для обязательных полей, type для типов значений и additionalProperties: false, если лишние поля нужно отклонять. Некорректный ответ обрабатывайте как ошибку. Такая проверка обеспечивает заданную структуру, но не достоверность ответа и не все бизнес-правила.
Ментальная модель: Синтаксис против Схемы
Чтобы решить проблему ненадежных выходных данных LLM, необходимо различать синтаксис и схему. Синтаксис относится к правилам самого формата JSON: каждая открывающая скобка должна иметь закрывающую скобку, а ключи должны быть заключены в двойные кавычки. Такой парсер, как Python's json.loads(), проверяет только эти правила.
Схема же определяет семантическое значение и структуру данных. В то время как синтаксис гарантирует читаемость файла, схема гарантирует пригодность содержимого для использования. LLM может легко создать JSON-объект, который синтаксически безупречен, но логически бесполезен, потому что он не предоставляет конкретную информацию, необходимую вашему приложению.
Пример: null, отсутствующее поле и допустимая строка
Рассмотрим приложение, которое ожидает профиль пользователя. Системе требуется поле 'email' в виде строки. LLM может сгенерировать следующий JSON:
Входной JSON: {"name": "John Doe", "email": null}
В данном случае JSON синтаксически идеален. Парсер успешно преобразует его в словарь Python. Однако, если ваш код попытается вызвать.split('@') для поля email, приложение аварийно завершится с ошибкой AttributeError, так как вместо строки оно получило NoneType.
При применении JSON Schema, определяющей 'email' как обязательную строку, этап валидации обнаружит эту ошибку до того, как данные попадут в вашу бизнес-логику.
# Install in your environment: python -m pip install jsonschema
import json
from jsonschema import Draft202012Validator
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
},
"required": ["name", "email"],
"additionalProperties": False
}
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(schema)
samples = [
'{"name": "Ada", "email": null}',
'{"name": "Ada"}',
'{"name": "Ada", "email": "ada@example.com"}'
]
for text in samples:
data = json.loads(text)
print("accepted" if validator.is_valid(data) else "rejected")
# Expected illustrative output:
# rejected
# rejected
# acceptedОжидаемый результат
Для трёх входных объектов ожидаемый иллюстративный вывод: rejected, rejected, accepted. В первом email присутствует, но JSON null превращается в Python None и не соответствует типу string. Во втором email отсутствует, поэтому срабатывает required. Третий соответствует этой схеме. Значение "not-an-email" тоже пройдёт: пример проверяет строковый тип, а не адрес почты. В Python jsonschema одного указания format недостаточно для проверки формата; при необходимости настройте отдельный проверяющий объект.
Диагностика: Почему LLM не проходят валидацию
LLM не проходят валидацию по нескольким причинам. Во-первых, они могут галлюцинировать имена полей, используя 'user_email' вместо ожидаемого 'email'. Во-вторых, они могут испытывать трудности со сложными типами, например, возвращая строку '10' вместо числа 10. В-третьих, они могут полностью пропускать поля, если промпт неоднозначен. Наконец, они могут включать нестандартные значения, такие как NaN или Infinity, которые, хотя иногда и принимаются определенными парсерами, не соответствуют строгому спецификации JSON (RFC 7159).
Распространенные ошибки
Распространенная ошибка заключается в предположении, что если парсер не выдал ошибку, то данные безопасны для использования. Другая ошибка - отсутствие учета значения 'null'; в JSON ключ может существовать, но иметь значение null, что фундаментально отличается от отсутствия ключа. Разработчики также часто забывают ограничивать количество свойств, позволяя LLM возвращать массивные, раздутые объекты, которые потребляют чрезмерное количество памяти и ресурсов CPU во время обработки.
Критерии принятия решения для валидации
Начните с контракта приложения: обязательные поля и явно заданные типы. Для запрета неожиданных полей используйте additionalProperties: false; само properties их не запрещает. Добавляйте границы и шаблоны только для конкретных требований. Отдельно ограничивайте размер ответа до разбора. Python json.loads по умолчанию принимает NaN и Infinity; если нужен строгий JSON, используйте parse_constant с возбуждением ошибки. Эти проверки не заменяют контроль доступа и проверку бизнес-правил.
Ограничения области применения
Валидация JSON Schema - это структурная проверка, а не логическая. Она может гарантировать, что поле 'price' является числом, но она не может гарантировать, что цена верна или что она соответствует цене в вашей базе данных. Кроме того, валидация схемы не защищает от атак типа отказ в обслуживании (DoS), если LLM генерирует многогигабайтный JSON-объект; вы должны установить ограничения на размер входной строки перед началом парсинга.
Резюме требований
Для эффективного внедрения убедитесь, что у вас есть: 1. Определенная JSON Schema для каждого ожидаемого ответа LLM. 2. Библиотека валидации (например, jsonschema для Python). 3. Стратегия обработки ошибок валидации (например, повторный запрос к LLM или возврат ошибки пользователю). 4. Ограничения на размер входных данных для предотвращения исчерпания памяти во время начальной фазы парсинга.
Что проверить
- Определяет ли схема все обязательные поля?
- Явно ли заданы типы (string против number)?
- Установлен ли лимит на размер входной строки перед парсингом?
- Настроен ли парсер на обработку или отклонение NaN/Infinity?
Границы применения
JSON Schema не может проверять согласованность бизнес-логики (например, обеспечение того, что 'start_date' идет перед 'end_date') или фактическую точность контента.