Почему LLM не помнит и что такое память

Урок объясняет, почему модель «забывает» и как память возвращает ей контекст.

Stateless — свойство модели не хранить состояние между запросами: каждый вызов независим, прошлые реплики модель не помнит.

Иллюзия памяти

Когда в чат-боте вы пишете «а теперь короче», бот будто помнит предыдущий ответ. На деле модель ничего не помнит: каждый запрос к API независим. Иллюзия памяти создаётся тем, что в новый запрос мы вручную подкладываем всю предыдущую историю сообщений. Память в LangChain — это и есть управление этой историей: что хранить, как подставлять, когда обрезать.

Как выглядит подстановка истории

Перед каждым новым вопросом к модели отправляют накопленные сообщения плюс новую реплику. Смоделируем накопление истории на чистом Python:

history = []

def ask(user_text):
    history.append({"role": "human", "text": user_text})
    # вместо реальной модели — заглушка
    reply = f"(ответ на: {user_text})"
    history.append({"role": "ai", "text": reply})
    return reply

ask("Что такое кэш?")
ask("А приведи пример")
print("Сообщений в истории:", len(history))
for m in history:
    print(m["role"], ":", m["text"])

Вывод:

Сообщений в истории: 4
human : Что такое кэш?
ai : (ответ на: Что такое кэш?)
human : А приведи пример
ai : (ответ на: А приведи пример)

Как работает под капотом

В LangChain история хранится в объекте ChatMessageHistory — это просто список сообщений с ролями. Перед вызовом модели цепочка берёт текущую историю, добавляет её в промпт через специальный плейсхолдер (MessagesPlaceholder), а после ответа дописывает в историю новую пару «вопрос — ответ». Поскольку контекст модели ограничен (есть лимит токенов), бесконечно расти история не может — поэтому появляются стратегии обрезки, о которых дальше.

Частые ошибки

  • Считать, что модель «запомнила». Помните вы (точнее, ваш код), а не модель.
  • Слать всю историю без ограничений. Длинная история раздувает запрос, стоит дороже и может упереться в лимит контекста.
  • Хранить историю в глобальной переменной для всех пользователей. У каждого диалога должна быть своя история по идентификатору сессии.

Итог

  • LLM stateless: между запросами модель ничего не помнит.
  • Память — это управляемая история сообщений, которую код подкладывает в каждый запрос.
  • История хранится как список сообщений и вставляется через MessagesPlaceholder.
  • Историю нельзя растить бесконечно из-за лимита контекста и стоимости.
Проверьте себя
1. Почему говорят, что LLM stateless?
AМодель забывает после перезагрузки сервера
BКаждый запрос к модели независим, прошлые реплики она не хранит
CМодель не умеет читать длинные тексты
DПамять отключена в целях безопасности
2. Как на практике создаётся «память» диалога?
AМодель сама записывает историю в файл
BКод подкладывает накопленную историю сообщений в каждый новый запрос
CИстория хранится внутри весов модели
DПамять включается параметром memory=True у API