Дата публикации
ai_products

AI-ревьюер для pull request’ов: как команда YADRO выбирала LLM и собирала бэкенд

Что нового

Команда YADRO собрала внутреннего AI-помощника, который автоматически ревьюит pull request’ы с автотестами.

Что он умеет:

  • Анализирует только добавленный и изменённый код в PR.
  • Ищет проблемы в стиле, логике и конструкциях кода.
  • Оставляет комментарии прямо в pull request’е с конкретными правками.
  • Снимает с инженеров рутину по поиску однотипных ошибок, особенно в коде стажёров.

Ключевые технические решения:

  • Используются локальные LLM в формате GGUF, оптимизированные под CPU.
  • Квантование «золотой середины» — Q4_K_M: разумный баланс между размером и качеством.
  • Протестированы несколько моделей, от компактных до более тяжёлых:

| Модель | Размер репозитория, GB | Размер GGUF, GB | |---------------------|------------------------|------------------| | Microsoft/phi-2 | 5.5 | 1.7 | | TinyLlama | 2.2 | 1.1 | | Mistral | 15 | 4.2 | | Qwen3 | 6 | 2.81 |

  • Для оценки качества брали реальную ошибку автотеста, связанную с неверной версией библиотеки: отсутствие символа tboost_set_log_level в libtboost_sdk.so.
  • Модели сравнивали по тому, как они объясняют ошибку и предлагают варианты исправления.

Фокус не на максимальной скорости, а на практической пользе: бот не самый быстрый, но хорошо ловит повторяющиеся ошибки и экономит время на ревью.

Как это работает

Архитектура в общих чертах

  1. Разработчик открывает pull request с изменениями в автотестах.
  2. CI/CD или Git-хук вызывает бэкенд AI-ревьюера.
  3. Бэкенд:
    • получает diff PR;
    • фильтрует только добавленные и изменённые участки кода;
    • формирует промт для LLM (контекст + инструкции по ревью);
    • отправляет запрос на локальный сервер с LLM в формате GGUF;
    • получает ответ и превращает его в комментарии к PR.
  4. Инженер видит комментарии бота и уже сосредотачивается на более сложных аспектах: корректность pytest-марок, соответствие автотеста описанию в TestY TMS и т.п.

Почему GGUF и квантование Q4_K_M

Команда запускала модели на CPU-сервере, без дорогих GPU. Для этого нужны компактные и быстрые форматы:

  • GGUF — бинарный формат, оптимизированный для работы с LLM на CPU: быстрее загружается и экономит память.
  • Квантование снижает точность чисел в весах модели, уменьшая размер и требования к RAM.
  • Профиль Q4_K_M:
    • большинство параметров хранится в 4-битном формате;
    • качество всё ещё приемлемое для анализа кода;
    • размер файлов — от 1.1 до 4.2 GB для протестированных моделей.

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

Тестовый сценарий для выбора модели

Чтобы сравнить модели не абстрактно, а по реальной пользе, им давали один и тот же кейс:

Ошибка автотеста:

AttributeError: /opt/tboost-sdk/libtboost_sdk.so: undefined symbol: tboost_set_log_level

Задача для LLM (перевод промта на русский):

Объясни, почему произошла ошибка: AttributeError: /opt/tboost-sdk/libtboost_sdk.so: undefined symbol: tboost_set_log_level. Как это пофиксить?

Критерии оценки:

  • Понимает ли модель, что происходит на уровне нативной библиотеки (.so) и символов?
  • Даёт ли реалистичные причины (сборка, версии, несовместимость), а не выдуманные истории?
  • Предлагает ли конкретные шаги по исправлению?

Как отвечали разные модели

Microsoft/phi-2

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

TinyLlama

  • «Рассказала» историю про установку libtboost_sdk через pip, которой тоже не было в исходных данных.
  • Предлагала переустановить библиотеку через pip, что не решает проблему отсутствующего символа в .so.
  • Вывод: ответы выглядят правдоподобно, но к реальной ошибке почти не привязаны.

Mistral

  • Правильно определила суть: в libtboost_sdk.so нет символа tboost_set_log_level.
  • Предложила проверить установку библиотеки и процесс сборки нативной части.
  • Указала на необходимость корректной сборки C-библиотеки и её совместимости с Python.
  • Вывод: здравое объяснение и адекватные шаги по исправлению.

Qwen3

  • Чётко описала проблему: символ не найден в .so.
  • Предложила несколько возможных причин, связанных с несовместимостью версий и установкой библиотеки.
  • Часть пунктов получилась повторяющейся, но общий посыл — разумный.
  • Вывод: даёт набор гипотез и направлений для поиска ошибки.

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

Что это значит для вас

Где AI-ревьюер реально помогает

  • Команды с большим потоком PR. Бот разгружает инженеров от однотипных комментариев и помогает не пропускать базовые ошибки.

  • Работа со стажёрами и джунами. Частые проблемы — огромные PR, повторяющиеся баги стиля и логики. AI-ревьюер стабильно указывает на такие вещи и обучает через комментарии.

  • Автотесты и инфраструктурный код. Для тестов особенно важны аккуратные конструкции, корректные маркировки, понятная логика. Бот помогает поддерживать единый уровень качества.

  • Инженеры, которые не хотят тянуть облачные сервисы. Всё крутится локально на CPU-сервере, без передачи кода во внешние API.

