Память агента: Как научить бота помнить вас спустя месяц

18.06.2026 13:00

Месяц назад вы потратили три часа, объясняя AI-ассистенту архитектуру вашего проекта. Вы загрузили схемы баз данных, описали запутанную бизнес-логику биллинга, выстроили контекст. Бот выдавал гениальные решения, учитывая каждую мелочь. Сегодня вы просите его добавить новую конечную точку в API, а он отвечает: «Конечно, расскажите подробнее о вашем проекте и используемом стеке».

Контекстное окно переполнилось. Бот вас забыл.

Это главная техническая боль современных LLM. Разработчики пытаются решить ее «в лоб» — заливают проблему деньгами и железом, увеличивая контекст до миллионов токенов. Но у этого подхода три фатальных изъяна. Первый — цена. Каждый раз, когда вы отправляете новое сообщение, вы платите за перечитывание всей истории диалога. Второй — скорость. Обработка огромного KV-кэша (Key-Value cache) увеличивает Time-To-First-Token до неприемлемых значений. Третий — эффект «потерянного посередине» (lost in the middle). Исследования показывают, что при контексте свыше 100 тысяч токенов модели отлично помнят начало и конец промпта, но полностью игнорируют факты, спрятанные в середине.

Скользящее окно (sliding window) — еще один костыль. Вы просто отрезаете старые сообщения, оставляя последние 10-20 реплик. Бот превращается в рыбку гуппи с пятиминутной памятью.

Чтобы научить агента помнить вас спустя месяц, ему нужна полноценная долгосрочная память (Long-term memory).

Векторы и математика смысла

Долгосрочная память работает не как текст, а как геометрия. Мы переводим слова в числа.

Когда пользователь пишет сообщение, система прогоняет его через специализированную embedding-модель (например, text-embedding-3-small от OpenAI или nomic-embed-text). Текст превращается в вектор — массив из тысяч чисел с плавающей точкой (обычно от 384 до 1536 измерений). Этот массив отражает семантический смысл фразы.

Вектор отправляется в специализированную векторную базу данных: Qdrant, Milvus, Pinecone или PostgreSQL с расширением pgvector. Базы используют алгоритмы вроде HNSW (Hierarchical Navigable Small World) для мгновенного поиска соседей в многомерном пространстве.

В следующий раз, когда пользователь задает вопрос «Как мы решили проблему с кэшированием?», система векторизует этот запрос и ищет в базе ближайшие векторы с помощью косинусного сходства (cosine similarity). Найденные куски прошлых диалогов извлекаются и подмешиваются в системный промпт текущего запроса. Модель получает только релевантные факты, а не всю простыню переписки.

Архитектура памяти: от свалок к операционным системам

Просто складывать векторы диалогов в базу — путь в никуда. База быстро превратится в свалку противоречивых фактов. Вчера пользователь любил Python, сегодня перешел на Go. Если извлечь оба факта, модель запутается.

Здесь на сцену выходят продвинутые архитектуры управления памятью, такие как MemGPT и Zep.

MemGPT применяет к LLM концепции классических операционных систем. У агента есть «оперативная память» (Core Memory — то, что всегда висит в системном промпте) и «жесткий диск» (Archival Memory — векторная БД). Агент сам решает, когда записать информацию на диск, когда обновить существующий факт, а когда выгрузить данные обратно в оперативную память. Это активный процесс. Модели дают доступ к инструментам (function calling): core_memory_append, core_memory_replace, archival_memory_search. Бот буквально пишет код, чтобы управлять своими воспоминаниями.

Zep работает иначе. Это быстрый асинхронный слой памяти (memory layer). Zep сидит между вашим приложением и LLM. Пока вы общаетесь с ботом, Zep в фоновом режиме суммаризирует диалоги, извлекает именованные сущности (entities) и строит граф знаний (Knowledge Graph). Когда пользователь говорит «Мою собаку зовут Рекс», Zep создает узел «Пользователь», узел «Рекс» и ребро «владеет собакой». При следующем запросе Zep автоматически обогащает промпт графовыми связями и релевантными векторами, не требуя от основной модели тратить токены на вызов функций.

Интеграция с RouterAPI

Как выстроить эту архитектуру на практике, если вы используете RouterAPI для доступа к зоопарку моделей?

RouterAPI берет на себя маршрутизацию, балансировку нагрузки, фолбеки и нормализацию цен между OpenAI, Anthropic, Google и локальными моделями. Но RouterAPI принципиально stateless — он не хранит состояние ваших диалогов и не управляет вашей базой.

Память должна жить на стороне вашего бэкенда. Интеграция выглядит как слоеный пирог:

  1. Перехват запроса: Сервер получает сообщение от пользователя.
  2. Фаза Retrieval (Извлечение): Сервер отправляет запрос в Zep или ваш самописный сервис памяти (например, на базе Qdrant). Сервис ищет семантические совпадения и возвращает блок контекста.
  3. Сборка промпта: Бэкенд формирует массив сообщений. В начало ставится системный промпт, затем инжектируется извлеченная память («Факты из прошлых бесед: ..»), затем идут последние несколько сообщений из скользящего окна для поддержания текущего контекста.
  4. Маршрутизация: Сервер отправляет этот тяжелый промпт в RouterAPI. RouterAPI, опираясь на ваши правила (например, маршрутизацию), проксирует запрос в лучшую доступную модель — скажем, Claude 3.5 Sonnet для сложных задач кодинга или Llama 3 для простых ответов.
  5. Фаза Ingestion (Запись): RouterAPI возвращает ответ. Сервер отдает его пользователю и асинхронно отправляет новую пару «запрос-ответ» в сервис памяти. Там фоновый воркер (возможно, использующий дешевую модель через тот же RouterAPI) сжимает диалог, извлекает факты и обновляет векторы.

Такое разделение обязанностей делает систему монолитной и устойчивой. RouterAPI гарантирует, что инференс выполнится быстро, дешево и без отказов, а ваш бэкенд жестко контролирует, что именно помнит агент, не привязываясь к конкретному вендору LLM.

Проблема мусора и суровая реальность

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

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

Решение кроется не в улучшении алгоритмов поиска, а в жесткой фильтрации на этапе записи.

Прежде чем отправить данные в векторную БД, их нужно очистить. Пропускайте сырые логи диалогов через дешевую LLM-прокладку, которая выжмет из текста только сухие, атомарные факты. Вместо сохранения простыни «Ну короче мы тут подумали и решили переписать бэкенд с питона на го, потому что тормозит» в базу должна лечь строчка: «Пользователь перевел бэкенд с Python на Go из-за проблем с производительностью».

Агенты с памятью не становятся людьми. У них нет подсознания или интуиции. Они остаются алгоритмами поиска по базе данных. И качество этой памяти, способность бота «узнать» вас спустя месяц, зависит исключительно от того, насколько безжалостно вы фильтруете информацию перед тем, как позволить алгоритму ее запомнить.

Теги

Ещё по теме