Агрегатор отрезал нас по IP
В конце июля весь текстовый маршрут лёг разом: агрегатор, через который шли запросы к языковым моделям, начал отдавать отказ «доступ запрещён политикой безопасности» на все три боевых адреса. Я проверил три версии по очереди. Блокировка аккаунта — не подтвердилась: тот же отказ приходил и на публичный список моделей, где ключ вообще не нужен. Проблема с ключом — не подтвердилась: тот же ключ из другой страны работал. Обход через прокси-шлюз, которым мы уже пользовались для другого вендора, — не помог. Осталось единственное объяснение: режут по адресу, а не по аккаунту, и разговор с поддержкой это не ускорит.
Я убрал посредника и пошёл в официальные интерфейсы вендоров напрямую. Появился отдельный реестр: чистое описание «модель → вендор, адрес, заголовки, идентификатор», без сетевого кода вообще. Способ доставки сделал свойством вендора, потому что замеры на бою дали разное: к одному вендору с наших адресов пускают напрямую, другой отвечает отказом и работает только через шлюз. Наружу формат потокового ответа не изменился ни на байт — ни мини-приложение, ни бот про вендоров не знают. Самое интересное нашлось не по документации, а сквозным прогоном на боевом контуре: один вендор отвергает привычное имя параметра для лимита ответа и требует своё, другой честно перечисляет модель в каталоге, но на генерации отвечает, что её больше нет. Оба случая по списку моделей невидимы — только живой запрос.
Фактура
- Симптом: отказ 403 с текстом про политику безопасности на всех трёх боевых адресах.
- Отвергнутые гипотезы: бан аккаунта (опровергнут безключевым запросом), плохой ключ (опровергнут запуском из другой географии), обход шлюзом (не сработал).
- Реестр вендоров — модуль без ввода-вывода: только резолв. Транспорт — свойство вендора; поддерживаются два «провода»: совместимый с общепринятым интерфейсом и нативный у одного из вендоров.
- Найдено только сквозным прогоном: отказ 400 на имя параметра максимальной длины ответа (имя параметра переехало в реестр, отдельно на вендора); отказ 404 «модель больше недоступна» на модель, присутствующую в каталоге; обязательный путевой префикс совместимого слоя, который нельзя терять при проксировании.
- Попутно закрыт рассинхрон хранимого имени модели: сервис писал короткий ключ, бот — полную строку, из-за чего выбор модели в интерфейсе сбрасывался на дефолтный.
- Предохранитель внешних вызовов разнесён по вендорам (раньше был общий) и научился учитывать успехи, а не только отказы.
- Служебные вызовы (перевод ответа, разбор изображения) отвязаны от жёстко зашитых моделей и переведены на «самую дешёвую доступную».
- Экономика при фиксированной цене ответа: потолок вывода снижен с 4096 до 1500 токенов, обрезка истории переведена с «последних 30 сообщений» на бюджет по токенам, у одного вендора включено кэширование префикса запроса.