Skip to content

ИИ-поддержка — это LLM-ассистент, который отвечает клиентам в тикетах и помогает наполнять базу знаний. Работает как fallback за движком автоответов по шаблонам: если ни одно правило не сработало, ассистент собирает контекст (клиент/подписка/сервера/статьи вики/история тикета), спрашивает у LLM ответ + уверенность и либо отправляет клиенту сам (высокая уверенность), либо кладёт черновик админу в чат тикета.

Дополнительно есть База знаний (/ai-knowledge) — внутренняя вики, куда админ вносит статьи, ассистент читает их через семантический поиск и цитирует в ответах. Плюс — вкладка «Предложения ИИ», которая генерирует статьи из истории закрытых тикетов и требует апрува от админа.

Что нужно для работы

  • Провайдер LLM с OpenAI-совместимым API. По умолчанию — OpenRouter, потому что один ключ покрывает и chat, и embeddings, и любую модель. Работают также OpenAI, Anthropic (через OpenRouter), Ollama, LM Studio, vLLM — всё, что говорит по контракту POST {base}/chat/completions.
  • Отдельная pgvector-БД (сервис kb-db в compose) — сюда пишется база знаний. Основная БД pgvector не требует.
  • Опционально: модель эмбеддингов — включает семантический поиск в вики и умную дедупликацию сгенерированных статей.

Приоритеты стоимости

Дороже всего LLM платит за автоответ клиентам в тикетах: он вызывается на каждое новое сообщение без сработавшего правила. Всё остальное (генерация статей, эмбеддинги) — по требованию.

Быстрый старт

  1. Добавьте сервис KB-БД в docker-compose.yaml — рядом с существующим db:

    yaml
    services:
      # Dedicated pgvector DB for the AI support knowledge base. Optional:
      # the bot runs fine without it (AI_KB_DATABASE_URL empty = KB/RAG disabled).
      kb-db:
        image: pgvector/pgvector:pg18
        container_name: 'rwp-shop-kb-db'
        restart: unless-stopped
        environment:
          - POSTGRES_USER=${AI_KB_POSTGRES_USER:-kb}
          - POSTGRES_PASSWORD=${AI_KB_POSTGRES_PASSWORD:-kb}
          - POSTGRES_DB=${AI_KB_POSTGRES_DB:-kb}
          - TZ=UTC
        ports:
          - '127.0.0.1:4312:5432'
        volumes:
          - kb-db-data:/var/lib/postgresql
        healthcheck:
          test: [ 'CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}' ]
          interval: 3s
          timeout: 10s
          retries: 3
        # Добавляйте только если бот и Remnawave находятся на одном сервере
        # и подключены к одной Docker-сети.
        networks:
          - remnawave-network
    
    volumes:
      kb-db-data:
        driver: local
        external: false
        name: rwp-shop-kb-db-data

    Также добавьте AI_KB_DATABASE_URL в environment сервиса bot, чтобы он видел новую БД:

    yaml
    services:
      bot:
        environment:
          - AI_KB_DATABASE_URL=${AI_KB_DATABASE_URL:-}

    Поднимите:

    bash
    docker compose up -d kb-db

    Схема создаётся автоматически при первом запуске бота — миграцию накатывать не надо.

  2. Пропишите переменную окружения в .env:

    AI_KB_DATABASE_URL=postgres://kb:kb@kb-db:5432/kb?sslmode=disable

    Пусто = KB и RAG выключены (ассистент всё равно работает, но без базы знаний).

  3. Перезапустите бота:

    bash
    docker compose down && docker compose up -d
  4. Настройте провайдера LLM в админ-панели/ai-settings:

    • Base URL: пусто (= OpenRouter), либо https://api.openai.com/v1, либо URL Ollama и т.д.
    • Модель: openai/gpt-4o-mini, anthropic/claude-sonnet-5 и т.д. (список подгружается автокомплитом из API провайдера).
    • API-ключ: ключ провайдера.
    • Модель эмбеддингов: openai/text-embedding-3-small (для OpenRouter/OpenAI). Пусто = семантический поиск выключен.
    • Включите «Включить ассистента».
  5. Наполните базу знаний/ai-knowledge → «Статья». Одна статья = одна тема + плейн-текст. Разметка не нужна — модель читает содержимое напрямую.

  6. Готово. Откройте тикет от тестового клиента — при уверенности выше порога ассистент ответит сам, иначе черновик появится над строкой ввода в чате тикета у админа.

Настройки на /ai-settings

