Agent Memory

Модуль 01 · Урок 1.1

Урок 1.1. LLM без памяти: stateless-модель против stateful-агента

На этой странице
  1. Цель лекции
  2. Зачем это нужно
  3. Основная идея
  4. Ключевые термины
  5. Stateless-природа LLM
  6. Почему история чата не равна памяти модели
  7. Prompt, state, knowledge и memory
  8. Context window как рабочее пространство
  9. Схема: LLM call против Agent loop
  10. Почему "просто положить все в контекст" не работает
  11. Что агенту действительно нужно помнить
  12. Пример: ассистент в IDE
  13. Примеры неправильного понимания памяти
  14. Мини-кейс: персональный ассистент
  15. Типичные архитектурные последствия
  16. Краткое резюме
  17. Вопросы для самопроверки
  18. Что дальше

Цель лекции

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

Зачем это нужно

Когда разработчики впервые добавляют LLM в продукт, часто возникает ощущение, что модель "помнит" пользователя. Она видит предыдущие сообщения в чате, подхватывает стиль разговора, ссылается на уже обсужденные детали и иногда выглядит как система с устойчивым внутренним состоянием.

Это полезная иллюзия, но опасная архитектурная предпосылка. Если считать, что память уже встроена в модель, легко построить систему, которая хорошо работает на короткой демо-сессии и разваливается в реальном использовании: забывает договоренности, смешивает проекты, повторяет старые ошибки, теряет важные ограничения и неправильно персонализирует ответы.

В этом уроке мы зафиксируем базовую границу: LLM-вызов сам по себе является stateless, а агент с памятью является stateful системой вокруг модели. Модель генерирует ответ по текущему входу и своим весам. Агентская система решает, что сохранить, где хранить, что достать, как подать это обратно в контекст и когда забыть.

Основная идея

LLM не имеет долговременной памяти в том смысле, в каком память нужна агенту. Во время одного вызова модель учитывает только то, что попало во входной контекст: системные инструкции, сообщения пользователя, историю диалога, результаты инструментов, найденные документы и другие фрагменты, собранные внешней системой.

Context window помогает модели работать с текущим вводом, но не является долговременным хранилищем. Это рабочее пространство на один вызов или на одну собранную итерацию агента. Если факт не попал в контекст, модель не может надежно использовать его в ответе, даже если этот факт был сказан пользователем неделю назад в другой сессии.

Память агента начинается там, где появляется отдельный слой управления состоянием: запись наблюдений, хранение фактов и событий, поиск релевантного прошлого, инъекция найденного в prompt, обновление устаревших сведений и удаление того, что больше не нужно или не должно храниться.

Главный вывод этой лекции: "добавим больше токенов" не является полноценной стратегией памяти. Большой контекст расширяет рабочее пространство, но не решает задачи отбора, структурирования, актуальности, безопасности, стоимости и качества извлечения.

Ключевые термины

Термин Короткое определение
LLM call Один вызов модели с конкретным входным контекстом и конкретным ответом.
Stateless Свойство компонента не хранить изменяемое состояние между независимыми вызовами.
Stateful agent Система, которая сохраняет и переиспользует состояние между шагами, сессиями или задачами.
Context window Максимальный объем токенов, который модель может учитывать в одном вызове.
Prompt Текстовая или мультимодальная инструкция, собранная для текущего вызова модели.
State Состояние системы: текущая задача, настройки, история, промежуточные результаты, сохраненные факты.
Knowledge Общие знания модели или внешней базы знаний. Они не обязательно связаны с конкретным пользователем или прошлым опытом агента.
Memory Управляемый слой сохранения и повторного использования информации, которая влияет на поведение агента во времени.

Stateless-природа LLM

Базовая LLM работает как функция от входа к выходу:

text
response = LLM(model_weights, current_context)

Веса модели содержат то, чему модель научилась во время обучения. Текущий контекст содержит то, что система передала модели прямо сейчас. Между этими двумя частями нет автоматической записи новых пользовательских фактов в "внутреннюю память" модели.

