Generator Evaluator

Паттерн «генератор + внешний оценщик»: качество обеспечивает не самооценка модели, а отдельный верификатор. Опирается на асимметрию: проверить решение легче и дешевле, чем создать. Для длинных задач разворачивается в трио Planner / Generator / Evaluator (harness-дизайн Anthropic).

Суть

Генератор выдаёт варианты, верификатор отбирает/судит. Самооценке агента доверять нельзя: «агенты уверенно хвалят свою работу, даже посредственную» — особенно на субъективных задачах (дизайн), где нет бинарного теста. Поэтому оценщик выносится наружу.

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

Одиночная модель в долгой автономной сессии «сходит с рельсов» и переоценивает себя. Внешний оценщик с явными критериями ловит брак, который модель приняла бы «на слово». Важно: если верификатор слабее генератора — система деградирует («слепой ведёт слепого»), поэтому верификатор должен быть сильным, а генератор может быть дешёвым.

Как работает

  • Best-of-N / Search against Verifier — генерируем N вариантов (повышая temperature), строгая модель-судья выбирает лучший. Так внутри работают Claude Code и топовые код-агенты.
  • Trust Gate / Executable Spec Layer — где есть объективная проверка, оценщик = автотесты (Pytest), которые агент не может изменить; при провале агент получает лог ошибки и переписывает решение (см. DoD в Agent Evals).
  • Planner / Generator / Evaluator (harness Anthropic) — трёхагентная архитектура для многочасовых сессий: планировщик декомпозирует, генератор пишет, оценщик критикует по критериям. Цикл генератор↔оценщик соответствует review/QA в обычной разработке.
  • Context resets — против «context anxiety» оценщик/оркестратор сбрасывает контекст и передаёт следующему агенту структурированный handoff-артефакт (отличие от compaction — см. Context Window).

Независимость через границу информации и полномочий

Evaluator не обязательно должен быть другой моделью. OpenCodeReview получает полезную независимость иначе: второй проход видит diff и готовые комментарии, но не траекторию поиска первого агента. Поэтому он не наследует случайные чтения, промежуточные догадки и самообоснование генератора (Source Independence).

Полномочия тоже асимметричны. Reflector работает как filter-only falsifier: не создаёт и не переписывает находки, а может только удалить комментарий по одному из двух проверяемых оснований — предмет замечания отсутствует в diff целевого файла либо конкретная строка diff буквально противоречит утверждению. По умолчанию комментарий сохраняется; ошибка разбора также сохраняет его, то есть evaluator fail-open относительно recall. Для memory safety, concurrency, linkage/declaration consistency и behavioural compatibility удаление дополнительно запрещено.

Это сужает риск самокоррекции: evaluator не пытается написать ответ лучше автора и не награждается за активность. Он выполняет более узкую задачу опровержения с меньшей информацией и меньшими правами. Но цена известна заранее: filter-only проход способен поднять precision, не восстановит пропущенные дефекты и потому не заменяет независимый генератор или исполняемый оракул.

Пример

Best-of-N: генератор выдаёт N вариантов (повышенная температура → разнообразие), отдельный верификатор оценивает каждый (проверить легче, чем сгенерировать), возвращается лучший.

def best_of_n(query, n=3):
    candidates = [think_then_answer(query, temperature=0.7).answer for _ in range(n)]  # N вариантов
    scored = [{"answer": c, **verifier_score(query, c)} for c in candidates]           # внешний судья
    scored.sort(key=lambda x: x["score"], reverse=True)
    return scored[0]                                                                   # лучший по оценке

Проверка взрослеет по месту включения

Один и тот же verifier можно внедрять ступенчато, не начиная с обязательного gate для всей команды:

  1. Standalone — человек отдельно запускает проверку после работы; дёшево проверить полезность критериев.
  2. Embedded — рабочая процедура сама вызывает проверку перед завершением.
  3. Chained — один skill вызывает другой и передаёт ему явный артефакт.
  4. Every PR — стабильная проверка становится общей политикой приёма.

Продвигать проверку вверх стоит по наблюдаемой повторяемости: частый ручной follow-up сначала встраивается в локальную процедуру, и только после стабильного trigger и приемлемого false-positive rate становится командным gate. Иначе сырой evaluator масштабирует шум быстрее, чем качество.

Если исправляющий агент может менять сам критерий, цикл замыкается неправильно: самый короткий путь к GREEN — ослабить тест. На время починки evaluator замораживается либо его изменение требует отдельного review и доказательства, что проверка не стала слабее (AI Native SDLC).

