Техническая документация

План сервиса: структура, взаимодействия и этапы реализации

Единый исполнимый план сервиса: как строить решение, из каких компонентов, в каком порядке и по каким принципам.

Документ фиксирует целевую модель реализации сервиса и подход к запуску MVP. Целевой эффект: рост продаж за счет более сильной консультации, подбора товаров, сравнения и перехода к заказу в Newton.by.

В документе собраны:

Бизнес-контекст и общая логика сервиса вынесены в Как работает сервис.

1. Архитектурная модель реализации

Архитектура MVP: modular monolith + отдельный indexing worker.

Состав сервиса:

  • один основной backend agent-service;
  • один фоновый процесс catalog-worker;
  • один Qdrant для semantic retrieval;
  • один внутренний PostgreSQL для состояния сервиса;
  • один Redis для cache, rate limits и фоновых задач;
  • Channel Gateway живет внутри agent-service как входной слой каналов;
  • внешние системы компании подключаются как adapters: Bitrix / Percona MySQL, QuadCRM API, МойСклад JSON API.

Архитектурные свойства:

  • MVP быстро запускается;
  • контроль архитектуры и SLA остается прозрачным;
  • координация между сервисами минимальна;
  • отладка и rollout упрощаются;
  • разделение на microservices относится к следующему этапу масштабирования.

2. Целевая архитектура

flowchart TB
    subgraph Channels["Каналы"]
        WEB[Сайт / web chat]
        MSG[Мессенджеры / соцсети]
    end

    subgraph Platform["Newton AI Assistant"]
        GATE[Channel Gateway]
        API[Agent Service]
        ORCH[Dialogue Orchestrator]
        RET[Retrieval Service]
        PRICE[QuadCRM Adapter]
        REQ[МойСклад Adapter]
        HANDOFF[Operator Handoff]
        AUDIT[Audit / Analytics]
        CACHE[(Redis)]
        APPDB[(Internal PostgreSQL)]

        GATE --> API
        API --> ORCH
        API <--> CACHE
        API --> APPDB
        ORCH --> RET
        ORCH --> PRICE
        ORCH --> REQ
        ORCH --> HANDOFF
        ORCH --> AUDIT
        AUDIT --> APPDB
    end

    subgraph Indexing["Catalog Indexing Contour"]
        IDX[Catalog Indexer]
        EMB[Embedding Worker]
        Q[(Qdrant)]
        META[(Catalog metadata in Internal PostgreSQL)]

        IDX --> EMB
        EMB --> Q
        IDX --> META
    end

    subgraph External["Внешние системы компании"]
        MYSQL[(Percona MySQL / Bitrix)]
        QUAD[QuadCRM API]
        MSAPI[МойСклад JSON API]
    end

    WEB --> GATE
    MSG --> GATE

    MYSQL --> IDX
    RET --> Q
    RET --> META
    PRICE --> QUAD
    REQ --> MSAPI

    style Channels fill:#f7faf4,stroke:#58af23,stroke-width:1.5px,color:#2d3130
    style Platform fill:#f8f8f8,stroke:#94979a,stroke-width:1.5px,color:#2d3130
    style Indexing fill:#eef3f1,stroke:#58af23,stroke-width:1.5px,color:#2d3130
    style External fill:#fbf4fb,stroke:#7e1c7e,stroke-width:1.5px,color:#2d3130
Рисунок 1: Service blueprint: целевая архитектура

3. Технологический стек MVP

Слой Базовый выбор Почему
Runtime Node.js + TypeScript единый runtime для API, adapters, workers и тестов
HTTP layer Fastify быстрый async I/O, plugin model, schema-driven routes
Contracts & validation TypeBox + AJV + OpenAPI typed DTOs, runtime validation, API contracts
Dialogue Orchestration явный orchestrator внутри backend контролируемая логика выполнения
HTTP adapters undici async API-клиенты для QuadCRM и МойСклад
Background jobs BullMQ + Redis sync jobs, embeddings, retry logic, scheduled jobs
Internal service DB PostgreSQL 16 + Prisma ORM сессии, audit trail, состояние синхронизации, mappings, metadata
Vector store Qdrant + @qdrant/js-client-rest semantic retrieval и payload filtering
Cache / rate limits Redis short-lived state, throttling, queue backend
Observability OpenTelemetry + Prometheus + Grafana + Loki или Sentry метрики, traces, ошибки, audit trail
Packaging Docker локальное окружение и доставка
Пилотный контур Docker Compose на одном VM MVP и пилотный запуск
Масштабирование Kubernetes после подтвержденной нагрузки масштабирование без раннего усложнения