Если пользователь сказал:

В этом проекте мы используем PostgreSQL, а не MongoDB.

модель может учитывать это утверждение в текущем диалоге, если сообщение осталось в истории или было включено в prompt. Но сама модель не переписывает свои веса после этой реплики и не получает встроенную гарантию помнить этот факт завтра.

В продуктовых интерфейсах история чата часто выглядит как память. На самом деле интерфейс или backend просто отправляет модели часть предыдущих сообщений. Это не меняет stateless-природу одного вызова. Состояние хранит не LLM, а приложение вокруг нее.

Почему история чата не равна памяти модели

История чата - это простейший способ дать модели прошлый контекст. Он полезен, но у него есть несколько ограничений.

Во-первых, история ограничена размером context window. Когда разговор становится длинным, старые сообщения нужно обрезать, сжимать или выбирать фрагментами. Что не попало в текущий prompt, то не участвует в рассуждении модели.

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

В-третьих, история чата плохо отделяет устойчивые факты от случайных реплик. Фраза "давай временно сделаем SQLite" может быть экспериментом на один час, а фраза "в продакшене нам запрещен SQLite" может быть долгосрочным ограничением. Memory layer должен различать такие вещи.

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

Prompt, state, knowledge и memory

Эти слова часто используют как синонимы, но для проектирования агента их нужно разделять.

Prompt - это то, что модель видит прямо сейчас. Он может содержать инструкции, вопрос пользователя, результаты поиска, краткую историю и выбранные memory records.

State - это состояние системы. Оно может включать текущую цель, выбранные параметры, результаты предыдущих шагов, список уже вызванных инструментов, активный проект, права доступа и другие данные, которые существуют вне одного текста prompt.

Knowledge - это знания о мире или предметной области. Часть таких знаний уже закодирована в весах модели. Другая часть может лежать во внешних документах, базе знаний или RAG-системе.

Memory - это не просто знание. Память связана с опытом конкретного агента, пользователя, проекта или организации. Она отвечает на вопросы: что уже происходило, что было решено, какие предпочтения известны, какие ошибки повторялись, какие процедуры надо соблюдать, какие факты устарели.

Коротко:

Слой Где живет На какой вопрос отвечает
Prompt Во входе текущего LLM-вызова "Что модель должна учитывать прямо сейчас?"
State В приложении или агентском runtime "В каком состоянии находится задача или сессия?"
Knowledge В весах модели, документах, базах знаний "Что известно о мире или домене?"
Memory В управляемом memory layer "Что агент должен помнить из прошлого опыта?"

Context window как рабочее пространство

Context window часто воспринимают как память, потому что он позволяет передать модели много текста. Но правильнее думать о нем как о рабочем столе: на него можно положить документы, заметки и инструкции, но сам стол не решает, какие документы важны, где они лежали вчера и что нужно выбросить.

Большое контекстное окно полезно. Оно позволяет удерживать длинные документы, сложные инструкции, больше истории и больше результатов инструментов. Но оно не заменяет memory layer по нескольким причинам.

Вопрос Context window Memory layer
Время жизни Один вызов или одна собранная итерация Между шагами, сессиями и задачами
Отбор Обычно задается внешней системой Является центральной задачей слоя памяти
Структура Текст, переданный в prompt Записи, факты, события, метаданные, связи
Актуальность Зависит от того, что положили в контекст Может хранить версии, timestamps, confidence, TTL
Стоимость Растет с количеством токенов в каждом вызове Расходуется на запись, хранение, поиск и инъекцию
Риск шума Высокий при длинной истории Снижается через retrieval, фильтры и политики
Управление доступом Трудно контролировать после инъекции в prompt Можно применять scopes, permissions и политики чтения

Контекст - это место, куда память попадает перед рассуждением. Но сама память - это система, которая решает, что именно туда попадет.

Схема: LLM call против Agent loop

