Update: persona-based architecture, voice specifics, fallback=lead pipeline
This commit is contained in:
1 parent
b5e112c53f
commit
1af355838a
1 file changed
+61
-16
+61
-16
@@ -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 → Аудио
|
||||
STT → Маршрутизатор → Персона
|
||||
↓
|
||||
Контекст + База знаний → Ответ
|
||||
↓
|
||||
LLM → TTS → Аудио
|
||||
↓
|
||||
Context Memory (Redis)
|
||||
↓
|
||||
Запись → Анализ → Улучшение
|
||||
«Не знаю» → Лид-форма + KB запись
|
||||
```
|
||||
|
||||
### Цикл «Не знаю» = рост базы знаний
|
||||
```
|
||||
Персона не знает ответ
|
||||
↓
|
||||
Честный fallback: «Я передам вопрос специалисту, оставьте контакт»
|
||||
↓
|
||||
Запись в content_entries как «запрошенная тема»
|
||||
↓
|
||||
Контент-менеджер видит в админке: «Клиенты часто спрашивают X, ответ ещё не добавлен»
|
||||
↓
|
||||
Контент-менеджер добавляет ответ → персона становится умнее без релиза
|
||||
```
|
||||
Reference in new issue
Block a user