Контекстна інженерія для ШІ-агентів у коді: чому великі вікна не рятують
Чому вікно на мільйон токенів не лагодить агентів для коду і як бюджет токенів, графи репозиторію та багаторівнева пам'ять дають їм потрібний контекст, а не просто більше контексту.
Великі вікна контексту не полагодили агентів для коду
ШІ-асистентів для коду стримує вже не інтелект. Слабке місце в тому, як вони зберігають, дістають і пов'язують інформацію по всій кодовій базі.
Коли з'явилися вікна на мільйон токенів, обіцянка звучала охайно: модель нарешті вмістить увесь ваш репозиторій. Кожен, хто напускав 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