С код-ревью есть такой парадокс: все согласны, что этот процесс важен, но времени на него обычно ни у кого нет. В результате ревью часто превращается в формальность. Очевидные баги при этом ловятся, а мелкие, вроде пропуска в условиях, перепутанных знаков, забытых edge cases и т.д., могут спокойно уехать в мердж и вернуться уже в виде задач в багтрекере. 

В Content AI мы активно внедряем ИИ в разработку, и одна из задач, которую мы решали в этом году, — автоматизация код-ревью. В этой статье рассказываем, как одна из наших команд собрала ИИ-ревьюера, встроенного в Pull Request, и что мы поняли спустя месяц использования. 

Что мы вообще хотели получить

Задача с самого начала была очень прагматичной. Мы хотели сделать жизнеспособный инструмент, который:

  • встраивается в наш текущий процесс разработки

  • требует минимум времени на интеграцию

  • умеет оставлять комментарии прямо в Pull Request

  • не блокирует merge

Последний пункт был особенно принципиален. нам нужен был именно ассистент, а не ИИ-руководитель отдела разработки.

Почему мы не взяли готовый сервис

На рынке ревью кода с ИИ есть готовые решения. Но почти все они в первую очередь ориентированы на GitHub и GitLab. В нашей корпоративной реальности выбор был уже гораздо скромнее, а имевшиеся варианты либо плохо встраивались, либо стоили заметно дороже, чем хотелось бы для MVP.

Поэтому мы решили сделать свое решение в виде тонкой интеграционной прослойки поверх уже имеющегося ИИ-инструмента. В качестве движка взяли уже использующийся ИИ-агент кода с non-interactive mode, где можно передавать промпт и получать ответ без ручного диалога.

До автоматизации мы пробовали запускать такой сценарий локально: разработчик сам просил агента посмотреть код и дать замечания. Это работало, но не особо масштабировалось на команду. Чтобы получить единый уровень ревью на всех PR, нужно было вынести агента из локальной среды в общий процесс. 

Архитектура MVP ИИ-ревьюера кода

Схема получилась довольно простая. На каждый Pull Request в CI-системе запускается отдельный шаг, который поднимает Docker-контейнер с Python-инструментом, который через API забирает diff и метаданные PR, собирает контекст. Затем дергает ИИ-агент с определенным промтом для ревью в non-interactive режиме и публикует ответ модели обратно в PR в виде inline-комментариев.

Технически это состоит из:

  • Python-скриптов для интеграции с системой CI/CD.

  • Docker, чтобы не размазывать зависимости по разным CI/CD машинам.

  • терминального клиента ИИ-агента

  • модели LLM, которую при необходимости можно менять

При этом Python-обвязка ничего не знает про ревью кода. Она занимается только двумя вещами: готовит модели правильный контекст и превращает ее ответ в комментарии PR. Все «ревьюерские» знания живут в промпте и в модели.

Смысл Python-обвязки очень простой: она готовит для модели правильный контекст, потом парсит ответ и переводит его в комментарии Pull Request.

Почему structured output — это необходимость

Один из самых полезных инженерных выборов в этом проекте — сразу требовать JSON-формат, а не просить модель написать отзыв в свободной форме.

Условно так:

Такой формат дает сразу несколько плюсов:

  • Ответ можно стабильно парсить. Не нужно гадать, где модель закончила один комментарий и начала другой.

  • Можно точно привязать замечание к строкам diff. А значит, можно подсветить проблему прямо в pull request. И можно ввести уровни критичности, у нас это critical, major, minor, info.

  • Можно дальше развивать систему. Например, добавлять suggested changes, фильтрацию по Severity, метрики ложных срабатываний и т.д.

Если есть задача построить полноценный код-ревью с ИИ, structured output это, по сути, обязательная часть конструкции.

Промпт важен, но контекст важнее

Сам промпт у нас достаточно базовый: мы просим модель концентрироваться на потенциальных багах, логических ошибках, проблемах качества кода, а ответ вернуть строго в заданном формате.

Он выглядит так:

You are a senior code reviewer. Your task is to review a Pull Request diff and provide actionable, specific feedback.

## Input

You will receive a unified diff of code changes. Analyze these changes carefully.

## Rules

1. Focus on real issues: bugs, security vulnerabilities, performance problems, logic errors, and significant code quality problems.

2. Do NOT comment on style preferences, formatting, or trivial naming unless it causes confusion.

3. Each comment MUST reference a specific file and line range from the diff.

4. Use the file paths exactly as they appear in the diff headers (e.g., src/utils.py).

5. Line numbers must correspond to the NEW version of the file (right side of the diff, lines with + prefix or unchanged context lines).

6. Be concise but clear. Explain WHY something is a problem and suggest a fix when possible.

7. Assign an appropriate severity to each comment.

8. Write all comments and the summary in Russian.

## Severity Levels

