← Назад в лабу

Граф кода не сделал моего агента дешевле

benchmarkmcpcoding-agentsevals

К этому бенчмарку меня вернули два числа. README codebase-memory-mcp — графа кода на tree-sitter, который отдаётся по MCP, — обещает на 99 % меньше токенов. Мой собственный прошлый прогон говорил, что cbm-lean, тонкая обёртка, которую я написал вокруг него, делает агента на 26 % дешевле обычного grep на haiku и на 18 % дешевле на sonnet. Первое число мне так и не удалось воспроизвести, а второе получилось из-за изъяна в моей постановке. Это повторный прогон на открытых репозиториях, с исправленным изъяном.

Постановка

Каждый вопрос прогонялся в трёх вариантах:

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

Репозитории такие: три небольших (шаблон FastAPI full-stack, ltx-2-mlx и avoid-ai-writing, от 1,6 тыс. до 5 тыс. узлов графа) и dub, монорепозиторий на Next.js с 25 тыс. узлов. Haiku 4.5 прошёл по всем, sonnet 5 — по dub: 252 запуска, $14,69 по ценам API.

Стоимость измеряется как tokenEquiv: входные токены, плюс 1,25 × записи в кеш, плюс 0,1 × чтения из кеша. Сырой оплаченный вход вводит в заблуждение, когда включено кеширование промптов: вариант, которому повезло попасть на прогретый кеш, выглядит дешёвым по причинам, не связанным с самим вариантом.

Результаты

Медианный tokenEquiv на запуск, в скобках — число правильных ответов:

условиязапусковcbm-leanсырой графgrep
Малые репозитории, haiku 4.510830 321 (28/36)43 846 (32/36)31 159 (33/36)
dub, haiku 4.57218 791 (22/24)20 687 (22/24)14 955 (20/24)
dub, sonnet 57217 227 (22/24)23 085 (22/24)13 348 (22/24)

Три результата выдерживают проверку:

Значения p получены знаковым ранговым критерием Уилкоксона по медианам для каждого вопроса.

Где ошибался каждый вариант

Подключить граф — не значит им пользоваться

Самый полезный результат дал пилот, а не основной прогон. Claude Code 2.1.283 по умолчанию прячет схемы MCP-инструментов за шагом ToolSearch: модель видит имена инструментов и должна загрузить схемы, прежде чем что-то вызвать. Haiku в headless-режиме этого не делал. В шести пилотных запусках граф не был вызван ни разу, с правилом маршрутизации или без него. На двенадцати вопросах по небольшим репозиториям:

конфигурациявызвал графверномедиана tokenEquiv
Загрузка по умолчанию, с правилом2 из 1211 из 1241 008
Схемы загружены, без правила4 из 129 из 1262 008
Схемы загружены, с правилом22 из 3628 из 3630 321

С загруженными схемами (ENABLE_TOOL_SEARCH=false) тот же вопрос о вызывающих функциях прошёл через два вызова графа за три хода. Подключённый граф без правила оказался самой дорогой конфигурацией из всех: каждая сессия платит за схемы, а модель в основном оставляет их без дела.

Если вы выпускаете MCP-сервер и тестируете его с настройками по умолчанию, сначала проверьте, вызывает ли его модель вообще.

Почему прежнее число было неверным

Первый бенчмарк шёл внутри моей папки с проектами. Её CLAUDE.md велел агенту использовать граф для структурных вопросов, а Claude Code подгружает файлы CLAUDE.md из родительских каталогов, поэтому эта инструкция дошла до каждого варианта, включая тот, где графа не было. Контрольная группа получила инструкции экспериментальной, а значит, сравнение измеряло правило не меньше, чем инструменты.

Повторный прогон держит репозитории вне любых деревьев, над которыми лежит CLAUDE.md, пропускает пользовательские настройки и хуки (--setting-sources project) и даёт правило только вариантам, у которых есть граф. Каждый из остальных контролей исправил неверный вывод в одном из прошлых раундов. Bash и Agent запрещены во всех вариантах, потому что ограниченные разрешения Bash не совпадают с командами через конвейер, а субагенты прячут ходы, хотя токены всё равно тратят. Порядок вариантов меняется между повторами, так что ни один вариант не идёт всегда на прогретом кеше. Запуск, который вызывает инструмент чужого варианта, отбрасывается. И ответы проверяются, потому что токены, сэкономленные на неверном ответе, — не экономия.

Что я сказал бы команде, которая подключает граф к агенту

Ограничения

Две модели, четыре репозитория до 25 тыс. узлов, два или три повтора, по двенадцать вопросов на каждый. Ни Opus, ни долгих интерактивных сессий, ничего больше 25 тыс. узлов. Приведены медианы, потому что повторные запуски одного и того же вопроса сильно различались.

Воспроизвести

Всё лежит в code-graph-vs-grep: вопросы с закреплёнными коммитами, драйвер бенчмарка, сырые запуски со всеми ответами и сам cbm-lean.

bash bench/setup.sh
node bench/run.mjs --reps 3
python3 bench/stats.py results/*.json