Runtime profile:

  • agent-service и catalog-worker работают на одном Node.js / TypeScript стеке;
  • embeddings запрашиваются через внешний API, а не считаются локальной ML-платформой;
  • Qdrant отвечает за vector search, а сервис отвечает за orchestration, business logic и интеграции.

4. Компоненты сервиса

4.1 agent-service

Ответственность:

  • включать Channel Gateway для сайта, мессенджеров и соцсетей;
  • принимать сообщения из сайта и будущих каналов;
  • хранить session state;
  • запускать orchestrator;
  • обращаться к Retrieval Service;
  • запрашивать цену через QuadCRM API;
  • писать заявки через МойСклад JSON API;
  • логировать события, ошибки и handoff.

4.2 catalog-worker

Ответственность:

  • читать измененные товары из Percona MySQL;
  • собирать search document;
  • генерировать embeddings через внешний embedding API;
  • обновлять Qdrant;
  • обновлять metadata и состояние синхронизации во внутреннем PostgreSQL.

4.3 Qdrant

Ответственность:

  • хранить vectors;
  • хранить часть payload для фильтров;
  • возвращать shortlist релевантных товаров.

4.4 Internal PostgreSQL

Ответственность:

  • session state;
  • conversation summaries;
  • состояние синхронизации и технические журналы;
  • mapping product IDs между системами;
  • catalog metadata для hydrate after retrieval;
  • audit trail по действиям агента.

4.5 Redis

Ответственность:

  • rate limiting;
  • short-lived cache;
  • job broker/result backend;
  • временные технические locks для sync.

4.6 Логическая модульная структура

Внутренние границы сервиса фиксируются сразу:

  • Channel Gateway: входные каналы и нормализация входящих сообщений;
  • Dialogue: orchestrator, state machine и routing сценариев;
  • Retrieval: работа с Qdrant и metadata lookup;
  • Pricing: адаптер QuadCRM API;
  • Requests: адаптер МойСклад JSON API;
  • Handoff: операторский handoff и правила эскалации;
  • Catalog Indexing: извлечение каталога, нормализация документов и постановка indexing jobs;
  • Platform: config, logging, telemetry, queue, database, auth, rate limits;
  • Contracts: HTTP DTOs, queue payloads и adapter contracts;
  • Shared: общие типы, utility-функции и error model.

catalog-worker запускается отдельно, но использует те же contracts, adapters и platform services.

4.7 Очереди и фоновые процессы

В BullMQ фиксируются отдельные очереди:

  • catalog-sync-incremental;
  • catalog-sync-full;
  • catalog-embedding-batch;
  • outbound-retry;
  • handoff-followup.

Это разделяет catalog indexing, внешние retries и операторские действия без раннего ухода в microservices.

5. Границы ответственности по системам

Система Роль Что читать / писать
Bitrix / Percona MySQL основной источник данных по каталогу только read-only
QuadCRM API основной источник данных по цене, акциям и, возможно, наличию только API calls
МойСклад JSON API основной источник данных по заявкам и бизнес-действиям только create/update через API
Qdrant слой поиска по каталогу upsert vectors, search
Internal PostgreSQL служебное состояние и метаданные внутреннее чтение и запись
Redis слой кеша и очередей внутреннее чтение и запись

6. Как будет идти sync каталога

flowchart TB
    H[15 min incremental sync<br/>by TIMESTAMP_X] --> B
    I[Nightly full sync] --> B
    A[(Percona MySQL / Bitrix)] --> B[Extract changed products]
    B --> C[Normalize catalog document]
    C --> D[Map attributes<br/>and categories]
    D --> E[Generate embedding]
    E --> F[(Qdrant)]
    D --> G[(Internal PostgreSQL)]

    J[Inactive or deleted products] --> K[Deactivate or remove<br/>from indexes]
    K --> F
    K --> G
Рисунок 2: Синхронизация каталога из Bitrix / Percona MySQL в слой поиска