- critical — Bugs, security vulnerabilities, data loss risks, crashes. Must be fixed before merge.

- major — Significant logic errors, performance issues, missing error handling. Should be fixed.

- minor — Code quality improvements, potential edge cases, minor improvements. Nice to fix.

- info — Suggestions, alternative approaches, questions for the author. Optional.

## Output Format

Return ONLY a valid JSON object with no additional text, markdown fences, or explanations outside the JSON. The response must be parseable by json.loads() directly.

Schema:

{

  "summary": "Brief overall assessment of the PR in 1-3 sentences.",

  "comments": [

    {

      "text": "Description of the issue and suggested fix.",

      "file_path": "path/to/file.ext",

      "line_start": 10,

      "line_end": 15,

      "severity": "critical|major|minor|info"

    }

  ]

}

Но очень быстро стало понятно, что проблема не столько в промпте, сколько в том, какое количество контекста мы даем модели. Мы попробовали несколько режимов.

1. Только diff

Самый дешевый и быстрый режим по токенам. Но и самый «слепой»: модель видит только измененные строки, а значит, хуже понимает общую логику.

2. Полные файлы, в которых были изменения

Это оказался хороший рабочий компромисс. Токенов тратится больше, зато модель уже видит окружающий код, соседние методы, контекст вызова, и качество замечаний заметно растет.

3. Полный репозиторий

Это наш следующий запланированный шаг. Идея в том, чтобы агент мог не просто смотреть измененные файлы, а при необходимости искать по всему репозиторию — заходить в определения функций, смотреть, как используются классы, разбираться в зависимостях.

Главное, что мешает включить этот режим прямо сейчас — размер репозиториев. Часть наших репо весят гигабайты, и выкачивать их в контейнер на каждое ревью слишком долго и дорого. Прежде чем включать full-repo по умолчанию, нужно научить инструмент работать с большими репами умнее: кэшировать, не качать каждый раз с нуля, забирать только релевантные части.

Например, если у вас есть внутренние библиотеки со знакомыми названиями функций, LLM может решить, что они ведут себя как стандартные аналоги, а они ведут себя иначе. Отсюда почти наверняка пойдут ложные замечания.

Это важный вывод сам по себе: если ИИ-ревьюер ошибается, проблема часто не в том, что модель плохая, а в том, что ей дали слишком мало контекста.

Как это встроено в процесс

Мы добавили к Pull Request отдельный Pipeline Step — условный ИИ-ревью. Он обязателен к запуску хотя бы один раз, но при этом не блокирует разработчика. Если модель оставила комментарий, человек может:

  • согласиться

  • поправить код

  • проигнорировать

  • закрыть замечание как нерелевантное.

Пример комментария от ИИ-ревьюера
Пример комментария от ИИ-ревьюера

Это было наше осознанное решение, потому что пока у модели проскакивают ложные срабатывания, превращать ее в жесткий gatekeeper нельзя.

С точки зрения UX это выглядит адекватно: в Pull Request появляются inline-комментарии с подсветкой конкретного места в коде и пометкой Severity. Разработчику не нужно идти в отдельный интерфейс, читать отдельный отчет или запускать что-то локально.

Что получилось за первый месяц

Скажем честно, что жесткие метрики мы в первый месяц не считали. Поэтому дальше будут просто наблюдения от реального использования.

Что можно сказать уже сейчас:

  • MVP действительно удалось собрать примерно за 3 дня

  • один запуск ревью в среднем занимает около 5 минут

  • команда восприняла инструмент позитивно.

  • по субъективной оценке, примерно каждый пятый комментарий пока мимо — чаще всего из-за нехватки контекста

  • остальные 80%замечаний нередко оказываются полезными: ИИ хорошо подстраховывает там, где человек просмотрел мелочь или не успел вчитаться

При этом мы не готовы пока сказать, что ревью стало в два раза быстрее или в три раза качественнее. То есть ревью очевидно ускорилось — но возможно, потому что люди стали смотреть менее вдумчиво. А может, это потому, что часть проблем раньше просто не замечали и сразу ставили ap Pull Request. В этом смысле ИИ тоже не столько ускоряет ревью, сколько повышает шанс поймать проблему до merge, а не после в виде бага.

Во сколько это обошлось

По стоимости внедрение ИИ-ревью кода тоже оказалась вполне приземленной историей.

Сначала мы укладывались примерно в 5000 рублей в месяц, но после расширения на большее число пользователей стало понятно, что этого мало. В итоге вышли примерно на 15 000 рублей в месяц.

В итоге получается примерно такая картина:

  • разовая разработка MVP занимает несколько дней

  • операционные расходы составляют порядка 15 000 рублей в месяц

  • на выходе получаем дополнительного внимательного ревьюера кода, расшаренного на всю команду разработки.

Где были проблемы

1. Повторный запуск ревью пока работает не идеально

