Mirror · техническая архитектура
Человек ведёт дневник и выговаривается, получает отчёты о своём психологическом состоянии, а система ранжирует зарегистрированных терапевтов по тому, насколько эффективны они будут именно для него. Ниже — как это работает под капотом.
Весь продукт — одно docker-compose-приложение, деплой одной командой. API не привязан к клиенту: iOS/Android/web-клиенты позже подключаются к тому же use-case-слою без дублирования логики.
docker-compose-стек · reverse proxy с авто-TLS на облачном VPS
Чувствительный к задержкам диалог, тяжёлая асинхронная аналитика и контроль качества разделены — каждый контур масштабируется и падает независимо.
Реальное время, ход за ходом. State machine на LangGraph выбирает разговорный ход; RAG заземляет ответы персоны.
Асинхронные задачи: ежедневные/еженедельные отчёты, обновление психологического портрета, мультиагентный подбор терапевта.
Оффлайн-эксперименты с LLM-судьёй и guard-метриками; живая A/B-аналитика по версиям промптов. Ни один промпт не едет в прод «на глазок».
Диалог — это граф состояний, а не один промпт. Каждое сообщение клиента проходит через граф; проверка на кризис — жёсткое ребро: промпт можно «уговорить», ребро графа — нет.
state machine на LangGraph · гештальт-интервенции (например, практика пустого стула) подключаются отдельными подграфами за роутером
Граф генерирует несколько кандидатов ответа, скорит их и выбирает ход вместо one-shot-генерации. Сейчас выключено конфигом, чтобы держать стоимость хода низкой для клиентов — путь в графе сохранён и включается per-persona.
Для персоны Ялома перед вызовом модели выполняется векторный поиск — его изданные книги нарезаны и проиндексированы, ответы опираются на реальные примеры работы с клиентами. Тот же пайплайн расширяется на зарегистрированных терапевтов по мере накопления истории сессий.
Каждый ответ LLM, попадающий в бизнес-логику, парсится в Pydantic-схему — и никогда не используется как сырой текст. LangChain отвечает за промпт-темплейты и парсинг структурированного вывода внутри узлов графа.
Весь доступ к моделям идёт через интерфейс LLMPort с тремя реализациями: Gemini (продакшн), Ollama (локальные эксперименты), stub (быстрые тесты). Смена провайдера — изменение конфига, а не рефакторинг.
Долгий AI-анализ никогда не блокирует живой диалог. Отчёты работают как LangChain-цепочки; подбор терапевта — мультиагентный пайплайн, где у каждого агента свой промпт и типизированный вывод.
мультиагентный пайплайн подбора · ежедневные/еженедельные отчёты — отдельные LangChain-цепочки над той же историей
Каждый вызов LLM тарифицируется против баланса пользователя («яломы») — контроль затрат и путь к монетизации с первого дня.
Голосовые сообщения и рукописные заметки распознаются через мультимодальный Gemini и попадают в тот же дневниковый пайплайн, что и текст.
Дифференциатор продукта — не картинки персон, а то, как терапевт разговаривает. Это сложнее всего проверить, поэтому у качества диалога свой пайплайн.
один полный прогон = 302 полных диалога по 10 ходов · судье доверяем только после 80%+ совпадения с ручной оценкой · версия, пробившая guard-порог, отклоняется независимо от остальных цифр
Одно правило держит кодовую базу в порядке по мере роста к нескольким клиентам: бизнес-логика никогда не живёт в транспортном хендлере.
app/core/use_cases/) — вызовы LLM, запись в БД, детекция кризиса, генерация отчётов, обновление портрета, подбор. Всё, что понадобится и будущему web-клиенту.app/bot/) — только Telegram-транспорт: разобрать событие, вызвать use case, отрисовать ответ. Никаких вызовов LLM, никакой прямой записи в БД.Приватность критична для терапевтических данных — следующие шаги переводят инференс и чувствительные данные полностью под контроль продукта.
Развернуть локальную модель (Ollama/vLLM) и подключить LoRA-адаптеры per-persona — свой стиль общения у каждой персоны терапевта, данные клиентов перестают покидать периметр. Локальный провайдер и эксперименты уже на месте.
Персональные данные вычищаются/маскируются перед любым внешним API-вызовом, пока облачная LLM остаётся продакшн-провайдером.
Чувствительное содержимое диалогов шифруется в базе данных.
Заменить ручной цикл «анализ проигравших → новый промпт → повторный прогон» на DSPy с откалиброванным LLM-судьёй в роли метрики. Плюс judge-оценки на сэмпле продакшн-трафика в Langfuse.