Модель синхронизации:

  1. Полный nightly sync, то есть полная ночная сверка каталога с индексом.
  2. Incremental sync, то есть синхронизация только измененных объектов, а не всей базы, каждые 15 минут.
  3. Основа incremental sync: TIMESTAMP_X как системное поле Bitrix со временем последнего изменения и статус активности ACTIVE со значениями Y/N.
  4. На каждом измененном товаре worker:
    • читает товар и связанные свойства;
    • нормализует в единый search document;
    • пересчитывает embedding;
    • делает upsert в Qdrant;
    • обновляет metadata в Internal PostgreSQL.

6.1 Как удалять и деактивировать неактуальные объекты

Постоянное сравнение всей Bitrix-базы на каждом цикле не используется.

Базовая стратегия:

  • incremental sync каждые 15 минут читает только измененные товары по TIMESTAMP_X;
  • если товар стал ACTIVE = N, то есть деактивирован в источнике, worker деактивирует его во внутренних метаданных и удаляет или скрывает из Qdrant;
  • если товар удален физически и больше не попадает в incremental выборку, это ловится на nightly full sync;
  • nightly full sync обновляет last_seen_at для всех реально существующих объектов;
  • после full sync все объекты, которые не были замечены, считаются удаленными и удаляются из Qdrant и внутренних метаданных.

Во внутреннем PostgreSQL используется таблица состояния индекса, например:

Поле Что означает
source_id ID объекта в исходной системе, обычно ID товара в Bitrix
source_type тип объекта, например product, section, offer
last_seen_at когда сервис в последний раз видел этот объект в источнике
last_indexed_at когда объект в последний раз был успешно переиндексирован
is_active активен ли объект с точки зрения источника на момент последней синхронизации
is_deleted признан ли объект удаленным после сверки
content_hash хэш нормализованного документа для определения, изменилось ли содержимое

Операционный результат:

  • каждые 15 минут идет дешевый incremental sync;
  • один раз в сутки идет reconcile;
  • drift, то есть расхождение между источником и индексом, и физические удаления закрываются без постоянного сравнения всей базы.

7. Что именно вытаскивать из Bitrix

На этапе discovery фиксируется реальная схема каталога. Рабочая схема извлечения включает:

  • b_iblock_element
  • b_iblock_section
  • b_iblock_section_element
  • b_iblock_property
  • b_iblock_element_property
  • при необходимости Catalog Product / SKU сущности для offers

Минимальный набор полей для индексации:

  • product_id
  • sku / article
  • name
  • brand
  • category path (путь по каталогу, например категория и подкатегория)
  • preview_text (краткое описание)
  • detail_text: (полное описание);
  • normalized attributes: нормализованные характеристики товара для фильтрации и сравнения;
  • url: ссылка на карточку товара;
  • active (для каталога)
  • updated_at (собирается из TIMESTAMP_X).

Не индексировать как vector truth:

  • цену;
  • остатки;
  • часто меняющиеся promo fields.

8. Сценарии работы сервиса

8.1 Консультация

  1. Пользователь пишет в диалоговом окне на сайте, мессенджер или соцсеть.
  2. agent-service принимает и нормализует входящее сообщение через Channel Gateway.
  3. Orchestrator определяет intention.
  4. При сценарии подбора Orchestrator вызывает Retrieval Service.
  5. Retrieval Service ищет в Qdrant и добирает metadata по товарам.
  6. Orchestrator собирает ответ, опирающийся на данные каталога, и сравнение релевантных вариантов.
  7. Ответ возвращается пользователю.

8.2 Получение цены

  1. После определения товара Orchestrator вызывает QuadCRM Adapter.
  2. Адаптер идет в QuadCRM API.
  3. Возвращает цену, акцию, при наличии availability / ETA.
  4. Ответ встраивается в финальную реплику.

8.3 Создание заявки

  1. Агент собирает согласие и обязательные поля.
  2. Формирует краткое резюме диалога.
  3. Вызывает МойСклад Adapter.
  4. Адаптер создает сущность через МойСклад JSON API.
  5. Пользователь получает подтверждение и номер заявки.

8.4 Handoff

  1. Если confidence низкий или пользователь просит человека, оркестратор запускает handoff.
  2. Диалог и резюме логируются.
  3. Создается операторская задача или request в согласованной системе.