Где не стоит на него полагаться

  • Архитектурные решения и сложная бизнес-логика. Локальные квантованные модели уровня Mistral/Qwen3 в GGUF хорошо ловят паттерны, но не заменяют опытного архитектора.

  • Безопасность и критичные участки. Проверка на уязвимости, криптографию, тонкие гонки потоков — зона ответственности людей и специализированных инструментов.

  • Проекты, где важна максимальная скорость фидбэка. Модели в GGUF на CPU работают медленнее, чем облачные LLM на мощных GPU. Если вам нужно ревью за секунды, такой подход может не устроить.

Практические выводы, если вы хотите сделать так же

  • Начинайте с чёткого сценария: что именно бот должен делать в PR (стиль, логика, тесты, безопасность?).
  • Не берите сразу «самую большую» модель. Пройдите путь, как в YADRO: от TinyLlama/phi-2 к Mistral/Qwen3 и посмотрите, где качество уже устраивает.
  • Обязательно проверяйте модели на реальных ошибках вашего проекта, а не на абстрактных примерах.
  • Заложите время на настройку промтов: от формулировки инструкций сильно зависит полезность комментариев.

AI-ревьюер не снимает с инженеров ответственность за код, но хорошо закрывает рутину и помогает выровнять качество по команде.

Место на рынке

YADRO собрала не публичный продукт, а внутренний инструмент, построенный на открытых моделях. Его логично сравнивать не с GPT-4o или Claude 3, а с другими локальными LLM и подходами к ревью кода.

По ключевым параметрам подход выглядит так:

  • Тип развёртывания.

    • Локальный сервер на CPU с GGUF-моделями.
    • Без зависимости от внешних API и их SLA.
  • Размер и ресурсы.

    • Используются модели от 1.1 до 4.2 GB в GGUF.
    • Это заметно легче, чем разворачивать полноразмерные не-квантованные версии (до 15 GB и выше).
  • Качество анализа кода.

    • Компактные модели вроде TinyLlama и phi-2 хуже справляются с техническим разбором ошибок и склонны «галлюцинировать».
    • Более крупные варианты уровня Mistral и Qwen3 дают внятные объяснения и реальные пути решения.
  • Интеграция в процессы.

    • Инструмент встраивается в существующий workflow ревью PR.
    • Работает рядом с TestY TMS, который команда YADRO использует для управления тестами.

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

Как запустить локальную LLM (общая схема)

В исходном материале нет полного кода бэкенда, но по описанию можно набросать базовый сценарий запуска локальной модели в формате GGUF на CPU.

1. Скачать модель в GGUF

Модели в формате GGUF обычно лежат на HuggingFace. Пример (общее направление, не конкретный репозиторий):

# Установить huggingface-cli, если его нет
pip install -U huggingface_hub

# Авторизоваться, если нужно
huggingface-cli login

# Скачать модель (примерное имя, подставьте нужное)
huggingface-cli download mistral-7b-instruct-q4_k_m --local-dir ./models/mistral-7b-q4

2. Запустить сервер с LLM

Один из вариантов — использовать llama.cpp или совместимые обёртки.

Пример для llama.cpp (концептуально):

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make

# Запуск сервера с GGUF-моделью
./server \
  -m ./models/mistral-7b-q4/model.gguf \
  -c 4096 \
  -ngl 0 \
  -t 8

Где:

  • -m — путь к GGUF-файлу.
  • -c — длина контекста (зависит от модели и ресурсов).
  • -ngl 0 — всё на CPU.
  • -t — количество потоков.

3. Подключить бэкенд ревьюера

На стороне вашего сервиса ревью кода логика выглядит так (псевдокод):

import requests

def build_prompt(diff: str) -> str:
    instructions = (
        "Ты помощник по ревью кода. "
        "Проанализируй только добавленные и изменённые строки. "
        "Ищи проблемы стиля, логики и типичные ошибки в автотестах. "
        "Отвечай кратко, в формате списка комментариев."
    )
    return f"{instructions}\n\nИзменения в PR:\n{diff}"


def call_llm(prompt: str) -> str:
    response = requests.post(
        "http://localhost:8080/completion",
        json={
            "prompt": prompt,
            "max_tokens": 512,
            "temperature": 0.2,
        },
        timeout=120,
    )
    response.raise_for_status()
    return response.json()["content"]


def review_pull_request(diff: str) -> str:
    prompt = build_prompt(diff)
    llm_answer = call_llm(prompt)
    return llm_answer

Дальше остаётся:

  • разобрать ответ модели;
  • сопоставить комментарии с конкретными строками diff;
  • отправить их в систему контроля версий (GitHub, GitLab, Gerrit и т.п.).

Этот каркас придётся адаптировать под ваш стек, но общая идея совпадает с тем, как YADRO интегрировала AI-ревьюера в свой процесс разработки.


Читайте также

AI-ревьюер для pull request’ов: как команда YADRO выбирала LLM и собирала бэкенд — VogueTech | VogueTech