AI-агент
Единый AI-модуль биллинга: база знаний, инструменты, разбор звонков, виджет для сайта, помощник в разделах панели и дашборд сессий.
Содержание раздела
AI-агент — единый универсальный AI-модуль
Всё, что касается искусственного интеллекта, собрано в одном нативном модуле /admin/ai/: мультипровайдерный чат с инструментами на прямом ORM, база знаний для бота и операторов, голосовой разбор звонков, собственный виджет для сайтов с настройками из админки и запись лидов в нашу CRM. Все ключи, промпты, история, дашборд и внешний вид виджета живут в биллинге (или на сервере лицензий), без зависимости от сторонних серверов.
Где живёт поведение бота, что он умеет вызывать сам, почему цены нельзя писать в промпт и что делать с очередью «бот не смог».
Карта возможностей модуля:
flowchart LR
AI(("AI-агент"))
AI --- P["Провайдеры"]
P --- P1["Подключённые провайдеры"]
P --- P2["ключи в БД или на лиц-сервере"]
AI --- CH["Каналы"]
CH --- CH1["ЛК и Мобильное"]
CH --- CH2["Виджет сайтов"]
CH --- CH3["Поддержка TG / VK / MAX"]
CH --- CH4["Email и Голос"]
AI --- T["Инструменты"]
T --- T1["Тарифы физ / бизнес"]
T --- T2["Покрытие по адресу"]
T --- T3["Баланс и сессия после SMS"]
T --- T4["Оформить заявку / перезвон"]
T --- T5["Обещанный платёж"]
AI --- W["Виджет"]
W --- W1["свой embed-скрипт"]
W --- W2["конфиг из админки: цвет / тексты / аватар / домены"]
AI --- R["Запись"]
R --- R1["crm_intake → сделка"]
R --- R2["эскалация → Поддержка"]
AI --- AN["Аналитика"]
AN --- AN1["токены по провайдеру + стоимость"]
AN --- AN2["сессии и дашборд"]
Обзор модуля (хаб)
Главная страница /admin/ai/ — единая точка управления: статусы API-ключей подключённых провайдеров, список каналов с выбранной моделью, стоимость токенов за месяц в рублях, переходы к разделам (промпты, база знаний, журнал звонков, сессии и дашборд). Ключи хранятся в БД (SystemSettings), не в .env — настраиваются из интерфейса.
Мультипровайдер: выбор модели
Для каждого из 7 каналов (Личный кабинет, Мобильное, Email/Поддержка, Виджет, Голос, Телефон, Подсказка оператору) выбирается провайдер и конкретная модель. Запросы маршрутизируются единым движком ai_prompt_builder.build(); ответы и токены логируются в ai_chat_log с разбивкой по провайдеру. Запросы к внешним API провайдеров идут через прокси (эти сервисы заблокированы из РФ).
База знаний
Раздел /admin/ai/kb/ — сценарии решения проблем (статьи KnowledgeArticle) с кодом, приоритетом и аудиторией (бот / оператор / оба). Интерфейс повторяет рабочую базу знаний поддержки: четыре вкладки (Сценарии решения, Дерево диагностики, Шаблоны ответов, Аналитика), фильтры по аудитории и приоритету, поиск. Карточка-аккордеон раскрывается в четыре колонки-шага (Уточнение → Диагностика → Решение → Если не помогло) с блоком эскалации и примечаниями. Активные статьи автоматически подмешиваются в системный промпт бота.
Инструменты на ORM (tool-use)
AI-ассистент умеет вызывать нативные функции напрямую через ORM, без HTTP к самому себе. Инструменты делятся на две группы:
- Справочные (по клиенту) — после подтверждения личности по SMS: проверка клиента и баланса, статус RADIUS-сессии, диагностика «нет интернета», история платежей, проверка массовой аварии по району, активация обещанного платежа.
- Диалоговые (лид/подключение) — бот сам работает с заявкой прямо в разговоре:
get_tariffs(название, скорость, цена; фильтр физ/бизнес),check_coverage(проверка покрытия по адресу через базуHomes),create_connection_lead(оформить заявку → сделка в CRM, максимально заполнив карточку),request_callback(обращение/перезвон → тикет Поддержки). Личность для этих инструментов не требуется.
Мультипровайдер: инструменты работают на всех подключённых провайдерах (tool-use loop реализован для каждого; токены суммируются по итерациям). Включается переключателем «Инструменты AI» в хабе (AI_TOOLS_ENABLED).
Диалог с инструментами (упрощённо):
flowchart TD
U["Клиент пишет/говорит"] --> M["AI-модель"]
M -->|"нужны данные"| T{"Инструмент"}
T -->|"get_tariffs"| TR["Тарифы: скорость+цена
физ/бизнес"]
T -->|"check_coverage"| CV["Покрытие по адресу
(Homes)"]
T -->|"check_subscriber
(после SMS)"| SB["Баланс / тариф / статус"]
T -->|"create_connection_lead"| LD["crm_intake →
сделка в CRM"]
T -->|"request_callback"| TK["Тикет Поддержки"]
TR --> M
CV --> M
SB --> M
LD --> M
TK --> M
M --> R["Ответ клиенту"]
Голос: Mango → расшифровка → анализ
Раздел /admin/reports/calls/ — журнал голосовых звонков (прежний
адрес /admin/ai/calls/ остался рабочим). Смотрят его операторы и
руководитель, поэтому с сентября 2026 он живёт в «Отчётах», рядом с журналом
голосовой почты.
ast_, номер задаётся в ASTERISK_CALLERID) и внешне
выглядел обычным исходящим: 12-секундные записи робота — 183 из 230 за неделю —
вытесняли живые разговоры из списка. Теперь журнал по умолчанию показывает
только людей, робот — по чипу «Автообзвон», у его строк значок. Счётчики шапки
считаются по тому же срезу. Записи робота не расшифровываются:
он читает наш же сценарий, платить за распознавание собственного текста незачем
(ключ --robot у команды transcribe_calls включает их
обратно).
Как это работает. Webhook Mango Office (/api/voice/mango/call/ и /record/) создаёт запись звонка, ищет клиента по телефону, скачивает запись и расшифровывает её через сервис распознавания речи, затем прогоняет транскрипт через AI (канал «Голос»): получается категория обращения, краткое резюме и признак необходимости эскалации — всё это попадает в тикет поддержки. Включается тумблером «Голос» в хабе (по умолчанию выключен — до подключения телефонии Mango).
Собственный виджет для сайтов (конфиг из админки)
Публичный анонимный AI-чат для встраивания на сайты организаций. Виджет полностью наш — static/js/smit-ai-widget.js, без внешних зависимостей и сторонних серверов.
Все настройки — в БД биллинга (карточка «Виджет на сайтах» в хабе /admin/ai/): цвет, заголовок, приветствие, аватар, кнопки-подсказки, положение кнопки, разрешённые домены (CORS). Виджет самонастраивается — при загрузке тянет конфиг из GET /api/ai/widget/config/ и строится только если включён.
Подключение сайтом — одна строка (код берётся по кнопке «Код встраивания»):
<script src="адрес вашей установки/static/js/smit-ai-widget.js" data-api="адрес вашей установки" data-org="3" defer></script>
Брендинг по организации (data-org)
Один файл виджета обслуживает все сайты, а оформление и маршрутизация подстраиваются под организацию сайта. Атрибут data-org на теге <script> задаёт id организации — он виден в её карточке.
- Фирменный цвет. Для организации, отличной от основной, цвет виджета берётся из её акцентного цвета в брендинге (карточка организации → Брендинг).
AI_WIDGET_COLOR, зелёный#43b77a). Цвет применяется к кнопке-лаунчеру, шапке окна, пузырям сообщений, кнопкам и полю ввода. - Маршрутизация чата и лидов. Диалог и заявки уходят в свою организацию: ассистент отвечает её персоной, показывает её тарифы, лид/тикет создаётся в её воронке и Поддержке.
- Определение организации. Приоритет — явный
data-org; если не задан, организация определяется по домену сайта (Origin) из списка организаций. Пусто и домен не распознан → основная организация.
Если data-org не указывать, виджет работает в оформлении и маршрутизации основной организации.
Совместимость с оформлением сайта. Виджет встраивается в страницу напрямую (не в изолированный контейнер), поэтому его стили заданы явно и не зависят от CSS сайта-хозяина: иконки табов «Чат/Голос» стоят в одну строку с подписью даже на сайтах с Tailwind (где базовый стиль делает svg блочным), а поле ввода всегда с тёмным текстом на белом фоне (на тёмнотемных сайтах иначе наследовался бы светлый текст — нечитаемо).
Лиды и обращения попадают в собственную CRM биллинга: заявка → сделка в воронке Deal (через crm_intake, с дедупом по телефону, геокодом и UTM), эскалация чата → тикет во внутренней Поддержке (SupportConversation), без внешних систем.
Архитектура виджета (всё в биллинге):
flowchart LR
SITE["Сайт клиента
<script src=smit-ai-widget.js>"] -->|"GET /config/"| CFG[("Настройки виджета
цвет/тексты/домены
в БД биллинга")]
SITE -->|"POST /chat/"| ENG["AI-движок биллинга
+ инструменты"]
ENG --> LEAD["create_connection_lead
/ widget lead"]
LEAD --> INTAKE["crm_intake
(дедуп/геокод/UTM)"]
INTAKE --> DEAL[("Сделка CRM")]
ENG -->|"эскалация"| SUP[("Тикет Поддержки")]
Голосовой режим виджета
Виджет умеет вести живой голосовой диалог: клиент говорит в микрофон, ассистент отвечает голосом (голосовая модель в режиме live-аудио). В окне виджета — вкладки Чат и Голос; вкладка «Голос» появляется только если режим включён в админке.
Настройка — карточка «Виджет на сайтах» → блок «Голосовой режим» в хабе /admin/ai/:
- Голос ассистента — 8 голосов с русскими именами и характером: Заря, Ксения, Лада, Арина (женские), Пётр, Захар, Фёдор, Олег (мужские). Кнопка «Прослушать» проигрывает образец выбранного голоса прямо в админке.
- Модель — выбирается из доступных голосовых моделей; язык распознавания/синтеза (BCP-47, по умолчанию
ru-RU). - Приветствие в голосе, автостарт разговора при открытии вкладки «Голос», показ транскрипта диалога, лимит длительности сессии (сек, 0 = без ограничения).
- WSS-URL прокси — адрес голосового прокси (
wss://адрес вашей установки/voicews).
Требует ключ провайдера и работающий голосовой прокси (контейнер smit-voice-ws).
Как устроено. Голосовой провайдер недоступен из России напрямую, а веб-сервер биллинга не держит WebSocket-сессии. Поэтому голос идёт через отдельный лёгкий прокси-контейнер smit-voice-ws на боевом сервере: браузер по защищённому WebSocket соединяется с ним, а он проксирует диалог через обходной канал. Ключ провайдера и системный промпт (с реальными тарифами) браузер получает разово по GET /api/ai/widget/voice-token/ — в коде страницы ключ не хранится.
flowchart LR
MIC["Браузер клиента
микрофон 16кГц"] -->|"WSS"| WS["smit-voice-ws
(прокси на сервере)"]
WS -->|"обходной канал"| G["Голосовая модель"]
G -->|"аудио 24кГц"| WS --> MIC
TOKEN["/api/ai/widget/voice-token/
ключ + промпт с тарифами"] -.-> MIC
Приватность и контроль. Ключ провайдера выдаётся только при включённом тумблере и не попадает в исходники страницы сайта. Разговор идёт напрямую браузер↔Google через наш прокси; текстовый чат работает независимо и без голосовых зависимостей.
Формы заказа на сайтах → лиды в CRM
В хабе /admin/ai/ есть конструктор форм подключения. Доступны три способа сбора заявок, все они шлют данные в один endpoint POST /api/crm/lead/ и создают сделку в CRM:
- Встраиваемый виджет формы —
order_widget.js: кнопка в углу сайта + модалка с формой (имя, телефон, e-mail, адрес, тариф, доп.услуги). Вставляется одной строкой<script ... data-auto-init>, изолирован через Shadow DOM, сам собирает UTM-метки страницы. Тарифы подгружаются из/api/crm/tariffs/. - Полностраничная форма
/order— многосекционная форма с экранами проверки и подтверждения; поддерживает UTM в query-строке. Демо встраивания виджета —/order-widget-demo. - AI-чат — при намерении подключиться бот предлагает оставить заявку.
Состав полей и тексты настраиваются в модалке «Формы заказа» (заголовок, цвет, телефон, видимость блоков). Главный выключатель приёма заявок — CRM_PUBLIC_LEAD_ENABLED (по умолчанию выключен, включается тумблером в хабе).
Маршрут заявки:
flowchart LR
W["Виджет
order_widget.js"] --> API["POST
/api/crm/lead/"]
O["Страница
/order"] --> API
CH["AI-чат"] --> API
API --> KS{"Приём
включён?"}
KS -->|"нет"| OFF["Отклонено
(disabled)"]
KS -->|"да"| INTAKE["crm_intake:
поиск клиента
по телефону + дедуп"]
INTAKE --> DEAL[("Сделка в CRM
воронка Deal
+ UTM")]
Тестовый AI-чат
Страница /admin/ai/test_chat/ — отработка сценариев ассистента так, как его видит клиент на сайте. Использует тот же движок, что и боевой виджет: создаёт реальные лиды и тикеты, показывает session_id, факт эскалации, номер тикета и ссылку на сессию в дашборде. Эскалация (фраза вроде «хочу оператора» или жалоба) создаёт тикет во внутренней Поддержке.
Эскалация чата в тикет:
flowchart LR
MSG["Сообщение
клиента"] --> AI["AI-движок"]
AI --> ESC{"Нужен
оператор?"}
ESC -->|"нет"| ANS["Ответ
клиенту"]
ESC -->|"да · ESCALATE_TO_HUMAN"| TK["support_tickets
create_ticket()"]
TK --> CONV[("Тикет
Поддержки
SupportConversation")]
TK --> ANS
Тест-кейсы и регрессионные прогоны
Страница /admin/settings/ai/eval/<канал>/ — банк тестовых вопросов и история прогонов
для каждого из семи каналов (ЛК, мобильное, email, виджет, голос, телефон, подсказка оператору).
- Кейс — вопрос клиента + критерии проверки: что ответ должен и не должен содержать, ожидается ли эскалация, лимит слов, плюс тестовый контекст клиента (имя, баланс, тариф, статус).
- Прогон идёт тем же движком, что настроен на канале: кейсы проверяются на той же модели, что настроена на канале, а не на модели «по умолчанию».
- «В тесты» из журнала диалогов — в карточке сессии на
/admin/ai/playground-log/кнопка заводит регрессионный кейс прямо из неудачного диалога: вопрос клиента и комментарий оператора «как надо» переносятся автоматически. Кейс создаётся черновиком — останется дописать критерии и включить его. - Кейсы хранятся в базе и редактируются в интерфейсе; файловый датасет репозитория продолжает подмешиваться к прогону.
/admin/ai/test_chat/
работает в режиме симуляции: реальные заявки, тикеты, SMS, звонки-верификации и платёжные ссылки
из тест-чата не создаются — ассистент получает ответ «действие выполнено» и продолжает
диалог.
Помощник в разделах панели
Помощник — кнопка в правом нижнем углу рабочей панели. Он только читает: объясняет данные открытой страницы, подсказывает следующий шаг и пишет черновики писем. Списания, блокировки, привязку платежей и отправку клиенту делает сотрудник — помощник ничего не меняет в системе.
Как начать с готового вопроса, что означает полоса «смотрю данные объекта», чем «уточнить» отличается от «начать заново» и зачем смотреть историю страницы перед новым запросом.
Отдельный блок в каталоге виджетов
Помощник заведён как встроенный виджет: карточка «AI-ассистент разделов» в каталоге /admin/settings/widgets/ с тумблером. Выключение убирает его со всех страниц, не трогая остальной AI-модуль — например, на время настройки провайдера.
Доступность решают две задвижки: модуль «AI-ассистент» и этот тумблер. Выключен модуль — помощника нет ни на одной странице, а карточка честно пишет об этом; при этом закрыты и серверные адреса, так что прямой запрос к API тоже ничего не даст.
flowchart LR MOD["Модуль
«AI-ассистент»"] --> GATE{"Обе задвижки
открыты?"} WID["Виджет
«AI-ассистент разделов»
каталог виджетов"] --> GATE GATE -->|"да"| ON["Кнопка на странице
и рабочие адреса"] GATE -->|"нет"| OFF["Помощника нет
адреса закрыты"]
Работает в двух режимах:
- по объекту — карточка клиента, сделка, обращение, платёж из выписки, посадочная страница: помощник видит саму запись со связями (баланс, блокировки, услуги, переписку, звонки);
- по разделу — списки и дашборды: помощник получает те же данные, что страница показывает человеку, и отвечает про них.
Где он есть
Клиенты и деньги: карточка клиента, счета, финансовые операции, журнал платежей, должники, очередь банковских выписок, очередь чеков, панель директора.
Поддержка: входящие, карточка обращения, дашборд, голосовая почта.
CRM: воронки, канбан сделок и карточка сделки, задачи, календарь, контакты, кампании и мастер кампании, боты продаж, лендинги.
Сеть и склад: состояние узлов доступа, карта сети, пулы адресов, номенклатура, остатки, движение и аналитика склада.
Тарификация: тарифы, услуги, лояльность, линейки услуг.
Прочее: IPTV-аккаунты, телефония, видеонаблюдение, журнал сообщений, база знаний, расход AI, настройки системы и личного кабинета.
Выделенные строки и открытый объект
Если в списке отмечены строки галочками, помощник отвечает про них, а не про раздел целиком: в шапке появляется «Выбрано записей: N», а первым вопросом — «Разобрать выделенные».
На карте сети выделение устроено иначе: там помощник видит открытый узел или трассу и набор включённых слоёв — чтобы не рассуждать обо всей сети, когда на экране одни опоры. Страница сообщает своё состояние сама, через функцию window.SMIT_ASSIST_CONTEXT(); так же может поступить любой другой экран.
Разговор: уточнить или начать заново
Под ответом три действия. «Уточнить» открывает поле, не теряя контекст: следующий вопрос уходит вместе с прошлым ответом, поэтому можно спрашивать «а по второй организации?» без повторения условий. «Начать заново» обрывает разговор и возвращает список заготовок — нужно, когда вопрос сменился и прежний контекст только мешает. «Переслать» — см. ниже.
История запросов по странице
Кнопка «История» в шапке панели показывает последние пять разборов этой же страницы — с автором и временем. Один и тот же вопрос по разделу задают по очереди несколько человек; прежде чем тратить ещё один запрос к модели, видно, что уже выясняли. Запись раскрывается на месте, ответ можно переслать коллеге.
Кнопки нет, пока по странице никто не спрашивал: пустая история только занимала бы место в шапке.
Переслать ответ коллеге
Под ответом есть кнопка «Переслать»: она раскрывается в тот же селектор сотрудника, что и поле «Ответственный». Можно выбрать человека или команду целиком — получателю придёт уведомление в шапке (колокольчик) с текстом ответа и ссылкой на страницу, где он получен.
Если основной провайдер молчит
Помощник не привязан к одному поставщику модели. Запрос идёт по цепочке Claude → Gemini → OpenAI: если у основного кончились средства, просрочен ключ или он недоступен, ответ приходит от следующего, а причина отказа попадает в журнал. Порядок меняется настройкой AI_ASSIST_ORDER — без обновления системы.
flowchart LR Q["Вопрос
по странице"] --> C1["Claude"] C1 -->|"ответ"| OK["Ответ сотруднику"] C1 -->|"нет средств
или недоступен"| C2["Gemini"] C2 -->|"ответ"| OK C2 -->|"недоступен"| C3["OpenAI"] C3 -->|"ответ"| OK C3 -->|"недоступен"| ERR["Честное сообщение
с причиной"] OK --> LOG["Журнал AI:
раздел, модель, токены"]
Расход считается по всем провайдерам: счётчики токенов у каждого называются по-своему, поэтому в журнал попадает и модель, которая реально ответила, — иначе часть запросов выглядела бы бесплатной.
Кому виден
Суперадмину — всегда. Остальным — по группам из настройки AI_ASSIST_GROUPS (список через запятую). Проверка стоит и при отрисовке страницы, и на стороне сервера, поэтому прямой запрос к API ничего не даст. Пустая настройка означает «только суперадмин». Поверх этого действуют обе задвижки из начала раздела: модуль и тумблер виджета.
Как подключить новую страницу
Серверная часть общая, странице достаточно объявить, о чём речь — одна строка в конце шаблона:
<div data-ai-assist data-scope="section" data-section="stock"
data-follow-selection="tbody input[type=checkbox]"
data-title="Склад" hidden></div>
Список разделов закрытый и живёт на сервере (billing/views/ai_assist.py): страница присылает только ключ, а откуда брать данные — решает сервер. Так со страницы нельзя попросить произвольный адрес.
Сколько это стоит
Один вопрос — 3–13 секунд и порядка 1,5–6 тысяч токенов (зависит от того, сколько данных на странице). Все разговоры попадают в общий журнал AI с пометкой раздела и модели, поэтому расход виден на дашборде «AI: расход и качество», а действие сотрудника — в аудите.
Дашборд AI-сессий
Дашборд /admin/reports/ai_chat_dashboard/ — единая аналитика всех AI-диалогов (ЛК, мобильное приложение, виджет на сайте). Это рабочий инструмент для оценки качества ассистента и обучения промпта. Сюда при запуске была перенесена история диалогов из внешнего сервиса (первоначально ~19 тыс. строк), сопоставленных с клиентами по телефону; дальше журнал пополняется в реальном времени, а поздние бэкфиллы (организации, разбивка на обращения) меняют разрезы аналитики.
Выпуск 3.7.0: общий каркас
Шапка — общий каркас с периодом и переходом в настройки; показатели — карточками в три колонки; у фильтров значки и подсветка выбранного; в списке сессий настраиваются колонки. В кольце каналов — только каналы клиентов, служебные источники подписаны словами.
Показатели и графики
Пять карточек сверху отвечают на вопросы «сколько было разговоров», «насколько они были длинными», «дошли ли до конкретного клиента» и «сколько это стоило»:
| Показатель | Что считается |
|---|---|
| Сессий | Обращения за период. В мессенджерах одна переписка тянется годами (session_id — это chat_id), поэтому обращения разделяются паузой: перерыв дольше AI_DIALOG_GAP_MIN минут (по умолчанию 30) начинает новое. В подписи — сообщения клиента и сводка по оценкам (👍/👎), если их ставили. |
| Решено без человека | Contained rate — доля сессий, где ассистент справился сам: без эскалации на оператора и без создания тикета. Главная метрика качества. В подписи — повторные обращения того же клиента в течение 72 часов: если их много, вопросы на деле не решаются, даже когда эскалаций мало. |
| Реплик на диалог | Все сообщения (клиент + ассистент) ÷ число сессий. Длинный диалог обычно означает, что с первого раза не поняли. |
| Без клиента | Доля сессий, где клиента не удалось связать с карточкой клиента. Для голосового канала это главный признак, что разговор не довели до конкретного человека. |
| AI не справился | Крупно — только обращения, ушедшие к человеку без понятной причины. Просьба клиента позвать оператора, сорвавшаяся проверка личности и оформление заявки по регламенту сюда не входят: это штатная работа, а не провал. Рядом — общее число переданных человеку, строкой ниже — разбивка по причинам. Август: к человеку ушло 40 обращений из 283, провалов среди них 12 (4,2 %) — остальное просьба клиента (16), заявка (11) и непройденная проверка (3). Пока карточка показывала все 40, картина выглядела втрое хуже правды. |
| Токены | Вход и выход отдельно, стоимость по прайсу каждой модели и цена одного обращения — расход за период ÷ число обращений. Общая сумма не отвечает на вопрос «дорого мы отвечаем или дёшево», пока её не поделить на разговоры: в августе вышло ≈ 2,21 ₽ за обращение. |
Сравнение с прошлым периодом
У «Обращений», «Решено без человека» и «AI не справился» под числом стоит изменение к предыдущему отрезку такой же длины — тому, что кончился в день начала выбранного. Август против июля: 283 обращения против 195, решено без человека 204 против 138, провалов 12 против 15.
Где ассистент буксует
Блок вместо прежнего списка «Последние 👎»: кнопки оценки за восемь месяцев собрали пять нажатий, и список всегда был пуст. Недовольство видно и без оценок — по трём признакам, которые считаются из журнала:
| Признак | Что означает |
|---|---|
| Вернулись с тем же вопросом за сутки | Тот же клиент обратился снова в течение 24 часов — вопрос закрыт формально, а не по сути. |
| Долгий разговор без результата | Восемь и более реплик, при этом ни заявки, ни передачи человеку: ассистент ходил кругами. |
| Бот сдался без причины | Те самые провалы из карточки выше — их и стоит читать в разборе. |
Расходы на модели и бюджет месяца
Блок «Расходы на модели» показывает, куда уходят деньги, в двух разрезах — по моделям и свёрнуто по провайдерам. Стоимость считается по прайсу каждой модели и курсу из настроек AI, поэтому расход по каждой модели виден отдельно.
| Колонка | Что показывает |
|---|---|
| Модель / Провайдер | Переключатель над таблицей. В режиме моделей рядом с названием — её провайдер. |
| Сообщений | Сколько ответов сгенерировано этой моделью за период. |
| Токенов вход / выход | Вход — промпт со всем контекстом, выход — сам ответ. Вход обычно в десятки раз больше. |
| Цена, $/Mtok | Прайс этой модели за миллион токенов: вход / выход. |
| Стоимость, ₽ | Себестоимость по прайсу и курсу. Это не сумма, начисленная по лицензии — она считается по тарифу на сервере лицензий и включает наценку. |
Над таблицей — полоса бюджета месяца: потрачено с начала месяца, прогноз до
конца и отметка прогноза на шкале. Цвет меняется при 80% и при превышении. Если лимит не задан
(настройка AI_BUDGET_MONTH_RUB), вместо шкалы показываются суммы и ссылка на
настройку — почтовый алерт о превышении при пустом лимите тоже молчит.
session_id. В мессенджерах он не заканчивается никогда, поэтому
одна «сессия» означала человека за всё время: внутри неё умещалось до 234 обращений, а одна
эскалация помечалась на всю переписку. После разделения на обращения показатель «решено без
человека» опустился с 94% до 73% — работа ассистента не изменилась, исчезла приписка.
Чья это заявка: как определяется организация
В мультиорганизационной установке каждый диалог, звонок и заявка должны принадлежать своей организации — от этого зависят и отчётность, и то, каким брендом бот представляется клиенту, и какие тарифы он предлагает. Признак берётся из первого источника, который смог ответить.
| Откуда обращение | Порядок определения |
|---|---|
| Чат виджета | Тест-площадка (pg_org) → явный org_id в запросе →
домен сайта (Origin/Referer сверяется с доменами организаций) →
организация по умолчанию. |
| Заявка из виджета | Домен сайта → организация клиента, если он найден → упоминание бренда в тексте → организация по умолчанию. Домен идёт первым, поэтому заявка с сайта попадает в его воронку, даже если клиент ещё не в базе. |
| Входящий звонок | Организация клиента → номер линии, на который позвонили (см. CRM → Телефонные линии: номер назначения задаёт сегмент, организацию и тип сделки) → организация по умолчанию. |
| Мессенджеры | Организация ящика канала → организация клиента → организация по умолчанию. |
Карта раздела
- AI-чат: дашборд
- Показатели
- Сессий
- Реплик на диалог
- Без клиента
- Эскалаций и тикеты
- Токены и стоимость
- Разрезы
- Период до всего времени
- Организация из шапки
- Канал: голос, виджет, бот
- Модель и провайдер
- Деньги
- Цена по прайсу модели
- Бюджет месяца и прогноз
- Себестоимость против начисления
- Списки
- Сессии страницами по 50
- Поиск и фильтры на сервере
- Последние отрицательные оценки
- Проблемные eval-кейсы
- Диалог
- Клик по строке
- Стенограмма в модалке
- Форматирование ответов
- Переход к клиенту
Откуда берутся цифры
flowchart LR
LOG["Журнал диалогов
ai_chat_log"] --> SESS["Обращения
session_id + dialog_no"]
SESS --> KPI["Показатели"]
SESS --> DAY["Активность по дням"]
SESS --> SRC["Каналы"]
SESS --> LIST["Список сессий
страницами"]
LOG --> TOK["Токены и стоимость"]
AB["Клиенты"] --> ORG["Организация сессии"]
SESS --> ORG
ORG --> BYORG["По организациям
+ «Без организации»"]
EVAL["Прогоны ai_eval"] --> CASES["Проблемные кейсы"]
Организация сессии определяется один раз — по первой записи с заполненным клиентом. Поэтому сумма по организациям сходится с общим числом сессий, а диалоги без опознанного клиента попадают в отдельную строку «Без организации», а не приписываются компании по умолчанию.
Список сессий
Список приходит страницами по 50 записей: поиск (по идентификатору сессии, каналу, ФИО и договору), фильтры канала и оценки, сортировка — всё считается на сервере. Клик по строке открывает стенограмму: реплики клиента и ассистента с временем, ответы в формате JSON показываются моноширинным блоком, имя клиента ведёт в его карточку.
Адрес /admin/reports/ai_chat_session/<id>/ при открытии человеком перенаправляет на дашборд с уже раскрытой сессией.
Тёмная тема и телефон
Период задаётся единым date-range-picker (общий для всех отчётов). Стоимость токенов считается из настроек AI_PRICE_* и курса AI_USD_RUB.
Список сессий и транскрипт
Блок «Все сессии за период» — таблица с фильтрами по каналу (Все/LK/Mobile) и фидбеку (Все/👍/👎/Эскал.), живым поиском (ID/клиент/договор) и сортировкой по столбцам. Клик по строке открывает транскрипт диалога в стиле iMessage: реплики клиента — справа (светло-серый градиент), Аиды — слева, с поддержкой markdown-форматирования (**жирный**, заголовки #/##/###, `код`). Клик по имени клиента открывает slide-панель клиента (как в других разделах) — без ухода со страницы.
Поток данных дашборда:
flowchart LR
LK["ЛК-чат"] --> LOG[("ai_chat_log
PG")]
MOB["Мобильное"] --> LOG
WID["Виджет сайта"] --> LOG
BOT["Внешний источник (ETL)"] --> LOG
LOG --> VIEW["dashboard/data/
агрегаты SQL"]
VIEW --> KPI["KPI + графики
ECharts"]
VIEW --> SESS["Список сессий
фильтры/поиск"]
SESS --> TR["Транскрипт
(iMessage)"]
SESS --> DR["Панель клиента
(AbDrawer)"]
Тёмная тема, мобильная версия и клавиатурная доступность (Enter/Space на строках, aria-sort) — поддержаны. ECharts отдаётся локально (не с CDN).
Статус: все 7 фаз реализованы (2026-06-13). Мультипровайдер, единый хаб, база знаний, инструменты на ORM, голос, виджет с воронкой и перенос истории диалогов работают на боевом сервере. Виджет сайта организации работает на собственном endpoint. Голосовой разбор включается после подключения телефонии Mango.