LLM и свой ключ
ReviewGate работает на вашей LLM. Провайдер за абстракцией: облако Anthropic, любой OpenAI-совместимый endpoint, модель подешевле или локальная модель в вашем контуре.
Yandex AI Studio
Один из OpenAI-совместимых провайдеров — полезен, когда данные должны оставаться в определённой юрисдикции. Нужны API-ключ сервисного аккаунта (роль ai.languageModels.user) и каталог (folder_id). Модель по умолчанию — Qwen3-235B, endpoint подставляется автоматически.
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 defaultsx-data-logging-enabled: false — запросы не логируются на стороне Яндекса. Если нужно строгое «код не покидает нашу сеть» — локальная модель ниже.Облако Anthropic
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:
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)REVIEW_CONCURRENCY (дефолт 3). При локальной модели это значение надо снизить под то, что реально тянет ваш инференс: Ollama из коробки обрабатывает запросы по одному — для неё ставьте 1 (параллелизм включается отдельно, см. OLLAMA_NUM_PARALLEL); vLLM умеет вести несколько запросов на одной карте (continuous batching) — ориентируйтесь на его фактическую пропускную способность и запас видеопамяти. Цифра выше возможностей железа ревью не ускорит — очередь просто переедет с бота на GPU. На облачном провайдере ориентир — ваши лимиты RPM/TPM; верхняя граница самого параметра — 64. Памятка по облачным провайдерам — ниже.Доступ к провайдеру через прокси
Если ваша сеть не достаёт до провайдера напрямую — корпоративная политика исходящего трафика, региональная блокировка — укажите боту HTTP(S) CONNECT-прокси: он направит туда только запросы к модели. Туннель слепой — TLS до провайдера остаётся end-to-end, прокси видит лишь хост, не код и не дифф.
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 — 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 |
Тюнинг
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