Update: persona-based architecture, voice specifics, fallback=lead pipeline

This commit is contained in:
neo committed 2026-06-10 21:18:03 +05:00
1 parent b5e112c53f
commit 1af355838a
1 file changed
+64 -19
+64 -19
View File
@@ -1,5 +1,8 @@
# 🏗️ Архитектура calls24
> На основе кейса Adict.ru: команда персон, а не один бот.
> Источник: "Как мы превратили чат-бот в команду из пяти ИИ-специалистов" (ЖК Авторский дом 12, Иркутск)
## Система: от звонка до звонка
```
@@ -32,11 +35,25 @@
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Замкнутый цикл обучения │ │
│ │ │ │
│ │ Робот звонит → Запись звонка → Анализ → Улучшение скрипта │ │
│ │ Робот звонит → Запись → Анализ → «Не знаю» → Лид + KB │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
## Персонализация: команда вместо одного бота
На основе кейса Adict.ru — клиент не должен разговаривать с «ботом». Он должен выбирать специалиста:
| Персона | Роль | Тон | Когда звонит |
|---------|------|-----|-------------|
| **Менеджер продаж** | Квалификация, предложение | Уверенный, деловой | Холодный звонок, входящий интерес |
| **Консультант** | Ответы на вопросы | Терпеливый, подробный | Сложные вопросы, сомнения |
| **Финансист** | Рассрочка, ипотека, цены | Точный, без воды | «Сколько стоит?», «Какие условия?» |
| **Куратор** | Постпродажное сопровождение | Заботливый, личный | Довольный клиент, referral |
**Принцип:** каждая персона — отдельный промпт, separate state machine, separate база знаний.
Клиент выбирает или система маршрутизирует автоматически.
## Компоненты
### 1. calls24-аналитика (voice-analyzer)
@@ -64,28 +81,32 @@ voice-bot/
├── main.py # FastAPI (порт 8461)
├── sip_proxy.py # WebSIP Proxy (SIP ←→ WebSocket)
├── realtime.py # Yandex Realtime WebSocket client
├── script.py # Управление скриптом (state machine)
├── router.py # Маршрутизация между персонами
├── persona.py # State Machine для каждой персоны
├── memory.py # Память контекста разговора (Redis)
├── fallback.py # Честный «не знаю» → лид + KB
├── voice_bridge.py # Короткий мостик при передаче роли
└── .env
```
**Функции:**
- Приём входящих / исходящие звонки
- Yandex Realtime API (STT→LLM→TTS в реальном времени)
- State Machine: приветствие → qualification → предложение → возражения → закрытие
- Контекстная память (текущий клиент, история, CRM-данные)
- Запись звонков для последующего анализа
**Критичные фичи голоса (из кейса Adict.ru):**
- **Прерывания:** клиент перебивает → система замолкает мгновенно
- **Пауза внутри мысли ≠ конец фразы:** ждём 1.5-2с тишины перед ответом
- **Мостик при передаче роли:** 300мс звуковой bridge, чтобы клиент не чувствовал разрыва
- **Защита ролей:** персоне нельзя уходить в чужую роль (финансист не даёт советы юриста)
### 3. calls24-ядро (core)
```
core/
├── api.py # Общий API (REST + WebSocket)
├── models.py # Pydantic модели (Call, Script, Pattern)
├── models.py # Pydantic модели (Call, Script, Pattern, Persona)
├── db.py # PostgreSQL / Qdrant
├── scheduler.py # Расписание звонков, напоминания
├── billing.py # Оплата за лид/бронь
├── integrations.py # Bitrix24, AmoCRM, 1С
└── auth.py # Авторизация клиентов
├── auth.py # Авторизация клиентов
├── content_admin.py # Админка для контент-менеджера
└── search.py # Гибридный поиск: BM25 + эмбеддинги
```
## Базы данных
@@ -93,15 +114,17 @@ core/
### PostgreSQL
```
calls (id, customer_id, type, recording_url, status, created_at)
call_transcripts (call_id, role, text, start_time, end_time)
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)
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 (векторный поиск)
### Qdrant (гибридный поиск: BM25 + эмбеддинги)
```
collection: call_embeddings
- call_id: string
@@ -112,6 +135,11 @@ 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}
```
## Поток данных
@@ -123,13 +151,30 @@ collection: script_patterns
запись в PG скрипт для робота
```
### Звонки робота
### Звонки робота (с маршрутизацией)
```
SIP-линия → WebSIP → WebSocket → Yandex Realtime
↓
STT → LLM → TTS → Аудио
↓
Context Memory (Redis)
↓
Запись → Анализ → Улучшение
STT → Маршрутизатор → Персона
↓
Контекст + База знаний → Ответ
↓
LLM → TTS → Аудио
↓
Context Memory (Redis)
↓
«Не знаю» → Лид-форма + KB запись
```
### Цикл «Не знаю» = рост базы знаний
```
Персона не знает ответ
↓
Честный fallback: «Я передам вопрос специалисту, оставьте контакт»
↓
Запись в content_entries как «запрошенная тема»
↓
Контент-менеджер видит в админке: «Клиенты часто спрашивают X, ответ ещё не добавлен»
↓
Контент-менеджер добавляет ответ → персона становится умнее без релиза
```