Ассистент

  • Base URL — OpenAI-совместимый эндпоинт. Пусто = OpenRouter (https://openrouter.ai/api/v1).
  • Модель — идентификатор модели у провайдера (например openai/gpt-4o-mini). Автокомплит из /v1/models.
  • API-ключ — маскированное поле. Ключ пишется в таблицу settings (не в env), как остальные секреты платёжных провайдеров.
  • Системный промпт — что модель делает, тон общения, границы. Пусто = встроенный дефолт с базовыми правилами (только факты из контекста, не менять аккаунт, эскалировать деньги/юридику).
  • Язык ответов — фиксированный язык (ru, en, uk, …). Пусто = язык клиента.

Порог и лимиты

НастройкаДефолтСмысл
Порог уверенности0.75Ниже — черновик админу, ≥ — автоответ клиенту. 1.0 = все ответы кладём в черновики.
Максимум вызовов на тикет в час3Защита от петли/раскрутки счёта
Дебаунс, сек30Не отвечать, если бот/админ уже писал недавно
Максимум токенов ответа1024Максимум output-токенов
Temperature0.3Ниже — детерминированнее, выше — креативнее
Сообщений истории в контексте12Сколько последних сообщений тикета видит модель
Заметки админавыклПередавать ли модели admin_notes клиента

Уведомления

  • Уведомлять админов о черновиках — Telegram-уведомление, когда модель не уверена и оставила черновик. Приходит с кнопками «Открыть чат» + «Открыть в браузере».
  • Очередь эскалации — при неуверенном ответе тикет автоматически перекладывается в выбранную очередь. Пусто = не перекладывать.

Эмбеддинги (RAG)

  • Модель эмбеддингов — например openai/text-embedding-3-small. По умолчанию использует основной Base URL и ключ (OpenRouter умеет и то и другое). Можно переопределить.
  • Размерность вектора1536 для OpenAI. Фиксируется при первом создании таблицы KB — смена требует пересоздания таблицы (см. Смена embedding-модели).
  • Статей в контексте (top-N) — сколько ближайших статей передаётся модели. 5 — обычно достаточно.
  • Категория шаблонов-фолбэка — если KB-БД не подключена, ассистент возьмёт шаблоны сообщений этой категории. Полностью опционально.
  • Переэмбеддить базу знаний — кнопка. Запускать после смены embedding-модели: перечитывает все статьи и генерирует эмбеддинги заново.

Плейсхолдеры и разделы

Ассистент умеет вставлять в ответ шаблонные переменные ({plan_name}, {days_left}, {share_link_url}, …) и ссылки на разделы мини-аппа (#[cabinet], #[install], #[billing], …). Модель видит только те переменные и ссылки, которые вы отметили в MultiSelect. Пустой список = разрешены все.

Полный список — см. Плейсхолдеры и разделы.

База знаний (/ai-knowledge)

Вкладка «Статьи»

Обычный CRUD. Каждая статья:

  • Заголовок — короткая формулировка вопроса или темы.
  • Содержимое — плейн-текст (не Markdown). Хорошо работает шаблон «Проблема → Решение (шаги) → Что делать, если не сработало».
  • Теги — свободные, для админ-поиска. Модель их не использует.
  • Переключатель «Использовать в ответах» — выключенная статья не участвует в поиске.

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

Вкладка «Предложения ИИ»

Пройтись по всем закрытым тикетам и попросить LLM сгенерировать статьи. Каждое предложение требует апрува админа перед сохранением.

Как работает:

  1. Админ жмёт «Сгенерировать из тикетов», задаёт период дат и лимит тикетов.
  2. Кнопка «Рассчитать» показывает количество тикетов, батчей и оценку токенов + предупреждение о стоимости.
  3. «Запустить» — фоновая генерация через sequence-очередь. Тикеты режутся на батчи (по умолчанию 15 на батч), каждый батч — один вызов LLM.
  4. Для каждой сгенерированной статьи считается семантический дедуп: если топ-1 сходство с существующей статьей ≥ порога (0.85 по умолчанию) — она помечается «Дубль» и не мешает работать с настоящими новыми статьями.
  5. Админ смотрит карточки, редактирует title/content/tags при желании, жмёт «Принять» (записывается в базу знаний) или «Отклонить».

Стоимость

Генерация — один LLM-вызов на батч. По оценке для средней инсталляции с 500 закрытых тикетов это ~34 батча и порядка 3-4 млн input-токенов. Реальная стоимость зависит от модели и провайдера — модалка показывает оценку в токенах, курс в USD смотрите у провайдера.

Настройки генерации из тикетов

Задаются в таблице settings (в UI не выведены — обычно дефолтов достаточно):

  • ai_kb_gen_batch_size = 15 — тикетов на LLM-вызов.
  • ai_kb_gen_max_messages_per_ticket = 20 — сколько последних сообщений тикета передаётся модели.
  • ai_kb_gen_duplicate_threshold = 0.85 — порог сходства для дедупа.

Автоответы в тикетах

Как срабатывает

Ассистент подключён как fallback после движка автоответов по шаблонам. Порядок:

  1. Клиент пишет в тикет.
  2. Проверяется, есть ли активное правило автоответа для триггера (new_ticket / new_message) — если да, отправляется шаблон, ассистент не вызывается.
  3. Если правила нет — включается ассистент (только для тикетов основного бота, bot_id = 0).
  4. Ассистент собирает контекст, спрашивает у LLM и:
    • уверен (score ≥ порога) → отправляет ответ клиенту как бот, тикет переходит в awaiting_reply, дальше существующий cron авто-закрытия закрывает тикет, если клиент не отвечает;
    • не уверен → пишет строку в support_ai_draft с status='pending_review', админ видит черновик в чате.

Что видит модель

В каждый запрос уходит:

  • Текущее время (UTC) — иначе модель не знает, какой сегодня день, и не может отвечать «сколько дней осталось».
  • Клиент — язык, скидка, температура лида, при опции — заметки админа.
  • Подписка — тип, дата окончания + предвычисленное days_left, доп. устройства.
  • Тариф — имя, тип, лимит трафика/устройств.
  • Состояние серверов — сводка из healthcheck + статус VPN-нод из xray-checker (если настроен).
  • База знаний — top-N ближайших статей по эмбеддингу последнего сообщения клиента.
  • История тикета — последние N сообщений + subject.
  • Список разрешённых плейсхолдеров и разделов — только те, что отмечены в настройках.

Черновики в чате тикета

Панель «Черновик AI» появляется над строкой ввода в чате тикета у оператора. Три кнопки:

  • В поле — вставить черновик в composer для правки перед отправкой.
  • Отправить — доставить клиенту как бот (те же каналы, что автоответ).
  • Отклонить — отбросить.

При ручном ответе админа в тикет все pending-черновики этого тикета автоматически помечаются dismissed — не копятся.

Смена embedding-модели

Размерность вектора фиксируется при первом создании таблицы KB. Если вы включили эмбеддинги с text-embedding-3-small (1536), а потом захотели перейти на модель с 3072 — таблицу нужно пересоздать:

bash
docker compose exec kb-db psql -U kb -d kb -c "DROP TABLE support_ai_knowledge"

После этого:

  1. Обновите Модель эмбеддингов и Размерность вектора на /ai-settings.
  2. Перезапустите бота — таблица создастся с новой размерностью.
  3. Верните статьи (если экспортировали) или включите «Переэмбеддить базу знаний» — если статьи не удалялись, эмбеддинги перегенерятся.

Плейсхолдеры и ссылки

Модели передаётся список разрешённых плейсхолдеров и разделов. Разворачивает их сервер уже перед доставкой клиенту.

Плейсхолдеры

ПлейсхолдерЗначение
{username}@username из Telegram
{first_name}Имя
{telegram_id}ID клиента в Telegram
{plan_name}Текущий тариф
{sub_name}Имя основной подписки
{expire_date}Дата окончания подписки
{days_left}Осталось дней до окончания
{time_left}Осталось времени (человекочитаемо)
{link_sub}Прямая ссылка на подписку
{share_link_url}Одноразовая ссылка «Установить на другое устройство»
{referral_link}Реферальная ссылка через бот
{referral_link_web}Реферальная ссылка через веб

Разделы

Разворачиваются в кликабельные ссылки в мини-аппе:

#[dashboard], #[plans], #[billing], #[purchases], #[promos], #[referrals], #[cabinet], #[security], #[server], #[install], #[traffic], #[support], #[partner]

Стоимость и лимиты

Что тратит токены:

ОперацияЧастотаОбычная стоимость
Автоответ клиентуНа каждое новое сообщение без сработавшего правилаОсновная строка расхода
Эмбеддинг статьи викиПри создании/редактировании статьиКопейки
Эмбеддинг запроса клиентаКаждый автоответ (для RAG)Копейки
Генерация статей из тикетовПо кнопке админаЕдиницы-десятки долларов на 500-1000 тикетов
Переэмбеддить базу знанийПо кнопке админаКопейки на десятки статей

Устранение неполадок

Модель не отвечает / молчит. Проверьте: (а) ai_support_enabled включено, (б) модель настроена, (в) API-ключ настроен, (г) бот перезапущен после смены AI_KB_DATABASE_URL. Логи ai-support: ... в stdout бота.

Клиенту приходит {plan_name} вместо имени тарифа. Проверьте, что в MultiSelect «Доступные плейсхолдеры для ИИ» этот ключ отмечен. Пусто = разрешены все.

«База знаний недоступна». AI_KB_DATABASE_URL не задан или KB-БД не запущена. docker compose up -d kb-db + перезапуск бота.

RAG отключён, ассистент только по шаблонам. Модель эмбеддингов не задана либо неверный ключ. Проверьте /ai-settings → «Эмбеддинги».

Генерация статей не стартует. Убедитесь, что настроен провайдер LLM (кнопка «Запустить» гейтится успешным «Рассчитать» и наличием KB-БД). Если запустилась, но не идут пропозалы — смотрите логи sequence-worker в stdout бота.