Код правильный, но неряшливый: как измерить slop в AI-коде
LLM уже почти идеально пишут корректный код — но формальная правильность не означает, что код хороший. Модели вводят ненужные абстракции, дублируют логику и принимают сомнительные решения, а каждая новая фича в vibe-coded проекте может взрывным ростом раздувать кодовую базу. Себастьян из Earendil (компании, стоящей за coding-агентом Pi) получил задачу разобраться, как измерять неряшливость кода, — и честно делится выводами: индустрия оценивает «slop» почти исключительно на глаз, но количественные метрики существуют, и они показывают, что код агентов примерно вдвое грязнее человеческого.
Корректность проверить легко, вкус — нет
Почему модели так сильны в правильности кода? Код масштабируемо верифицируется: генерируем — прогоняем через скрытые тесты — получаем чёткий сигнал вознаграждения. А вот неряшливость автоматически поймать почти невозможно: её оценка требует человеческой интуиции и вкуса. Автор пришёл к задаче с физическим бэкграундом и планом сначала изучить литературу и практики других компаний — и был разочарован тем, насколько всё «vibes-based»: вместо методик сплошные маркетинговые слоганы вроде «End-to-end coding agents» и «Human-level evaluation without human-level cost».
Три способа измерения — и у каждого звёздочка
AI как судья. Самый распространённый подход в индустрии и, по наблюдениям автора, почти не работает. Наивный вариант — попросить модель оценить код по шкале от 1 до 10 — по сути эквивалентен генератору случайных чисел. Более изощрённый — дать судье два решения A и B и спросить, какое лучше, — страдает от того, что модель меняет предпочтение при переименовании решений. У больших моделей эффект слабее, но суть не меняется: просьба к LLM оценить собственный код — не замена нормальной оценке. Направления с рубриками и тестами, которые пишет сама модель, интересны, но до реальной борьбы со slop им пока далеко.
Человек оценивает AI. Идеальный способ гарантировать читаемость кода людьми — с поправкой на огромный разброс в качестве самих инженеров. Минус очевиден: не масштабируется ни для обучения моделей, ни для больших бенчмарков с множеством провайдеров.
Простейший метод. Обычный прирост числа строк (LOC) в исследованиях автора оказался на удивление эффективной метрикой неряшливости — с ироничной оговоркой: если начать оптимизировать под неё, она перестанет быть осмысленной, работает закон Гудхарта. Впрочем, старая поговорка предупреждала об этом давно: «Измерять прогресс программирования строками кода — как измерять прогресс строительства самолёта его весом».
Verbosity и Erosion: две метрики из SlopCodeBench
Две более строгие метрики автор позаимствовал из работы SlopCodeBench — они хорошо отделяют зрелые кодовые базы от LLM-slop.
Verbosity измеряет объём дублирующихся и избыточно многословных строк — как долю от всех строк кода:
Verbosity = |AST-Grep flagged lines ∪ clone lines| / LOC
Правила поиска проблемных строк — набор ручных эвристик, реализованных через AST-Grep, — что само по себе подчёркивает человеческий элемент в любой такой оценке.
Erosion измеряет, какая доля массы кодовой базы сконцентрирована в немногих больших и сложных функциях. Масса функции — это цикломатическая сложность, умноженная на квадратный корень из числа строк:
mass(f) = CC(f) · √SLOC(f)
Erosion = Σ mass(f) [f: CC(f) > 10] / Σ mass(f) [all f]
Иначе говоря, эрозия — это отношение массы функций с цикломатической сложностью больше 10 к массе всех функций кодовой базы.
Числа говорят сами за себя. В установившихся репозиториях средняя Verbosity составляет 0,15 ± 0,06, у кода, сгенерированного агентами, — 0,33 ± 0,10. По Erosion: 0,31 ± 0,17 у репозиториев против 0,68 ± 0,20 у агентов. Код агентов в среднем примерно вдвое более многословный и «эродированный». Автор проверил метрики на собственных vibe-coded проектах: Verbosity доходила до 0,4, а Erosion — до 0,75, так что результат не артефакт устройства бенчмарка. Любопытная деталь: один широко известный «vibey» open-source проект набрал неожиданно мало по обеим метрикам — вероятно, из-за сильной связанности функций и огромной массы разнородного кода, которые снижают средние значения.
Почему агенты не разберутся со slop сами
Отдельная деталь в устройстве SlopCodeBench объясняет, почему агенты сами не справляются со своим мусором. В отличие от обычных кодинг-бенчмарков, где агент получает полный список инструкций в начале, а в конце его ждут скрытые тесты, здесь всё наоборот: проводится несколько раундов «инструкция → тест», причём между чекпоинтами контекст модели стирается. Это намного точнее имитирует итеративный процесс — то, как coding-агенты реально используются людьми.
Результат: плохие решения накапливаются со временем, и по строгому критерию «все тесты пройдены на всех чекпоинтах» даже передовые модели показывают 0% (тестировались GPT 5.6 sol xhigh и подобные модели; Fable 5.1 и Astra пока не проверяли). Обычные оговорки про слишком строгие тесты и двусмысленные формулировки задач в силе, но общий тренд очевиден. И это должно стать предупреждающим знаком для всех, кто радостно добавляет в проект десятки и сотни тысяч строк в день.
Что дальше
Среди перспективных направлений автор называет coupledness (связанность функций), code churn, cohesion и другие метрики. Если вы работаете над evals и хотите обсудить тему, он открыт к разговору: sebastian@earendil.com.