The Jerusalem PostKinneret water level rises one cm. after weekend rains, remains 39 cm. below last year's heightPunchPHOTOS: NEMA receives six Nigerian returnees from USSky TG24Una mattina gloriosa, il romanzo di Antonio Monda sul Titanic diventa una mostra a RomaZDF heuteAktuelle Pressemitteilungen des ZDF01netCe mini PC embarque un Core i7, 16 Go de RAM et Windows 11 Pro : son prix, 206 € seulementPremium TimesOpen a FirstBank account digitally, anytime, anywhereCBS NewsMore races called as Democratic majority comes into focusLa TerceraA horas de la definición del título: delantero de Colo Colo protagoniza grave choque en estado de ebriedadInteriaStrzelanina w Krakowie. Ranny policjant odzyskał przytomnośćSRF NewsMidterms 2026 – Trump will gegen die Demokraten ermitteln lassenIl Sole 24 OreRoma, travolto da monopattino pirata: muore fisico CervellatiCNN بالعربيةفي الذكرى الخمسين لفيلم "روكي".. جولات في فيلادلفيا تعيد إحياء مشاهده الشهيرة
The Daily Newsstand · Free, Always
Sunday, November 8, 2026

Пять слоёв памяти ИИ-ассистента: что реально работает в проде, а что осталось в библиотеке

Translate

Мы делаем ИИ-ассистента, который живёт сразу в трёх мессенджерах: Telegram, MAX и ВКонтакте, и пользуются им около 1200 человек. Про мост в MAX я уже писал, а сегодня расскажу о том, что лежит под ним, то есть о памяти.

Главная жалоба на чат-ботов всегда звучит одинаково: «он меня не помнит». Формально так и есть, потому что своей памяти у LLM нет, и всё, что она якобы помнит, кладём в контекст мы сами. Вся работа сводится к тому, что положить, откуда взять и что выбросить, как при сборке ящика перед гонкой: ключ на семнадцать должен лежать под рукой, а весь гараж с собой не увезёшь. У нас на это ушло пять слоёв, и, признаюсь честно, не все они делают то, что мы планировали.

Три входа, одно ядро

Telegram, MAX и VK для нас только транспорт. Каждый мессенджер подключён тонким адаптером, который принимает апдейт, отдаёт его в общий ingress и доставляет обратно ответ. Агенты, LLM-слой и память живут на сервере в единственном экземпляре, так что колёса под этой машиной можно менять, а двигатель остаётся тем же.

 Telegram      MAX        VK
    │           │          │
    └────── ingress ───────┘
               │
    ядро: агенты + LLM-роутинг
               │
    память: файлы, PostgreSQL + pgvector, SQLite + FTS5

Ограничение здесь есть, и скрывать его незачем: один и тот же человек в Telegram и в MAX пока существует как два разных user_id, потому что общего идентификатора мессенджеры не дают. Привязать новый вход просто, это всего лишь строка в таблице идентичностей, а вот слить то, что уже накопилось в двух профилях, заметно сложнее. Привязку мы делаем.

Слой 1. Файл на агента

Каждый ответ дописывается в memory.md конкретного агента у конкретного пользователя, полным текстом и без обрезки при записи. Новая запись сравнивается с десятью последними, и если это почти дубль с перекрытием от 0.7, она получает пометку [refines: ...]. Размер файла ограничен капом: когда файл его перерастает, старые записи целиком уходят в архив, где их ещё можно найти. Сейчас в архиве лежит 11 674 записи по 134 субъектам.

Промпт мы ограничиваем на чтении, а не на записи, и это решение я считаю одним из главных. Обрезать при записи значит потерять навсегда, тогда как обрезать при чтении значит всего лишь не показать сейчас.

Слой 2. Раунды

Это основной слой. Раунд представляет собой пару «сообщение и ответ» в PostgreSQL, с embedding vector и генерируемым tsvector, и таких пар сейчас 16 333 у 657 пользователей.

Эмбеддинги считает отдельный контейнер text-embeddings-inference на CPU с моделью deepvk/USER2-small. GPU у нас нет, а само приложение своей модели не грузит. Если сервер эмбеддингов вдруг недоступен, ход идёт дальше без векторов, и ответ никого не ждёт.

Поиск по смыслу и поиск по словам мы сливаем не через RRF, хотя начинали именно с него:

score = similarity + lexical_weight * (lexical / best_lexical)

