Продакшен-фича на AI, которой я владею, работала вчера. Сегодня ломается на каждом четвёртом вызове. Кода не правили. Промпт не трогали. Модель не переключали. Retrieval-индекс не перестраивали. Ничто в системе, по любому чтению диффа, не сдвинулось. И всё же четверть ответов неверны — тихо уверенно неверны, так что ни один пользователь не зарепортит баг. Они просто заметят, что продукт стал тупее, чем неделю назад, и уйдут.
Так выглядит жизнь без evals. И причина, по которой большинство команд, отгружающих AI в 2026, до сих пор без evals, в том, что дисциплина сложнее, чем кажется, дороже, чем выглядит, и не даёт удовлетворяющей зелёной галочки. Это также единственная инженерная практика, отделяющая команды, отгружающие AI-продукты, от команд, отгружающих AI-демо.
Это третья опора трилогии. Контекст-инжиниринг — это то, что рантайм собирает в момент вызова модели. Spec-driven development — это то, что пишет команда, из чего рантайм потом собирает. Evals — это то, как вы узнаёте, что хоть что-то из этого работает. Без третьей опоры первые две складываются — спека становится верой, контекст — театром, а ваша «AI-фича» — штукой, которая трижды отработала на демо.
Тезис жёстче, чем людям удобно. Если вы отгружаете AI-фичи без evals, у вас не продукт. У вас демо с пользователями.
Почему традиционное тестирование не работает
У каждого инженера, читающего это, тридцать лет интуиции тестирования построены на одной несущей предпосылке: тестируемая система детерминирована. На одном и том же входе она даёт один и тот же выход. Юнит-тест — это пара (вход, ожидаемый выход), которую можно прикрепить к коммиту и гонять вечно.
Эта предпосылка теперь неверна для значимого куска вашей кодовой базы.
Вызов модели — это не функция. Это распределение вероятностей по выходам, из которого берётся выборка. Два идентичных вызова дают разные строки, обе потенциально валидные. Вызов, давший верный ответ в марте, в апреле может дать другой верный ответ — или неверный, — потому что Anthropic, или OpenAI, или ваш retrieval-индекс, или ваш системный промпт, или описания инструментов, или версия модели, или max_tokens, или температура сместились на волос. Вся модель пирамиды тестирования — юнит, интеграция, e2e, всё зелёное, отгружаем — стояла на предпосылке, которая теперь только частично верна. Слой юнит-тестов на дне пирамиды работает для всего ниже границы модели. Выше неё пирамида переворачивается и ведёт себя странно.
Соблазн — отмахнуться. «Поставим температуру в ноль и напишем ассерты». Это покупает примерно три недели ложной уверенности. temperature=0 — это не детерминизм, это низкая дисперсия. Порядок tool-вызовов всё ещё плавает. Retrieval может вернуть разные чанки на тот же запрос, потому что в индексе появился новый документ. Модель за API-эндпоинтом может обновиться без предупреждения. Иллюзия детерминизма — это то, что делает баг, когда он приходит, нерасследуемым.
Evals — это дисциплина намеренного тестирования недетерминированной системы правильными инструментами. Это не юнит-тесты с лишними шагами. Это форма другая.
Что такое eval на самом деле
Eval — это тройка (вход, утверждение о поведении, рубрика оценки), которая прогоняет всю систему — вызов модели, инструменты, retrieval, историю, всё, — и оценивает выход против рубрики, терпимой к естественной дисперсии системы, но при этом ловящей реальные регрессии.
В зрелых кодовых базах встречаются четыре формы, и они лежат на спектре от «дёшево и хрупко» до «дорого и честно».
| Форма | Что делает | Когда использовать | Стоимость | Что ловит |
|---|---|---|---|---|
| Строковое / regex-совпадение | Проверяет наличие или отсутствие литеральных паттернов в выходе | Отказы с высокой ставкой, форматы фиксированной формы, наличие структурных полей | Бесплатно | Катастрофические промахи, поломки формата |
| Структурная проверка полей | Парсит выход как JSON/XML и ассертит конкретные поля | Форма tool-вызовов, schema-bound выходы, лейблы классификации | Дёшево | Дрейф схемы, переворот лейблов, кривые ответы |
| LLM-as-judge | Вторая (обычно сильнее, от другого вендора) модель оценивает выход по рубрике | Открытые выходы, тон, полезность, многокритериальное качество | Средне ($) | Регрессии качества, тонкий дрейф, поломки персоны |
| Ревью человеком | Реальный человек оценивает выборку | Калибровка эталона, калибровка модели-судьи, новые модели отказа | Дорого ($$$) | Всё остальное; пол, относительно которого вы калибруете остальные формы |
Ошибка — выбрать одно и считать достаточным. Строковые совпадения почти бесплатны, но почти ничего не говорят о том, хорош ли выход — только о том, что он не катастрофически сломан. LLM-as-judge ловит нюансы, но наследует биасы и моды отказа своей модели. Ревью человеком — единственный честный ответ на «это вообще хорошо?», но не масштабируется до CI. Зрелые eval-сьюты слоят все четыре: дешёвые проверки гейтят каждый прогон, LLM-судьи сэмплируют процент, люди калибруют судью против отложенного золотого набора с квартальной периодичностью.
Четыре слоя evals
Ловушка, в которую я наблюдаю команду за командой, — думать, что eval — это одна вещь. Это как минимум четыре, и каждый слой ломается по-своему, если его пропустить. Фрейм параллелит пять слоёв контекста намеренно — читатели, усвоившие тот фрейм, могут пользоваться им и здесь.
Capability evals. Делает ли сама модель нужное вообще, в изоляции? Это те evals, которые гоняют Anthropic и OpenAI, чтобы решить, может ли новая модель заменить предыдущую. Вы их не пишете. Вы их потребляете — и обращаете внимание, когда model card публикует оценки, материально сдвинувшиеся на бенчмарке, близком к вашему случаю. Capability evals — это нулевой этаж. Если модель не может задачу сама, никакой контекст-инжиниринг не спасёт.
Behavior evals. Учитывая ваш промпт и ваш контекст, выдаёт ли модель нужную форму? Это слой, на котором останавливается большинство команд, и он самый дешёвый. Behavior evals ловят «в JSON правильные поля», «отказ срабатывает, когда должен», «модель выбирает инструмент A, а не B». Если гоните только один слой — гоните этот. Но behavior evals недостаточно — они верифицируют форму, не суть.
System evals. Даёт ли вся пайплайн — retrieval, планирование, tool-вызовы, история, суммаризация, отказ, всё, — правильный end-to-end результат на реалистичном входе? System evals — там, где живёт большинство реальных багов. Retrieval вернул не тот чанк. Сумматор истории выкинул ограничение. Планировщик вызвал нужный инструмент с неверными аргументами. Behavior eval на каждом компоненте прошёл; end-to-end поведение упало. Большинство команд никогда не гоняли system eval. Это видно.
Regression evals. Когда что-то меняется — правка системного промпта, новый инструмент, бамп версии модели, ребилд retrieval-индекса, твик Claude.md — какие ранее проходившие примеры теперь падают? Regression evals — это слой, ловящий «отгрузили правку промпта во вторник и тихо сломали 12% клиентских флоу». Без regression evals вы не знаете, что сломали ваши изменения. Узнаёте от пользователей. Потом узнаёте, что изменение, которое вы обвиняете, — не то, которое сломало, потому что за неделю отгрузили три изменения. Regression evals — единственный самый высокорычажный слой, чтобы добавить, если его нет.
Паттерн: большинство команд делают частичные behavior evals, никаких system evals и ад-хок regression. Команды, отгружающие надёжные AI-фичи, делают все четыре, с чёткой историей владения каждым.
Четыре сложные проблемы eval-инжиниринга
Намеренно отзеркаливая фрейм контекст-инжиниринга: дисциплина сводится к четырём проблемам, всплывающим на каждой нетривиальной AI-фиче. Ни одна не решается добавлением eval-кейсов. Все четыре — системно-инженерные.
Покрытие: как вы знаете, что ваш eval-набор представляет то, что реально делают пользователи?
Eval-набор, который вы написали на первый день, основан на входах, которые вы вообразили, что пользователи будут слать. Реальные входы отличаются способами, которые вы не предвидели — другая длина, другие языки, другая вежливость, другие попытки сломать систему, другие домены, о которых вы не думали. Eval-набор, не отражающий продакшен-трафик, — это декорация.
Команды, которые это решают, относятся к курированию eval-набора как к продолжающейся data-pipeline задаче. Санитизированные продакшен-промпты непрерывно сэмплируются в набор. Краевые случаи, однажды сломавшиеся, закрепляются. Набор растёт; старые кейсы прунятся, когда перестают быть репрезентативными; покрытие меряется против реального распределения трафика. Команды, которые так не делают, пишут двадцать кейсов на первый день, отгружают и удивляются, когда система ломается на двадцать первом.
Стабильность: как отличить реальную регрессию от шума?
Недетерминированная система даёт разные ответы на каждом прогоне. Ваш eval-скор будет плавать даже без изменений под капотом. Часть этой флуктуации — бессмысленная дисперсия; часть — передний фронт реальной регрессии, которую надо ловить. Разделять эти две вещи труднее, чем кажется.
Ответ статистический, не алгоритмический. Прогоните каждый eval-кейс N раз (5–20 в зависимости от стоимости), агрегируйте и берите pass-rate (не pass/fail) как метрику. Ставьте пороги, держа в уме дисперсию: переход с 95% на 92% за один прогон — шум; устойчивый переход с 95% на 85% за три прогона — регрессия. Это ближе к дисциплине A/B-тестов, чем к дисциплине юнит-тестов. Инженеры, которые раньше не делали experiment design, находят этот кусок самым неудобным.
Стоимость: как гонять тысячу evals и не разориться?
Каждый eval-прогон — это один или больше вызов модели. Серьёзный eval-сьют — скажем, триста кейсов, пять сэмплов на каждый, LLM-as-judge сверху — это полторы тысячи вызовов модели за прогон, плюс по два на кейс (тестируемая система плюс судья), итого три тысячи вызовов. По реалистичным ценам 2026 это нетривиальный счёт за CI-билд. Прогоняйте на каждом PR — и к концу квартала получите вопрос от финансов.
Зрелые команды тиерят сьют: маленький smoke-набор гоняется на каждом PR, полный сьют — ночью на main, самый большой LLM-судья сэмпл — еженедельно. Критические пути получают больше сэмплов; long-tail кейсы — меньше. Стоимость — это бюджет, которым явно управляют так же, как минутами CI. Команды, которые не тиерят, либо не гоняют ничего, либо бессмысленно жгут деньги.
Дрейф: что происходит, когда ваши золотые ответы устаревают?
Ответ, верный в феврале, может быть неверен в мае, потому что продукт изменился, данные изменились, политика изменилась или мир изменился. «Налоговая ставка прошлого года» больше не правильный ответ. «CEO компании X» обновляется без предупреждения. Ваш eval-набор гниёт, если его не поддерживать. И гниль невидима, пока проходящий eval на самом деле не тестирует неверное поведение.
Дисциплина двуединая: где можно — пиньте золотые ответы к дате и источнику, и ревьюйте eval-набор по расписанию. Последнее звучит занудно; так и есть. Это также единственный способ держать набор честным. Считайте поддержку eval-набора повторяющейся инженерной строкой бюджета, а не разовой инвестицией.
Пять правил, выученных в продакшене
Пронумерованы, потому что заработаны, а не выведены.
1. Реальные промпты, никогда не синтезированные. Самая частая ошибка, которую я вижу, — команды наполняют eval-набор промптами, которые написали сами, в голосе, которым, как они воображают, говорят пользователи. Реальные пользователи так не говорят. Они опечатываются. Вставляют markdown. Включают нерелевантный контекст. Обрывают предложения на полуслове. Eval-набор, построенный из воображаемых входов, рассказывает о воображаемой системе, не о вашей реальной. Всегда засевайте набор санитизированным продакшен-трафиком. Всегда.
2. LLM-as-judge нужна другая модель. Соблазн — оценивать выход Claude с помощью Claude. Дешевле и промпт знакомый. Это также обратная связь, льстящая вашей системе. Используйте другую модель, идеально от другого вендора, для судьи — а на evals с высокими ставками используйте модель сильнее той, которую оцениваете. Та же семья, оценивающая себя, ловит форму, не суть. Кросс-вендорное оценивание ловит вещи, в которых семья коллективно плоха.
3. Считайте eval-дрейф багом, а не шумом. Когда ранее проходивший eval начинает падать без изменения кода, ленивая реакция — повторить, увидеть, что прошёл, и пройти мимо. Взрослая реакция — расследовать. Что-то сдвинулось — модель за API, ваш retrieval-индекс, апстрим-зависимость. «В следующий раз прошёл» — не закрытый тикет. Тихо деградирующие продакшен AI-фичи почти всегда сперва выглядят как тихий eval-дрейф; команда, научившаяся гоняться за дрейфом, ловит инциденты на три недели раньше команды, которая нет.
4. Гоняйте regression evals на изменениях промпта и контекста, а не только при свопе модели. Большинство команд с хоть какой-то регрессионной дисциплиной гоняют её только при смене версии модели. Правка системного промпта в два слова может уронить тридцать evals — и уронит. Новый инструмент в тулбоксе может сломать tool-routing на входах, не имеющих к нему никакого отношения. Реорганизованный AGENTS.md может изменить, как модель интерпретирует каждый промпт. Считайте каждое изменение в контекстном пайплайне кандидатом на регрессию и гейтите его eval-сьютом так же, как гейтите код тестами.
5. Evals принадлежат CI. Если они не блокируют, они декорация. Ночной eval-отчёт, который никто не читает, — не eval-сьют. Дашборд с красными квадратами, который всё равно отгружается, — не eval-сьют. Весь смысл evals в том, что они предотвращают попадание регрессий в продакшен — а значит, должны блокировать. Да, это тяжело. Да, дисперсия делает это тяжелее. Да, вопрос стоимости реален. Решайте эти проблемы вместо проблемы «убрать гейт». Команда, которая не гейтит, делает eval-театр, не eval-инжиниринг.
Где это всё-таки ломается
Я бы продавал что-то, оставив только это. Evals необходимы; они не достаточны; и есть реальные случаи, где дисциплина не применяется чисто.
- По-настоящему открытые выходы. «Напиши стих о потере». Рубрики нет. LLM-as-judge может оценить тон и соблюдение ограничений, но не может оценить хороший стих. Для таких поверхностей evals ловят пол (безопасность, формат, длина), а потолок принадлежит людям. Притворяться иначе — это evals, оценивающие среднее и наказывающие исключительное.
- Многоходовые root-cause задачи. Семиходовой агентский ран падает на ходу седьмом. Причина — ошибка состояния на ходу втором. Eval флагит падение на седьмом, но дифф между проходящим и падающим трейсом зарыт на пять ходов вглубь. Нужны trace-level evals — оценивающие пайплайн, не только финальный выход, — и у большинства команд нет тулинга. Честный ответ в 2026 — тулинг multi-turn evals ещё изобретается; ждите, что поле инвестирует туда дальше.
- Стоимость на самых больших сьютах. Серьёзный eval-сьют серьёзного AI-продукта может стоить дороже за CI-прогон, чем весь остальной CI. Хитрого трюка, который это уберёт, не существует. Стоимостью управляют тиерами, сэмплингом и бюджетной дисциплиной — или принимают, что покрытие ограничено счётом.
- Eval-набор как продукт. Сам eval-набор становится штукой, которую вы владеете, версионируете, ревьюите и поддерживаете. Это ещё одна кодовая база, спрятанная внутри вашей кодовой базы. Команды, не относящиеся к этому серьёзно, кончают папкой с протухшими ассертами, которую все ненавидят гонять. Команды, относящиеся к eval-набору как к первоклассному артефакту — владеемому, ревьюимому, рефакторимому, — получают компаундящуюся отдачу.
Честная рамка: evals не подлежат обсуждению для отгружаемых AI-продуктов в 2026, и они тяжелее, чем звучат. Команды, владеющие дисциплиной, обгоняют команды, не владеющие, не потому что инженеры лучше, а потому что они на самом деле знают, что отгружают.
Карьерный угол: eval-инженер — новая роль
Три слоя лестницы, три разные ставки.
Джуниоры. Самый быстрый способ стать полезным на AI-команде — вызваться владеть eval-набором. Никто не хочет. Работа неблагодарная. Это также то место, где вы учите систему, обнаруживаете реальные моды отказа, и где сеньоры заметят вашу работу, потому что вы ловите их баги раньше пользователей. Инженер, который пришёл на первом году и построил реальный eval-сьют для реальной фичи, делает более полезную работу, чем инженер рядом, отгрузивший вдвое больше строк агентского кода. Рычаг компаундится так же, как с тестами, только сильнее, потому что цена пропущенной регрессии выше.
Мид-левелы. Карьерный риск реален. Если последние три года вы становились лучше в написании AI-фич и пропустили eval-дисциплину — вы инженер хуже, чем думаете. Восстановительный ход — взять самую флаки AI-фичу на команде и владеть её eval-сьютом end-to-end на квартал. За три месяца eval-работы вы выучите о продакшен-AI больше, чем за год фича-работы. Вы также будете единственным человеком на команде, который умеет ответить «оно работает?» чем-то кроме вайбов — а это вопрос, который задают в комнатах, где случаются повышения.
Сеньоры и стафф. «Покажите ваш eval-сьют» — это новое «покажите ваш test coverage». Это вопрос, который я теперь задаю на каждом AI-инженерном собесе, и качество ответа говорит о кандидате больше, чем любой другой сигнал. На вашем уровне работа не в написании evals — в владении дисциплиной. Установить планку, что блокируется. Построить кросс-функциональную мышцу, чтобы держать human review в петле. Убедить финансы профинансировать eval-счёт. Договориться с продактом отгружать с гейтом по pass-rate evals, а не по дате запуска. Это политические и архитектурные задачи, замаскированные под задачи тестирования, и именно это работа, за которую платят сеньорам.
Рынок не догнал. Число инженеров, способных построить серьёзный eval-сьют для агентской системы, достаточно мало, чтобы хайринг-менеджеры, с которыми я говорю, описывали это как навык в однозначных процентах. Премия будет уменьшаться, по мере того как дисциплина становится стандартной практикой, тем же путём, что юнит-тестирование между 2005 и 2015. Окно, где этот навык редок, — это примерно сейчас — восемнадцать месяцев, два года потолок.
Более глубокая мысль
Спека — это истина. Контекст — это сборка. Evals — это доказательство.
Это три разных артефакта, три разные дисциплины, три разные группы мышц. Зрелый AI-инжиниринг 2026 делает все три. Команды, с которыми я работаю и которые делают только одно, отгружают демо. Команды, делающие два, отгружают продукты, тихо деградирующие. Команды, делающие все три, отгружают продукты, которые продолжают работать — что оказывается единственной фичей, которую может различить кто-либо вне инженерки.
Рамка, которую я дольше всего внутренне принимал, такая: в недетерминированной системе тест-сьют — это то, что делает систему реальной. Без evals ваша AI-фича — это среднее трёх демо и ваша надежда. С evals — это система, которую вы реально понимаете. Разница — это разница между инженером и экскурсоводом.
Если хотите глубже, курсы ниже покрывают части дисциплины, которые я преподаю чаще всего: Building LLM-Powered Apps: RAG & Agents для дизайна system-evals по retrieval и агентским пайплайнам, Building with Claude API: Production AI Apps with the Anthropic SDK для продакшен-рантайма, где evals живут в CI, Building Agents with the Claude Agent SDK для тулинга multi-turn агентских evals, и Claude Code Mastery: Agentic Coding for Engineers для ежедневного воркфлоу обращения с eval-сьютом как с первоклассным артефактом рядом со спекой и контекстным пайплайном.