grep, граф или LSP: что дешевле для контекста агента? 936 тестов | AiManual
AiManual Logo Ai / Manual.
24 Июн 2026 Гайд

grep, граф или LSP: что дешевле и точнее для контекста кодового агента? Результаты 936 прогонов на Apache Superset

Результаты 936 прогонов на Apache Superset: grep, граф или LSP — какой метод сбора контекста дешевле и точнее для кодового агента? Неожиданные выводы.

Реклама
cliv2

Кодовый агент — как подросток: без четкого контекста начинает нести чушь. Я потратил неделю на 936 прогонов, чтобы выяснить, какой метод кормить его дешевле и точнее. Спойлер: ripgrep не всегда ваш друг.

Вы замечали? Даёшь LLM задачу «найди баг в функции X», а она приносит три файла с упоминанием X, пропуская импорты и зависимости. Потом тратит $0.20 на перебор токенов. Или наоборот — загружает всю кодобазу, и счет на API взлетает до небес. В этом исследовании я загнал три актуальные модели (GPT-5, Claude 4, Gemini 2.5) через четыре инструмента сбора контекста на кодобазе Apache Superset (версия 4.3, ~2300 файлов, 340k строк кода). Всего 78 разнотипных задач — от «найди декларацию класса Chart» до «объясни цепочку вызовов при рендеринге дашборда». Итог — 936 замеров стоимости, точности и латентности.

Если хотите сразу увидеть сырые цифры и код бенчмарка — сравнение 21 инструмента далеко не убежало, но там без драмы.

Методология: как я убил неделю жизни

Четыре инструмента — четыре подхода к сбору контекста:

  • ripgrep — классический текстовый поиск regex с умными .gitignore и параллельными потоками.
  • Граф зависимостей — на основе AST со статическим анализом (pyright + graphlens). Каждый узел — функция/класс, ребро — вызов/импорт.
  • LSP — Language Server Protocol (python-language-server через MCP-сервер SocratiCode). Возвращает точные определения, ссылки, hover.
  • Семантический поиск — srag с эмбеддингами code-bert (модель jina-embeddings-v3 onnx).

На каждую из 78 задач (34 простых «найди декларацию», 28 средних «найди вызовы функции», 16 сложных «объясни поток данных между модулями») каждый инструмент передавал свой контекст каждой модели. Стоимость считалась по актуальным прайсам на 24.06.2026: GPT-5 — $2/M input, Claude 4 — $1.5, Gemini 2.5 — $0.75. Точность оценивал как F1-score (совпадение релевантных файлов с эталоном, составленным разработчиками Superset).

Инструмент Средний контекст (токенов) Латентность (мс) Требование
ripgrep~2 100120ничего
Граф зависимостей~8 400450AST + граф
LSP (MCP)~15 200670LSP сервер
Семантический~22 0002 100эмбеддинги

Средний контекст — размер возвращаемых данных, засунутых в промпт. ripgrep экономит, потому что возвращает только совпадающие строки и ближайшие 5 строк контекста. LSP разворачивает целые реализации. Граф — только имена и пути, но при типичном запросе «найди все места, где используется класс ChartStatus» граф приносит 40+ узлов с их описаниями.

Цифры не врут (ну, почти)

Обобщённые результаты по всем трём моделям (усреднённые значения F1-score и стоимость за запрос в $):

Тип задачи Инструмент F1-score Стоимость ($)
Простые (декларации)ripgrep0.920.002
Граф0.940.008
LSP0.970.015
Семантический0.740.021
Средние (вызовы)ripgrep0.610.003
Граф0.910.011
LSP0.950.018
Семантический0.550.025
Сложные (потоки данных)ripgrep0.330.004
Граф0.850.014
LSP0.890.021
Семантический0.420.030

Обратите внимание: ripgrep гениально дёшев и точен для простых задач — 0,2 цента при F1=0.92. Но как только задача пересекает границы одного файла, точность падает в полтора раза. LSP стабилен, но дорог. Граф — лучший тандем цена/точность для средних и сложных задач. Семантический поиск провалился везде — ну да, код это не текстовый документ, а граф с именованными функциями.

Важный нюанс. Выше — средние по трём моделям. Как и в статье Context Lens, Gemini сжирает токены в 15 раз быстрее Claude? У нас похожая картина: Gemini 2.5 на ripgrep-контексте даёт F1=0.88 на простых задачах, а Claude 4 — 0.93, но Gemini стоит втрое дешевле. Если ваш бюджет жёсткий — берите Gemini с ripgrep.

Разбор полетов: где кто облажался

ripgrep — скорость и дешевизна, но слепота к импортам

