中文翻译暂不可用,显示俄语原文。

Как вы реализуете память агента (Memory) на разных уровнях?

Краткий тезис

Память агента — это многоуровневая система, имитирующая человеческое запоминание. Я комбинирую краткосрочную память (буфер последних сообщений в Redis) для поддержания контекста диалога, долгосрочную память (векторное хранилище важных фактов) для хранения знаний о пользователе, семантическую память (эмбеддинги обобщённых выводов) и рабочую память (переменные текущей сессии). В фреймворках вроде LangChain это реализуется через ConversationBufferMemory и VectorStoreRetrieverMemory, но на продакшене требуется кастомная интеграция с учётом времени жизни данных, сжатия контекста и механизмов забывания.


1. Зачем агенту память и какие бывают уровни

В AI-агентах память необходима, чтобы:

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

Выделяют четыре основных уровня памяти, аналогичных когнитивным процессам человека:

УровеньАналог человекаПример данных
Краткосрочная (Short‑term)Рабочая память, удержание нескольких секундПоследние 5 сообщений чата
Долгосрочная (Long‑term)Факты, хранящиеся годамиДень рождения пользователя, его любимый жанр книг
Семантическая (Semantic)Обобщённые знания, концепции«Пользователь предпочитает короткие ответы»
Рабочая (Working / Episodic)Переменные текущей задачиВыбранная категория товара в процессе покупки

В продакшен-системах обычно комбинируют все уровни, управляя их размером и временем жизни (TTL).


2. Краткосрочная память (Conversation Buffer)

Термин: Conversation Buffer — хранит последние k сообщений в порядке их поступления.

Реализация:

  • Чаще всего используют Redis (in‑memory key‑value store) с TTL (например, 30 минут).
  • Для каждого сеанса (session_id) сохраняем список сообщений.
  • При каждом новом запросе отправляем буфер в prompt или в messages (ChatML).

Пример кода на Python:

import redis
import json

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

def get_buffer(session_id: str, max_tokens: int = 2000) -> list:
    key = f"agent:buffer:{session_id}"
    messages = json.loads(r.get(key) or "[]")
    # оставить последние N сообщений, не превышающих лимит токенов
    return messages[-5:]  # например, последние 5

def append_to_buffer(session_id: str, role: str, content: str):
    key = f"agent:buffer:{session_id}"
    messages = json.loads(r.get(key) or "[]")
    messages.append({"role": role, "content": content})
    r.setex(key, 1800, json.dumps(messages))  # TTL 30 минут

Плюсы: быстрый доступ, простота.
Минусы: ограниченный размер, потеря контекста при длинных диалогах (проблема «lost in the middle»).

Для решения проблемы длинного контекста применяют суммаризацию (сжатие предыдущих сообщений в одно саммари) и замену буфера на гибрид: последние N сообщений + саммари старой истории.


3. Долгосрочная память (Vector Store Memory)

Термин: Long‑term memory — хранит факты, извлечённые из разговоров, в виде эмбеддингов в векторной БД.

Принцип работы:

  1. После каждого витка диалога агент решает, какую информацию стоит запомнить (например, «пользователь любит научную фантастику»).
  2. Кандидаты в память превращаются в эмбеддинги (через ту же модель, что используется в RAG) и сохраняются в векторное хранилище (ChromaDB, Pinecone, Qdrant, FAISS).
  3. При новом запросе извлекаются наиболее релевантные воспоминания (top‑k) и подмешиваются в контекст.

Инструменты:

  • LangChain VectorStoreRetrieverMemory — удобная обёртка.
  • Mem0 — специализированная библиотека для управления долгосрочной памятью агентов.

Пример с LangChain и Chroma:

from langchain.memory import VectorStoreRetrieverMemory
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
vectorstore = Chroma(collection_name="agent_memory", embedding_function=embeddings)
memory = VectorStoreRetrieverMemory(
    retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
    input_key="input",  # ключ ввода
    output_key="output",
    memory_key="history"
)
# Сохранение опыта
memory.save_context({"input": "как тебя зовут?"}, {"output": "Меня зовут Ассистент."})
# Извлечение релевантных воспоминаний
relevant = memory.load_memory_variables({"input": "напомни своё имя"})

Важно: нужно настроить механизм запоминания (какие части диалога сохранять) и забывания (удалять устаревшие факты по TTL или при неиспользовании).


4. Семантическая память

Термин: Semantic memory — хранит обобщённые выводы, а не конкретные диалоги. Например: «Пользователь предпочитает технические ответы с формулами» или «Пользователь всегда просит примеры кода».

Отличие от долгосрочной:

  • Долгосрочная память — сырые факты (например, «любит научную фантастику»).
  • Семантическая память — агрегированные паттерны (например, «все вопросы пользователя связаны с Python и ML»).

Реализация:

  • Используем ту же векторную БД, но данные предварительно обобщаются (например, через LLM: «Из последних 10 диалогов выдели 3 устойчивых характеристики пользователя»).
  • Ключи могут быть не просто текстом, а концептами (например, эмбеддинг фразы «стиль общения: краткий»).

Пример агрегации через LLM:

def summarize_to_semantic(memory_facts: list[str]) -> str:
    prompt = f"Обобщи следующие факты в 2-3 кратких вывода о пользователе:\n{chr(10).join(memory_facts)}"
    # вызов LLM
    return llm.invoke(prompt)

