Как вы знаете я разрабатываю
Summit и в процессе я поднаторел, где и почему LLM лажает с суммаризацией. Сюрприз — всё то же самое воспроизводится в ИИ код-ревью.
## Размер убивает качество
Я начинал с тестирования коротких аудио и поэтому скармливал весь транскрипт целиком ЛЛМке. В итоге конечно пришлось разбивать на части, но потому что контекст у локальных моделей ограничен. Т.е. я разбиваю транскрипт, суммаризирую каждую часть отдельно, потом агрегирую. Однако для облачных провайдеров я думал оставить обработку в один проход.
Как же я удивился когда качество при таком подходе оказалось ниже, чем если использовать чанкинг и там и там.
То же самое происходит с код-ревью: PR на 10 000 строк — как двухчасовой митинг — слишком много контекста, поэтому модель теряет фокус. Прямо как мы ставим LGTM на такой PR, модель ловит банальные проблемы, но пропускает структурные. Иронично, что если код писать с помощью ИИ, то PR получаются тоже большие и выбить клин клином не получится, но попросить ИИ разбить изменение на несколько PR не сложно.
–––
## 2: Один промпт — один вопрос
Поначалу я просил Summit сделать всё сразу: «Вытащи ключевые инсайты, задачи, принятые решения и открытые вопросы. Make no mistakes»
Работало это прямо плохо. Модели давали кучу галлюцинаций. В итоге я перешел на несколько проходов: один промпт — одна задача.
Параллель с код-ревью тут прямая. Если в один промпт просить найти баги, проверить архитектуру, типы, да еще и стиль — то модель не может нормально сфокусироваться ни на чём, что-то находит, но мало и не там.
Решение: ревьювить надо кучей специализированных суб-агентов. Один ищет баги. Второй проверяет архитектуру. Каждый — с одной чёткой задачей.
–––
## 3: Проблема изоляции контекста
Тут у меня пока нет решения — но кажется, это самое важное.
Когда мы делаем код-ревью, мы не делаем его в изоляции. Мы знаем:
- Кто написал код: джун или перфекционист, который срезает углы только по железной причине?
- Как код развивалась последние пять лет.
- Что запланировано дальше — это меняет оценку сегодняшних компромиссов.
- Что было смержено на прошлой неделе, и почему.
ИИ не знает ничего из этого. Оно видит только диф и промпт.
Прямо как с митингами: когда мы пишем заметки во время митинга, мы помним что решили во вторник, кто в команде склонен обещать лишнего, что висит без решения уже месяцы, у кого просто рванул пердак и записывать не стоит.
Чтобы решить это для митингов можно например проактивно подгружать саммари предыдущих встречи с теми же участниками.
Для ревью загружать последних N коммитов перед ревью PR или предстоящие тикеты — чтобы ревьюер понимал куда движется кодовая база
Но понятное дело, что просто загружать предыдущие митинги не значит, что контекст актуален для этого звонка в том числе. Мы фильтруем контекст на лету, потому что у нас есть ментальная модель проекта.
Кажется, что двигаться нужно в сторону графа контекста, который бы размечал связи в данных, а не просто подтягивал строчки как это делает простой RAG.
В контексте код ревью узлами могут быть инженеры, коммиты, тикеты, решения. А ребрами - связи “написал”, “зависит от”, “блокирует”.
Так же обязательно дата изменений. Потому что более свежее решение имеет гораздо больший вес, чем старое.
Таким образом, когда модель будет делать ревью PR который меняет билинг, то вместо голого диффа, она увидит кто менял эти файлы в последний раз и почему, какие дальнейшие изменения запланированы, какие архитектурные ограничения тут есть и что тут ломалось после предыдущих изменений.
Если простой RAG найдет контекст по строчке билинг, то эта штука должна достать что-то типа: этот модуль отрефачили 2 недели назад из-за инцидента на проде, а функцию, которую PR меняет, вообще решено деприкейтить и даже тикет на это есть и автор этого PR тот же самый челик, из-за которого инцидент и произошел.
Примерно как любой сеньор и видит PR.
Так уж вышло, что я сейчас стараюсь решить эту 3 проблему как для Summit так и в компании. Так что о результатах напишу.