Проблема: LLM-приложения не умеют «помнить»
Современные LLM-сервисы — персональные ассистенты, автономные агенты, образовательные платформы — работают месяцами с одними и теми же пользователями. Однако контекстное окно модели конечно, дорого и чувствительно к задержкам. Просто добавлять всё больше истории в промпт не получится: это и неэффективно, и архитектурно тупиковый путь — никакого управления жизненным циклом, консолидации или забывания там нет.
На практике долгосрочное состояние обычно хранится в разрозненных логах, поверхностных кешах и наборе эвристик. Как следствие — ассистент задаёт вопросы, которые уже задавал неделю назад, или противоречит своим прежним советам. Это не проблема качества модели, а проблема управления данными.
Существующие решения бьют мимо цели. Грубое хранение сессий раздувает хранилище и зашумляет выдачу. Графы знаний (knowledge graphs, KG) — Zep, Mem0-graph — слишком медленно строятся при высоких нагрузках: в продакшне отдельные клиенты генерируют свыше миллиарда токенов памяти в сутки. Узкоспециализированные решения вроде Memobase заточены под чат-ботов и не переносятся на агентов или образовательные приложения.
Ключевая идея: Memory Base как парадигма управления данными
Авторы из ByteDance вводят понятие Memory Base (база памяти) — новый архитектурный уровень для персистентного состояния LLM-приложений. Он строится на трёх принципах.
-
Селективное извлечение. Система не хранит сырые логи, а выделяет из них только информационно насыщенные фрагменты — «события» (events).
-
Statefulness и эволюция. Память — не статичный архив, а живой жизненный цикл: события периодически консолидируются в обновляемые «сущности» (entities), старые данные сжимаются или удаляются.
-
Обобщаемость. Одна инфраструктура с конфигурируемой схемой закрывает разные прикладные сценарии без переработки ядра.
На этих принципах построена система VikingMem — сервис управления Memory Base поверх VikingDB (облачная векторная база ByteDance).
Как это устроено
Модель данных: событие и сущность
Базовая единица памяти — событие (event): дискретная, временно-метированная, семантически целостная запись, извлечённая из входного потока. Каждый тип события описывается схемой в JSON-подобном формате: EventType, Description и набор Properties с типами и описаниями. Схема одновременно ограничивает (не даёт сохранять шум) и направляет LLM при извлечении.
Сущность (entity) — персистентное, эволюционирующее состояние: профиль пользователя, библиотека инструментов агента, прогресс ученика. Схема сущности содержит поля с AggregateExpression — выражением, которое указывает, какие события обновляют этот атрибут и каким оператором.
Операторы реализуют логику эволюции:
-
статистические —
SUM,COUNT,AVG,MAX— работают без LLM, точны в арифметике; -
LLM-based —
LLM_MERGE(инкрементальное слияние, дедупликация, разрешение противоречий),TIME_COMPRESS(прогрессивная консолидация по тематическим таймлайнам).
TIME_COMPRESS работает по принципу «ленивого слияния»: свежие события хранятся с высокой детализацией, а события в неактивных тематических ветках после истечения временного окна синтезируются в сводку; после сохранения сводки исходные события получают TTL и со временем удаляются.
Связь между событиями и сущностями выражается как параметрический запрос, а не зашитый в промпт код: keys задаёт группировку (по пользователю, паре пользователь–ассистент, теме), filters — окно отбора, Op — оператор из фиксированной библиотеки. Прикладная логика появляется только на краях пайплайна — в шаблонах извлечения и внутри LLM-операторов.
Извлечение памяти
Однопроходное извлечение (one-pass extraction). Традиционный подход требует отдельного LLM-вызова на каждый тип памяти. VikingMem компилирует все схемы событий и сущностей в один промпт и обрабатывает входные данные за один инференс. Это напрямую снижает стоимость и задержку.
Prefix-cache оптимизация. Системная инструкция и схемы памяти фиксированы между запросами — их KV-кеш переиспользуется, что дополнительно снижает потребление токенов.
Интеллектуальная сегментация (Intelligent Memory Segmentation, IMSM) работает в два этапа. Первый — семантическая фильтрация значимости: LLM отсеивает приветствия и прочий наполнитель. Второй — разбиение на события: LLM выдаёт список пар (start, end) — координаты тематических сегментов — что позволяет объединять несмежные фрагменты одной темы. Если разговор переходил от рекурсии к игровому алгоритму и обратно, метод объединит оба фрагмента про рекурсию в одно событие, исключив шум.
Entity Update Algorithm (EUA). Обновление строковых полей сущности обычно требует второго LLM-вызова. EUA устраняет это: при извлечении LLM генерирует компактный патч в формате <<<< SEARCH … ==== … >>>> REPLACE, а EUA применяет его через приближённый поиск по редакционному расстоянию, устойчивый к мелким неточностям модели. Никакого дополнительного LLM-вызова не нужно. При каждом обновлении VikingMem предварительно извлекает из VikingDB топ-5 кандидатов сущностей через ANN-поиск и включает только их в промпт — длина контекста остаётся управляемой.
Извлечение (retrieval)
Многопутный recall с time-decay и бизнес-весами. Основной путь — гибридный поиск (dense + sparse). Итоговый скор каждого кандидата: взвешенная сумма нормализованного скора поиска, временно́го скора (экспоненциальный спад после настраиваемого окна свежести) и бизнес-скора (приоритеты по типу или весу конкретного события). Вспомогательный путь — граф ключевых слов, где embedding ключевого слова усредняется из embeddings содержащих его сегментов; это покрывает запросы вроде «помнишь мой никнейм?», где семантическое сходство с воспоминанием низкое.
Multi-vector reranking вдохновлён ColBERT: векторы для reranking предвычисляются при сохранении события, применяются квантизация и token-merge для сжатия. Cross-encoder типа mGTE даёт p99 задержку в секунды; ColBERT-подобный подход удерживает reranking в пределах десятков миллисекунд.
Результаты
Оценка проводилась на двух бенчмарках: LOCOMO (10 долгосрочных диалогов, 1000+ сообщений каждый) и LongMemEval_s (500 разговоров, в среднем ~115 000 токенов). Метрики: LLM-Judge Score (оценщик — та же модель, что генерирует ответ), F1-score по токенам, задержка поиска (p50, p95 в секундах).
| Метод | LOCOMO Overall (GPT-4o-mini) | LOCOMO Overall (GPT-4.1-mini) | LongMemEval Overall (GPT-4o-mini) | p95 задержка, с |
|---|---|---|---|---|
VikingMem |
88.83 |
90.12 |
66.36 |
0.39 |
Mirix |
78.66 |
85.38 |
— (тайм-аут) |
25.76 |
Full-Context |
77.47 |
86.36 |
55.00 |
— |
Zep |
75.14 |
79.09 |
63.21 |
0.63 |
Mem0 |
66.88 |
62.47 |
42.80 |
0.20 |
RAG |
60.26 |
65.32 |
— |
0.43 |
По F1-score на LOCOMO VikingMem показывает 54.98% против 53.03% у Full-Context и 47.03% у Zep.
Эффективность извлечения. Сравнение трёх стратегий на LOCOMO (три типа памяти: одно событие и две сущности):
-
Multiple Prompts: $0.35, 11.02 с, Score 88.86
-
One-pass без EUA: $0.11, 12.32 с, Score 88.83
-
One-pass с EUA: $0.07, 7.42 с, Score 88.77
Хранилище. На LongMemEval VikingMem хранит 16.82% токенов от объёма Naive RAG, сохраняя сопоставимое или лучшее качество ответов.
Аблация на LOCOMO (GPT-4o-mini, базовый Score 88.83):
-
без Multi-Vector Rerank: −3.64 пункта, +6.8 мс к p95
-
без IMSM: −5.32 пункта, задержка не меняется
-
без Entity Memory: −1.9 пункта
-
без Keyword Graph: −1.91 пункта, −25.8 мс к p95
Частота использования операторов в 100+ реальных схемах клиентов: в Social Companionship LLM_MERGE применяется в 100% схем, TIME_COMPRESS — в 72%; в Education и Agent Memory доминируют агрегационные операторы (MAX, AVG).
Ограничения и открытые вопросы
Ряд ограничений авторы обозначают явно или они следуют из описания системы.
-
Зависимость от качества LLM при извлечении. Вся сегментация и патчи для EUA генерируются языковой моделью. Деградация модели или неподходящий промпт могут незаметно испортить базу памяти.
-
Time-weighting отключён на бенчмарках. Оба датасета содержат преимущественно фактические вопросы, где временно́й приоритет не нужен, поэтому функция была отключена. Вклад time-decay в реальных сценариях не измерялся в рамках публичных бенчмарков.
-
Аблация проводилась только на LOCOMO. Насколько выводы переносятся на LongMemEval и другие распределения — не проверялось.
-
Масштабирование при множестве сущностей. ANN-поиск топ-5 кандидатов перед патчингом ограничивает длину контекста, но точность при очень большом числе сущностей не анализируется.
-
Конфигурация схем требует экспертизы. Гибкость Event-Entity модели — её сила, но и слабость: написание корректных
AggregateExpressionтребует понимания семантики операторов. Документация и примеры вынесены во внешние материалы. -
Оценка ограничена двумя бенчмарками. LOCOMO (10 диалогов) мал по числу сессий; LongMemEval_s — один подсет. Поведение на агентских или образовательных трассах оценивалось только качественно.
Кому это важно и что с этим делать
VikingMem интересен прежде всего инженерам, которые строят production-сервисы с долгосрочным контекстом: AI-компаньонов, персонализированные поисковые системы, автономных агентов, образовательные платформы. Проблема, которую решает система, — не академическая: разрозненное хранение состояния в логах и кешах уже сейчас создаёт технический долг и ухудшает пользовательский опыт.
Ключевые практические выводы:
-
Однопроходное извлечение с общей схемой — простой способ снизить стоимость инференса при сложной памяти. Если вы сейчас делаете N раздельных вызовов LLM для разных типов памяти, это прямой кандидат на оптимизацию.
-
ColBERT-подобный reranking вместо cross-encoder позволяет держать p95 задержку reranking в десятках миллисекунд вместо секунд — важно для любого интерактивного сервиса.
-
Event-Entity абстракция — полезный шаблон проектирования даже без VikingMem: разделение «что произошло» (событие) и «каково текущее состояние» (сущность) делает память версионируемой и тестируемой.
-
TIME_COMPRESS — практичный механизм для управления объёмом хранилища в долгосрочных сервисах: хранить детальные недавние события и агрегированные сводки по старым.
Часть кода открыта в репозитории OpenViking (Context Database for AI Agents). Коммерческий сервис доступен через BytePlus VikingDB.
Оригинал статьи: arXiv:2605.29640