ZenAi: от кода до продакшна — деплой, React Admin, TG-авторизация и live-синхронизация
Date: 2026-02-27
Project: ZenAi — ИИ-менеджер для Telegram (C:\Tools\ZenAi)
Duration context: длинная сессия (вторая половина дня — деплой, админка, авторизация, синхронизация)
Что было сделано
Деплой на продакшн
- Первый деплой на Ubuntu 24.04 (155.212.129.22) через Docker Compose: 4 контейнера (api, worker, postgres pgvector/pg16, redis 7-alpine).
- Первая Alembic-миграция
0bbc55db5763: 14 таблиц + pgvector extension. - 34 API-эндпоинта зарегистрированы,
/healthотвечает OK. scripts/_deploy_ssh.py— SFTP upload +docker compose build+ restart.- Исправлен Dockerfile: добавлены
COPY alembic/иCOPY alembic.ini(без них миграции не работали в контейнере). - В
alembic/env.pyдобавленimport pgvector.sqlalchemy.vector— без этого autogenerate не рендерил VECTOR-тип.
React Admin (Этап 6)
- Полноценная React Admin панель: Vite + React Admin v5 + TypeScript + MUI5.
- Кастомный
dataProviderпод FastAPI: offset/limit пагинация,X-Total-Count, маппинг путей ресурсов. authProvider— JWT auth (login/logout/refresh/checkAuth/getIdentity).- Dashboard с метриками из
/ops/overview+ таблица здоровья аккаунтов. - 6 ресурсов: Conversations (ChatTimeline с пузырями), TG Accounts (CRUD + pause/resume), KB Documents (workflow publish/archive + ChunksList), Alerts (ack/resolve), Audit Logs (expandable before/after JSON), CRM Sync Events (retry для failed).
admin/Dockerfile— multi-stage build (node:20 → nginx:alpine),nginx.confс SPA fallback + API proxy.scripts/create_admin.py— создание первого admin-пользователя.- Русская локализация через
ra-language-russian. - Хелпер
src/api/pagination.py—paginated_response()сX-Total-CountиContent-Range.
TG-авторизация по телефону
- 3 эндпоинта:
auth/start(отправка кода),auth/verify-code(проверка + 2FA detection),auth/verify-2fa(облачный пароль). - Состояние авторизации хранится в Redis с TTL 5 мин.
- Обработка всех Telethon ошибок (
ApiIdInvalidError,PhoneNumberBannedError,FloodWaitError,PhoneCodeExpiredError,SessionPasswordNeededError) с русскими сообщениями. - Admin: пошаговый визард (телефон → код → 2FA → готово) + вкладка импорта
.session-файла. - Кнопка «Проверить подключение» на странице аккаунта.
TG-авторизация по QR-коду
- 4 эндпоинта:
auth/qr-start,auth/qr-status/{id},auth/qr-complete/{id},auth/qr-2fa. _qr_wait_task()— asyncio background task: ожидание сканирования с timeout 120 сек, результат в Redis.- TelegramClient хранится в module-level dict (не в Redis), т.к.
qr_login.wait()требует живой клиент. - QR генерируется через
qrcode[pil], передаётся как base64 PNG. - Admin:
QrAuthWizardс 3 шагами + polling каждые 2 сек + обновление QR при истечении.
KB: файлы и entries
- Парсер файлов
src/rag/file_parser.py: PDF (pymupdf), DOCX (python-docx), XLSX (openpyxl), XLS (xlrd), TXT, MD. - Endpoint
POST /kb/documents/upload— multipart/form-data, валидация расширения и размера (20 МБ). - Модель
KbEntry— многоблочная структура: text/file entries с позиционированием и CRUD. - 6 endpoint-ов для entries + хелпер
_rebuild_document_content()для автосклейки. - Admin: карточки entries с кнопками перемещения, диалоги добавления текста/файла.
Persistent Telegram pool + live handlers
AccountPoolвapp.state.tg_pool— единый пул клиентов, живёт всё время работы сервера.live_handler.py— TelethonNewMessagehandler на каждый подключённый клиент. Сохраняет входящие и исходящие в БД с дедупликацией поtg_message_id.- Автоматическое создание контактов и диалогов для новых собеседников.
- Health endpoint показывает количество подключённых аккаунтов.
Синхронизация диалогов
TelegramSyncService:sync_dialogs()(get_dialogs → upsert contacts + conversations),load_history()(lazy load последних 100 сообщений).- ARQ cron
sync_all_accountsкаждые 15 мин. - Миграция: поля
source,tg_chat_id,tg_chat_title,synced_at,history_loaded(conversations),tg_message_id(messages). - Admin: полный редизайн списка (аватары, фильтры, МСК-время) и чата (разделители дат, лейблы бот/оператор, auto-refresh 10 сек).
Логирование и мониторинг
structlog— JSON в production, human-readable в dev.RequestLoggingMiddleware— логирование каждого HTTP-запроса (method, path, status, duration_ms).AnomalyDetector— Redis-based: silence (>2 мин без ответа), spam (>3 сообщений/10 сек), repetition (2+ одинаковых ответа).
Проблемы и решения
Проблема: Alembic не видит VECTOR-тип в контейнере
Симптомы: alembic revision --autogenerate генерирует миграцию, но VECTOR-колонки пропущены.
Решение: import pgvector.sqlalchemy.vector в alembic/env.py — без явного импорта SQLAlchemy не регистрирует кастомный тип.
Проблема: React Admin не получает total count для пагинации
Симптомы: список показывает 0 записей, хотя данные есть.
Решение: кастомный paginated_response() хелпер на бэкенде — явно ставит X-Total-Count и Content-Range в headers + expose_headers в CORS.
Проблема: QR-авторизация и 2FA
Симптомы: при QR-логине с включённой двухфакторной Telethon бросает SessionPasswordNeededError, но её перехватывали как “QR expired” и регенерировали QR.
Решение: Отдельный except SessionPasswordNeededError перед генеральным except, запись статуса needs_2fa в Redis, отдельный фронтенд-шаг для ввода пароля.
Проблема: ValueError на load-history — float duration
Симптомы: 503 на эндпоинте загрузки истории из Telegram.
Решение: Telethon возвращает duration медиа как float, а формат :02d ожидает int. Добавлен int() cast.
Ключевые решения
- Кастомный dataProvider вместо готового — React Admin не имеет официального провайдера для FastAPI. Написан свой с маппингом offset/limit, кастомными путями и
X-Total-Count. - Module-level dict для QR-клиентов —
qr_login.wait()требует живойTelegramClient, его нельзя сериализовать в Redis. Поэтому dict в памяти процесса + результат polling через Redis. - Lazy load истории —
sync_dialogs()тянет только метаданные + последнее сообщение. Полная история — по запросу админа черезload-history. Экономит трафик и время при первичной синхронизации. - Persistent pool с fallback — если аккаунт подключён в persistent pool → используем его. Если нет → создаём temp pool на время запроса. Покрывает оба кейса без дублирования кода.
Источники и ссылки
Из сессии
- React Admin — Data Provider — документация по кастомным data provider-ам
- Telethon — TelegramClient — API Telethon для авторизации
- Telethon QR Login Issue #3665 — решение 2FA при QR-авторизации
Дополнительный контекст
- React Admin + FastAPI Discussion — обсуждение интеграции React Admin с FastAPI, подходы к data provider
- Telethon QR Authorization (SO) — паттерн
wait()+recreate()+SessionPasswordNeededError - opentele — Login via QR — альтернативная реализация QR-логина для Telegram
Что дальше
- Динамические воронки — замена хардкодного FSM на data-driven движок с шагами из БД.
- Улучшение промптов и качества бота (лаконичность, RAG grounding, вовлечение).
- Typing emulation и уведомления при завершении воронки.
- Message debounce — группировка серий сообщений в один LLM-вызов.