Простейший LLM-вызов выглядит линейно: приложение собирает prompt, модель отвечает, ответ возвращается пользователю.

flowchart LR U[User input] --> P[Prompt] P --> L[LLM call] L --> R[Response]

Stateful-агент добавляет цикл. Он наблюдает среду, читает память, собирает контекст, рассуждает, действует и записывает новые сведения.

flowchart LR U[User / Environment] --> O[Observe] O --> MR[Memory read] MR --> CA[Context assembly] CA --> L[LLM reasoning] L --> A[Action / Tool use] A --> RES[Result] RES --> MW[Memory write] MW --> M[(Memory stores)] M --> MR L --> R[Response]

Важно заметить: LLM остается компонентом внутри цикла. Память не появляется магически внутри модели. Ее создает агентская система, которая управляет входами и выходами модели.

Почему "просто положить все в контекст" не работает

На маленьком примере можно отправить модели всю историю. На реальной системе это быстро становится слабой стратегией.

Первый фактор - стоимость. Чем больше токенов в prompt, тем дороже каждый вызов. Если агент выполняет несколько шагов, длинный контекст оплачивается снова и снова.

Второй фактор - latency. Большой вход обычно увеличивает время обработки. Для интерактивного ассистента это влияет на ощущение скорости, а для агента с инструментами умножается на количество итераций.

Третий фактор - шум. Модель может начать учитывать нерелевантные детали, старые решения или случайные фразы. Иногда дополнительный контекст ухудшает ответ, потому что размывает приоритеты.

Четвертый фактор - конкуренция за внимание. Даже если контекст технически помещается, важная информация может быть плохо использована, особенно если она находится среди длинного массива похожих фрагментов.

Пятый фактор - управление жизненным циклом. Память должна обновляться и забываться. Если пользователь поменял предпочтение, агенту нужно заменить старый факт новым, а не держать оба факта в сырой истории и надеяться, что модель выберет правильный.

Что агенту действительно нужно помнить

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

Типичные категории:

  • Пользовательские предпочтения: язык, формат ответа, уровень детализации, запреты, привычные инструменты.
  • Состояние задачи: текущая цель, выбранный подход, уже выполненные шаги, открытые вопросы.
  • Проектные факты: стек, архитектура, соглашения, важные файлы, ограничения команды.
  • История решений: какие варианты рассматривались, что было принято, почему отказались от альтернатив.
  • Результаты инструментов: успешные команды, ошибки, диагностика, ссылки на артефакты.
  • Процедуры: как в этом проекте запускать проверки, оформлять изменения, писать документацию.
  • Уроки из опыта: повторяющиеся failure modes и способы их избегать.

Эти данные имеют разную структуру и разное время жизни. Некоторые живут только в текущей сессии. Некоторые должны сохраняться месяцами. Некоторые можно использовать сразу, но нельзя записывать без разрешения. Именно поэтому память проектируют как слой, а не как одну длинную строку в prompt.

Пример: ассистент в IDE

Представим coding agent, который помогает разработчику в репозитории.

В первой сессии пользователь говорит:

В этом проекте не добавляй новые зависимости без обсуждения. Тесты запускаются через npm test, но перед этим нужно поднять локальную базу.

Если это просто чат с историей, агент будет помнить эти условия, пока они остаются в контексте. Через несколько дней, в новой сессии, он может снова предложить новую библиотеку или запустить тесты без базы, потому что старое сообщение не было передано в prompt.

Если это агент с memory layer, система может сохранить несколько разных записей:

Тип записи Содержание Как используется
Preference Пользователь хочет обсуждать новые зависимости заранее. Политика перед изменением package.json.
Project fact Тесты запускаются через npm test. Подсказка при выборе команды проверки.
Procedure Перед тестами нужна локальная база. Шаг в workflow перед запуском тестов.
Scope Эти правила относятся к конкретному репозиторию. Не применяются автоматически к другим проектам.

При следующей задаче агент извлекает только релевантные записи и добавляет их в рабочий контекст. Модель не "вспомнила" сама. Система восстановила нужные сведения и передала их модели в подходящий момент.