Семантическая память помогает агенту адаптировать свой тон, глубину ответа и стиль без явных инструкций.


5. Рабочая память (Working / Session Memory)

Термин: Working memory — временные переменные, относящиеся к текущей сессии или задаче.

Примеры:

  • Текущий выбранный товар в корзине.
  • Шаг процесса (например, «пользователь проходит аутентификацию»).
  • Результаты предыдущих вызовов инструментов.

Реализация:

  • Простое хранилище в памяти процесса (словарь Python) или Redis с коротким TTL.
  • В LangChain — через ConversationTokenBufferMemory или кастомный класс, наследующий BaseMemory.
from dataclasses import dataclass, field
from typing import Any

@dataclass
class WorkingMemory:
    session_id: str
    variables: dict = field(default_factory=dict)
    
    def set(self, key: str, value: Any):
        self.variables[key] = value
    
    def get(self, key: str) -> Any:
        return self.variables.get(key)

# Использование в цепочке
working = WorkingMemory("session_123")
working.set("current_step", "checkout")

Рабочая память живёт только до конца сессии (или timeout) и не сохраняется между сессиями.


6. Реализация в LangChain: основные типы памяти

LangChain предоставляет готовые классы для разных уровней:

КлассУровеньОсобенности
ConversationBufferMemoryКраткосрочнаяХранит все сообщения, может переполниться.
ConversationSummaryMemoryКраткосрочная сжатаяСуммаризирует старые сообщения, буфер содержит саммари + последние N.
VectorStoreRetrieverMemoryДолгосрочнаяХранит факты в векторной БД, извлекает по релевантности.
ConversationEntityMemoryСемантическаяИзвлекает именованные сущности и их атрибуты.
ConversationTokenBufferMemoryКраткосрочнаяОграничивает память по количеству токенов (отбрасывает старые).

Как комбинировать:

memory = CombinedMemory(
    memories=[
        ConversationBufferMemory(k=5),           # последние 5 сообщений
        VectorStoreRetrieverMemory(retriever=...), # долгосрочные факты
        ConversationSummaryMemory()               # саммари истории
    ]
)

Продакшен-советы:

  • Устанавливайте TTL на все уровни.
  • Для краткосрочной памяти используйте Redis Cluster, чтобы избежать потери при сбое одного узла.
  • Для долгосрочной — регулярная дедупликация и реранжирование фактов по важности.

7. Продвинутые техники

7.1. Рефлексия (Reflective Memory)

Агент периодически пересматривает свою память, выделяет противоречия, делает новые выводы. Реализуется через отдельный цикл «reflection», запускаемый после N диалогов.

7.2. Синтез воспоминаний (Memory Synthesis)

Несколько близких фактов объединяются в один обобщённый, чтобы уменьшить шум и экономить токены. Например:

  • Факт 1: «Пользователь купил книгу по Python».
  • Факт 2: «Пользователь спросил про асинхронность».
  • Синтез: «Пользователь изучает продвинутый Python».

7.3. Иерархическая память (Hippocampal‑inspired)

По аналогии с гиппокампом человека: краткосрочная память (быстрая, нестабильная) постепенно консолидируется в долгосрочную (медленная, устойчивая). В программной реализации — асинхронная запись из буфера в векторную БД с проверкой повторений.


8. Инструменты и библиотеки для памяти агентов

ИнструментОписание
MemGPT (Letta)Система с иерархической памятью, автоматическим сжатием и «разрывами» контекста.
Mem0Библиотека для управления долгосрочной памятью с поддержкой профилей пользователей.
ZepOpen‑source сервис памяти для чатов (сохраняет историю, извлекает релевантные фрагменты).
LangChain MemoryГотовые классы для быстрого прототипирования.
Cassandra / ScyllaDBМожно использовать как долгосрочное хранилище с временными метками.

9. Пет-проект для закрепления

Задача: Разработать Telegram-бота-ассистента, который запоминает предпочтения пользователя и поддерживает контекст между сессиями.

Инструменты:

  • Python, python-telegram-bot
  • LangChain (Memory)
  • Redis (краткосрочная память)
  • ChromaDB (долгосрочная память)
  • OpenAI API (LLM, эмбеддинги)

Шаги:

  1. Реализовать ConversationBufferMemory на Redis для каждого chat_id.
  2. Добавить VectorStoreRetrieverMemory, куда после каждого диалога отправляется обобщение (через LLM summary).
  3. При получении сообщения — собрать буфер + top‑5 релевантных фактов из Chroma и отправить в LLM.
  4. Реализовать команду /forget_me, очищающую долгосрочные воспоминания пользователя.

Ожидаемый результат:

  • Бот помнит, что пользователь просил называть его «Алексей» и отвечать кратко, даже если прошло несколько дней.
  • При длинном диалоге — автоматически сжимает старые сообщения в саммари (не теряя важных деталей).
  • Возможность инспекции памяти (команда /memory выводит текущие факты).

10. Связь с другими вопросами

ВопросТема
47Как управлять состоянием (state) агента?
44Как спроектировать архитектуру агента?
45Как агент выбирает и вызывает инструменты?
50Как масштабировать агента до тысяч параллельных сессий?
32Как реализовать механику «chain of thought» в агенте?
20Как вы оцениваете качество работы RAG-системы (связь через векторное хранение)?

Навигация