Разработчикам · Архитектура

Как устроен Brandside.ai

Brandside.ai — AI-модуль для регистрации товарных знаков: пользователь ведёт диалог через React-виджет, backend формирует ответы через LLM Gateway и строит черновик заявки. Эта страница описывает архитектуру системы для партнёров и разработчиков, встраивающих виджет.

Документ — Архитектурный обзор Версия — v0.1 (альфа) Стек — Python + FastAPI + React

01Обзор архитектуры

Система состоит из четырёх основных компонентов: виджет (React/TypeScript), AI Backend (Python/FastAPI), LLM Gateway (TensorZero) и внешние LLM-провайдеры. Виджет общается с backend через REST (JSON), backend обращается к базе данных и к LLM-провайдерам через абстрактный шлюз.

Диаграмма архитектуры Brandside.ai: Пользователь → Виджет → AI Backend → LLM Gateway → LLM Provider; Backend → PostgreSQL + pgvector и Object Storage
КомпонентСтекНазначение
AI WidgetReact 19.2, TypeScript 6, Vite 8Диалоговый интерфейс, Shadow DOM изоляция
AI BackendPython 3.13, FastAPI, Pydantic v2, SQLAlchemy 2.0Управление сессиями, бизнес-логика, конвейер LLM
LLM GatewayTensorZeroАбстракция над провайдерами, горячая замена
PostgreSQL + pgvectorPostgreSQL 17, pgvectorДанные сессий и вектора МКТУ-базы знаний

02AI Виджет

Технология и изоляция

Виджет реализован на React 19.2 с TypeScript 6 в строгом режиме (strict: true). Он упакован в самодостаточный standalone-бандл и монтируется в Shadow DOM — стили виджета не конфликтуют со стилями страницы-хозяина и наоборот.

Бандл подключается через один тег <script> и не требует отдельной установки React или других зависимостей на стороне хозяина.

Транспорт: REST

В альфа-версии виджет общается с backend исключительно через REST (JSON): создание сессии, отправка сообщения, загрузка изображения. Все операции — синхронные запросы с ожиданием ответа.

Подключение

Виджет доступен по пути /widget/index.standalone.js. После загрузки скрипта доступен глобальный объект BrandsideAIWidget. Конфигурация передаётся через /config.js, который загружается до виджета.

03AI Backend

Слоёная архитектура

Backend построен по принципам Clean Architecture: слои API, Use Cases, Domain и Infrastructure строго разделены. Внешние зависимости (FastAPI, SQLAlchemy) присутствуют только на слое Infrastructure — бизнес-логика не зависит от фреймворка.

СлойОтветственность
APIHTTP-маршруты FastAPI, Pydantic-схемы запросов и ответов
Use CasesСценарии использования: старт сессии, обработка сообщения, загрузка изображения
DomainАгрегаты Session, Identity, Draft; доменные события
InfrastructureРепозитории SQLAlchemy, порт LLM Gateway, объектное хранилище

Сессии и учётные записи посетителей

Доступ к защищённым операциям регулируется через систему инвайт-кодов: тестировщик получает одноразовый код, обменивает его на cookie __Host-bs_identity, после чего может создавать сессии диалога. Подробности — в разделе «Пользователям».

Каждая сессия изолирована: история сообщений и черновик принадлежат конкретной сессии и недоступны другим.

База данных

Основные данные (сессии, история сообщений, черновики, учётные записи посетителей) хранятся в PostgreSQL. МКТУ-база знаний индексируется через расширение pgvector: при обработке описания бизнеса backend выполняет векторный поиск по ней, чтобы точнее предложить классы.

04LLM Gateway

LLM Gateway (реализован на TensorZero) — абстрактный слой между backend и внешними LLM-провайдерами. Бизнес-логика обращается к Gateway через единый интерфейс независимо от того, какой провайдер используется в данный момент.

Горячая замена провайдера (например, с OpenAI на Anthropic) не требует изменений в бизнес-логике backend — только обновления конфигурации Gateway. Это решение зафиксировано в ADR-007.

Gateway также выполняет анонимизацию персональных данных (PII) перед отправкой в LLM: четыре категории данных заменяются на обратимые метки вида [REDACTED_TYPE_N].

05Безопасность и PII

Анонимизация

Перед отправкой в LLM содержимое сообщений проходит через конвейер анонимизации: персональные данные четырёх категорий (имена, контакты, идентификаторы, финансовые данные) заменяются обратимыми масками, зашифрованными по AES-256. После получения ответа маски раскрываются обратно.

Ограничение запросов

Каждая сессия ограничена 10 сообщениями в минуту. Запросы сверх лимита отклоняются с кодом 429 Too Many Requests.

Cookie __Host-bs_identity выпускается с атрибутами HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=2592000. В базе данных хранится только хеш токена (SHA-256), а не сам токен.

Никогда не раскрывайте API-ключи LLM-провайдеров в публично доступных файлах (config.js, клиентском коде). Ключи должны быть только в серверной конфигурации.

06Встраивание виджета

Быстрый старт

Для встраивания виджета на страницу необходим контейнер с идентификатором widget-root и два скрипта: конфигурация и бандл виджета.

<!-- 1. Контейнер виджета -->
<div id="widget-root"></div>

<!-- 2. Runtime-конфиг (загружается первым) -->
<script src="/config.js"></script>

<!-- 3. Загрузчик -->
<script src="/assets/bootstrap-widget.js?v=0.0.2"></script>

Конфигурация

Файл /config.js задаёт публичные параметры без секретов. Основной параметр — apiBaseUrl: базовый URL backend без суффикса /api. Значение вычисляется из текущего origin, поэтому один и тот же статический артефакт работает и на локальном стенде, и в production без пересборки.

Параметр apiBaseUrl не должен включать суффикс /api. Правильно: https://brandside.ru. Неправильно: https://brandside.ru/api.

Статические ресурсы

CSS, логотип и загрузчик лежат в /assets. Бандл виджета и его стили отдаются отдельно из /widget. Это позволяет пересобирать виджет независимо от HTML-страниц лендинга.