Files

11 KiB
Raw Permalink Blame History

🏗️ Архитектура calls24

На основе кейса Adict.ru: команда персон, а не один бот. Источник: "Как мы превратили чат-бот в команду из пяти ИИ-специалистов" (ЖК Авторский дом 12, Иркутск)

Система: от звонка до звонка

┌─────────────────────────────────────────────────────────────────────┐
│                        КЛИЕНТ (бизнес)                              │
│   Звонки операторов (WAV/MP3)  →  SIP-линии  →  CRM (Bitrix24)     │
└────────┬──────────────────────────────┬──────────────────┬──────────┘
         │                              │                  │
         ▼                              ▼                  ▼
┌─────────────────────┐  ┌────────────────────┐  ┌──────────────────┐
│  calls24-аналитика   │  │  SIP-коннектор     │  │  calls24-робот   │
│  (FastAPI + LLM)    │  │  (WebSIP Proxy)    │  │  (Yandex Realtime│
│                     │  │                    │  │   WebSocket)      │
│  • STT (распозн.)  │  │  SIP ←→ WebSocket  │  │                  │
│  • LLM-анализ      │  │  RTP ↔ Media       │  │  • STT→LLM→TTS   │
│  • Паттерны продаж  │  │  (аудио микшир.)   │  │  (задержка <1с)  │
│  • Рекомендации    │  │                    │  │  • Brand Voice   │
└────────┬────────────┘  └────────┬───────────┘  └────────┬─────────┘
         │                        │                        │
         ▼                        │                        │
┌─────────────────────────────────────────────────────────────────────┐
│                    calls24-ядро (FastAPI)                           │
│                                                                     │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────────────┐   │
│  │ PostgreSQL│  │  Qdrant  │  │   Redis  │  │  Yandex AI API  │   │
│  │(звонки,  │  │(векторы  │  │(очереди, │  │ (speech-realtime│   │
│  │ скрипты) │  │ звонков) │  │ кэш)     │  │  -250923)       │   │
│  └──────────┘  └──────────┘  └──────────┘  └──────────────────┘   │
│                                                                     │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                 Замкнутый цикл обучения                       │  │
│  │                                                              │  │
│  │  Робот звонит → Запись → Анализ → «Не знаю» → Лид + KB      │  │
│  └──────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

Персонализация: команда вместо одного бота

На основе кейса Adict.ru — клиент не должен разговаривать с «ботом». Он должен выбирать специалиста:

Персона Роль Тон Когда звонит
Менеджер продаж Квалификация, предложение Уверенный, деловой Холодный звонок, входящий интерес
Консультант Ответы на вопросы Терпеливый, подробный Сложные вопросы, сомнения
Финансист Рассрочка, ипотека, цены Точный, без воды «Сколько стоит?», «Какие условия?»
Куратор Постпродажное сопровождение Заботливый, личный Довольный клиент, referral

Принцип: каждая персона — отдельный промпт, separate state machine, separate база знаний. Клиент выбирает или система маршрутизирует автоматически.

Компоненты

1. calls24-аналитика (voice-analyzer)

voice-analyzer/
├── main.py           # FastAPI (порт 8460)
├── stt.py            # Yandex STT (locazli) / Yandex Speech
├── analyzer.py       # LLM-анализ звонков (Qwen35B / Yandex GPT)
├── pattern.py        # Выявление паттернов продаж
├── report.py         # Генерация отчёта (HTML/PDF)
└── .env              # API ключи

Функции:

  • Приём аудиофайлов (WAV/MP3, до 100МБ)
  • Распознавание речи (Yandex STT / Whisper)
  • Анализ текста: скрипт, тайминги, возражения, конверсия
  • Сравнение операторов: кто лучше, почему
  • Генерация отчёта: «что нужно исправить»
  • Экспорт паттернов для генерации скрипта

2. calls24-робот (voice-bot)

voice-bot/
├── main.py           # FastAPI (порт 8461)
├── sip_proxy.py      # WebSIP Proxy (SIP ←→ WebSocket)
├── realtime.py       # Yandex Realtime WebSocket client
├── router.py         # Маршрутизация между персонами
├── persona.py        # State Machine для каждой персоны
├── memory.py         # Память контекста разговора (Redis)
├── fallback.py       # Честный «не знаю» → лид + KB
├── voice_bridge.py   # Короткий мостик при передаче роли
└── .env

Критичные фичи голоса (из кейса Adict.ru):

  • Прерывания: клиент перебивает → система замолкает мгновенно
  • Пауза внутри мысли ≠ конец фразы: ждём 1.5-2с тишины перед ответом
  • Мостик при передаче роли: 300мс звуковой bridge, чтобы клиент не чувствовал разрыва
  • Защита ролей: персоне нельзя уходить в чужую роль (финансист не даёт советы юриста)

3. calls24-ядро (core)

core/
├── api.py            # Общий API (REST + WebSocket)
├── models.py         # Pydantic модели (Call, Script, Pattern, Persona)
├── db.py             # PostgreSQL / Qdrant
├── scheduler.py      # Расписание звонков, напоминания
├── billing.py        # Оплата за лид/бронь
├── integrations.py   # Bitrix24, AmoCRM, 1С
├── auth.py           # Авторизация клиентов
├── content_admin.py  # Админка для контент-менеджера
└── search.py         # Гибридный поиск: BM25 + эмбеддинги

Базы данных

PostgreSQL

calls (id, customer_id, type, recording_url, status, created_at)
call_transcripts (call_id, role, text, start_time, end_time, persona)
call_analysis (call_id, score, script_issues, objections, conversion)
scripts (id, name, version, state_machine_json, created_at)
patterns (id, script_id, type, text, win_rate, context)
customers (id, name, company, industry, phone, created_at)
leads (id, customer_id, call_id, status, revenue, created_at, fallback_reason)
personas (id, name, role, tone, state_machine_id, knowledge_base_id)
content_entries (id, topic, answer, source, quality_score, updated_at)

Qdrant (гибридный поиск: BM25 + эмбеддинги)

collection: call_embeddings
  - call_id: string
  - embedding: float[768]  (text-embedding-3-large)
  - payload: {customer_id, type, score, script_issues}

collection: script_patterns
  - pattern_id: string
  - embedding: float[768]
  - payload: {type, text, win_rate, context}

collection: content_kb
  - entry_id: string
  - embedding: float[768]
  - payload: {topic, answer, source, quality_score}

Поток данных

Анализ звонка

Аудиофайл → STT → Текст → LLM-анализ → Паттерны → Отчёт
   ↓                                           ↓
 запись в PG                          скрипт для робота

Звонки робота (с маршрутизацией)

SIP-линия → WebSIP → WebSocket → Yandex Realtime
                                    ↓
                            STT → Маршрутизатор → Персона
                                                 ↓
                                    Контекст + База знаний → Ответ
                                                 ↓
                            LLM → TTS → Аудио
                                                 ↓
                         Context Memory (Redis)
                                                 ↓
                         «Не знаю» → Лид-форма + KB запись

Цикл «Не знаю» = рост базы знаний

Персона не знает ответ
        ↓
  Честный fallback: «Я передам вопрос специалисту, оставьте контакт»
        ↓
  Запись в content_entries как «запрошенная тема»
        ↓
  Контент-менеджер видит в админке: «Клиенты часто спрашивают X, ответ ещё не добавлен»
        ↓
  Контент-менеджер добавляет ответ → персона становится умнее без релиза