# 🏗️ Архитектура 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, ответ ещё не добавлен» ↓ Контент-менеджер добавляет ответ → персона становится умнее без релиза ```