llm

LLM и свой ключ

ReviewGate работает на вашей LLM. Провайдер за абстракцией: облако Anthropic, любой OpenAI-совместимый endpoint, модель подешевле или локальная модель в вашем контуре.

bring-your-own-keyКлюч — ваш. Бот поднимается и без него (health работает), но ревью-задача упадёт с понятной ошибкой, пока ключ не задан. Это и есть экономика бесплатного продукта: маржинальная стоимость — ваш запрос к LLM.

Yandex AI Studio

Один из OpenAI-совместимых провайдеров — полезен, когда данные должны оставаться в определённой юрисдикции. Нужны API-ключ сервисного аккаунта (роль ai.languageModels.user) и каталог (folder_id). Модель по умолчанию — Qwen3-235B, endpoint подставляется автоматически.

.env — Yandex AI Studio
LLM_PROVIDER=yandex
LLM_API_KEY=<the API key of a YC service account>
LLM_FOLDER_ID=b1g...                       # the Yandex Cloud folder
# the Qwen3-235B model and the llm.api.cloud.yandex.net endpoint are the defaults
запросы не логируются на стороне провайдераБот шлёт x-data-logging-enabled: false — запросы не логируются на стороне Яндекса. Если нужно строгое «код не покидает нашу сеть» — локальная модель ниже.

Облако Anthropic

.env — облако
LLM_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-opus-4-8     # cheaper: claude-sonnet-4-6 / claude-haiku-4-5
моделькогда
claude-opus-4-8максимум качества (дефолт; код-ревью чувствительно к интеллекту)
claude-sonnet-4-6баланс цена/качество
claude-haiku-4-5дёшево и быстро для больших объёмов. Режим рассуждений эта модель не поддерживает — ReviewGate сам повторит запрос упрощённым и скажет об этом в сводке: находок будет меньше и они площе

Бонус Anthropic-пути — prompt caching: системный блок промпта кэшируется, и повторные ревью в том же репозитории читают его из кэша примерно за десятую часть цены входных токенов; судья переиспользует тот же префикс.

Локальная LLM

Для изолированного контура наружу не должно уходить ничего. Ollama и vLLM поднимают OpenAI-совместимый API — бот ходит на него напрямую, без отдельного шлюза. Быстрый старт через Ollama: ollama pull qwen3-coder:30b-a3b-q8_0, затем направьте бота на endpoint:

.env — локально
LLM_PROVIDER=ollama                       # an OpenAI-compatible provider
LLM_BASE_URL=http://localhost:11434/v1    # endpoint Ollama (или vLLM)
LLM_MODEL=qwen3-coder:30b-a3b-q8_0        # the model tag
# LLM_API_KEY=                            # Ollama needs none; OpenRouter/OpenAI require it
LLM_TIMEOUT_MS=900000                     # a very slow local model (the default is 600000)
REVIEW_CONCURRENCY=1                      # SET IT EXPLICITLY: the default is 3, but Ollama serves one at a time (vLLM more)
строгий JSONvLLM соблюдает JSON-схему принудительно (guided decoding); Ollama держит её слабее, поэтому бот дополнительно подстраховывается устойчивым парсером и повтором запроса. Локальная 30B заметно слабее облачного Claude по тонким замечаниям — осознанный трейд-офф за «код не покидает контур».
конкурентность — по возможностям железаЕсли несколько разработчиков открывают MR/PR одновременно, часть ревью встаёт в очередь: бот ведёт их параллельно до REVIEW_CONCURRENCY (дефолт 3). При локальной модели это значение надо снизить под то, что реально тянет ваш инференс: Ollama из коробки обрабатывает запросы по одному — для неё ставьте 1 (параллелизм включается отдельно, см. OLLAMA_NUM_PARALLEL); vLLM умеет вести несколько запросов на одной карте (continuous batching) — ориентируйтесь на его фактическую пропускную способность и запас видеопамяти. Цифра выше возможностей железа ревью не ускорит — очередь просто переедет с бота на GPU. На облачном провайдере ориентир — ваши лимиты RPM/TPM; верхняя граница самого параметра — 64. Памятка по облачным провайдерам — ниже.
код не уходит наружуС локальной моделью весь поток ревью остаётся внутри контура. Подробнее об этом — на странице «Безопасность».

Доступ к провайдеру через прокси

Если ваша сеть не достаёт до провайдера напрямую — корпоративная политика исходящего трафика, региональная блокировка — укажите боту HTTP(S) CONNECT-прокси: он направит туда только запросы к модели. Туннель слепой — TLS до провайдера остаётся end-to-end, прокси видит лишь хост, не код и не дифф.

.env — прокси
LLM_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
LLM_PROXY=http://user:pass@proxy.example.com:8888   # слепой CONNECT-туннель
каждый — свой проксиПрокси задаёт сама инсталляция: вендор не становится узким горлышком, и при блокировке вы решаете вопрос на своей стороне, не затрагивая других. Локальной модели прокси не нужен вовсе — как и провайдеру, до которого ваша сеть достаёт и так.

Несколько провайдеров (мультивендор)

Ансамблевое ревью (llm.generators / llm.judges / llm.arbiter) может разводить роли по разным вендорам: например, основной генератор — Claude, второй — DeepSeek, арбитр — сильнейшая модель Anthropic. Разные модели видят разные проблемы — это поднимает полноту ревью, а арбитр удерживает точность.