ripgrep прекрасен, когда нужно найти строку. Но он не знает, что class Chart это родитель для class BarChart. Запрос «найди все методы, переопределённые в Chart» — ripgrep пасует. Результат: 0.33 F1 на сложных задачах. Причина — 80% релевантных файлов не содержат прямого упоминания искомого термина, они лишь наследуются.

И если вы строите агента, который сам заворачивает grep в рекурсию (как Claude Code с tool-call «Read»), то он раздует контекст до 15к токенов за полминуты. Проверено: сжатие латентности — полезная штука, но без понимания семантики это всё равно слепые тычки.

Граф зависимостей — золотая середина, если граф не огромен

Пользовался graphlens — он строит AST-граф и по запросу находит все связанные узлы. На средних задачах выдал 0.91 F1 при 0.011$ — это почти вдвое точнее ripgrep и на 40% дешевле LSP. Сложный момент: когда запрос затрагивает глобальный граф (например, «рисуй цепочку вызовов от UI до БД»), инструмент вытягивает 27к+ токенов, и цена взлетает до 0.02-0.03$. В таких случаях Codag помогает визуализировать, где граф избыточен, и отфильтровать шум.

LSP — точность, но цена кусается

LSP — идеальный инструмент для одного блока: зашёл на определение, получил сигнатуру и докстринг. Проблема: каждый вызов — отдельный round trip. Агент хочет обойти 20 мест? Получится 20х0.01$ + контекст. Итоговая стоимость среднего запроса почти вдвое выше графа. Плюс надо держать LSP-сервер — на Superset это ram-hungry питон. MCP-сервер SocratiCode упрощает интеграцию, но сам LSP не бесплатен в ресурсах.

Семантический поиск — не для кода

Тестил srag с эмбеддингами code-bert. На простых запросах «найди функцию handle_resize» точность 0.74 — хуже простого ripgrep. На сложных — F1 0.42. Почему? Code-bert обучен на NLP-задачах, а код — это не близость слов, а структура. Мой обзор srag уже намекал: семантика кода — это граф вызовов, а не тематическое сходство. Для чисто текстовых запросов типа «найди где мы используем JWT» — ещё туда-сюда, но для задач агента — увы.

Как не надо: три типичные ошибки

💡
Ошибка 1: Кормить агента всем, что выдал ripgrep. Получите шум из 300 строк, где 90% нерелевантны. Всегда дополняйте ripgrep фильтром по языку или типу файла.
💡
Ошибка 2: Загружать весь граф зависимостей при старте. Построение полного графа Superset заняло ~4 секунды, а потом держать его в памяти. Лучше строить подзапросом или через гибридный поиск — сначала grep, потом граф от найденного.
💡
Ошибка 3: Использовать LSP для поиска «всех использований» — это 20 вызовов к серверу. Вместо этого сделайте один grep по референсам, а LSP юзайте только для уточнения сигнатуры.

Ваш личный алгоритм выбора

На основе 936 прогонов я вывел тривиальный, но работающий алгоритм:

  1. Задача в одном файле (исправить функцию, найти класс) → ripgrep. Если точность не устраивает — добавьте LSP на одно определение.
  2. Задача смежная (рефакторинг модуля, переименование) → граф зависимостей. Он даст все места, которые нужно поменять, за 0.01-0.02$.
  3. Задача cross-file (понимание потока данных через 5+ файлов) → граф + LSP. Сначала графом найти цепочку, потом LSP для каждого узла.
  4. Задача поисковая (найти упоминание term) → ripgrep или семантический, если термин синонимичен (например, «модуль аутентификации»).

Если бюджет совсем жесток, юзайте Gemini 2.5 + ripgrep. Это даст F1 0.8 на простых и 0.3 на сложных при ~0.001$ за запрос. Как выжать максимум из маленькой LLM — как раз про такой сценарий, но с фокусом на промпт-инжиниринг.

Что дальше? 2027 год приближается

Уже сейчас виден тренд на гибридные MCP-серверы, которые объединяют grep, граф и LSP в один API. Например, graphlens умеет отдавать одновременно и текстовые совпадения, и AST-связи. Агент сам решает, какой тип контекста запросить. В следующем году, возможно, LLM с пониманием кода на уровне AST вообще отпадет необходимость в сложных тулах — модель сама встроит граф. Но пока — ваш выбор между деньгами и точностью. Надеюсь, мои 936 прогонов помогут вам не сжечь бюджет.

P.S. Полные данные и скрипты бенчмарка выложил на GitHub (ссылка в профиле, не реклама). Если повторите на своей кодобазе — дайте знать, интересно сравнить.

Подписаться на канал