TL;DR
TEM — схема памяти для агента. Когда факт о пользователе меняется (переехал, сменил работу, поменял тариф), старое значение не стирают. Его хранят вместе с новым, расставляют все версии по порядку появления и ставят на устаревших метку [historical]. Последняя версия остаётся без метки. Модель получает готовый «хронологический срез» с подсказкой, что актуально, а что уже в прошлом.
Основная проблема: сохранить старые значения мало. Если дать модели все версии подряд, она путает «сейчас» и «раньше». Берёт старый адрес как текущий, отвечает про не ту смену или вообще тянет не тот факт. Авторы сравнили три варианта с одинаковыми фактами и порядком. Если перезаписывать старое новым, на вопросы про прошлое модель почти не отвечает. Если хранить всё без меток, получается лучше, но нестабильно. Если добавить только метку [historical], точность растёт в разы на всех моделях. Подставлять «где-то в тексте уже есть подсказка» бесполезно: модель надо явно подвести к ответу.
Метод состоит из трёх частей: хранить версии, упорядочить их по источнику и пометить устаревшие. Для читателя главное в последней части: явная пометка статуса рядом с фактом работает как правило подачи данных. Её можно использовать вручную в чате или в файле памяти агента, без всякого кода.
Схема метода
ЗАПИСЬ: новый факт → добавить как новую версию (старое НЕ стирать)
каждая запись = субъект + отношение + значение + источник (сессия/дата)
версии одного «субъект+отношение» = одна группа
СТАТУС: в группе версия с самым поздним источником = актуальная (без метки)
все остальные = [historical]
ПОДАЧА: выбрать релевантные факты (до 15)
→ отсортировать по порядку источника (старые → новые)
→ поставить [historical] на устаревших
→ отдать модели вместе с вопросом
ОТВЕТ: модель сама выбирает нужную версию по формулировке вопроса
(«сейчас» → без метки, «до переезда» → предыдущая)
В оригинале это программная система: код извлекает факты и ищет по ним. Но итоговый «кусок контекста» для модели — просто текст, который можно собрать вручную.
Пример применения
Задача: Вы ведёте в ChatGPT-проекте заметки по клиенту — владельцу магазина товаров для дома. За год он сменил маркетплейс, тариф и подрядчика. Вы просите: «Почему он ушёл с Wildberries, и что у него сейчас?» Без разметки модель путает порядок или берёт старое как текущее.
Промпт:
Факты о клиенте «Дом и уют», в порядке появления (от старых к новым).
Метка [historical] = значение заменено более поздним.
Без метки = актуальное значение.
- Основная площадка | Wildberries | источник: созвон 12.02 [historical]
- Основная площадка | Ozon | источник: созвон 20.06 [historical]
- Основная площадка | Яндекс Маркет + свой сайт | источник: созвон 03.10
- Тариф рекламы | 30 000 ₽/мес | источник: созвон 12.02 [historical]
- Тариф рекламы | 80 000 ₽/мес | источник: созвон 20.06 [historical]
- Тариф рекламы | 45 000 ₽/мес | источник: созвон 03.10
- Причина ухода с WB | рост комиссий и штрафы за приёмку | источник: созвон 20.06
Отвечай только по . Если вопрос про «сейчас» — бери значения без метки.
Если про прошлое — выбери версию, которая действовала в нужный момент.
Не выдавай историческое значение за текущее.
Вопрос: Где клиент продавал до Ozon, почему ушёл и какой бюджет на рекламу у него сейчас?
Результат: Модель должна ответить по трём частям вопроса: предыдущая площадка (Wildberries), причина ухода (из записи без метки про причину) и текущий бюджет (запись без метки, 45 000 ₽). Историческое значение (80 000 ₽) она не должна выдать за текущее.
Почему это работает
Слабость модели. Когда в контексте лежат несколько значений одного факта, они все «похожи по смыслу» на вопрос. Модель должна сама решить, какое из них актуально, а какое нет. Порядок записей подсказывает не всегда: версии могут идти вразнобой, а слова «сейчас» и «до переезда» требуют сопоставить вопрос с цепочкой событий. Поэтому она ошибается, особенно небольшие модели.
Сильная сторона. Модель хорошо работает с явными пометками в тексте. Если рядом с фактом стоит [historical], ей не надо вычислять статус. Достаточно прочитать метку и сопоставить с вопросом. Выбор версии под вопрос она делает сама, хорошо.
Как метод это использует. TEM разделяет два дела: что показать (релевантные факты) и как подать (по порядку, с пометкой статуса). Статус считает код по простому правилу: всё, что не последнее в группе, — историческое. Поэтому даже если свежая версия не попала в выборку, старая всё равно остаётся с меткой и не выдаёт себя за актуальную.
Рычаги управления: - Метка → можно заменить на «устарело», «заменено значением X от даты» или добавить дату. Смысл тот же: статус виден сразу. - Порядок → от старых к новым, как в оригинале. Метка при этом нужна всё равно: в эксперименте порядок был одинаков, а разница определялась только ею. - Лимит фактов → в оригинале до 15. Короткий срез дешевле и не перегружает модель. - Правило в инструкции («бери без метки для “сейчас”») → в оригинале такого правила не было, модель сама выбирала. Это ваше усиление, его стоит проверить.
Шаблон промпта
Факты о {субъект}, в порядке появления (от старых к новым).
Метка [historical] = значение заменено более поздним.
Без метки = актуальное значение.
- {параметр_1} | {значение_v1} | источник: {дата/сессия_1} [historical]
- {параметр_1} | {значение_v2} | источник: {дата/сессия_2} [historical]
- {параметр_1} | {значение_v3} | источник: {дата/сессия_3}
- {параметр_2} | {значение} | источник: {дата/сессия}
Отвечай только по .
Если вопрос про «сейчас» — используй значения без метки.
Если вопрос про прошлое — выбери версию, которая действовала в нужный момент.
Не выдавай [historical] за текущее.
Вопрос: {вопрос}
Подставьте:
- {субъект} — клиент, проект, сотрудник;
- {параметр} — то, что меняется (адрес, тариф, стек, должность);
- версии и даты — из ваших заметок.
Правило: в каждой группе (один субъект + один параметр) все версии, кроме самой поздней, получают метку. Поздняя метки не получает.
🚀 Быстрый старт — вставь в чат:
Вот шаблон хронологической памяти с метками [historical]. Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, что у вас меняется со временем, какие есть версии и даты, какие вопросы вы будете задавать. Это нужно, чтобы правильно собрать группы версий и расставить метки. Затем она соберёт блок из ваших заметок.
Ограничения
⚠️ Только однозначные обновления: метод предполагает, что новое значение заменяет старое (адрес, работа). Если предпочтения действуют одновременно (любит кофе и любит чай), метка
[historical]будет ложью.
⚠️ Порядок = порядок записи, а не события: статус определяется тем, когда факт попал в память. Если о переезде рассказали позже, чем о более свежем событии, порядок собьётся. Авторы это признают.
⚠️ Противоречия внутри одной записи не решаются: если в одной сессии два разных значения, метод их не разберёт.
⚠️ На открытых диалоговых вопросах метки почти не помогли: на публичном бенчмарке с вопросами про детали событий и связи между фактами результат с метками и без был практически одинаковым. Метка помогает именно с вопросом «какая версия факта актуальна».
⚠️ Слабые модели и синтетические данные: проверяли на небольших открытых моделях (4–20 млрд параметров) и на сгенерированных диалогах. На сильных моделях разрыв может быть меньше.
⚠️ Полная система требует кода: автоматическое извлечение фактов и поиск по ним — это программа. Вручную можно повторить только подачу.
⚠️ Сравнение с другими системами памяти некорректно: авторы сами пишут, что оценки по генераторам и метрикам разные.
Как исследовали
Авторы сгенерировали 60 вымышленных персон и 600 диалогов. В них люди меняли город, работу и любимый напиток. Затем составили 420 вопросов трёх видов: «где живёт сейчас», «где жил раньше» и «где жил перед последним переездом». Проверяли на четырёх открытых моделях и шести способах хранения памяти, всего получилось около 10 тысяч ответов.
Ключевой дизайн — абляция (исследователи убирают одну деталь и смотрят, что изменится). Взяли одни и те же факты в том же порядке и различили два варианта: с меткой [historical] и без. Так отсеяли влияние поиска и порядка: менялась только метка. Результат: на вопросах про прошлое точность вырастала до 97–100 %. Без меток при том же содержании выходило 42–82 %. Простая перезапись старого новым давала 0–8 %.
Любопытно, что метки подтянули и «обычные» вопросы: «где живёт сейчас» тоже стало лучше. Модели без пометок не уверены даже в актуальном значении, когда рядом лежат старые. Ещё один плюс: подача занимала в среднем 94–118 токенов, примерно вдвое меньше, чем у RAG, который кладёт в контекст куски исходных диалогов.
Для честности авторы проверили метод на публичном наборе LoCoMo (1 540 вопросов). Гибридная память обошла обычный RAG при том же бюджете, но метки при этом почти не повлияли. Вывод: метка решает задачу выбора версии, а остальной выигрыш там дала организация контекста.
Адаптации и экстраполяции
🔧 Техника: добавить дату события → убрать главное ограничение метода
Это моя адаптация, в статье такого нет. Авторы признают, что порядок записи не равен порядку события. В заметках добавьте две даты:
источник: созвон 03.10 | действует с: 01.09. Тогда о задержанных сообщениях модель не запутается. Проверьте на своих данных.
Экстраполяция: правило для файла памяти агента (идея не из статьи, но следует из её вывода). В CLAUDE.md/AGENTS.md или проектной памяти:
## Правила ведения памяти проекта
- Решения и параметры, которые изменились, НЕ удаляй.
- Старую запись помечай [historical] и добавляй: «заменено на: {что} от {дата}».
- Актуальная запись — без метки, внизу группы.
- При ответе про «сейчас» используй только записи без метки.
- При ответе про «почему мы раньше…» ищи записи [historical].
Так агент не теряет историю решений (почему отказались от базы X) и не принимает отменённое за действующее.
Ресурсы
- TEM: Temporal State Tracking Memory for Large Language Model Agents — Pengfeng Song, Yunkai Zhuang, Liye Shi (Zhejiang Wanli University, Ningbo, China).
- Код: https://github.com/sungkites/TEM
- Бенчмарки в работе: LoCoMo, LongMemEval, LongBench.
- Системы памяти для сравнения: MemGPT, MemoryBank, A-MEM, Mem0, MemoryOS, Zep.
