Контекстная инженерия для ИИ-агентов в коде: почему большие окна не спасают
Почему окно на миллион токенов не чинит агентов для кода и как бюджет токенов, графы репозитория и многоуровневая память дают им нужный контекст, а не просто больше контекста.
Большие окна контекста не починили агентов для кода
ИИ-ассистентов для кода сдерживает уже не интеллект. Слабое место в том, как они хранят, достают и связывают информацию по всей кодовой базе.
Когда появились окна на миллион токенов, обещание звучало аккуратно: модель наконец-то вместит весь ваш репозиторий. Каждый, кто натравливал ChatGPT (Codex), Cursor, Claude Code или Gemini (Antigravity) на настоящий проект, знает, чем это заканчивается. Просите исправить баг в AuthService.ts, и модель забывает о хелпере, который лежит в двадцати файлах от него. Добавляете новый API-маршрут, и она пишет код под устаревшую версию интерфейса. Окно огромное, а ответ всё равно неверный.
Дело не в том, что модель мала. Плохо управляется контекст.
Бюджет токенов важнее лимита токенов
Окно контекста — это потолок, а не память, которую можно заполнять как угодно. В репозитории среднего продакшен-проекта одновременно лежит очень много всего:
- исходный код в сотнях файлов
- git-диффы незавершённых изменений
- стек-трейсы и логи
- документация API
- конфигурационные файлы
- README и заметки об архитектуре
Запихивать всё это в промпт дорого и в основном бессмысленно. Сравните с оперативной памятью в операционной системе: ноутбук с 32 ГБ не загружает в память весь диск только потому, что мог бы.
Агенты для кода ведут себя так же и распоряжаются бюджетом токенов. Вопрос уже не в том, что поместится, а в том, что заслуживает токенов.
Что получает приоритет
Вверху списка — редактируемый файл, а с ним недавние изменения в git, импортируемые им зависимости и функции, причастные к ошибке. Внизу — посторонняя документация, старые логи, неиспользуемые модули и далёкие закоулки репозитория.
Решать, что попадёт в модель, а не просто увеличивать окно, — вот что стали называть контекстной инженерией.
Почему в больших проектах больше галлюцинаций
Галлюцинации в коде редко бывают случайными. Обычно модель получила только кусок картины. Возьмём такую последовательность. Сначала загружается UserService.ts:
`UserService.ts` is loaded.
Затем PermissionManager.ts так и не попадает в контекст:
`PermissionManager.ts` is not loaded.
И наконец модель заполняет дыру логикой прав доступа, которую сама придумала:
The model invents permission logic.
С точки зрения модели отсутствующая информация выглядит точно так же, как несуществующая. Исследования длинного контекста добавляют вторую проблему: моделям бывает трудно использовать важные детали, спрятанные в середине очень длинного промпта, — этот эффект называют Lost in the Middle. Так что большие окна сглаживают часть сбоев, но ошибок поиска не устраняют.
Представьте репозиторий как граф
Эта мысленная модель меняет подход к задаче. Репозиторий — не куча файлов, а граф. Узлы — значимые сущности: файлы, классы, функции, API и модели базы данных. Рёбра — связи: импорты, вызовы функций, наследование и потоки данных.
Теперь дайте агенту задачу вроде "исправь таймаут аутентификации". Ему не нужно читать 400 файлов. Он идёт по графу и забирает окрестность вокруг аутентификации, а это намного дешевле, чем загружать всё.
Идите по зависимостям, а не только по ключевым словам
Классическая генерация с поиском (RAG) ищет фрагменты, семантически близкие к запросу. Это помогает, но у кода есть структура, которой нет у прозы. Конвейер получше выглядит так:
User query -> Semantic search finds relevant functions -> Graph traversal expands connected dependencies -> Context optimizer compresses everything into the token budget
В итоге агент получает не разрозненные фрагменты, а связанный контекст. Это центральная идея графового поиска, например GraphRAG от Microsoft. Учтите, что GraphRAG — исследовательская архитектура, и никто не подтверждал, что она работает внутри коммерческих ассистентов для кода.
История чата — это не память
Распространённое заблуждение — считать историю разговора памятью. На деле у агентов для кода три уровня:
- Рабочий контекст: текущий промпт и активные файлы
- Скользящее окно: недавние сообщения и правки
- Поисковая память: знания о репозитории, которые подтягиваются по запросу
Поэтому Cursor или ChatGPT (Codex) могут вести долгую сессию работы с кодом, не таская в промпте каждое прежнее сообщение. Они достают нужное тогда, когда оно нужно, а не проигрывают весь разговор заново. Реализации у продуктов разные, но многоуровневая схема — общий паттерн современных агентов.
Как выглядит конвейер контекста
Будущее не за бесконечными окнами, а за конвейерами получше. Контекстный движок мог бы делать следующее:
- Превращать репозиторий в AST.
- Строить по нему графы зависимостей и графы вызовов.
- Создавать эмбеддинги, чтобы работал семантический поиск.
- Начинать с подходящих узлов и расширяться по зависимостям.
- Сжимать найденное перед отправкой в LLM.
Поиск в ширину может собрать ближайшие зависимости, а центральность в графе или ранжирование в духе PageRank — выдвинуть самые влиятельные файлы. Так что для его создания обычная программная инженерия нужна как минимум не меньше, чем работа с моделями.
Читать нужные токены
Гонка за большими окнами важна, но всей проблемы она не решит. Ассистент становится лучше не оттого, что читает больше токенов, а оттого, что читает нужные в нужный момент. Это и есть переход от промпт-инженерии к контекстной инженерии. И если агентам предстоит строить продакшен-софт, отношение к репозиторию как к графу, а не как к гигантскому текстовому файлу, может оказаться одной из важнейших архитектурных идей для следующего поколения ассистентов.
Где почитать подробнее
- Исследование слабых мест длинных промптов, Lost in the Middle (ACL 2024): https://aclanthology.org/2024.tacl-1.9/
- Документация Microsoft GraphRAG: https://microsoft.github.io/graphrag/
- Репозиторий GraphRAG на GitHub: https://github.com/microsoft/graphrag
- Оригинальная статья о RAG, NeurIPS 2020: https://arxiv.org/abs/2005.11401
- Building Effective AI Agents: https://www.anthropic.com/engineering/building-effective-agents