Контекст, легаси и большие кодовые базы
Оптимизация retrieval, токенов и скорости обработки
Вопросы участников:
- Часто вопрос касается в оптимизации БД с LLM! Конечно, для этого есть GraphRAG, VectorRAG, Call Functions, но хотелось бы узнать, как можно еще лучше оптимизировать скорость обработки и снижение токенов на LLM модели
Сначала разложим, где именно тратятся токены и время. В retrieval-системе есть три независимых рычага: что ищем (индекс и способ извлечения), сколько кладём в контекст (объём и упаковка) и что не пересчитываем заново (кэш). GraphRAG и VectorRAG — это про первый рычаг, но крупный выигрыш по токенам и латентности чаще даёт второй и третий.
Первый рычаг — выбор индекса под тип вопроса. VectorRAG (плотный поиск по эмбеддингам) хорош для локальных фактологических запросов, но проваливается на глобальных вопросах уровня всей базы. GraphRAG от Microsoft Research строит из данных граф сущностей, заранее считает сводки по сообществам (алгоритмы Leiden/Louvain) и отвечает через map-reduce по этим сводкам. На глобальных вопросах это даёт выигрыш по полноте и разнообразию с долей побед около 70-80% против наивного RAG, причём сводки верхнего уровня расходуют лишь 2-3% токенов на запрос по сравнению с прогоном по всему исходному тексту. Вывод: не выбирайте один индекс — маршрутизируйте запрос. Точечные вопросы уводите в вектор или лексический поиск, обзорные — в граф.
Второй рычаг — чанкинг и упаковка контекста. Для кода line-based чанкинг режет функции и классы посередине, и retrieval тащит нецелостные куски. Structure-aware подход cAST разбивает код по узлам AST (через tree-sitter), рекурсивно дробит крупные узлы и сливает мелкие соседние, измеряя размер чанка не строками, а непробельными символами. Это плюс 4.3 к Recall@5 на RepoEval и плюс 2.67 к Pass@1 на SWE-bench — и, что важнее для вашего вопроса, меньше мусорных токенов в контексте при той же полноте.
Третий рычаг — не пересчитывать общий префикс. Если system-промпт, инструкции и стабильная часть базы знаний одинаковы от запроса к запросу, их держат в prompt caching (кэшировании промптов). На платформе Claude чтение из кэша стоит около 10% цены обычного входного токена, а запись — на 25% дороже базовой; приём окупается уже после двух-трёх повторных использований префикса. По замерам Anthropic кэш 100k-токенного промпта снижает время до первого токена примерно с 11.5 до 2.4 секунды и режет стоимость входа до 90%.
Отдельный приём — селективный retrieval: не ходить в базу, когда модель справится и так. Repoformer учит модель самой решать, нужен ли внешний контекст, и пропуск лишних обращений даёт до 70% ускорения инференса без потери качества; около 40% запросов можно обслужить вообще без retrieval.
Что пойдёт не так без этого разбора:
- Слепая вера в один индекс. Вектор на глобальном вопросе вернёт похожие, но нерелевантные чанки — модель уверенно ответит мимо. Лечится маршрутизацией и гибридом (лексика + вектор + граф).
- Дорогой граф там, где хватило бы вектора. Построение графа сущностей — недешёвый предпроцессинг; он оправдан под частые обзорные запросы, а не под точечный поиск.
- Инвалидация кэша. Любое изменение префикса (даже таймстамп в начале) сбрасывает кэш. Стабильное — в начало промпта, переменное — в конец.
- Раздувание контекста ради полноты. Чем больше скармливаете, тем сильнее размывается внимание — подробнее в следующем подразделе.
Ссылки
- From Local to Global: A Graph RAG Approach to Query-Focused Summarization (arXiv)
- cAST: Enhancing Code RAG with Structural Chunking via AST (arXiv)
- Repoformer: Selective Retrieval for Repository-Level Code Completion (arXiv)
- Prompt caching with Claude (Anthropic)
Контекстное окно на большом монолите и микросервисах
Вопросы участников:
- Когда агент генерирует фичу для большого монолита или набора микросервисов на FastAPI, как решается проблема контекстного окна? Вы скармливаете ему AST проекта или используете RAG по кодовой базе?
- Сложно внедрить ИИ в большой контекст
Прямой ответ на дилемму: на большой базе не скармливают ни весь AST, ни всю базу через вектор — оба упираются в контекстное окно и в размывание внимания. Промышленные кодовые базы — это миллионы токенов против примерно 200k окна у актуальных моделей (оценка из работы по восстановлению архитектуры легаси), поэтому задача не влезть целиком, а подать только релевантный срез.
Почему не стоит грузить окно под завязку. Классическая работа Lost in the Middle показывает U-образную кривую: модель хорошо использует информацию в начале и в конце контекста и проваливается в середине; при удлинении контекста качество монотонно падает, а модель с расширенным окном не обязательно лучше использует его содержимое. То есть больше контекста не равно лучше ответ.
Что делают на практике вместо этого:
- Агентный поиск как основа. Агент навигирует по коду как инженер: смотрит дерево файлов, делает grep/ripgrep по символам, читает нужные файлы, идёт по импортам. Команды Claude Code и подобных инструментов отказались от векторного индекса в пользу такого живого поиска — он не устаревает, не требует инфраструктуры и не течёт наружу.
- Карта репозитория (repo map) по AST. Aider строит карту через tree-sitter на 40+ языках, ранжирует файлы алгоритмом PageRank по графу ссылок и укладывает в бюджет (по умолчанию около 1k токенов) только сигнатуры и определения — агент видит API проекта, не читая его целиком.
- Семантический индекс как усиление, а не замена. Cursor замеряет: связка grep + семантический поиск даёт на 12.5% выше точность ответов по базе, чем один grep, и плюс 2.6% к удержанию сгенерированного кода на репозиториях от 1000 файлов. Вектор помогает, когда вы не знаете имя символа и термины постановки не совпадают с кодом.
Под ваш FastAPI-кейс это ложится так: для фичи в конкретном сервисе агент по grep и AST находит роутер, схемы Pydantic, слой зависимостей и модели, читает их точечно и генерирует изменение. На монолите добавляют repo map; на наборе микросервисов берут по одному сервису за задачу плюс контракт (OpenAPI-схема) на стыке, а не весь набор сразу.
Что пойдёт не так:
- Чистый вектор по коду проваливается на структуре. Вызов
processPayment()не обязательно эмбеддится близко к своему определению — связь по импортам вектор не ловит. Отсюда гибрид: лексика + структура (AST и граф вызовов) + вектор. - AST целиком тоже не панацея. Полный AST монолита не влезет в окно; ценность AST в навигации (кто кого вызывает, карта сигнатур), а не в подаче всего дерева в промпт.
- Устаревание индекса. Код меняется ежедневно, а эмбеддинги отражают состояние на момент индексации; живой поиск всегда актуален, а индекс требует инкрементального переиндекса (например, по Merkle-дереву).
Ссылки
- Lost in the Middle: How Language Models Use Long Contexts (arXiv)
- Improving agent with semantic search (Cursor)
- CodeRAG-Bench: Can Retrieval Augment Code Generation? (arXiv)
- ArchAgent: Scalable Legacy Software Architecture Recovery with LLMs (arXiv)
Brownfield: внедрение AI-DD в существующий проект
Вопросы участников:
- Вопрос про brownfield. Когда внедряешь AI-DD в существующий проект: Есть ли реальные кейсы, как это работает в продакшене? Как быть со спеками? Что имеет смысл коммитить в гит, а что нет? Как защититься от дрифта между спеком и кодом? Как не скатиться в ситуацию с markdown монстром?
Разберём по подпунктам, потому что вопрос составной.
Механика спек-подхода. Spec-Driven Development выносит
спецификацию в центр процесса: цепочка Spec → Plan → Tasks →
Implement, где каждая фаза даёт markdown-артефакт, который
кормит следующую и даёт агенту структурированный контекст
вместо разовых промптов. Открытый инструмент — GitHub Spec
Kit (команда specify init, 30+ интеграций с агентами). Это
и есть каркас, в который встраивают AI-DD.
Реальные кейсы и продакшн. Публичных промышленных метрик
пока мало — честно держите это в голове, — но экосистема
вокруг brownfield быстро растёт. Для Spec Kit есть отдельное
расширение под существующие проекты с командами scan,
bootstrap, validate, migrate: оно сканирует стек и
архитектуру, фиксирует технологический стек как факт и
обратной разработкой поднимает спеки с уже написанного кода.
Принцип расширения прямой: не улучшать существующую
архитектуру, а точно её отразить.
Что коммитить в git, а что нет. В репозиторий идут
долгоживущие артефакты: constitution проекта, spec.md,
plan.md, tasks.md, AGENTS.md — они версионируются
вместе с кодом и проходят ревью как код. Не коммитят разовый
контекст под конкретную сессию агента, сырые дампы кодовой
базы и эмбеддинг-индексы (они устаревают и раздувают
историю). Правило простое: в git — то, что описывает
намерение и переживёт сессию; мимо git — то, что можно
пересобрать.
Дрифт спека против кода — главная боль brownfield. Спека говорит одно, код делает другое, агент читает устаревшую спеку и генерирует конфликтующий код. Защита строится в три слоя:
- Спека — источник намерения, а не второй экземпляр кода. Держите её на уровне требований и контрактов, не дублируйте реализацию, иначе каждая правка кода порождает правку спеки.
- Автоматическая проверка дрифта. Расширения вроде spec-kit-sync сравнивают спеки с кодом, помечают разошедшиеся требования и неспецифицированные фичи и предлагают стратегию: backfill (код прав — обновить спеку), align (права спека — поправить код), supersede (новый документ важнее) или передать на решение человеку.
- Гейт в цикле. Автономная генерация останавливается при обнаружении дрифта — это не даёт ранней ошибке компаундиться в цепочку.
Как не сделать markdown-монстра. Монстр возникает, когда документацию генерируют как плоские фрагменты — гора несвязных файлов, которые никто не читает и которые сами разъезжаются с кодом. Противоядие — структура и инкрементальность: подходы на графе знаний репозитория (RepoDoc) держат документацию модульной и перекрёстно-связанной и обновляют только затронутые изменением части через распространение семантического влияния, экономя, по замерам авторов, до 85% токенов против плоской регенерации. То есть спеки должны быть модульными, привязанными к коду и обновляться точечно, а не расти безгранично.
Ссылки
- GitHub Spec Kit
- spec-kit-sync — обнаружение дрифта спека и кода
- spec-kit-brownfield — SDD для существующих кодовых баз
- RepoDoc: Knowledge Graph-Based Documentation and Incremental Updates (arXiv)
Крупный проект без нормальной документации, это проблема?
Короткий ответ: да, это проблема, но решаемая — и во многом именно LLM снимают её остроту. Работа по восстановлению архитектуры легаси прямо фиксирует две беды таких систем: код на миллионы токенов не влезает в окно (около 200k), а без документации модель не отличает бизнес-логику от вспомогательного кода и начинает выдумывать идентификаторы при попытке описать целые файлы.
Хорошая новость: документацию можно поднять из самого кода снизу вверх. Устоявшийся паттерн — иерархическая суммаризация:
- Парсим код в AST (tree-sitter, Jedi, JDT) и режем на осмысленные единицы: функции, классы, файлы.
- Суммаризируем мелкое, затем агрегируем: метод → файл → пакет → репозиторий, идя по графу вызовов (caller/callee) в топологическом порядке, чтобы контекст ребёнка был готов раньше родителя.
- Заземляем на бизнес-контекст. Один только код даёт сухие технические сводки; добавление домена и постановки задачи в промпт делает описания осмысленными (показано на телеком-системе BSS с локальными моделями).
Конкретные инструменты этого класса: RepoAgent (генерирует и поддерживает документацию по всему репозиторию, синхронизируя её с кодом через git-хуки), RepoDoc (граф знаний репозитория, плюс 32.5% к покрытию API и на 85% меньше токенов против плоской генерации), ArchAgent (восстанавливает бизнес-выровненную архитектуру и README из графа ссылок на уровне файлов, классов и функций).
Практический план для вашего случая:
- Сначала автогенерация обзорного слоя: карта модулей, диаграммы потоков, README по точкам входа — чтобы у агента и у людей появился верхнеуровневый контекст.
- Затем инкрементальная поддержка: обновлять документацию только для изменённых частей, а не гонять весь репозиторий.
- Дальше — тот же brownfield-подход из предыдущего подраздела: обратной разработкой поднять спеки на ключевые фичи и завести проверку дрифта.
Что пойдёт не так:
- Сгенерированная документация тоже врёт. На уровне файла и пакета LLM склонна к преувеличениям и выдумкам — валидируйте результат (тесты, ссылки на реальные символы, выборочное ревью), особенно на бизнес-логике.
- Документация без привязки к коду мгновенно устаревает. Разовая генерация — путь к тому же markdown-монстру. Обязательна инкрементальная синхронизация с изменениями.
- Слепое доверие на архитектурных решениях. Модель сильна на микроуровне (функция, файл) и слабее на системном; верхнеуровневые выводы перепроверяет человек.
Ссылки
- RepoAgent: LLM-Powered Repository-level Code Documentation (arXiv)
- RepoDoc: Knowledge Graph-Based Documentation and Incremental Updates (arXiv)
- ArchAgent: Scalable Legacy Software Architecture Recovery with LLMs (arXiv)
- Hierarchical Repository-Level Code Summarization for Business Applications (arXiv)