Нужен был бот, который отвечает в Telegram от имени конкретного человека и пишет так, как писал бы он: лексика, длина сообщений, пунктуация, эмодзи — без «ассистентского» тона. Бот подключается к аккаунту через Telegram Business и отвечает только короткому списку разрешённых собеседников.
Важно было не просто сделать бота, а честно сравнить подходы: RAG на базовой модели, дообучение собственной модели и гибрид — на одних и тех же данных и одной метрике.
• Пайплайн данных: парсинг экспорта Telegram Desktop → пары «реплика → ответ» → разбиение по времени (без утечки будущего в обучение), отчёт по данным.
• Профиль стиля: 20–30 правил письма, которые можно править вручную.
• Три режима за одним интерфейсом: RAG (базовая модель + профиль + ближайшие примеры из Chroma), finetuned (Qwen 2.5 7B + LoRA на Unsloth, сервинг vLLM на Modal) и hybrid.
• Бот на aiogram 3 для Telegram Business: fail-closed фильтры и белый список, валидация ответа (одна перегенерация, иначе тишина), «человеческая» доставка с паузами, команды управления, dry-run.
• Система оценки: слепой LLM-судья по 4 критериям (стиль, уместность, «не ассистент», непротиворечивость), сравнение прогонов, HTML-отчёт. Каждый прогон привязан к коммиту и версии данных — любую цифру можно воспроизвести.
• Деплой на VPS, тесты pytest, ruff, pre-commit, проверка истории на утечку личных данных (gitleaks) перед публикацией.
Результаты на 80 отложенных парах, оценка 1–5 слепым судьёй:
— RAG (в продакшене): 3.38, p50 задержка 1.5 с;
— дообученная Qwen 2.5 7B + LoRA: 2.83;
— гибрид: 2.73.
Вывод: на таком объёме данных хорошо настроенный RAG бьёт дообучение — и это подтверждено цифрами. Шум между прогонами ≈±0.1, так что разница реальная.
Код открыт: github.com/klitale/digital-twin (без личных данных), его можно запустить на своём экспорте чата. Срок: около недели, 44 коммита.