← AI Advent 2026

День 30: свой сервис на локальной модели

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

Итог дня

Читаю результаты прогона…

Читаю результаты прогона…

  • Повторов на каждую пробу — нет данных. Разницу в секунду этот замер от шума не отличает.
  • Пробы через прод работают только при включённой частной сети на ноутбуке, и включает её владелец на окно проверки. Пока сеть выключена, все пробы этим путём дают один и тот же ответ «провайдер недоступен» и ни одной гипотезы не различают.
  • Судьи и оценок качества здесь нет: страница показывает коды ответов и времена, а не то, насколько ответ хорош. Проверить ответ по этой странице нельзя.
  • Ограничение, у которого нет отрицательной пробы, помечено словом «не проверялось». Защита без проверки — не защита.
Как это мерено

Два пути, и они разные по сути. Через публичный API — тот самый адрес, которым идёт посетитель: запрос уходит на сервер, сервер выбирает локального провайдера и дотягивается до ноутбука по частной сети. Напрямую в Ollama — запрос с самого ноутбука на петлю, без сервера и без сети вовсе.

«Полное время» — настенное время от первого отправленного запроса до последнего полученного ответа, а не сумма времён запросов: при очереди это не одно и то же. «Обслужено» и «Отказано» считаются по коду ответа, причина отказа берётся из тела ответа дословно.

Прогон записывает коды, времена и причины. Текстов ответов он не записывает вовсе — не прячет, а не получает: то, чего в записи нет, не может утечь на публичную страницу.

Чего этот замер не мерил
  • Качества ответов. Их тексты сюда не идут; что модель отвечает по делу, мерено в днях 26 и 28, а не здесь.
  • Потолка железа. Ноутбук был в обычной работе владельца, а не на изолированном стенде.
  • Устойчивости во времени. Пробы шли одним окном в один день; что будет через неделю работы, этот замер не говорит.
  • Поведения при многих посетителях. Запросы шли с одного адреса; ограничение частоты на адрес при этом видно, а общая нагрузка сайта — нет.
  • Потолка размера запроса у роутера. Снаружи он недостижим: публичный API обрезает тему раньше, и до роутера длинный запрос не доходит.

Что уже было закрыто

  • Ноутбук владельца доступен серверу как домашний сервер: частная сеть до машины, служба Ollama слушает только её адрес, а не все интерфейсы.

    Закрыто раньше09.09.2026

    ADR 2026-09-09-0258 · запись 2026-09-09-0258-mac-tailnet.md

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

    Закрыто раньше08.09.2026

    ADR 2026-09-08-1748 · router/config/providers.json · router/src/health.js

  • Чат на локальной модели уже в проде: день 11 работает с профилями и слоями памяти, и воспроизводить его здесь незачем.

    Закрыто раньше16.09.2026

    день 11 · days/day11/

  • Именной ключ и суточный потолок на ключ, а также полностью локальный контур ключевого профиля — решение принято и выкачено до этой недели.

    Закрыто раньше07.10.2026

    ADR 2026-10-07-1349 · запись 2026-10-08-0957-keyed-uncensored-model-server.md

  • Порядок «лимит до вызова» — инвариант проекта, а не настройка: ни один запрос не вызывает модель раньше, чем пройдёт проверку частоты и суточного лимита.

    Закрыто раньше07.09.2026

    инвариант I-4 · days/day5/limits.js

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

Доступ

Чем именно закрыт сервис, что увидит посетитель без доступа и где живёт ключ. Значений ключей, адресов частной сети и имён машин в ней на этой странице нет — ни в тексте, ни в данных.

Читаю результаты прогона…

Ограничения: что сработало

По каждому ограничению — его значение, сработало ли оно на отрицательной пробе и что при этом увидел клиент. Код ответа и текст ошибки стоят как есть: именно их получает посетитель, а не пересказ.

Читаю результаты прогона…

Почему проба частоты дала не только отказ по частоте

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

Для проверяемого утверждения этого достаточно: ограничение частоты срабатывает и клиент видит ровно тот код и текст, которые стоят в таблице. Чего проба не говорит — это каким по счёту запросом ограничение включается: для такого счёта нужно чистое окно, а окно было занято.

Окно частоты считается на адрес, и значение потолка взято из таблицы выше, а не из этого текста. Потолок размера запроса у роутера снаружи недостижим вовсе: публичный API отвергает слишком длинную тему раньше, чем запрос дойдёт до роутера, — поэтому в таблице стоит ограничение публичного API, а не роутера.

Чат на локальной модели

Чат по локальной модели уже работает в проде — это день 11 с профилями и слоями памяти. Эта страница его не воспроизводит: второй экран с тем же назначением был бы вторым источником правды, а не новой возможностью.

Открыть день 11

Пример вызова

Через публичный API
curl -sS https://challenge.zpq.ai/day5/api/answer -H 'content-type: application/json' -d '{"sphere":"fintech","model":"mac-qwen3","maxTokens":64}'

Ключа в этой команде нет, и это не пропуск: публичный API ключа от клиента не требует вовсе, а ключ приложения для роутера живёт на сервере и до браузера не доходит. Адреса ноутбука в частной сети здесь тоже нет — путь до него выбирает сервер, а не клиент.

Задание дня

День 30 «Локальная LLM как приватный сервис»: на VPS или домашнем сервере, HTTP API, чат; проверить доступ по сети, стабильность при нескольких запросах, базовые ограничения (rate limit / max context).