Примеры неправильного понимания памяти

Ошибка 1: "История чата уже является памятью".

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

Ошибка 2: "Если контекстное окно достаточно большое, memory layer не нужен".

Большое окно помогает держать больше данных в одном вызове, но не решает, какие данные важны, какие устарели, какие можно показывать модели и какие относятся к текущему пользователю или проекту.

Ошибка 3: "Vector database - это и есть память".

Vector database может быть частью memory layer, особенно для semantic retrieval. Но память включает запись, фильтрацию, права доступа, обновление, забывание, ранжирование, представление фактов и связь с агентским циклом.

Ошибка 4: "Knowledge base и memory - одно и то же".

Knowledge base обычно хранит внешние знания: документацию, статьи, справки, спецификации. Память агента хранит опыт и состояние: что происходило с этим пользователем, проектом, задачей и самим агентом.

Ошибка 5: "Нужно помнить все".

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

Мини-кейс: персональный ассистент

Пользователь просит:

Помоги подготовить письмо инвестору в моем обычном стиле.

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

Stateful-агент может использовать память:

  • извлечь предпочтение: "пользователь пишет коротко, без чрезмерного энтузиазма";
  • извлечь факт: "компания сейчас готовит seed round";
  • извлечь прошлое событие: "в прошлом письме инвестор попросил уточнить retention";
  • извлечь процедурное правило: "перед отправкой всегда дать пользователю финальную версию на подтверждение".

Именно эта связка делает ассистента похожим на продолжение предыдущей работы, а не на новый генератор текста каждый раз.

Типичные архитектурные последствия

Если LLM stateless, то архитектура агента должна явно отвечать на несколько вопросов.

Что записывать? Не каждую фразу, а сведения, которые могут повлиять на будущие решения: предпочтения, факты, события, процедуры, результаты.

Где хранить? Разные типы памяти требуют разных представлений: короткий session state, профиль пользователя, журнал событий, документы, vector index, graph, policy files.

Когда извлекать? Не вся память нужна в каждом запросе. Агенту нужен retrieval, который учитывает задачу, пользователя, проект, время и права доступа.

Как подавать в prompt? Даже найденная память должна быть компактно и явно встроена в контекст: с источником, приоритетом, временем и пояснением, почему она релевантна.

Как обновлять? Новые факты могут уточнять или отменять старые. Без механизма обновления агент будет сохранять противоречия.

Как забывать? Память может устаревать, становиться нерелевантной или требовать удаления по политике приватности.

Эти вопросы будут подробно разбираться в следующих модулях. Сейчас важно увидеть, что все они находятся вне одного LLM-вызова.

Краткое резюме

LLM-вызов сам по себе stateless: модель не записывает новые пользовательские факты в долговременное состояние между независимыми запросами. Она работает с весами модели и текущим контекстом.

Context window - это рабочее пространство, а не память. Оно позволяет передать модели релевантные данные сейчас, но не управляет их хранением, обновлением, поиском и забыванием.

Память AI-агента - это внешний memory layer: система записи, хранения, retrieval, context assembly, обновления и удаления информации. Такой слой превращает набор отдельных LLM-вызовов в stateful-агента, который способен поддерживать непрерывность, персонализацию и обучение на прошлом опыте.

Вопросы для самопроверки

  1. Почему история чата в интерфейсе не означает, что LLM имеет внутреннюю долговременную память?
  2. Чем prompt отличается от state?
  3. Почему большой context window не заменяет memory layer?
  4. Какие типы информации агенту стоит помнить о пользователе или проекте?
  5. Почему стратегия "сохранять все" может ухудшить качество агента?

Что дальше

В следующей лекции мы посмотрим на AI Agent как на систему: где именно расположен memory layer, как он связан с planner, tools, policies и environment, и почему память становится частью агентского цикла observe -> retrieve -> reason -> act -> write.

Обновлено 08.08.2026