AISellerBot — AI-продавец для интернет-магазинов
Мультитенантная SaaS-платформа: встраиваемый виджет на Preact, FastAPI-бэкенд, RAG по каталогу 134K+ товаров с GigaChat и pgvector.
Задача клиента
RAG-агент с 9 инструментами
ReAct-loop, semantic cache, RRF, business rerank
SalesAgent — pipeline из 4 ступеней: semantic-cache lookup (similarity > 0.92 — отдаём кэш без LLM), history summarisation (>6K токенов сворачивается в summary), ReAct loop с max_loops от 5 (trial) до 20 (superadmin), post-processor _sanitize_agent_response ловит провайдер-утечки. 9 tools: product_search (semantic+keyword RRF+business-rerank), keyword_search_product (FTS), product_details, check_stock, kb_search, application_rules_search, company_info, create_lead, entity_search/details.
Виджет на Preact (1 981 LOC)
Shadow-root, WebSocket, ProjectGroup-binding
Single-script loader монтируется в shadow-root любого сайта клиента, читает data-* атрибуты со script-тега. Главный компонент Widget — иконка-пузырь → панель чата с messagesEnd auto-scroll, consent banner, saved-messages в localStorage по tenantSlug. ProductCarousel — горизонтальный карусель карточек товаров. useWebSocket: URL /ws/chat/{tenantSlug}?group={groupSlug}, exponential backoff reconnect, message queue при оффлайне, ping/pong heartbeat.
Multi-tenant архитектура
Tenant + Membership + Project/ProjectGroup, JWT с tenant_id
Три слоя изоляции. Tenant — биллинг-сущность (plan: trial/starter/business/enterprise/superadmin). Membership — пользователь в нескольких тенантах с ролями owner/admin/operator/member. Project/ProjectGroup — внутри тенанта несколько витрин-магазинов; ProjectGroup объединяет N проектов в одного бота. JWT payload: sub (user_id), tenant_id, type=access. get_current_tenant проверяет активный Membership; get_current_project — что project.tenant_id == tenant.id.
Ingestion и Robotint
8 форматов фидов + Playwright-краулер + 8 методов детекта
Ingestion (3 930 LOC): Playwright-краулер для SPA, html_product_parser для HTML без feed-а (schema.org JSON-LD, microdata, OpenGraph, CSS-heuristics), api_crawler для Bitrix REST. 6 форматов: yml.py (Yandex Market), google_merchant.py, commerceml.py (1С), csv_parser.py, json_feed.py. Document_processor для PDF/DOCX/XLSX. Robotint — суперадминская подсистема рыночной аналитики: 8 методов детекта виджета колеровки на сайтах конкурентов.
Встраиваемый виджет
Настраиваемое поведение
Каждый аспект бота конфигурируется через admin-панель
Proactive triggers
url_match / time_on_page / exit_intent / cart_signal / idle
A/B experiments
Deterministic split по hash(visitor_id + experiment_id)
Visitor profiles
Долгоживущая память (project_id, visitor_id) UNIQUE
Behavior templates
Пресеты по vertical (paint, ecommerce, services-b2b)
Operator handoff
needs_human=TRUE → claim/release/close в /inbox
Custom prompts
Per-tenant tone, facts JSONB, few-shot — всё в БД
Архитектура
Виджет на сайте клиента: чат с подбором товара
Preact 10 в shadow-root, не конфликтует с CSS магазина. ProductCarousel рендерит карточки из каталога, handoff на оператора через needs_human=TRUE.
Inbox оператора: handoff от бота
Бот ставит needs_human=TRUE по escalation_rules (жалоба, цена, юр. вопрос, требование контакта). Оператор делает claim, отвечает, release/close.
| Пользователь | Последнее сообщение | Канал | Сентимент | Ждёт | Действие |
|---|---|---|---|---|---|
| Гость #21408 | Спасибо, оформляю! | site | positive | 12 мин | бот |
| Гость #21407 | У вас на сайте 2 190, а тут — почему? | site | neutral | 3 мин | |
| Гость #21396 | Перезвоните пожалуйста, +7 905 *** | VK | neutral | 1 мин | |
| Гость #21391 | Брак, банка вскрыта | TG | negative | 8 мин | |
| Гость #21384 | Можно ли смешать VGT и Текс? | site | neutral | 20 мин | бот |
Аналитика диалогов и интентов
Метрики из ai_queries: диалоги, leads из create_lead, время ответа, доля автоматизации. Топ-интенты обновляются каждый час.
Технический стек
Результаты
"AI-консультант, который знает весь каталог из 7 000+ товаров, отвечает за 1.5 секунды и работает 24/7 без выходных — это не фантастика, а production-система с 20 000+ embeddings"