Проверка pull request с использованием LLM
В современной разработке программного обеспечения использование систем контроля версий, таких как Git, стало стандартом для совместной работы команд. Git позволяет разработчикам эффективно работать над проектами, создавая изолированные ветки (feature branches) для реализации новых функций или исправления ошибок. Это обеспечивает параллельную работу над разными задачами без вмешательства в основную ветку кода.
Когда работа над задачей завершена, разработчик создает pull request (PR) — запрос на слияние изменений из feature branch в основную ветку. Pull request становится центральной точкой обсуждения: команда проводит code review, чтобы убедиться в качестве кода, его соответствии стандартам и отсутствии ошибок. Code review — это важный этап, который помогает поддерживать высокий уровень кода и делиться знаниями внутри команды.
В этой статье мы рассмотрим, как можно автоматизировать процесс code review с использованием нейронных сетей. Мы интегрируем Python-скрипт с BitBucket Server и OLLAMA-сервером, чтобы модель на основе искусственного интеллекта помогала анализировать код в pull request, предлагать улучшения и выявлять потенциальные проблемы. Такой подход позволяет ускорить процесс review и повысить его качество.
План: - сервер хранения кода (BitBucket) - сервер OLLAMA + модель - скрипт
BitBucket
Для работы с BitBucket API необходимо сгенерировать токен доступа. Токен должен иметь права на доступ к проекту и репозиторию. Создать его можно в разделе Manage account → HTTP access tokens.
После генерации токен используется для аутентификации при подключении к BitBucket API. Например, если ваш проект находится по адресу:
https://bitbucket.example.com/projects/<название проекта>/repos/<репозиторий>/browse
,
то REST API для получения информации о pull request с номером 1 будет выглядеть так:
https://bitbucket.example.com/rest/api/latest/projects/<название проекта>/repos/<репозиторий>/pull-requests/1
.
OLLAMA сервер
OLLAMA — это платформа, которая позволяет запускать большие языковые модели (LLM) локально или на сервере. С ее помощью можно легко развернуть модели для обработки текста, анализа данных или генерации кода. OLLAMA предоставляет простой API для взаимодействия с моделями, что делает ее удобным инструментом для интеграции в различные приложения.
Модели для OLLAMA можно скачать из библиотеки, доступной на официальном сайте: https://ollama.com/library. Библиотека включает популярные модели, такие как LLaMA, Mistral и другие, которые можно использовать для решения широкого круга задач. После загрузки модели ее можно запустить на сервере и отправлять запросы через API, получая ответы в реальном времени.
Установим OLLAMA на отдельном сервере Ubuntu. Используем скрипт, который скачает, распакует, создаст пользователя и сервис.
curl -fsSL https://ollama.ai/install.sh -o install.sh
sh ./install.sh
Разрешим OLLAMA доступ со всех хостов в сети:
systemctl edit ollama
[Service]
Environment="OLLAMA_HOST=0.0.0.0"
Перезапустим сервис
systemctl restart ollama
systemctl status ollama
Скачаем LLM модель deepseek-r1:14b
ollama pull deepseek-r1:14b
Проверим доступ API через запрос curl:
curl http://localhost:11434/api/generate -d '{
"model": "deepseek-r1:14b",
"prompt": "Why is the sky blue?",
"options": { "num_ctx": 4096 }
}'
Список моделей загруженных в OLLAMA:
ollama list
ollama ps
Скрипт
Для автоматизации процесса проверки pull request с использованием LLM создадим Python-скрипт. Этот скрипт будет выполнять следующие действия: - Забирать данные об открытых pull request из BitBucket. - Отправлять код на анализ в LLM через OLLAMA API. - Размещать ответ модели в виде комментария в pull request.
Скрипт сохраним по пути /opt/pr_review.py.
#!/usr/bin/env python3
# LLM review Pull Request
import requests
import re
from datetime import datetime, timedelta
# Constants
BITBUCKET_API_TOKEN = "<your-bitbucket-token>"
BITBUCKET_ALL_PR_URL = "https://bitbucket.example.com/rest/api/latest/projects/<название проекта>/repos/<репозиторий>/pull-requests"
OLLAMA_URL = "http://ollama.example.com:11434/api/chat"
## All PR
response = requests.get(BITBUCKET_ALL_PR_URL, headers={"Authorization": f"Bearer {BITBUCKET_API_TOKEN}", "Accept": "application/json;charset=UTF-8"}, params={"state": "OPEN", "limit": 99})
response.raise_for_status()
now = datetime.now()
two_hours_ago = now - timedelta(hours=2)
recent_pr_ids = []
if response and response.json()["values"]:
recent_pr_ids = [pr["id"] for pr in response.json()["values"] if datetime.fromtimestamp(pr["createdDate"] / 1000) > two_hours_ago]
# PR diff
for pr in recent_pr_ids:
BITBUCKET_PR_ID = pr
BITBUCKET_PR_DIFF_URL = f"https://bitbucket.example.com/rest/api/latest/projects/<название проекта>/repos/<репозиторий>/pull-requests/{BITBUCKET_PR_ID}.diff"
response = None
response = requests.get(BITBUCKET_PR_DIFF_URL, headers={"Authorization": f"Bearer {BITBUCKET_API_TOKEN}"})
response.raise_for_status()
git_diff = response.text
# LLM review of the diff
llm_request = f"Given the following git diff of an Ansible pull request, identify and list any issues found: Broken Code, Syntax Errors, Duplicate Code, Null Variables, Unused Code, Mutable Existence, Code Optimization, Confusing Code. \nReview and provide a list of any issues found, being clear, simple, and concise in your assessment. List only detected issues. Provide brief descriptions and locations where each issue occurs. \n{git_diff}"
data = {"model": "deepseek-r1:14b", "stream": False, "messages": [{ "role": "user", "content": f"{llm_request}" }], "options": { "num_ctx": 8192 }}
response = None
response = requests.post(OLLAMA_URL, json=data, headers={"Content-Type": "application/json"})
response.raise_for_status()
if response and response.json()["message"]["content"]:
llm_review_raw = response.json()["message"]["content"]
llm_review = re.sub(r"<think>.*?</think>\n?", "", llm_review_raw, flags=re.DOTALL)
# PR comment
BITBUCKET_PR_COMMENTS_URL = f"https://bitbucket.example.com/rest/api/latest/projects/<название проекта>/repos/<репозиторий>/pull-requests/{BITBUCKET_PR_ID}/comments"
data = {"text": f"Please note that this comment is generated by an AI model and may not be fully accurate or reliable. \n{llm_review}"}
response = requests.request("POST", BITBUCKET_PR_COMMENTS_URL, json=data, headers={"Authorization": f"Bearer {BITBUCKET_API_TOKEN}", "Accept": "application/json;charset=UTF-8", "Content-Type": "application/json"})
response.raise_for_status()
Скрипт можно забрать в GitHub репозитории.
Чтобы скрипт запускался автоматически, настроим задание в планировщике cron. Для этого создадим файл /etc/cron.d/pr_review и добавим в него строку:
MAILTO=notify@example.com
0 */2 * * * root /usr/bin/python3 /opt/pr_review.py
Эта настройка будет запускать скрипт каждые два часа. Убедитесь, что у скрипта есть права на выполнение (chmod +x /opt/pr_review.py
), а также проверьте, что Python установлен и доступен по пути /usr/bin/python3
.
Время проверки одного pull request в среднем для deepseek:14b(9Gb) на машине с 8CPU,26GBRAM составляет 8 минут.