Каждый, кто делал бота поддержки или автоматизацию на языковых моделях, знает эту боль. Вы отправляете текст клиента в облачный API, ждёте, пока запрос долетит до дата-центра, отстоит очередь и вернётся, а потом ещё разбираете вежливый абзац, чтобы понять: так это жалоба или вопрос о доставке? Платите за каждый вызов. И молитесь, чтобы интернет не моргнул.

Cortiq Mobile делает то же самое иначе. Модель решений лежит в памяти вашего телефона, отвечает одним JSON и не тратит время на дорогу: на реальном Android-смартфоне нативное решение занимает 13–22 миллисекунды (Jev1.3 при хорошей связи 350-900мс). Это не чат, который что-то «пишет». Это классификатор с честным «не знаю», доступный по HTTP любой программе в вашей сети.

Локальная Decision-модель на iPhone приняла решение
Локальная Decision-модель на iPhone приняла решение

Решение принято прямо на телефоне: вариант card_arrival, уверенность 99,8 %. Ниже на экране — время, которое ушло на ответ.

Приложение: Google Play · исходный код: infosave2007/cmfmobile · документация Decision API: docs/mobile-decision.md

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

Обычная языковая модель генерирует текст токен за токеном. Модель решений не генерирует ничего. У неё есть навыки — наборы меток. Например, навык banking77 знает 77 типов банковских запросов, clinc150 — 150 бытовых намерений, massive — команды голосового ассистента. Получив текст, модель оценивает, какая метка описывает его лучше всего, и возвращает её вместе с уверенностью. Если уверенности мало, она отказывается — и это штатный ответ, а не ошибка.

Для кода это меняет всё. Вместо «попросить модель ответить в JSON и надеяться» вы получаете контракт: три поля, которые всегда на месте.

{"accepted": true, "choice": "card_arrival", "confidence": 0.998}

Правило одно: действуете при accepted: true и непустом choice. Пришло accepted: false и choice: null — отдаёте задачу человеку или уходите в безопасную ветку. Никаких регулярок по свободному тексту.

Запуск за пять минут

  1. Установите Cortiq Mobile на Android из Google Play (на iPhone — через TestFlight).

  2. Скачайте модель решений. Модели → Hugging Face → Готовые → infosave/cmf-decision. Нажмите «Скачать», затем «Загрузить в движок». Первая вкладка приложения станет «Решения» — там можно сразу проверить модель вручную: выбрать навык, нажать «Подставить пример» и «Принять решение».

  3. Запустите сервер. Вкладка «Сервер» → включите «Требовать bearer-токен» → «Запустить сервер». На экране появятся адрес телефона, токен и QR-код. Порт по умолчанию — 8080.

Всё. Телефон стал сервером принятия решений для вашей локальной сети.

Первый запрос

# PHONE_TOKEN возьмите с экрана «Сервер»; не храните его в исходниках.
curl "http://PHONE_IP:8080/v1/decide" \
  -H "Authorization: Bearer $PHONE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"skill":"banking77","text":"Where is my card?","profile":"balanced"}'

Ответ придёт с полями accepted, choice, confidence, а также с таймингами: timings_us.total — полное время работы модели, resonance — только этап сравнения с метками. Поле profile задаёт политику уверенности: balanced для большинства задач, quality-first, когда ложное срабатывание дороже отказа, cost-saver, когда важнее принять решение.

Тот же вызов из Python:

import requests

PHONE = "http://PHONE_IP:8080"
HEADERS = {"Authorization": f"Bearer {PHONE_TOKEN}"}

def decide(skill: str, text: str) -> str | None:
    r = requests.post(f"{PHONE}/v1/decide", headers=HEADERS,
                      json={"skill": skill, "text": text, "profile": "balanced"},
                      timeout=5)
    r.raise_for_status()
    d = r.json()
    return d["choice"] if d["accepted"] and d["choice"] else None

label = decide("banking77", "I still have not received my new card")
if label == "card_arrival":
    open_card_delivery_ticket()
elif label is None:
    escalate_to_human()

Какие навыки есть и что они умеют

Не нужно держать список меток в голове — спросите у телефона:

curl -H "Authorization: Bearer $PHONE_TOKEN" http://PHONE_IP:8080/v1/skills
curl -H "Authorization: Bearer $PHONE_TOKEN" http://PHONE_IP:8080/v1/skills/banking77

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

Для сложных сценариев есть типизированный маршрут POST /v1/decisions: вы передаёте состояние (state) и список вопросов (questions), а получаете ответ на каждый. Это тот же контракт Cortiq, что и в настольной версии, так что код переносится между телефоном и сервером без изменений.

Насколько быстро и сколько клиентов выдержит

Мы проверяли на Xiaomi с Android 14 по обычному домашнему Wi-Fi, клиент — ноутбук. Нативное решение внутри телефона — 13–22 мс. Полный HTTP-запрос с сетью, разбором JSON и очередью:

Клиентов одновременно

Решений в секунду

Задержка p50 / p95

1

13,6

63 / 137 мс

4

27,4

135 / 209 мс

При 16 параллельных клиентах телефон не копит бесконечную очередь, а честно отвечает 429 «подождите» лишним запросам, обрабатывая остальные с той же скоростью. Для интеграций оптимально 1–4 клиента: этого хватает на десятки решений в секунду. Все 22 проверки контракта прошли, включая корректные коды ошибок: 400 на битый JSON, 401 без токена, 404 на неизвестный навык. Полный протокол — в репозитории.

Для сравнения масштаба: 63 миллисекунды — это полный круг по Wi-Fi до телефона и обратно, включая само решение. Облачному API за это время обычно хватает лишь на то, чтобы установить соединение.

Когда модель не уверена: оракул по вашему желанию

Отказ модели — не тупик. В приложении есть оракул: при отказе локальной модели вы можете одним нажатием отправить запрос внешнему HTTPS-провайдеру с вашим собственным ключом (по умолчанию предлагается MiMo через OpenRouter, но подойдёт любой OpenAI-совместимый). Оракул выключен по умолчанию, включается в «Настройки → Оракул», каждый внешний вызов требует подтверждения, а ключ лежит в защищённом хранилище телефона. Через API телефона ключ потратить невозможно: удалённый клиент получает только локальные решения.

Оракул выключен по умолчанию
Оракул выключен по умолчанию

Оракул выключен по умолчанию и включается только вручную.

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

Два совета напоследок

Включайте токен до запуска сервера и держите телефон в домашней или офисной сети: локальный API работает по HTTP и рассчитан на доверенное окружение. Одна модель в памяти — пока загружена модель решений, чат-маршруты отвечают 409; это нормально, так телефон защищает вас от путаницы между двумя разными API.

Итог

Классификация намерений, маршрутизация заявок, фильтрация команд для умного дома, первая линия поддержки — всё это задачи, где нужен не текст, а решение. Cortiq Mobile даёт для них API, который живёт в телефоне, отвечает за десятки миллисекунд, не требует подписки и умеет честно сказать «не знаю». Загрузите модель, запустите сервер, сделайте первый curl — дальше это просто ещё один сервис в вашей сети. Только быстрее и ваш.

Ссылки

Комментарии (1)


  1. JBFW
    02.10.2026 14:54

    Предполагаю внутри подобие rag-системы: ищет нечто релевантное, вместо текста отдает Y/N...