Когда в апреле мы опубликовали предыдущий пост в блоге о нашем ИИ-ревьюере кода, средняя стоимость ревью составляла приемлемые 1,19 доллара. К концу августа эта цифра выросла примерно до 2,46 доллара. Мы не вносили никаких существенных архитектурных изменений: координатор по-прежнему передавал работу тому же набору специализированных ревьюеров, а уровни риска определяли степень интенсивности проверки.
Примерно в середине сентября мы поставили перед нашими агентами задачу выяснить, куда уходят эти токены, и сократить их — агрессивно. При высоком уровне качества кода средняя стоимость ревью теперь составляет всего 0,77 доллара, что на 68% меньше по сравнению с 2,43 доллара — средним показателем за две наши самые дорогие недели до начала работ. Нашей главной целью было снижение затрат, но в рамках этой работы нам также удалось оптимизировать ревьюер, так что теперь медианное время ревью составляет всего 1 минуту 32 секунды вместо 4 минут 9 секунд ранее.
Около 40% экономии было достигнуто за счет изменений и оптимизации кода ревьюера, а остальное — благодаря экспериментированию с используемыми моделями и уровнем их ресурсоемкости.
Как ревью подорожало вдвое
На графике ниже показана стоимость среднего ревью по дням недели начиная с марта. Соотношение уровней ревью зафиксировано, поэтому дни с большим количеством крупных ревью не искажают данные.
Стоимость одного ревью неуклонно росла: от 1,22 долл. (март) → 1,44 долл. (июнь) → 1,74 долл. (июль) и, наконец, до 2,32 долл. (август). Небольшая часть этого связана с тем, что большее количество ревью попало в самый дорогой уровень (59% ревью в марте и 65% в августе). Мы считаем, что этому есть простое объяснение: модели становятся намного лучше и функциональнее. Естественно, инженеры создают более масштабные и сложные изменения, а значит, большее их число попадает в категорию «полного ревью». Тем не менее, мы обнаружили, что основная часть роста затрат на самом деле была связана с изменением моделей в течение этих месяцев.
В начале августа мы перевели всех ревьюеров на модели Anthropic, что увеличило стоимость одной задачи с 1,38 до 2,03 доллара. Мы сделали этот выбор, потому что в ходе оценочного тестирования модели Anthropic показали себя лучше на этой конкретной рабочей нагрузке, чем другие модели.
Наш внутренний проверяющий стандартов, Codex, в итоге перешел на Claude Opus 4.7 из-за сочетания производительности и надежности. Из-за этого его стоимость выросла примерно с 0,25 доллара за ревью до 0,88 доллара в августе, что сделало его дороже самого агента-координатора.
Коэффициент попадания в кэш также увеличился: с 85,7% в апреле до 97% к сентябрю, в то время как количество токенов на одно ревью увеличилось более чем в три раза — с 0,91 млн до 2,99 млн. Высокий процент попадания в кэш при трехкратном увеличении числа токенов все равно обходится значительно дороже, даже с учетом низкой стоимости чтения из кэша.
Что еще изменилось со времени нашей последней публикации?
Одно из самых больших изменений заключается в том, что ревьюер теперь работает на OpenCode v2, что представляет собой полную переработку с нуля по сравнению с v1. Перед тем как полностью перевести все ревью с v1 на v2, мы запустили каждое ревью в каждом тестовом репозитории как на v1, v2 в сравнительном теневом режиме. В 98% протестированных пулл-реквестов мнения обеих версий относительно решения об одобрении совпали, поэтому в начале октября мы перевели всех пользователей за один раз и удалили код v1. При сравнении двух дней с одинаковыми моделями ревью полного уровня на v2 выполняются примерно на 13% быстрее. В настоящее время мы также экспериментируем с другими способами запуска нашего внутреннего ИИ-ревьюера, в том числе исключительно на Durable Objects с использованием pi-durable. Надеемся в скором времени поделиться новыми подробностями, так что следите за обновлениями!
Итак, куда же девались токены?
Прямо перед тем, как мы сосредоточились на оптимизации затрат, наши расходы на ИИ-ревью распределялись следующим образом: выходные токены составляли около 23%, затраты на запись в кэш — 43%, а затраты на чтение из кэша — 34%. Это означает, что большая часть денег уходила на контекст, который модель уже видела или собиралась увидеть снова.
Это абсолютно логично, если углубиться в отдельную сессию. Ревьюер качества кода делал в среднем 16,6 вызова большой языковой модели (LLM) на одно ревью, и за эти вызовы он записал в кэш 72 тыс. токенов и прочитал обратно 1,08 млн, поскольку каждый вызов отправляет весь разговор в качестве контекста. Стоимость сессии растет как с увеличением количества вызовов, так и с увеличением размера контекста, и за последние несколько месяцев мы постепенно увеличили оба параметра.
Стоит потратить несколько минут, чтобы почитать о том, как работает кэш промптов Anthropic. Он работает путем кэширования частей промпта, которые уже были вычислены большой языковой моделью (LLM). Они известны как префиксы, поскольку они работают только с сообщениями в начале разговора, а не в середине или в конце. Это означает, что будущий запрос может повторно использовать более ранний префикс вплоть до той части разговора, которая отличается от того, что было закэшировано. В нашем случае инструменты окружения, системный промпт и сообщения в начале сессий нашего ИИ-ревьюера редко меняются, поэтому они являются отличными кандидатами для кэширования префиксов. Префикс сохраняется только там, где его завершает точка останова кэша. Запись в кэш стоит в 1,25 раза дороже обычной цены ввода, а чтение — в 0,1 раза, при этом запись истекает через пять минут, если к ней никто не обращается.
Это означало, что у нас было две задачи: сделать так, чтобы первый запрос каждой сессии читал данные из кэша, а не записывал в него, и сделать так, чтобы в каждой сессии использовалось меньше вызовов.
Совместное использование закэшированного префикса для каждого репозитория
Начиная с 14 сентября ревьюер фиксировал использование токенов для каждого первого вызова LLM ревьюером, а также хэш первого системного блока в том виде, в котором он был отправлен провайдеру.
Данные показали, что первый запрос сессии обнаруживал закэшированный префикс лишь в 14–26% случаев. Каждая сессия начинается с одних и тех же определений инструментов и одного и того же промпта агента, что составляет от 11 тыс. до 21 тыс. токенов, которые абсолютно идентичны в каждом проверяемом репозитории, поэтому почти все они должны были приводить к попаданию в кэш.
Проблема заключалась в том, как OpenCode v1 формировал системный промпт: он создавал один блок, содержащий промпт нашего агента, за которым следовал раздел окружения с рабочей директорией и датой, и помещал единственную точку останова кэша в конец этого блока. Общая часть никогда не сохранялась отдельно, поэтому ревью в одном репозитории никогда не могло повторно использовать то, что было записано ревьюером в другом.
16 сентября мы добавили маркер в конец каждого промпта агента и хук плагина, который разделял блок на две части по этому маркеру. Первая половина теперь заканчивалась байтами, общими для всех заданий, и получала собственную точку останова. Чтобы сохранить это состояние, нам пришлось убрать все специфичные для репозитория элементы из начала, поэтому список доступных навыков был отключен, а описания инструментов не могли меняться от задания к заданию.
В тот же день мы также перенесли справочный индекс (таблицу внутренних стандартов, файл навыков и список справочных файлов) нашего внутреннего проверяющего стандартов (Codex) в его промпт. До этого каждая сессия тратила первые три хода на чтение этих файлов с помощью вызовов инструментов. Количество вызовов LLM на один запуск сократилось с 15,9 до 9,6, а стоимость одного запуска упала с 1,12 до 0,72 доллара.
В совокупности это снизило стоимость одного ревью с 2,47 до 2,02 доллара, и падение стало заметно сразу же после того, как мы запустили релиз.
Меньше вызовов, меньше затрат
Следующий набор изменений был выпущен 21 и 23 сентября. Сами по себе они не были особенно впечатляющими, но в совокупности они позволили сэкономить около $0.20 на каждом ревью.
Изменение
Что происходило
Эффект от изменения
Удаление инструментов, которые рецензенты не могли использовать
Суб-рецензенты могли видеть инструмент, публикующий финальный комментарий к ревью. В 57% — 76% сессий они пытались вызывать его, получали отказ при проверке на сервере и тратили еще один вызов на восстановление
Один пустой вызов исчез, а в каждый запрос суб-рецензента стало передаваться примерно на 2.9 тыс. токенов определений инструментов меньше
Параллельное чтение файлов
В 64% обращений рецензента качества кода модель делала ровно один вызов инструмента, обычно для чтения одного файла
Рецензенты читают общий контекст и все свои патчи в первом ответе, объемом до 150 КБ
Пропуск рецензентов при повторных ревью
Около двух третей наших задач — это второе или последующее ревью того же запроса на слияние, и часто трем рецензентам больше не на что смотреть.
При повторных ревью полного уровня ревью AGENTS.md пропускаются в 56% случаев, проверки производительности — в 23%, а проверки документации — в 13%.
Остановка после публикации ревью
OpenCode возвращал результат модели еще на один шаг, в ходе которого весь диалог читался заново ради написания никому не нужной саммари.
Экономия около $0.07 на задачу
Разделение медленного рецензента и неработающего провайдера
Рецензент, исчерпавший лимит времени, обрабатывался как сбой провайдера и запускался заново с тем же лимитом времени.
В сочетании с увеличенными лимитами времени и меньшими затратами усилий тайм-ауты рецензентов безопасности сократились с 1.8% запусков практически до нуля
Отмена отмененных задач
Kubernetes-исполнитель GitLab не отправляет сигнал скрипту задачи при ее отмене. В выборке из 446 отмененных задач 358 продолжали выполняться до окончания ревью.
Задачи проверяют собственный статус каждые 15 секунд и останавливаются в случае отмены
Самым сложным изменением было объединение одного префикса для трех рецензентов. Рецензенты качества кода, безопасности и производительности теперь отправляют идентичные первые запросы с одними и теми же инструментами, общим файлом правил, а затем запросом на слияние, содержащим каждый патч. Инструкции каждого конкретного рецензента следуют после этого, и мы следим за тем, чтобы один из них записывал кэш, а два других читали из него.
Элемент кэша не может быть прочитан до тех пор, пока ответ, записавший его, не начал передаваться постримингово, а все три рецензенты запускаются одновременно. Поэтому второй и третий ждут начала ответа первого (до 20 секунд), прежде чем отправить собственный первый запрос. Это немного замедляет их и экономижает около девяти центов на каждого рецензента.
Изменение моделей и усилий
На следующем графике показана та же линия с начала сентября с отметкой каждого изменения.
Если разделить этот период по каждому релизу и каждому изменению конфигурации, изменения в коде окажутся меньшей частью экономии.
На изменения в коде приходится $0.65 из $1.67, а на изменения моделей и усилий — $1.06. Каждый шаг сравнивает часы будней до изменения с часами после него, так что это не является статистически строгим контролируемым экспериментом.
Координатор запускал три комбинации модели и усилий с августа. На той же модели задачи полного уровня со средним уровнем усилий завершались на 20% быстрее, поэтому мы отказались от двух других. В более позднем рандомизированном разделении модель Opus 5.5 со средним уровнем усилий не показала измеримых изменений в результатах ревью или критических замечаниях по сравнению с Opus 5, поэтому мы переключились на нее. Opus 5.5 с высоким уровнем усилий стоила дороже, чем Opus 5.5 со средним, при этом не давая значимого прироста в количестве найденных проблем.
Opus 5.5 обходится дешевле за токен, чем Opus 5, но цена обуславливает лишь около $0.20 от общего падения. Остальное достигается за счет отправки и генерации меньшего количества токенов. С начала сентября чтение кэша на одно ревью сократилось на 82%, запись в кэш — на 54%, а вывод — на 67%.
Самым последним изменением стала новая модель. 3 октября мы разделили всех рецензентов Sonnet 50/50 между Sonnet 5 и Sonnet 5.5. Спустя два с половиной дня модель Sonnet 5.5 оказалась на 62% дешевле в расчете на запуск для проверки качества кода, на 58% для производительности и на 47% для безопасности. Обе модели стоят одинаково за токен, так что вся экономия получена за счет использования меньшего количества токенов. На ревью полного уровня рецензенты версии 5.5 оставляли примерно столько же критических и предупреждающих замечаний, сколько и рецензенты Sonnet 5, поэтому 5 октября мы перевели их всех на версию 5.5.
На модели Sonnet 5.5 при среднем уровне усилий рецензент качества кода делает 1.7 вызова LLM на запуск вместо 6.2, причем более половины его запусков завершаются за один вызов, а это значит, что они не открывают никакой другой файл в репозитории. При высоком уровне усилий он делает 3.4 вызова на запуск. Мы опасались, что из-за этого ревью станут более поверхностными, что мы и рассматриваем в разделе о качестве ниже.
Чтобы проверить, приводит ли увеличение усилий к возвращению найденных проблем на более крупных уровнях, с 5 октября рецензент качества кода был разделен 50/50 между средним и высоким уровнями усилий на модели 5.5. Спустя один день высокий уровень усилий обходится на 61% дороже за запуск и генерирует на 58% больше критических и предупреждающих замечаний. Это примерно два цента на ревью, и приведенный ниже раздел о качестве показывает, что эти дополнительные замечания стоят того, поэтому мы переводим оценку качества кода на высокий уровень усилий. Показатели стоимости в этой публикации учитывают это.
Задержка
Мы не ставили целью ускорить ревью, но меньшее количество вызовов также означает меньше ожидания, что ведет к более быстрому проведению ревью и более довольным инженерам.
Самые медленные ревью улучшились сильнее всего. За четыре недели до 14 сентября 37.9% ревью занимали более пяти минут, а теперь — всего 0.7%. Сегодня 99-й перцентиль работает быстрее, чем три четверти ревью в апреле. Каждый уровень со временем ускорялся: медианное время полного ревью сократилось с 5м 16с до 1м 54с, облегченного — с 2м 58с до 1м 14с, а тривиального — с 77 секунд до 30.
К августу медианное время ревью было на 14% больше, чем мы фиксировали в апреле, а 99-й перцентиль — на 48% больше, поэтому значительная часть этой работы просто вернула нас на прежний уровень.
Качество ревью
Более дешевое ревью не имеет большой ценности, если оно также находит меньше проблем, и первый график здесь выглядит так, будто именно это и произошло.
С рецензентом качества кода на Sonnet 5.5 при высоком уровне усилий количество критических и предупреждающих замечаний снизилось на 40% по сравнению с концом августа. Для проверок безопасности и производительности, которые остаются на среднем уровне усилий, этот показатель упал на 56% и 71%. Само по себе уменьшение количества серьезных замечаний не говорит о том, пропускаются ли реальные проблемы или сокращается уровень шума, поэтому мы рассмотрели это с двух точек зрения.
Во-первых, мы проверили, принимают ли авторы меры на основе того, на что указывает рецензент. Для выборок критических и предупреждающих замечаний мы сравнили подвергшийся ревью коммит со следующим пушем автора и засчитали замечание как отработанное, если строки, на которые оно указывало, изменились. Строки на расстоянии от 30 до 40 от каждого замечания менялись примерно в 15% случаев в каждый период, что дает базовый уровень для правок, происходящих случайно.
До изменений авторы реагировали на 34% серьезных замечаний рецензента качества кода. Теперь этот показатель составляет 59%. Рецензент отмечает меньше проблем, но те, что он указывает, с гораздо большей вероятностью приводят к изменениям, поэтому количество замечаний, приведших к изменениям на 1000 рецензий, осталось примерно прежним. Теперь мы зафиксировали 132 против 145 ранее, что находится в пределах погрешности. По всем четырем рецензентам серьезные замечания, приведшие к изменениям, увеличились с 229 до 321 на 1000 рецензий.
Во-вторых, мы привлекли две модели от разных провайдеров для оценки ослепленной выборки из 657 замечаний от трех рецензентов Sonnet с приложенными diff-файлами, на которые ссылался каждый из них, без указания периода, к которому они относятся. Разногласия передавались третьей модели. Каждое замечание получило метку: важное, незначительное, дубликат, ошибочное или не подлежащее проверке, а его степень серьезности оценивалась как справедливая, слишком высокая или слишком низкая.
Большая часть исчезнувших замечаний представляла собой незначительные проблемы, а также дубликаты и замечания, которые эксперты не смогли проверить по diff-файлу. Количество важных замечаний на одну рецензию изменилось с 0.28 ранее до 0.30 теперь, и интервалы пересекаются. Более значительное изменение коснулось степени серьезности. Ранее эксперты оценивали 0.46 критических замечаний или предупреждений на одну рецензию как более серьезные, чем они того заслуживали. Теперь этот показатель составляет 0.14, что означает снижение на 70% и является самым наглядным результатом исследования. Значительная часть падения числа критических замечаний связана с тем, что рецензент перестал называть незначительные вещи критическими.
Таким образом, ответ зависит от рецензента. Что касается качества кода при высоком уровне усилий, то исчезнувшие замечания в основном представляли собой шум и завышенную серьезность, при этом система по-прежнему находит примерно столько же реальных проблем, как и раньше. Средний уровень усилий действительно привел к потере реальных находок. При случайном разделении качество кода со средним уровнем усилий привело примерно к четверти от числа замечаний, на которые отреагировали при высоком уровне, именно поэтому мы переводим его на высокий уровень. Производительность также потеряла реальные замечания: эксперты обнаружили примерно на 64% меньше важных проблем с производительностью на одну рецензию, что на практике составляет примерно на одно важное замечание меньше на каждые 24 рецензии полного уровня. Безопасность снизилась примерно на четверть, хотя это статистически не значимо. Оба направления по-прежнему работают со средним уровнем усилий, и их тестирование на высоком уровне — следующий шаг.
Ни один из методов не идеален. Тот факт, что автор изменил отмеченные строки, доказывает лишь то, что он что-то сделал, а не то, что замечание было верным. Эксперты — это тоже модели, и в каждой группе насчитывается всего от 35 до 66 замечаний. Кроме того, окно «сейчас» охватывает всего один день. Тем не менее, оба метода согласуются друг с другом, и ни один из них не указывает на то, что качество кода находит меньше реальных проблем.
Надежность также осталась на высоте. Рецензии, завершающиеся без вынесения вердикта, сократились с 0.79% до 0.27%, а повторные попытки рецензента по безопасности — с 3.5% до 0.04%.
К чему мы в итоге пришли
Средняя стоимость одной рецензии теперь составляет $0.77 вместо $2.43, а медианное время ее завершения — 1 минуту 32 секунды вместо 4 минут 9 секунд. Главная единовременная экономия была достигнута благодаря проверке того, что реально доходило до провайдера при первом запросе в каждой сессии, и поиску способа упорядочить эти сообщения максимально согласованным образом для разных коммитов, запросов на слияние и репозиториев. Остальная экономия средств была получена за счет непрерывных экспериментов с различными моделями и сочетаниями усилий при одновременном отказе от любых предвзятых мнений в отношении конкретных моделей.
Более дешевые рецензии не означали автоматически худшее качество, но и не гарантировали идеальный результат. Качество кода при высоком уровне усилий находит примерно столько же реальных проблем, как и раньше, но с гораздо меньшим количеством шума и намного меньшим количеством завышенных степеней серьезности. Производительность потеряла реальные замечания при среднем уровне усилий, и безопасность, возможно, тоже, поэтому тестирование обоих направлений на высоком уровне — следующий шаг. Если вы запускаете агентов в каком-либо объеме, мы бы порекомендовали проверить в первую очередь две вещи: действительно ли первый запрос каждой сессии считывает данные из кэша и продолжают ли ваши рецензенты находить реальные проблемы на том уровне усилий, за который вы платите.
Если вы будете на конференции Cloudflare Connect в Сан-Франциско, я расскажу о том, как мы создали рецензента вместо того, чтобы покупать готовый, в рамках моего выступления It’s time to build, not buy во вторник, 20 октября, в 12:30 по тихоокеанскому времени. Я также буду находиться в лаунже для спикеров Speaker Connection с 13:10, если вы захотите задать вопросы по любым цифрам из этой статьи.

.png)








