Разработчик под ником, опубликовавший кейс на Habr, собрал сервис второй памяти, который каждую ночь около двух часов по московскому времени запускает конвейер обработки переписки в Telegram. Сначала Telethon скачивает новые сообщения из отмеченных пользователем чатов и папок, через час второй воркер превращает их в структурированную память: режет на куски, прогоняет через DeepSeek, раскладывает по таблицам и выгружает в markdown-файлы. К утру у человека появляется дополнительная информация в сервисе второй памяти.
Автор сознательно отказался от стандартного подхода с векторной базой и RAG. Переписка плохо делится на фрагменты: один факт собирается из десятка реплик в разных чатах, а нарезка по 500 токенов разрывает историю. Человек в одном чате Саша, в другом Александр, в третьем у него непонятный ник — поиск возвращает пять почти одинаковых фрагментов вместо одного знания. С актуальностью ещё хуже: в марте договорились об одном, в июне передумали, а в индексе лежат оба варианта с одинаковым весом. Вместо фрагментов автор строит карточки: люди, проекты, темы, факты, задачи и связи между ними. Каждый факт привязан к сообщению, из которого он был вытащен.
| Метрика | Значение |
|---|---|
| Пользователей в базе | несколько |
| Источников на пользователя | 7 (3 папки и 4 чата) |
| Чатов | 34 |
| Сущностей | 281 |
| Тем | 147 |
| Человек | 108 |
| Проектов | 26 |
| Фактов | 1815 |
| Задач | 184 |
| Дневных заметок | 133 |
| Токенов на входе | 3028 тысяч |
| Токенов на выходе | 7027 тысяч |
| Всего токенов | 10,05 млн |
| Стоимость обработки | меньше 10 долларов |
| Среднее время задания | 205 секунд |
| Самое долгое задание | почти 12 минут |
Схема конвейера выглядит так. Telethon забирает сообщения по выбранным источникам. Каждое сырое сообщение получает запись в таблице состояния: ожидает, в процессе, обработано, ошибка. Планировщик в следующий прогон берёт только то, чего в этой таблице нет, — так автор не платит дважды за обработку одного и того же. Сообщения группируются по ключу «источник:чат», сортируются по дате и режутся на куски по 100 штук. Внутри куска только один чат, чтобы модель видела связный диалог. Из куска собирается транскрипт вида [дата] Отправитель: текст с обрезкой по 30 тысячам символов.
На каждый кусок идёт один вызов DeepSeek, который должен вернуть строгий JSON с полями daily_note, topics, people, projects и links. В промпт подкладывается список уже известных сущностей пользователя с просьбой переиспользовать имена. Без этого один и тот же проект каждый прогон называется по-новому, и база быстро превращается в мусорку. Когда все куски задания готовы, запускается merge. Сущности ищутся по ключу (пользователь, тип, каноническое имя), повторные упоминания не плодят дубликаты, а обновляют summary. Факты и задачи привязываются к сущностям, связи уходят в отдельную таблицу, а каждая запись ссылается на id исходных сообщений.
Последний шаг — выгрузка в обычные markdown-файлы Daily, Knowledge, People, Projects. Ссылки между заметками оформлены как [[wiki-links]], так что vault открывается в Obsidian. Экспорт идемпотентный: перед записью блока считается его sha256, и если такой блок уже выгружался, он пропускается. Готовая карточка выглядит примерно так: «Поездка в Анталью», собирались в сентябре, бюджет около 350 000 ₽ на двоих, [[Аня]] предложила даты, [[Саша]] уточнил расклад по отелю и перелёту. Связь в файл не пишется, она живёт в базе: у каждого факта и задачи есть ссылки на конкретные сообщения.
Цифры на момент публикации: в базе несколько пользователей, на одного в среднем по 7 источников (3 папки и 4 отдельных чата), но даже они за пару месяцев теста сгенерировали десятки тысяч сообщений в 34 чатах. Из этого получилось 281 сущность: 147 тем, 108 человек, 26 проектов. Плюс 1815 фактов, 184 задачи и 133 дневные заметки. По токенам вышло 10,05 млн: 3028 тысяч на входе и 7027 тысяч на выходе. Ответы дороже входа больше чем вдвое, потому что JSON со схемой занимает много места. По тарифам DeepSeek это меньше десяти долларов на все сообщения.
Одно задание — обработка всех новых сообщений одного пользователя за прогон — идёт в среднем 205 секунд. Самое долгое заняло почти 12 минут. Так как всё работает ночью, 12 минут вполне приемлемо. Что ломалось: часть заданий отменилась на середине, в базе остался текст cancelled — model changed to v4-flash. Автор менял модель на лету, а задание в этот момент выполнялось. Часть чанков посчитана одной моделью, часть другой. Данные не сломались, но такой подход требует аккуратности.
Для отрасли кейс показателен не технологией, а экономикой. Персональная память на небольших объёмах стоит копейки, а основная работа уходит не в LLM, а в инфраструктуру: таблицы состояния, дедупликацию, идемпотентный экспорт и привязку фактов к исходным сообщениям. Векторная база, которую обычно ставят первой, здесь оказалась лишней.

