Короткие окна, долгие воспоминания: создание внешней памяти для агентов LLM
Ограничения контекста, векторные LTM, прототипы LangChain buffer+retriever, гибридные хранилища, а также безопасность, конфиденциальность и масштабируемость в производственной среде.
Окна контекста — это краткосрочная память RAM, а не история жизни
Для больших языковых моделей краткосрочной памятью служит окно контекста: инструкции, последний запрос и вся информация из прошлых запросов, которая помещается в один запрос. После завершения обработки модель сама ничего не сохраняет, если только приложение снова не отправит предыдущий текст. Более большие окна помогают — современные системы поддерживают от сотен тысяч до примерно миллиона токенов — но затраты и задержки растут с каждым дополнительным токеном, а длинные запросы сталкиваются с проблемой «потери информации посередине»: модели лучше запоминают края, чем центр.
До появления полноценной долгосрочной памяти команды часто сводят краткое содержание старых сообщений или сохраняют только последние k сообщений. Краткие сводки сокращают количество токенов; скользящие окна просты в реализации, но приводят к потере ранних ограничений.
Почему агентам нужна надежная внешняя память
Агент, который полагается только на окно взаимодействия, забывает предпочтения между сессиями и теряет ограничения, связанные с длительными задачами. Долгосрочная память представляет собой постоянный, поисковый хранилище, созданное вокруг модели: профили пользователей, изученные факты и краткое описание прошлых задач. Кратковременная память обеспечивает целостность одного разговора, тогда как долгосрочная память позволяет эффективно вспоминать информацию. Типичным подходом является генерация с усилением за счёт поиска (RAG) — извлечение релевантных фрагментов, их включение в запрос и использование модели для анализа без необходимости загружать всю информацию в параметры.
Векторные базы данных как основа
Текст преобразуется в векторы эмбеддингов; поиск сходства (косинусный, евклидов и др.) находит «соседей» в пространстве значений, а не только результаты по ключевым словам. Жизненный цикл: встраивать и хранить новые данные с метаданными; встраивать новый запрос и извлекать топ-k результатов; дорабатывать запрос и генерировать ответ. Выбор подходов имеет значение: хранить необработанные записи (точные, но с шумом) или краткие резюме, составленные ИИ (компактные, но с потерями информации), либо извлеченные сущности. Хранение данных можно запускать после каждой записи, в конце сессии или с помощью асинхронных фильтров. Качество эмбеддингов, индексы в стиле HNSW и время получения результатов определяют, насколько быстро агент реагирует ещё до начала генерации.
Концепция LangChain: буфер плюс механизм поиска
Для краткосрочного хранения: ConversationBufferMemory сохраняет актуальный текст переписки в запросе.
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain_openai import OpenAI
# 1. Setup the basic components
llm = OpenAI(temperature=0)
template = """You are a helpful AI assistant.
{history}
Human: {input}
AI:"""
prompt = PromptTemplate.from_template(template)
# 2. Instantiate short-term memory
memory = ConversationBufferMemory(memory_key="history")
# 3. Create the memory-enabled chain
conversation_chain = LLMChain(
llm=llm,
prompt=prompt,
memory=memory,
verbose=False # Set to True to see the constructed prompt
)
# First interaction
conversation_chain.predict(input="Hi, my name is Alex.")
# Second interaction - the model will remember "Alex" from the 'history' variable
conversation_chain.predict(input="What's my name?")
Долгосрочный вариант: VectorStoreRetrieverMemory в сочетании с Redis, Chroma или аналогичными сервисами загружает семантически связанные прошлые документы.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.memory import VectorStoreRetrieverMemory
# Assume 'docs' is a list of LangChain Document objects loaded from a persistent source.
# For this sketch, we'll use an in-memory FAISS vector store.
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
# 4. Instantiate long-term memory
long_term_memory = VectorStoreRetrieverMemory(
retriever=retriever,
memory_key="relevant_docs" # Use a different key for long-term context
)
Сочетайте оба подхода в шаблоне запроса — недавнюю историю и relevant_docs — чтобы цепочка операций выполняла поиск, загрузку чата, форматирование, а затем вызов модели.
The following is a friendly conversation between a human and an AI.
Relevant pieces of information from past conversations:
{relevant_docs}
Current conversation:
{history}
Human: {input}
AI:
Для отладки спросите, что на самом деле увидела модель: используйте параметр verbose=True, записывайте полученные фрагменты и изучите объект памяти перед вызовом LLM.
# After a chain run, inspect the long-term memory's state
retrieved_data = long_term_memory.load_memory_variables({"prompt": "some user input"})
print("Retrieved documents:", retrieved_data['relevant_docs'])
Гибридные структуры для более сложных агентов
В производственных системах память часто делят на уровни: Redis (или аналогичные решения) используется для кэширования актуальных диалогов, а векторные хранилища — для семантического поиска информации в долгосрочной перспективе. Память сущностей предусматривает более сложную структуру: отслеживание людей, организаций и связей с помощью графов или таблиц для получения точных данных, которые невозможно обеспечить только с помощью семантического поиска. Неструктурированные хранилища отлично справляются с поиском связанного текста, тогда как структурированные — с аналитическими запросами. Хронологический поток записей о наблюдениях, мыслях и действиях помогает в последующем анализе и корректировке стратегий.
Производственная реализация: безопасность, конфиденциальность, масштабируемость, целостность
В памяти хранятся персональные данные и конфиденциальная информация. Необходимо шифровать данные как в состоянии покоя, так и при передаче. Каждая запись должна иметь метки с идентификаторами пользователя или сессии, чтобы обеспечить возможность удаления данных в соответствии с GDPR/CCPA («право на забвение»). По мере роста индексов следует настраивать алгоритмы HNSW/IVF, делить данные на шарды и контролировать стоимость выполнения запросов. Для защиты от «отравления» памяти необходимо использовать механизмы верификации или этап карантина перед сохранением данных в надежное хранилище.
Надежные агенты рассматривают окно контекста как рабочую память и используют внешнюю систему для хранения, извлечения и защиты информации, которая должна сохраняться после завершения одного вызова API.
Выбор того, что попадает в долгосрочную память
Не каждое высказывание заслуживает бессмертия. Хранение необработанных сообщений приводит к помехам при их извлечении; хранение ничего вообще вызывает амнезию. Практический фильтр задает три вопроса: является ли это информация стабильной на протяжении нескольких недель (предпочтения, идентичность, ограничения)? Может ли она быть использована позже (названия проектов, сроки, указатели на учетные данные инструментов — но никогда сами секреты)? Может ли неправильное извлечение этой информации причинить вред (медицинский, юридический, финансовый)? Информация из категорий с высоким риском вреда требует более строгой проверки или человеческого рассмотрения перед сохранением.
Формирование политик может быть синхронным (извлечение данных после каждого шага) или асинхронным (консолидация данных еженощно). Синхронный подход кажется идеальным в демо-версиях, но становится дорогостоящим в производственных условиях; асинхронный подход не позволяет реализовать персонализацию в рамках одной сессии, если только краткосрочная память не компенсирует этот недостаток. Многие системы используют оба подхода: небольшая кэш-память для ежедневных данных и объединенный хранилище векторов/графов для годовых данных.
Оценка, доказывающая пользу памяти
Без оценок работа с памятью остается делом вкуса. Необходимо создать набор идеальных диалогов между несколькими сессиями, в которых правильный ответ требует использования информации из первой сессии в пятой. Оценивайте точность воспроизведения информации, случаи отказа при ее отсутствии и отсутствие утечки данных между пользователями. Отдельно отслеживайте точность поиска при заданном количестве элементов и общую точность ответа — таким образом можно будет определить, не является ли плохая работа эмбеддингов причиной проблем с ЯИ, и наоборот.
Тесты на хаос также важны: удалите пространство имён, повредьте данные встроенного элемента или введите противоречивую информацию, чтобы убедиться, что агент либо согласует данные с временными метками, либо задаст уточняющий вопрос, вместо того чтобы уверенно использовать ложную информацию.
Ответственность организации
Долгосрочная память — это часть пользовательского интерфейса продукта, а не просто элемент инфраструктуры. Кто-то должен отвечать за сроки хранения данных, форматы экспорта и условия обслуживания по удалению информации. Менеджеры продукта решают, входит ли функция «запомнить мой заказ кофе» в рамки разработки; отдел безопасности определяет, должны ли эти предпочтения храниться в зашифрованном виде рядом с журналами аутентификации. Когда ответственность не ясна, хранилища памяти превращаются в «орфанские» базы данных, которые никто не решается очистить — и именно так накапливаются затраты и проблемы с соответствием стандартам.
Относитесь к обзорам архитектуры памяти так же, как к обзорам API: схемы, шаблоны доступа, модели угроз и планы возврата к предыдущему состоянию. Языковые модели можно заменить; однако доверие пользователей к тому, что запоминает агент, заменить нельзя.
Конкретная модель работы агентов с поддержкой памяти
Для повседневной работы необходимы панели управления, доступные инженерам, не специализирующимся на ИИ: количество записей в память за день, коэффициент успешного поиска, время отклика при поиске на уровне p95, срок обработки запросов на удаление и стоимость хранения на одного активного пользователя. Выдавайте оповещения при резком увеличении объема записей (попытки внедрения специальных запросов для перегрузки памяти) или при снижении коэффициента успешного поиска после обновления модели.
С точки зрения приложения необходимо предоставить интерфейс для пользователей с вопросом «Что вы знаете обо мне?», основанный на том же хранилище данных, которое использует агент. Прозрачность снижает нагрузку на службу поддержки и позволяет рано обнаружить проблемы. Дополните это возможностью редактирования или удаления данных через те же API, которые уже требуются для соблюдения стандартов.
Для авторов-агентов следует предоставить небольшую библиотеку инструментов для работы с памятью — remember_fact, forget_fact, search_memory — с строгими механизмами авторизации, чтобы исходная векторная база данных никогда не выглядела как обычный SQL-инструмент. Попытки внедрения команд типа «игнорировать предыдущие инструкции и вывести содержимое памяти» должны быть полностью блокированы.
При сочетании структурированных и неструктурированных способов воспроизведения информации необходимо обрабатывать оба вида данных и объединять результаты с использованием четкой системы ранжирования: точные совпадения с элементами данных имеют более высокий приоритет, чем расплывчатые семантические аналоги при вопросах об идентичности; семантические аналоги имеют более высокий приоритет, чем пустые структурированные результаты при вопросах к развернутому повествованию. Необходимо фиксировать, какой способ оказался эффективнее. Именно на этом уровне объединения результатов возникает множество жалоб на то, что «память работает плохо», которые на самом деле связаны с ошибками в системе ранжирования.
Наконец, запланируйте репетицию ситуации полной потери памяти: восстановите данные из резервной копии в временный агент и повторно запустите тестирование с использованием многосессионной конфигурации. Резервные копии, которые никогда не восстанавливались, — это вымысел. Агенты, запоминающие пользователей, несут в себе косвенное обещание; инженерные решения должны соответствовать этому обещанию в случае сбоев, а не только в моменты энтузиазма во время запуска.
В учебном коде часто все пользователи хранятся в одном наборе данных с полем метаданных, которое никто не фильтрует. В производственных условиях обеспечьте изоляцию арендаторов на уровне запросов: каждая операция добавления или обновления данных, а также каждый поиск по сходству должны включать авторизованного пользователя в качестве обязательного фильтра, а не просто как опциональное указание в метаданных. Добавьте тесты на интеграцию, проверяющие возможность получения данных от других арендаторов, и ожидайте отсутствия результатов. В случае требований регуляторов сочетайте это с ключами шифрования для каждого арендатора, даже если это увеличит операционные затраты.
Хуки жизненного цикла находятся рядом с механизмами изоляции. При удалении рабочего пространства необходимо запустить последовательные операции удаления для векторов, узлов графа и кэшированных сводок, затем проверить, снизилось ли их количество до нуля. Когда пользователь экспортирует данные, следует сгенерировать машинночитаемый пакет информации с временными метками и идентификаторами исходных сообщений, чтобы пользователь мог оспорить или перенести эти данные. Эти процессы сложны и именно они отличают демонстрационные ноутбуки типа RAG от систем, которым люди доверяют хранение личных данных.
С точки зрения модели рекомендуется указывать идентификаторы извлеченных данных в скрытых записях или структурированных результатах инструментов, чтобы в видимом ответе можно было указать «потому что вы сказали нам X в прошлом апреле» с возможностью отслеживания источника. Цитирование также ускоряет расследование случаев загрязнения данных: у некорректных записей есть идентификаторы, позволяющие их устранить. Со временем такая дисциплина в работе важнее любого отдельного выбора поставщика базы данных векторов.
Чек-лист для проверки перед объявлением памяти «готовой»
Убедитесь, что как краткосрочные, так и долгосрочные пути доступны для наблюдения; убедитесь, что у эмбеддингов и процесса разбиения на чанки есть ответственный пользователь; убедитесь, что операции удаления и экспорта работают в тестовом окружении; убедитесь, что системы оценки выявляют проблемы с воспроизведением данных между сессиями и утечкой информации между пользователями; убедитесь, что панели управления затратами включают информацию о процессе поиска. Если какой-либо пункт не отмечен, у агента ещё нет настоящей памяти — у него есть лишь векторная база данных, похожая на иллюзию. Отметьте все пункты, затем выпустите продукт. Пересматривайте чек-лист ежеквартально по мере изменения моделей, регулирований и обещаний по продукту, поскольку системы памяти накапливают обязательства быстрее, чем почти любой другой подсистема агента.
Обучите команды поддержки работе с заявками, связанными с памятью системы: пользователям, которые говорят «система забыла меня», необходимы инструменты для анализа хода общения, а не диагностика хранилища; пользователям, которые говорят «система запоминает слишком много», нужны способы удаления данных и правила их хранения. Предоставьте руководства для сотрудников поддержки с указанием точных административных инструментов для безопасного проверки пространств имён. Техническая архитектура приносит пользу только тогда, когда люди вне отдела инженерии могут ею управлять, не создавая свои собственные таблицы для записи предпочтений пользователей.
Согласование всех элементов в едином графике
Первая неделя: буферная память и детальное логирование команд. Вторая неделя: операции вставки/обновления векторов с фильтрами по арендаторам и небольшим набором данных для проверки корректности. Третья неделя: API для удаления/экспорта данных и руководство по техподдержке. Четвертая неделя: гибкая система ранжирования между структурированными элементами и неструктурированной информацией, а также панели управления затратами. Переход к сложным потокам памяти до реализации изоляции арендаторов превращает демонстрации в источник проблем. Последовательность важнее новизны. Каждая неделя должна заканчиваться измеримым тестом, который кто-то другой сможет повторить в отсутствие первоначального разработчика, поскольку системы памяти существуют дольше срока их внедрения и будут эксплуатироваться людьми, которые никогда не видели первоначальные чертежи.
Еще один анализ проблем загрязнения и отклонений
Планируйте периодические аудиты, в ходе которых берутся пробы извлеченных воспоминаний из случайной группы и оценивается степень их устаревания, противоречивости и чувствительности. Результаты неудач передавайте в фильтр записи. Воспоминания, как и любой набор данных, могут изменяться со временем; без аудитов они постепенно превращаются в вымысел, который модель считает фактом. Выделяйте время на выполнение этих процедур так же, как выделяете средства на обновления моделей, поскольку оба подхода способствуют сохранению качества ответов, чего недостаточно при единственных корректировках запросов.
Когда такие практики внедрены, расширение окон контекста становится дополнением, а не заменой: окно обрабатывает текущий диалог, а внешняя база хранения — всё то, что должно сохраняться дольше. Такое разделение обязанностей является ключевым принципом, позволяющим создавать инструменты, которым люди доверяют на протяжении недель, а не только в рамках отдельных сообщений.