From fa5d7501c24bf213c4adf7ef6d2cd3247f496367 Mon Sep 17 00:00:00 2001 From: elios Date: Mon, 1 Sep 2025 04:17:10 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20plan/readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plan/readme | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 2 deletions(-) diff --git a/plan/readme b/plan/readme index 656e83d..8ff425f 100644 --- a/plan/readme +++ b/plan/readme @@ -1,7 +1,6 @@ Базовая инфраструктура (через Dockge/docker-compose) Cтек сервисов: - Postgres → основная БД. MinIO → S3-хранилище для файлов. Metabase → визуализация/аналитика. @@ -11,4 +10,184 @@ NocoDB → low-code UI к базе. Nginx Proxy Manager (NPM) → проксирование и домены с SSL. UI (Next.js) → наш интерфейс для админки/авторизации. -Все сервисы описаны в compose.yaml с restart: unless-stopped, так что они поднимаются сами после старта docker-демона. \ No newline at end of file +Все сервисы описаны в compose.yaml с restart: unless-stopped, так что они поднимаются сами после старта docker-демона. + +UI (Next.js) — авторизация и защита +Next.js 15 + TypeScript + Tailwind. +Credentials provider (логин/пароль из Postgres). + + +План разработки +Этап 1. Каркас данных и ingestion (MVP-поток) + +Задачи + +Схема БД (минимум): +channels (id, type: asterisk|mobile|tg|wa|web, status, meta) +contacts (id, phone/email/username, source, last_seen) +interactions (id, channel_id, contact_id, started_at, ended_at, status: new|in_progress|done|lost, assignee, tags[]) +calls (id, interaction_id, direction, asterisk_uniqueid, mobile_device_id?, cdr_json, recording_uri, duration_sec) +transcripts (id, call_id, lang, text, segments_json, qa_scores_json) +sales_1c (id, external_id, doc_date, amount, items_json, contact_key) +match_sales (interaction_id, sale_id, match_score, method, note) +events_audit (id, actor, action, resource, diff, ts) + +API (FastAPI) — первый набор эндпоинтов: +/ingest/asterisk/cdr (POST) — приём CDR/AMI событий (или периодическая выгрузка CDR через скрипт). +/ingest/call-recording (S3 PUT webhook или локальный uploader) — складировать в MinIO и возвращать recording_uri. +/ingest/1c/upload (CSV) — загрузка отчёта продаж. +/interactions (GET/POST/PATCH) — базовый CRUD. +/calls/:id/transcribe (POST) — постановка в очередь на транскрипцию. +/config/* — чтение/запись настроек (через таблицу settings, с аудитом). + +Воркеры (ASR, синхронизация): +asr_worker: берёт задачи из Rabbit → качает запись из MinIO → транскрибирует (Whisper-cpp/ffmpeg) → пишет в transcripts. +sales_linker: после каждого нового interaction/call и после загрузки 1С прогоняет matching (по телефону, времени, сумме) → создаёт/обновляет match_sales. + +UI (Next.js): + +Страницы: +/calls — список (фильтры: дата, длительность, статус ASR). +/calls/[id] — карточка звонка (аудио-плеер из MinIO, транскрипт, авто-теги). +/review — очередь «недозакрытых» обращений (status != done). +/settings — форма с настройками (Asterisk, MinIO, 1С, ASR, фичфлаги) → работает с API /config. +Результат/критерии + +Звонок из Asterisk превращается в запись в БД + файл в MinIO + транскрипт в transcripts. + +CSV из 1С грузится → sales_1c заполнена → есть связи match_sales. +UI показывает звонки, транскрипцию, статус обработки; настройки меняются без config.yaml. +Metabase: 2 дашборда — «Воронка обращений» и «Утечки (lost vs sold)». + +Этап 2. Мобильные SIM (минимально жизнеспособно) + +Задачи + +Android-клиент (реалистично; iOS ограничена): +Запрос READ_CALL_LOG (или интеграция с системным журналом) + отправка метаданных вызовов (вход/выход, номер, длительность) → в API /ingest/mobile/call. + +Опционально запись аудио: для Android 10+ нужно Legal/Accessibility подход (не всегда возможно). Если запись нельзя — хотя бы журнал + обязательный «после-звонка» чек-лист (кнопки «лид создан/закрыт/отложен»). + +Личный ключ сотрудника в приложении: device_id → users_devices. + +Сопоставление с контактами/интеракциями: номер → contacts → interactions/calls с channel=mobile. +Результат + +Хоть и без аудио, но все мобильные звонки попадают в систему как факт обращения (время, номер, длительность, менеджер). + +На дашбордах видно долю мобильных, их исход, и их вклад в утечки. + +Комментарий: iOS практически не даёт доступ к журналу/записи. Рассматриваем workaround: «после-звонка» форма в приложении + привязка по пушам/уведомлениям. Для малого объёма звонков у вас это ок. + +Этап 3. Речевая аналитика и «умные» теги + +Задачи +ASR улучшение: +Whisper-cpp «medium» RU или WhisperX (если GPU тянет) + VAD. +Выход: segments_json (таймкоды). + +LLM-разметка (Ollama → llama3:8b/qwen): +Суммаризация, субъективные метрики (вежливость, конфликт), детект intent (цель клиента), авто-теги (товары/услуги), выявление upsell-возможностей. +Складировать в transcripts.qa_scores_json и interactions.tags. + +UI: +На /calls/[id] — боковые метрики (авто-теги, intent, рекомендации). +На /review — фильтры по тегам/рискам («эскалация», «повторный звонок», «нет ответа»). +Результат + +Каждому звонку автоприсваиваются теги/инсайты. Видно, что упустили/что продали. + +Этап 4. 1С интеграция (операционализация) + +Задачи +Cron-интеграция (в отдельном контейнере scheduler): +Раз в день: GET/PUT отчёта 1С (или SFTP/почта) → /ingest/1c/upload. +Логи: в events_audit. + +Правила матчинга (настраиваемые в /settings): +окно времени (±N дней), +mapping полей телефона/контакта, +веса для match_score. + +Отчёт «реализация vs обращения» в Metabase: + +матрица: канал × статус × реализация. +Результат +Автосверка обращений и реальных продаж. Видно потери >45% на уровне фактов. + + +Этап 5. База знаний и эксперт-контур (LLM-ассистент) + +Задачи + +Хранилище знаний: +kb_docs (id, source: web|internal|manual, title, content, meta, tags, updated_at) +b_vectors (doc_id, chunk, embedding) — можно pgvector/Chroma. +kb_cases (принятые экспертами вопросы/ответы/решения). + +Пайплайн пополнения: +Импорт каталога авто/оборудования (официальные источники, YAML/CSV). +Импорт внутренних регламентов/кейсов. +(Опционально) web-scrape производителей (этично и с кэшем). + +Чат для установщиков/менеджеров: +/qa — RAG: поиск по kb_vectors + ответ LLM + источники. + +Кнопка «Отправить на ревью эксперту» → kb_cases (статус pending → approved). + +Результат +Рабочий ассистент-эксперт: отвечает по автоэлектронике и ассортименту, срастается с вашей базой. + +Этап 6. UI-настройки и анти-саботаж + +Задачи +/settings: + +Вкладки: Интеграции (Asterisk, 1С, MinIO), ASR/LLM, Правила матчинга, Фичфлаги. +Валидация + тест соединения (ping к Asterisk, S3 put/get). + +Роли: +admin, expert, reviewer, user (менеджер). +RBAC в UI и API. + +Протоколирование: +Любая правка настроек → в events_audit. + +Метки невыполненных действий менеджера (например, пропущенный callback) → в interactions. +Результат + +Все настройки меняются из UI; есть история; права разграничены; виден саботаж как факт. + +Этап 7. Дашборды контроля (Metabase + алерты) + +Задачи + +Метрики: +Утечки: % обращений без статуса «done» и без матчинга с 1С. +SLA звонка: среднее время ответа/перезвона. +Инсайты ASR/LLM: топ-причины отказов, частота «нет товара», частота upsell-окна. + +Алерты: +Порог очереди ASR (настройка в settings.alerts.thresholds). +Пики пропущенных/коротких звонков. + +Результат +Регулярные отчёты + e-mail/Telegram-уведомления о провалах/рисках. + +Технические детали и стандарты + +API: FastAPI, CORS только на ui.домен. Swagger для эндпоинтов. + +Файлы: все записи/CSV → MinIO (S3) с логикой TTL/retention. + +Очереди: RabbitMQ (prefetch, dead-letter для падений ASR). + +ASR: для вашей нагрузки (≤30 звонков/день) хватит CPU Whisper-cpp; при апгрейде GPU — WhisperX. + +LLM: Ollama локально (llama3:8b/qwen) для тэггинга/саммаризации; RAG для Q&A. + +Безопасность: секреты в secrets (шифрование/переменные окружения), роль-бэйзд доступ, аудит. NPM — закрыть админку наружу по IP/паролю. + +Резервные копии: pg_dump по крону + минус-диффы MinIO; хранение на отдельном диске/облаке. + +Развёртывание: все сервисы в одном compose.yaml, у ui — build: ./ui, restart: unless-stopped. Прокси через NPM на домены. \ No newline at end of file