Сколько итераций держать цикл

По длине цикла «генератор ↔ ревьюер» источники расходятся, и разница в них не фактическая, а нормативная.

Как бывает. В разборе CrewAI цикл исполнителя и ревьюера уходил на шесть-семь ретраев: ревьюер раз за разом отклонял текст и удовлетворился только с седьмого прохода. Это наблюдение из отладки — так система действительно себя вела.

Как надо. Продакшен-практика ставит жёсткий потолок в единицы итераций с эскалацией человеку. Аргумент простой: агентный цикл — это while True с привязанной кредиткой, и каждая лишняя итерация стоит денег и латентности, а прирост качества после первых проходов не гарантирован.

Разрешение противоречия: шесть-семь итераций — это симптом, а не режим работы. Если ревьюер отклоняет результат столько раз подряд, проблема почти всегда не в генераторе, а в том, что критерии приёмки не выражены явно и ревьюер спорит с задачей, а не с ответом.

Отдельно важно, чем цикл кормить. Работает только внешний конкретный сигнал: ValidationError с указанием, какое поле не прошло и почему, — модель исправляет на следующей попытке. Не работает intrinsic-самопроверка вида «ты уверен? проверь ещё раз»: ответ был правильный, модель под давлением меняет верное поле на неверное. Это тот же принцип, что и в разделе выше про самооценку, только применённый к циклу: сигнал должен приходить извне и быть конкретным.

Сколько вариантов и как оценивать невыразимое кодом

Best-of-N. Отдача от N убывающая: разброс качества между вариантами конечен, и после нескольких генераций новые почти не приносят лучшего кандидата, тогда как стоимость растёт строго линейно. Поэтому N подбирают не «побольше», а от того, насколько дороже ошибка, чем лишняя генерация: там, где ошибка стоит одного повторного запроса пользователя, хватает одного прохода; там, где она попадает в необратимое действие, N оправдан вместе с внешним верификатором. Adaptive compute — именно про это: тратить N только на шагах, где нужна надёжность (Agent CostControl).

Субъективные задачи. Отсутствие бинарного теста не означает отсутствия критерия — оно означает, что критерий надо выписать. Рабочая форма — набор отдельных бинарных проверок вместо одной шкалы: не «оцени качество от 1 до 10», а «соответствует ли тону», «есть ли ответ на заданный вопрос», «нет ли утверждений сверх источника» — каждая с PASS/FAIL. Бинарность здесь не упрощение, а условие согласуемости: по шкале 1-10 два человека не сойдутся, по «прошло/не прошло» — сойдутся (LLM as Judge, монадическая оценка и обязательное рассуждение до вердикта).

Выбрать из нескольких — не то же, что переписать своё

Паттерн выше требует, чтобы оценщик был внешним, и опирается на то, что самооценке доверять нельзя. Рядом в базе стоит более жёсткое утверждение: внутренняя самокоррекция без внешнего сигнала на задачах рассуждения не работает и местами ухудшает результат (Chain of Thought, Huang et al.). Из двух вместе получается, что модель не может быть верификатором сама себе.

Это верно для ревизии и неверно для селекции. Различие не в том, кто проверяет, а в том, что делают с проверкой:

Ревизия Селекция
Что происходит модель переписывает свой ответ модель выбирает лучший из N уже готовых
Верхняя граница нет — можно уехать куда угодно лучший кандидат в наборе (оракул)
Нижняя граница нет — результат может стать хуже исходного случайный выбор из N
Чем платит ошибка суждения испорченным ответом невыбранным лучшим кандидатом

У селекции испортить нечего: худшее, что делает плохой верификатор, — выбирает наугад, то есть возвращает к базовому уровню. У ревизии такой опоры нет, и потому предупреждение Huang к ней применимо, а к выбору из N — нет.

Это подтверждено на самопроверке, а не выведено умозрительно. В LLM-as-a-Verifier deepseek-v4-flash выступает и генератором, и верификатором на Terminal-Bench 2.1: Best-of-3 поднимает 79.4% → 86.5% ± 1.1% при оракуле 92.1%, Best-of-5 — 78.7% → 88.0% ± 0.6% при оракуле 96.6%. Интервалы существенны: разница между 86.5 и 88.0 при них заметно менее уверенная, чем выглядит по одним точечным значениям. Та самая модель, которой нельзя доверить переписывание собственного ответа, отбирает свои же траектории с пользой.