Дополнительный вендор объявляется именованным бэкендом в env инсталляции: LLM_BACKEND_<ИМЯ>_BASE_URL / _API_KEY / _MODEL / _PROVIDER / _PROXY / _JSON_MODE / _MAX_TOKENS / _TIMEOUT_MS / _BUDGET_TOKENS (ИМЯ — латиница/цифры без подчёркиваний; имя default зарезервировано — под ним всегда доступен основной провайдер инсталляции, настроенный плоскими LLM_*). В .reviewgate/config.yml роль ссылается на бэкенд по имени: backend: deepseek — ключи и адреса остаются у оператора, из репозитория их не переопределить; backend: default явно адресует основной провайдер.

.env — бэкенд DeepSeek + config.yml — роли
# .env — a named backend (the keys stay with the operator)
LLM_BACKEND_DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
LLM_BACKEND_DEEPSEEK_API_KEY=sk-...
LLM_BACKEND_DEEPSEEK_MODEL=deepseek-v4-flash   # or deepseek-v4-pro
LLM_BACKEND_DEEPSEEK_JSON_MODE=none            # rejects json_schema; json_object returns empty content on long prompts
LLM_BACKEND_DEEPSEEK_MAX_TOKENS=64000          # the reasoning eats the same ceiling as the answer

# .reviewgate/config.yml — review roles across different vendors
llm:
  generators:
    - model: claude-sonnet-4-6      # pass 1 — the main vendor
    - backend: deepseek             # pass 2 — independent, another vendor
  judges:
    - model: claude-opus-4-8        # the judge: weighs the union and collapses duplicates
потолок трат — колонка каталога_BUDGET_TOKENS — бюджет токенов прогона для этого бэкенда (вход + выход + кэш). Политика компании лимитирует дорогие облачные вендоры, локальные — незачем: нет переменной — нет лимита. Барьеры фиксированные (80% нотис · 100% громкий нотис, ревью выполняется целиком · 300% — стоп с публикацией собранного) и пользователями не переопределяются; из config.yml репозитория лимиты недоступны — это ручка оператора. Подробнее — что делать при остановке по бюджету.
сеть и приватность — по вендоруLLM_PROXY на именованные бэкенды не распространяется: если прокси нужен одному из них — задайте его собственный _PROXY. И помните: дифф уходит каждому выбранному вами вендору — оценивайте их политику обработки данных так же, как для основного. Если провайдер не принимает строгую JSON-схему (response_format: json_schema) — поставьте _JSON_MODE=none: форму ответа тогда держат промпт и парсер. Живой пример — DeepSeek: json_schema он отвергает, а его json_object на реальном ревью-прогоне (длинный промпт) отдаёт пустой ответ — JSON уезжает в рассуждения. Reasoning-модели тратят потолок ответа ещё и на размышления — задайте бэкенду свой _MAX_TOKENS (64000 для DeepSeek v4 — то же число не выше потолка Sonnet 5).

Параллельные ревью (REVIEW_CONCURRENCY)

Несколько MR/PR, открытых одновременно, бот ведёт параллельно — по умолчанию до трёх (REVIEW_CONCURRENCY=3, допустимо 1–64). Команде от ~10 разработчиков стоит поднять значение сразу при установке — иначе в часы пик ревью ждут друг друга. Верхнюю планку в пределах диапазона задаёт не бот, а ваш LLM: ревью — токеноёмкий запрос (вход нередко 50–150 тысяч токенов, а ансамбль — несколько вызовов на один MR/PR), поэтому у облачных провайдеров упор обычно случается в лимит токенов в минуту, а не запросов.

облачный провайдерчто ограничивает параллелизмгде смотреть
Anthropicтарифные tier (растут с накопленной оплатой): отдельные лимиты запросов (RPM) и входных/выходных токенов в минуту (ITPM/OTPM). На младших tier токенов может не хватать даже на одно крупное ревью без пауз — рабочий параллелизм появляется с Tier 2–3. Кэш-чтения у актуальных моделей в ITPM не считаются, а бот кэширует системный промпт автоматически — это заметно поднимает реальную пропускную способностьConsole → Limits
OpenAIта же механика: tier-лимиты RPM/TPM на модельPlatform → Limits
DeepSeekжёстких лимитов не публикует — под нагрузкой динамически замедляет ответы: параллелизм работает, но время ответа плаваетdocs API
Yandex AI Studioквоты облака на каталог (запросы в секунду, одновременные генерации); поднимаются запросом на увеличение квотыконсоль YC → Квоты
OpenRouterлимиты зависят от ключа/баланса и провайдера, на которого маршрутизируется модельЛК OpenRouter
упёрлись в лимит — не страшно, но медленноКогда конкурентных ревью больше, чем пропускает провайдер, лишние запросы получают 429/перегрузку. Бот такие ревью не роняет: повторяет с паузами, а при затяжной перегрузке честно пишет уведомление в MR/PR. Но очередь при этом тянется — поэтому поднимайте значение постепенно и смотрите на тайминги в блоке «🔬 Диагностика прогона». Для локальной модели — врезка выше: ориентируйтесь на возможности инференса, а не на число в конфиге.

Тюнинг

.env — тюнинг
LLM_EFFORT=high              # low | medium | high | xhigh | max
LLM_MAX_TOKENS=16000         # the cap on output tokens
LLM_DIFF_CHAR_BUDGET=400000  # the character budget for the diff in the prompt (~100K tokens)
LLM_CACHE_TTL=1h             # the prompt cache TTL (Anthropic only): 1h | 5m | off
конфиг важнее envРоли в .reviewgate/config.yml переопределяют эти переменные — можно держать настройку модели рядом с кодом проекта.