Сейчас при перезапуске инструмент часто ревьюит Pull Request фактически заново.
А LLM — не детерминированная система, сегодня она найдет одно, а завтра другое. В итоге можно получить дубли, новые формулировки старых замечаний и просто шум.

Правильное поведение здесь другое: ревьюить только дельту с последнего запуска. Это у нас уже в планах.

2. Нельзя жестко завязываться на одну модель

На практике провайдеры, модели и доступность могут меняться. Где-то меняются лимиты, где-то — условия доступа, где-то внезапно перестает работать то, что работало вчера.

Из этого очень простой инженерный вывод: делайте модель заменяемой, не зашивайте архитектуру под одного поставщика.

У нас есть понимание, что показало себя лучше всего, но сама интеграция сделана так, чтобы модель можно было переключать.

3. Безопасность остается в приоритете

Мы сознательно не стали давать агенту прямой широкий доступ к репозиторию через MCP. Вместо этого сделали более консервативную схему: Python-инструмент сам забирает только нужные данные, а модели отправляется уже подготовленный контекст.

Плюсы тут такие:

  • отдельный технический пользователь

  • токен с минимально нужными правами

  • ограничение доступа на уровне интеграции

Да, это не снимает вопрос передачи кода внешней модели вообще. Но если компания использует облачные ИИ-инструменты в разработке, этот вопрос все равно придется решать на уровне политики безопасности. Но одно дело — дать агенту право ходить и смотреть что угодно, и совсем другое — отдавать только строго собранный контекст конкретного Pull Request.

4. Не все задачи должны решаться через LLM

Например, если у вас часто всплывает проблема с неожиданной сменой кодировки в файлах, то для такой проверки ИИ не нужен вообще. Это проще и надежнее проверить обычным детерминированным скриптом.

Хороший ИИ-ревьюер — это не одна LLM на все случаи жизни, а комбинация LLM и обычных инженерных правил.

Что планируем улучшать

Если смотреть на этот инструмент не как на разовый MVP, а как на внутренний продукт, то вектор развития довольно понятный.

1. Дать модели больше контекста

Чтоб ИИ-ревьюер видел не только измененные файлы, но и:

  • полный репозиторий

  • связанные зависимости

  • внутренние библиотеки

2. Сделать инкрементальное доревью

Чтобы повторный запуск анализировал только новые изменения, а не весь Pull Request заново.

3. Добавить suggested changes

Для тривиальных случаев было бы удобно, если бы ИИ не просто писал комментарий, а сразу предлагал правку в формате Apply change.

4. Вынести это из разового Pipeline в сервис

Идеальный сценарий выглядит как сервис, который:

  • сам следит за новыми Pull Request

  • сам доревьюивает изменения

  • сам проверяет, что замечание действительно исправлено.

Но это уже следующий уровень зрелости. Туда разумно идти только тогда, когда доверие к качеству замечаний станет заметно выше.

Советы тем, кто захочет повторить такой подход

  1. Не делайте первую версию блокирующей. Сначала ИИ должен заслужить доверие. 

  2. Сразу требуйте structured output. Текст в свободной форме красивый, но бесполезный для автоматизации.

  3. Тратьте время не только на промпт, но и на сбор контекста.

  4. Модель LLM часто определяет качество. Сделайте так, чтобы ее можно было легко заменять. 

  5. Безопасность конфиденциальной информации должна быть в приоритете. Минимизируйте доступы, чтобы автоматизация не обернулась утечками комтайны. Отдельный сервисный пользователь, scoped token, никакого лишнего чтения и т.д.

  6. Разделяйте ИИ и rule-based проверки. LLM не лучший инструмент для детерминированных вещей.

  7. Если хотите потом доказывать эффект цифрами, закладывайте измерения заранее.
    Например, можно замерять время до Pull Request, количество post-merge дефектов, долю принятых ИИ-комментариев, долю ложных срабатываний. 

Мы этого сразу не сделали, и теперь можем уверенно говорить про пользу, но не можем прямо сейчас продемонстрировать ее на графиках.

Вывод

Главный эффект от кода-ревью с ИИ для нас оказался в том, что в процессе появилась дешевая, быстрая и довольно внимательная дополнительная пара ИИ-глаз.

Этот ассистент не всегда оказывается прав, ему явно не хватает контекста, его нужно контролировать. Но даже в таком виде он уже приносит пользу: помогает ловить проблемы до того, как они станут реальными багами, и в целом делает ревью менее зависимым от человеческой усталости. Для MVP, который собрали за три дня, — результат, как нам видится, более чем достойный.


Это блог компании Content AI. Мы помогаем работать с информацией умнее — автоматизировать обработку документов, извлекать данные и повышать качество бизнес-процессов с помощью собственных технологий и современного ИИ. Здесь рассказываем, как разрабатываем продукты и делимся опытом, архитектурными решениями и кейсами внедрения интеллектуальной автоматизации.

Наш Telegram-канал со всеми новостями: https://t.me/content_ai