Перейти к содержимому
GitRiverGitRiver
EN
Навигация

Помощник на языковых моделях

Разбор упавшей сборки и изменений пулл-реквеста языковой моделью: выбор поставщика, граница закрытого контура, учёт расхода и пределы

Появилось в 1.1.0. В версии 1.0.0 этой возможности нет — что меняется при переходе.

Помощник разбирает упавшие задачи CI по журналу и изменения пулл-реквеста. Модель выбирает администратор установки: свой узел внутри контура или облачный поставщик с OpenAI-совместимым интерфейсом. Возможность редакции Pro.

Настройка: Администрирование → Помощник ИИ.

Граница контура

Это первое, что нужно знать при развёртывании в закрытом контуре.

Ненастроенный или выключенный помощник не делает ни одного исходящего запроса. Отказ выдаётся до того, как собран запрос к модели: содержимое журнала никуда не уходит. Установка без настроенного поставщика ведёт себя ровно так, как если бы помощника в продукте не было.

Настроенный помощник обращается ровно по одному адресу - тому, что задал администратор. Автоматические переходы по 3xx запрещены: ответ чужого сервера не может увести содержимое запроса на другой хост.

Поставщик Схема Адрес Куда уходит содержимое
Свой узел http или https любой, включая приватные диапазоны внутрь контура
Облачный только https обязан резолвиться в публичный адрес (защита от SSRF) внешнему поставщику

Приватные диапазоны разрешены только своему узлу: http://ollama:11434/v1 в сети docker резолвится в приватный адрес, и общий запрет закрыл бы именно тот случай, ради которого закрытый контур и разворачивают. Облачному поставщику http запрещён: исходный код уходил бы на чужую сторону открытым текстом.

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

Секреты CI в журнал не попадают: значения маскируемых переменных вырезаются при записи журнала, то есть ещё до того, как журнал может быть отдан модели.

Поставщики

Подходит любой сервер с интерфейсом POST {base_url}/chat/completions:

  • Ollama - http://узел:11434/v1, модель вида qwen2.5-coder:7b;
  • vLLM, llama.cpp server, LM Studio - свой адрес, модель по имени;
  • облачные поставщики с тем же интерфейсом - https://…/v1 и ключ доступа.

Ключ доступа хранится зашифрованным (AES-256-GCM) и не возвращается ни в одном ответе API: интерфейс показывает лишь признак «задан». Пустое поле ключа при правке настроек означает «оставить прежний».

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

Сколько ждать модель. «Ожидание ответа» - от 1 до 600 секунд, по умолчанию 180. Три минуты, а не одна: рассуждающая модель думает до ответа, а локальная на процессоре считает медленно. Если модель не уложилась, участник видит именно это - «модель не ответила за столько-то секунд», а не «поставщик недоступен».

Разбор упавшей задачи CI

На странице конвейера у упавшей задачи появляется кнопка «Разобрать сбой». Помощник получает контекст задачи (репозиторий, ветка, имя, стадия, код возврата, образ) и хвост журнала, а возвращает причину, объяснение и что сделать.

  • Ответ помечен как машинный - читателю видно, что текст написан не человеком, и какой моделью.
  • Журнал отдаётся хвостом: причина падения почти всегда в конце, а начало занято установкой зависимостей. Если журнал не поместился целиком, об этом сказано и модели, и читателю.
  • Разбор доступен тем, у кого есть право записи в репозиторий. Права на чтение недостаточно намеренно: обращение тратит месячный предел владельца репозитория, и на публичном репозитории посторонний исчерпывал бы чужой предел одним циклом запросов.
  • Успешная задача на разбор не отправляется.

Разбор изменений пулл-реквеста

Участник с правом записи нажимает «Разобрать изменения». Модель получает заголовок, описание, ветки и текст изменений, а ответ публикуется обычным комментарием с пометкой «Сгенерировано моделью».

  • Комментарий обычный намеренно: иначе разбор не попал бы ни в ленту обсуждения, ни в ветки, ни в счётчик нерешённых. Пометку ставит сервер; объявить свой комментарий машинным клиент не может.
  • Автор комментария - тот, кто запросил разбор: видно, по чьей просьбе он появился, а права на правку и удаление остаются обычными.
  • Файлы отдаются модели целиком и по порядку, пока хватает объёма: половина патча - это выдуманный контекст, по которому модель делает выводы о коде, которого не видела. Двоичные и не поместившиеся файлы перечисляются отдельно.
  • Запрос без изменений на разбор не отправляется.

Учёт расхода и пределы

Расход относится на владельца репозитория - пользователя или группу, ту же сторону, на которую считаются квоты хранилища. Не на того, кто нажал кнопку: разбор сборки командного репозитория - расход команды.

Окно учёта - календарный месяц. Умолчание задаётся в настройках помощника, переопределение владельца - в таблице расхода. Ноль означает «без ограничения», и переопределение важнее умолчания: ноль у владельца снимает предел установки, а не запрещает обращения.

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

Сверх месячного предела действует предел частоты - 10 обращений в минуту на клиента, общий для разбора сбоя, разбора изменений и проверки связи. Превышение - 429 с заголовком Retry-After.

Что видно в отказе. Подробность отказа поставщика уходит только администратору - в проверку связи и в журнал сервера. Тому, кто нажал «Разобрать сбой», возвращается код отказа без подробностей: поставщики возвращают в сообщениях префикс предъявленного ключа, а текст ошибки соединения содержит адрес узла модели.