Как работает memory compression для агентов (long-term memory)?
Краткий тезис
Memory compression — это механизм, позволяющий LLM-агенту хранить и использовать информацию из прошлых взаимодействий, не выходя за лимит контекстного окна. Вместо хранения всего лога событий агент сжимает историю с помощью трёх стратегий: summarization (суммаризация каждые N шагов), memory|selective memory (выбор только важных событий) и hierarchical memory (эпизодическая + память|семантическая память). Это даёт сжатие в 10–50x и лежит в основе систем вроде MemGPT и RAPTOR.
1. Проблема: контекстное окно и «забывание» агентов
Long-term memory (долговременная память) в контексте AI-агентов — это способность сохранять и извлекать информацию, полученную в ходе длительных сессий или между сессиями. Без неё агент «забывает» всё после каждого шага или перезапуска.
Контекстное окно LLM (например, 4K–200K токенов) быстро заполняется логами действий, результатами инструментов, прошлыми ответами. Если не сжимать, агент либо теряет важные детали, либо начинает генерировать нерелевантные ответы. Memory compression решает эту проблему, уменьшая объём хранимой информации без существенной потери полезного содержания.
Основные цели:
- Увеличить эффективную длину «помни» агента.
- Снизить стоимость вызовов LLM (меньше токенов на вход).
- Улучшить качество ответов за счёт релевантной ретроспективы.
2. Summarization: сжатие через саммари каждые N шагов
Самый распространённый метод. Агент ведёт лог событий (действия, наблюдения, мысли). Через каждые N шагов (часто N = 10) запускается LLM summirization — модель пишет краткое изложение последних событий. Это сжатие может быть:
- Глобальным: одно саммари всей истории.
- Скользящим окном: саммари последнего окна, а предыдущие сжаты в иерархию.
Пример псевдокода
class AgentWithSummarization:
def __init__(self, llm, summarize_every=10):
self.history = [] # полный лог событий
self.summaries = [] # накопленные саммари
self.step = 0
self.summarize_every = summarize_every
def act(self, observation):
self.history.append(observation)
self.step += 1
if self.step % self.summarize_every == 0:
new_summary = self.llm.summarize(self.history[-self.summarize_every:])
self.summaries.append(new_summary)
# опционально: сброс истории до последнего окна (если нужно)
# формируем контекст: [предыдущие саммари] + [последние N событий]
context = "\n".join(self.summaries) + "\n".join(self.history[-self.summarize_every:])
return self.llm.generate(context)
Преимущества: простота, универсальность. Недостатки: каждое саммари теряет детали; при неверной суммаризации ошибки накапливаются.
3. Selective memory: запоминаем только важное
Вместо сжатия всего лога, агент оценивает «важность» каждого события и сохраняет только самые значимые. Селективность может быть реализована через:
- Attention-based: веса внимания из LLM показывают, какие части контекста были наиболее релевантны для ответа. События с высоким весом сохраняются.
- Heuristic rules: например, сохранять только действия, изменившие состояние системы (вызов инструмента, полученный результат).
- Learned scoring: отдельная модель регрессии оценивает важность события (train на данных агента).
Пример с attention score
def compute_importance(observation, response):
# гипотетически получаем attention матрицу из LLM
# возвращаем средний вес этой обсервации в последнем ответе
return torch.mean(attention_weights[observation_position])
Проблемы: как определить «важность»? Часто субъективно; редкие, но критические события могут быть отброшены.
4. Hierarchical memory: эпизодическая + семантическая
Самый продвинутый подход, используемый в MemGPT и RAPTOR. Память делится на два уровня:
- Эпизодическая память (Episodic memory) — хранит сырые события с временными метками («агент сделал X в момент T»). Похожа на лог.
- Семантическая память (Semantic memory) — обобщённые знания, извлечённые из эпизодов («факт: пользователь предпочитает Python»).
Иерархия сжатия
- Сырые события → эпизодическая память (высокая детализация, большой объём).
- Периодически запускается consolidation — из эпизодов выделяются факты, паттерны, суммаризации → семантическая память.
- Контекст формируется из семантической памяти (всегда) + последних эпизодов (скользящее окно).
Схема
[Эпизодическая память] ---консолидация--> [Семантическая память]
| |
+---скользящее окно---context---+---------+
Преимущества: сочетание конкретики и обобщения; масштабируется до очень длинных сессий. Инструменты: MemGPT использует виртуальные контексты – эпизодическая память во внешнем хранилище, семантическая – в контексте LLM. RAPITOR строит иерархическое дерево суммаризаций.
5. Compression ratio (коэффициент сжатия)
Compression ratio = (размер исходного лога) / (размер сжатого представления). Для summarization обычно 10–50x в зависимости от длины саммари и окна. Selective memory даёт 2–10x (если отбрасывать 50–90% событий). Hierarchical может достигать 100x+ за счёт агрегации.
| Метод | Типичный ratio | Потеря информации |
|---|---|---|
| Summarization | 10–50x | Средняя (детали теряются) |
| Selective memory | 2–10x | Высокая (отбор субъективен) |
| Hierarchical | 10–100x | Низкая (сохраняется суть) |
Важно: высокая компрессия может привести к collapse – семантическая память становится слишком общей и перестаёт быть полезной для конкретных задач.
6. Инструменты и реализации
- MemGPT (Letta): использует иерархическую память с виртуальными контекстами. Агент оперирует в двух режимах: рабочий контекст (семантическая память + последние наблюдения) и внешнее хранилище (эпизодическая память). Сжатие происходит автоматически через функции
summarizeиarchive. - RAPTOR: строит дерево саммари – на каждом уровне окна объединяются в более короткие саммари, корень дерева – глобальная суммаризация. Используется как иерархический retriever для RAG.
- LangChain Memory: ConversationSummaryMemory, ConversationSummaryBufferMemory, VectorStoreRetrieverMemory.
- CrewAI, AutoGen: встроенные механизмы краткосрочной/долгосрочной памяти с опцией сжатия.
Пример с LangChain
from langchain.memory import ConversationSummaryBufferMemory
from langchain.llms import OpenAI
llm = OpenAI(model_name="gpt-3.5-turbo-instruct")
memory = ConversationSummaryBufferMemory(
llm=llm, max_token_limit=200, return_messages=True
)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "I like Python"}, {"output": "great"})
print(memory.load_memory_variables({})) # вернёт саммари + последние диалоги
7. Компромиссы и граничные случаи
- Скорость vs качество: частая суммаризация (каждый шаг) – дорого; редкая – риск переполнения контекста.
- Ошибки компрессии: если саммари неточно, агент будет опираться на неверные факты. Нужен механизм верификации (например, сравнение с исходным логом при неопределённости).
- Домен-зависимость: в технической поддержке важны точные детали (номер заказа) – summarization может их потерять. Тогда лучше selective memory с ключевыми полями.
- Масштабирование: при тысячах шагов иерархия может стать слишком глубокой – время доступа растёт. Используют кэширование или приближённые методы (например, только верхние уровни).
8. Бенчмарки и метрики оценки
Оценивать memory compression напрямую сложно. Используют прокси-метрики:
- Recall of past events: запрашивают у агента детали прошлых шагов и считают долю правильно вспомненных.
- Faithfulness: проверяют, не сфабриковал ли агент факты на основе сжатого контекста.
- Task success rate: выполнение длинной многошаговой задачи с памятью vs без.
- Token efficiency: среднее число токенов в контексте на шаг.
Пример теста
# агент взаимодействует 50 шагов, затем спрашиваем: "Какое было первое действие?"
# сравниваем ответ с истиной
9. Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 893 | Основы архитектуры долговременной памяти агентов |
| 895 | Различие эпизодической и семантической памяти |
| 896 | MemGPT: архитектура и реализация |
| 890 | Проектирование агентной системы (RAG + агенты) |
| 892 | Роль retrieval в агентных системах |
| 901 | Тестирование и валидация памяти агентов |
Пет-проект для закрепления
Задача: Реализовать класс агента, который использует иерархическую memory compression (summarization + selective) для длительной беседы.
Инструменты: Python, openai, langchain (опционально), pandas.
Шаги:
- Написать
Eventкласс с полями: timestamp, action, observation, importance (0-1). - Эпизодическая память – список всех событий.
- Семантическая память – список строк-саммари.
- Каждые 10 шагов: запускать
llm.summarize(last_10_events)и добавлять в семантику. Для selective – сохранять только события с importance > 0.7. - Контекст: все семантические саммари + последние 3 события.
- Протестировать: дать агенту 30 инструкций (например, запомнить список покупок, затем через 20 шагов спросить его). Замерить точность recall.
Ожидаемый результат:
- Агент правильно вспоминает факты из начала разговора (после сжатия).
- Контекст не превышает 2000 токенов.
- Метрика recall > 0.8.
Навигация
- Предыдущий: 893
- Следующий: 895
- Индекс: 00. Индекс разборов