Оракул — та величина, которой в паттерне не хватало. Он говорит, сколько вообще можно выиграть отбором: разрыв между Pass@1 и Pass@k — это весь бюджет верификатора, и внутри него измеряется, насколько он хорош. Без оракула прирост «на 8 пунктов» не с чем сравнить. На Terminal-Bench Best-of-5 верификатор забирает около половины доступного разрыва (78.7 → 88.0 при потолке 96.6); на MedAgentBench разрыв узкий изначально (70.2 → 73.3 при потолке 75.0), и там отбор почти исчерпан. Узкий разрыв — сигнал, что тратить на Best-of-N нечего, и считать его надо до того, как строить отбор.

Заголовочный результат той же работы — про разные модели: GPT-5.5 генерирует, gemini-2.5-flash проверяет, 83.1% → 86.5% при оракуле 92.1% на Terminal-Bench V2. Пара 86.5 / 92.1 здесь совпадает с Best-of-3 самопроверки выше — совпадение в данных, сверено по первоисточнику 2026-09-12, не ошибка копирования (Benchmarks Agents). Это ровно то, что паттерн и утверждал; новое здесь — вторая установка, где проверяющий и проверяемый совпадают.

Граница асимметрии: свойство, у которого нет быстрого оракула

Весь паттерн стоит на том, что проверить дешевле, чем создать. У этой асимметрии есть условие, которое обычно не проговаривают: у проверяемого свойства должен быть быстрый и надёжный оракул. Тесты дают чистый вердикт за секунды — потому на них и удаётся крутить обучение миллионы раз.

Там, где оракула нет, асимметрия разворачивается в обратную сторону. Цена плохой архитектуры выражается неделями и месяцами: она приходит в тот момент, когда кто-то открывает файл ради правки в одну строку и обнаруживает, что править придётся в одиннадцати местах. Связать этот случай с решением, которое его породило, нечем — между ними месяцы и десятки изменений.

Отсюда потолок у оценщика-модели, и формулируется он неприятно точно: если бы модель надёжно отличала хороший код от плохого, она с большей вероятностью написала бы сразу хороший. Добавление ещё одного проверяющего агента и увеличение бюджета токенов поднимают пол — ловят явные глупости, — но не двигают потолок, потому что потолок задан тем, чему модель научили.

Практическое разделение для проектирования:

Свойство Оракул Чем работает оценщик
поведение по спецификации тест, исполнение, схема вердиктом: паттерн работает как обещает
безопасность вызова детерминированное правило, песочница вердиктом
сопровождаемость, связность, уместность решения быстрого оракула нет только полом: ловит грубое, приёмкой быть не может

Для третьей строки замена вердикту не «судья построже», а измерение по времени: структурные величины вроде эрозии и многословности, снятые на серии изменений, показывают наклон там, где точечная оценка показывает только уровень (Agent First Repository). Человеческое чтение здесь остаётся арбитром не по традиции, а потому что заменить его нечем.

Довод взят из эссе практика, а не из замера, и опирается на устройство обучения моделей, а не на эксперимент. Но он объясняет уже замеренное: почему инструкция «пиши качественно» сдвигает начальный уровень и не трогает скорость деградации (Generated Test Quality, Agent First Repository).

Связано с

  • Reflexion — самокритика того же агента между попытками вместо отдельного критика внутри задачи; это ревизия, и разбор выше объясняет, почему к ней предупреждение применимо, а к Best-of-N нет

  • Chain of Thought — предупреждение про самокоррекцию, область которого здесь сужена

  • Benchmarks Agents — Terminal-Bench и рамка «Pass@1 против оракула Pass@k»

  • Generated Test Quality — лестница «исполняется → покрывает → убивает мутантов»: оракул, который у сгенерированных тестов всё-таки есть

  • Agent Architecture — где этот слой встраивается в master loop

  • Agent Evals — Trust Gate / executable spec как форма оценки

  • Plan and Execute — Planner здесь = планировщик из plan-and-execute

  • Reasoning Effort — почему внешняя оценка надёжнее самокоррекции (нюанс риска self-reflection)

  • LLM as Judge — техника судьи (критерии, бинарность, калибровка), на которой стоит этот паттерн

  • Multi Agent Patterns — критик/ревьюер как обязательный паттерн MAS (каскад ошибок 90%→65%)

  • Source Independence — другая информационная граница важнее формального названия «второй агент»

  • Agent Code Review — применение filter-only falsifier к комментариям ревью