Validation Loops

Циклы валидации — механизм автоисправления, когда вывод модели типово верен (Structured Output), но логически неверен. Паттерн Validate → Repair → Retry: при провале проверки модель получает точное описание ошибки и переписывает ответ. Сила не в самом retry, а в содержательности ошибки.

Суть

После того как структура гарантирована, остаётся бизнес-логика: даты, диапазоны, кратности, межполевые инварианты. Их проверяют валидаторы; при провале поднимается ModelRetry, и модель видит свой прошлый ответ + причину ошибки.

Зачем это нужно

Технически валидный JSON может быть бизнес-неверным: дата конца раньше даты начала, priority=critical без флага requires_human, сумма не сходится. Кейс юр.документов: добавление output-валидаторов снизило логические ошибки с 4.7% до 0.0%, исправление с первой попытки в 94% случаев.

Как работает

Три независимых уровня проверки:

  1. JSON Schema / типы — автоматически (тип поля, обязательность, enum, диапазоны).
  2. @field_validator — правило для конкретного поля и нормализация (строку "$1,200.50"1200.50).
  3. @agent.output_validator — последний рубеж: бизнес-логика, в т.ч. обращение к БД/API через ctx.deps (Agent Deps).

При провале — raise ModelRetry("поле X провалило проверку Y по причине Z"). Защита от бесконечного цикла: retries=3 на агенте, после исчерпания — UnexpectedModelBehavior (связь с лимитами в Agent CostControl).

agent = Agent('openai:gpt-4o-mini', output_type=TicketClassification,
              deps_type=TicketDeps, retries=3)

@agent.output_validator
async def validate_output(ctx: RunContext[TicketDeps],
                          output: TicketClassification) -> TicketClassification:
    if output.priority == "critical" and not output.requires_human:
        raise ModelRetry("priority=critical обязывает requires_human=True")
    if output.estimated_minutes % 15 != 0:
        raise ModelRetry(f"{output.estimated_minutes} не кратно 15")
    return output

# число потраченных retry: result.usage().requests - 1

Связано с

  • PydanticAI — где реализованы валидаторы и ModelRetry
  • Structured Output — типовая валидация, поверх которой идёт бизнес-проверка
  • Agent CostControl — retries=3 и стоп при UnexpectedModelBehavior

Открытые вопросы

  • оптимальный лимит retries vs стоимость (retry_overhead_tokens)
  • что делать при исчерпании попыток: fallback-ответ vs алерт vs отказ