8.5 Правила работы сервиса

Сервис работает по жестким правилам:

  1. Сначала сервис помогает клиенту разобраться, сравнить варианты, выбрать товар и перейти к заказу в Newton.by.
  2. Агент не придумывает цену и не кэширует ее как долгоживущую истину.
  3. Агент не создает заявку без явного согласия пользователя.
  4. Агент собирает только минимально нужные персональные данные.
  5. Если confidence низкий, запускается handoff вместо “смелого ответа”.
  6. Каталог, цены и заявки остаются в системах-источниках, агент только оркестрирует сценарий.

Из этого формируется модель оркестрации:

  • при консультации агент предлагает shortlist и уточняющие вопросы;
  • при консультации агент помогает сравнить релевантные альтернативы, а не только возвращает один товар;
  • при ценовом вопросе агент сначала определяет товар, а потом вызывает QuadCRM API;
  • при заказе / возврате / консультации агент сначала собирает обязательные поля, потом пишет в МойСклад;
  • при сомнении агент эскалирует сценарий, а не фантазирует.

9. Границы MVP

В MVP входят:

  • web channel;
  • retrieval по каталогу;
  • получение цены через QuadCRM API;
  • создание заявок через МойСклад JSON API;
  • handoff на оператора;
  • audit trail;
  • базовые метрики качества.

Что не входит в MVP:

  • полноценная омниканальность по всем мессенджерам сразу;
  • автоматическое принятие сложных решений по возврату;
  • автономный checkout;
  • сложный recommendation engine;
  • отдельные microservices по каждому модулю.

10. План реализации

Пакет Что делаем Результат
WP0 Discovery схема каталога, ID mapping, методы API, обязательные поля подтвержденные integration contracts
WP1 Foundation Node.js / TypeScript scaffold, Fastify, Prisma, Redis, Qdrant, CI/CD рабочая платформа
WP2 Catalog Extract read-only извлечение из Bitrix / MySQL нормализованный документ каталога
WP3 Indexing embeddings, upsert в Qdrant, планировщик sync рабочий корпус поиска
WP4 Agent Core Fastify, sessions, orchestrator, retrieval tool основной backend сервиса
WP5 Pricing адаптер QuadCRM и contract tests актуальная цена в диалоге
WP6 Requests адаптер МойСклад и contract tests создание заявок
WP7 Handoff & Audit резюме диалога, handoff, журнал действий, маршрут к оператору управляемая обработка сложных сценариев
WP8 Pilot тестовые диалоги, метрики, tuning ограниченный пилот на живом трафике

11. Definition of done для MVP

MVP считается готовым, когда:

  • агент отвечает по каталогу на ограниченном живом трафике;
  • retrieval работает из собственного Qdrant, а не напрямую из MySQL;
  • цены берутся через QuadCRM API;
  • заявки пишутся через МойСклад JSON API;
  • есть handoff сценарий;
  • есть audit trail по каждому созданному request;
  • есть dashboard по базовым метрикам;
  • есть runbook на запуск, rollback и reindex.

12. Ключевые BA-решения до старта разработки

Перед стартом разработки фиксируются:

  • какие customer journeys входят в MVP;
  • какие поля обязательны для order / return / consultation request;
  • какие каналы входят в первую волну;
  • что считается успешной консультацией с точки зрения подбора, сравнения и перевода в действие;
  • какие метрики считаются бизнес-успехом пилота;
  • в какой системе живет операторский handoff.

13. Итоговая архитектурная модель

Для MVP архитектурная модель выглядит так:

  • Node.js / TypeScript как единый runtime для backend и worker-процессов;
  • не microservices, а modular monolith для agent-service;
  • отдельный worker для sync и embeddings;
  • Qdrant как retrieval engine;
  • отдельный internal PostgreSQL, а не reuse внешних БД компании;
  • API-first интеграции с QuadCRM и МойСклад;
  • read-only доступ к Bitrix / Percona MySQL;
  • поэтапный rollout с ранним MVP и ограниченным живым трафиком.

Модель дает рабочий баланс между:

  • скоростью запуска;
  • контролем над архитектурой;
  • качеством retrieval;
  • безопасностью для production-систем Newton.by;
  • возможностью потом масштабироваться без болезненного переписывания.