lexical_weight равен 0.02, так что слова лишь разводят близкие по смыслу кандидаты. Это скорее винт тонкой настройки, чем ручка газа. Для лексики используются Snowball-основы и BM25, а русский или английский стеммер выбирается по самому слову. Раунду без вектора, который только что записан или попал под смену модели, временно достаётся k-я лучшая близость по его месту среди совпадений по словам. Благодаря этому свежая запись не проваливается ниже всех проиндексированных, но и не взлетает выше ответа по смыслу из-за одного случайно общего слова.

На один ход поднимается не больше 4 раундов и 3000 символов. Они идут в конец промпта с датами, под заголовком, который подаёт их как запись разговора, а не как инструкции. Так мы защищаемся от инъекции через собственную память, потому что обмануть систему можно и её же воспоминаниями.

Слой 3. Судья

Вспоминать стоит не всё. Дешёвая модель читает раунды пользователя и называет те, что могут понадобиться позже, а сомнительное предпочитает оставить. Логика здесь та же, что с топливом перед вылетом: случайно вспомненная болтовня обойдётся в лишнюю строку, а забытый факт будет стоить ответа, которому он был нужен.

Слой 4. Выжимки

Когда личный разговор затихает, он сворачивается в датированную выжимку, немного похожую на запись в лётной книжке, где остаются дата и главное. Источником правды по-прежнему служат раунды, а выжимка несёт только то, что уже не помещается в окно последних сообщений. Каждый отрезок сворачивается один раз, поэтому повторный запуск ничего не дублирует. Сейчас выжимок 899.

Кто что может читать

Отдельная политика определяет, какой агент может читать сказанное другому. Чувствительные агенты (врач, диетолог, юрист, таролог) никогда не становятся источником для остальных, ведь вряд ли кому-то понравится, если секретарь, согласовывая встречу, вдруг посочувствует по поводу диагноза или поинтересуется ходом судебного дела. Агенты, которых создал сам пользователь, источником тоже не служат. Свою собственную историю каждый агент читает всегда.

Слой 5. Канонические факты и навыки

Это SQLite с FTS5 и библиотека памяти, с которой всё начиналось. Именно здесь проект разошёлся с планом, как трасса на бумаге расходится с трассой под колёсами.

Канонические факты сейчас есть только у 3 субъектов, всего 1486 записей. Если пользователь исправляет ассистента, факты, близкие к поправке по косинусу с порогом 0.60, мягко удаляются, и таких уже 221. Обычные пользователи живут на раундах и выжимках.

Для навыков агентов предусмотрен вес удержания strength: при использовании навык подкрепляется, а те, что не трогали 14 дней, затухают с множителем 0.85 и нижней границей 0.05. Из 362 навыков у 187 вес уже снижен.

Каждая версия записи связана цепочкой хэшей: prev_hash и self_hash в memory_history, 893 из 894 строк, а оставшаяся первая строка как раз и есть начало цепочки. Важные файлы агентов при изменении хэшируются SHA-256. Проверка показывает то самое место, где цепочка порвана.

Что осталось в библиотеке

На полке в гараже запчастей всегда больше, чем стоит на мотоцикле, и с библиотекой вышло так же. В ней есть второй FTS-индекс и RRF поверх BM25 и векторов на paraphrase-multilingual-MiniLM-L12-v2, но на проде у этого слоя стоит MEM_SEMANTIC=0: векторный путь выключен, и работает BM25 по индексу с основами Snowball. Поиск по смыслу переехал в слой раундов. Планового запуска затухания в коде прода я тоже не нашёл. Снижение веса навыков видно в данных, а вот подтвердить его регулярность я не могу.

На систему памяти Роспатент принял решение о выдаче патента на полезную модель: заявка № 2026120741, приоритет от 02.07.2026, патентообладатель ООО «Лиза Студио». В формулу вошли темпоральная классификация для семантического кэша, подкрепление и затухание, кросс-языковая консолидация через два индекса и RRF, а также цепочка хэшей. Формула шире того, что сейчас включено в проде, и я специально разделяю одно и другое.

Что мы вынесли

  • Обрезать на чтении, а не на записи.

  • Хранить исходные раунды, а выжимки считать производными.

  • Подавать память в промпт как данные, а не как инструкции.

  • Разделять, кто что может читать, сразу, не дожидаясь первой утечки.

  • Проверять, что реально включено в проде, а не что лежит в библиотеке.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.