AI-инжиниринг

Memory для чатботов: как LLM помнит контекст - buffer, summary, vector memory

Цели урока

  • Понять, почему LLM не имеет встроенной памяти и как это решается на backend
  • Реализовать Buffer Memory и Window Memory для простых чатботов
  • Освоить Summary Memory для длинных разговоров с суммаризацией
  • Применять Vector (episodic) Memory как RAG по истории разговора
  • Спроектировать Hybrid Memory с PostgreSQL persistence для production

Предварительные знания

  • RAG pipeline и vector search
  • Chat Completions API
  • RAG Fundamentals
  • API Integration

LLM не помнит ничего. Каждый запрос - чистый лист. Иллюзия памяти в ChatGPT - это просто весь контекст диалога передаётся заново каждый раз. Character.ai делает это для 20 миллиардов сообщений в день. MemGPT (Letta) пошёл дальше: LLM сам управляет своей памятью, сам решает что записать и что забыть. Retention чатбота без правильной памяти - 15%. С hybrid memory architecture - 60%.

  • ChatGPT использует window memory + server-side persistence в PostgreSQL - каждый chat хранится и может быть продолжен через месяц
  • Character.AI обрабатывает 20B+ сообщений/день - personality memory между сессиями реализована через vector store + entity extraction
  • Intercom AI Support - hybrid memory с vector search по истории тикетов клиента, агент знает все прошлые обращения
  • MemGPT (Letta, 2023) - LLM сам управляет своей памятью: main context + archival storage + recall storage, entity extraction из разговора

Память родилась из ограничения context window

Отслеживание состояния диалога - старая задача из task-oriented чатботов, но память как забота LLM пришла вместе с эпохой ChatGPT. Когда ChatGPT запустился 30 ноября 2022 года, его context window был около 4096 токенов - как только разговор перерастал этот объём, самые ранние реплики выталкивались и модель их просто забывала. Именно это жёсткое ограничение - причина существования всех memory-архитектур. **LangChain** (Harrison Chase, октябрь 2022) дал первые широко используемые абстракции памяти - buffer, window и summary memory - готовые паттерны вместо ручного управления историей. В 2023 году **MemGPT** (Charles Packer с коллегами, UC Berkeley) пошёл дальше: рассматривать context window как RAM операционной системы и позволить LLM подгружать факты из внешнего хранилища и выгружать обратно, самому решая что хранить. Позже проект стал Letta.

Stateless LLM: почему модель забывает всё

LLM не помнит ничего. Каждый запрос - чистый лист. Иллюзия памяти в ChatGPT - это просто весь контекст диалога передаётся заново при каждом вызове. Character.ai делает это для 20 миллиардов сообщений в день. Не магия - инженерия.

Это не баг и не ограничение реализации. LLM **stateless по архитектуре** - как HTTP без cookies. Каждый `chat.completions.create()` - независимая математическая операция: вектора пришли, вектора ушли, никакого состояния не осталось. Память - это инженерная надстройка поверх stateless API, не встроенная функция модели.

Проблема не только в принципе - в масштабе. Передавать всю историю каждый раз значит платить за каждый токен каждого прошлого сообщения. 50K tokens в истории × 1000 запросов/день × `2.5 USD/1M` input = **`125 USD` в день** только на контекст. Вот где начинается настоящая инженерия памяти.

ПроблемаОписаниеПоследствие
Context window limitGPT-4o: 128K tokens ~ 200 страниц. Разговор на 500 сообщений может превысить лимитОшибка API или обрезка контекста
СтоимостьКаждый токен в messages оплачивается. 50K tokens x 2.5 USD/1M = 0.125 USD за запросРасходы растут линейно с длиной разговора
LatencyБольше tokens - дольше processing. 100K tokens = 2-5 секунд дополнительной задержкиUX деградирует на длинных разговорах
Lost in the middleLLM хуже обрабатывает информацию в середине длинного контекстаРанние сообщения 'забываются' даже если переданы

"Lost in the middle" - исследование Stanford (2023): LLM хорошо помнит начало и конец контекста, но теряет информацию в середине. При 100+ сообщениях accuracy падает на 20-30% для фактов из середины разговора.

LLM запоминает разговор между сессиями - как человек после встречи

Модель stateless по архитектуре. Любая память между сессиями - инженерная надстройка: база данных + Redis + вектора. Без этого каждая сессия - первое знакомство

ChatGPT 'помнит' прошлые разговоры потому что OpenAI хранит их в базе и подгружает релевантное в системный промпт. Это RAG над историей чатов, а не встроенная память модели. Убери базу данных - и GPT-4o ничем не отличается от свежего инстанса без единого воспоминания

Почему LLM не помнит предыдущие сообщения между API-вызовами?

Buffer Memory: полная история сообщений

Самый простой подход: хранить **все** сообщения и передавать при каждом запросе. Это **Buffer Memory** - модель видит полную историю разговора. Никакой хитрости, никакого сжатия - просто растущий список.

Buffer Memory честен: ничего не теряет и ничего не скрывает. Именно поэтому его используют для коротких сессий с кодогенерацией - когда каждая строка диалога критична. Но цена этой честности растёт линейно. Сообщение #100 тащит за собой сообщения #1-99 как якорь.

ПлюсыМинусы
Полный контекст - ничего не теряетсяСтоимость растёт линейно: 100 сообщений x 0.002 USD = 0.20 USD за запрос
Простейшая реализацияContext window переполняется на длинных разговорах
Модель видит весь ход диалогаLost in the middle: ранние сообщения деградируют
Подходит для коротких сессий (10-20 сообщений)Не подходит для customer support (100+ сообщений за сессию)

Map в памяти Node.js - только для прототипов. В production - PostgreSQL или Redis. При рестарте сервера Map обнуляется, и все разговоры теряются.

Разговор длится 200 сообщений. При использовании Buffer Memory стоимость каждого нового запроса...

Window Memory: скользящее окно последних N сообщений

Зачем передавать весь разговор, если последние 10-20 сообщений содержат 90% нужного контекста? **Sliding window** - это та же логика, что в трансформерах при обработке длинных документов: берём окно фиксированного размера и двигаем по тексту. **Window Memory** хранит только последние N сообщений (или K tokens) и отбрасывает всё за пределами окна.

Более точный вариант - лимит по tokens, а не по количеству сообщений:

Window Memory - хороший default для большинства чатботов. Рекомендация: maxTokens = 25% от context window модели. Для GPT-4o (128K) - 32K tokens на историю, остальное для system prompt + RAG context + generation.

При Window Memory с лимитом 20 сообщений. На сообщении #50 пользователь ссылается на тему из сообщения #5. Результат?

Summary Memory: LLM как компрессор истории

Window Memory теряет ранние сообщения молча. **Summarization memory** решает это иначе: вместо удаления старых сообщений - сжать их через тот же LLM. Дешёвая модель (gpt-4o-mini, `0.15/1M` tokens) компрессирует 50 сообщений в 2-3 параграфа, сохраняя ключевые факты. Дорогая модель получает компакт - и не видит разницы.

Суммаризация запускается по порогу - это принципиально. Дополнительный LLM call после каждого сообщения убьёт latency. Но по порогу в 2000 tokens - это нечастая операция, почти незаметная для пользователя. Ошибки суммаризации накапливаются как в испорченном телефоне - поэтому для критичных данных нужен другой подход.

ПлюсыМинусы
Фиксированная стоимость - summary не растёт бесконечноПотеря деталей при суммаризации
Ключевые факты сохраняютсяДополнительный LLM call для суммаризации (+latency, +cost)
Подходит для длинных разговоров (100+ сообщений)Ошибки суммаризации накапливаются ('испорченный телефон')
Контролируемый размер контекстаСложнее дебажить - какие факты потерялись?

Суммаризация теряет нюансы. Пользователь сказал 'бюджет примерно `50K USD`, но может быть `70K USD` если включить маркетинг'. Summary: 'бюджет `50`-70K'. Потерян контекст 'если включить маркетинг'. Для критичных данных - лучше vector memory.

Summary Memory суммаризирует старые сообщения когда...

Vector Memory: семантический поиск по истории

Buffer тонет в стоимости. Window теряет прошлое. Summary теряет детали. **Episodic (vector) memory** - принципиально другой подход: каждое сообщение сохраняется как embedding через `text-embedding-3-small` (1536 dim, `0.02/1M` tokens), и при каждом запросе HNSW-индекс за 3 мс находит **семантически близкие** фрагменты из всей истории. RAG, только по собственному разговору.

Именно этот принцип лёг в основу **MemGPT** (теперь Letta) - системы, где LLM сам управляет своей памятью: решает что записать в long-term storage, что вытащить обратно, что забыть. Entity extraction поверх вектора - ещё один слой: из разговора автоматически извлекаются именованные сущности (имена, компании, задачи) и хранятся отдельно. Пользователь упомянул 'наш стартап TokenFlow' - следующий сеанс уже знает контекст.

ПлюсыМинусы
Находит релевантный контекст из любой точки историиEmbedding call для каждого сообщения (+latency, +cost)
Масштабируется на 1000+ сообщенийТеряет последовательность - сообщения вырваны из порядка
Работает как RAG по собственной историиСложнее реализация - нужна vector DB
Фиксированный размер контекстаНе подходит для пошаговых инструкций (важен порядок)

Vector Memory при обработке нового сообщения...

Hybrid Memory и PostgreSQL Persistence

Каждый тип memory закрывает что-то одно. Production-решение - **hybrid**: Window даёт immediate context, Summary держит сжатую историю, Vector вытаскивает семантически близкое из любой точки. Три слоя, один запрос. Именно так работают enterprise AI-ассистенты - и именно поэтому они не забывают, что клиент говорил три месяца назад.

PostgreSQL schema для production

Сравнение всех стратегий memory - когда применять:

СтратегияДлина разговораCostAccuracyСценарий
Buffer< 20 сообщений$$$100%Короткие задачи: генерация кода, перевод
Window (last N)Любая$70-80%Customer support, casual chat
Summary20-200 сообщений$$80-85%Консультации, coaching, длинные сессии
Vector (episodic)Любая$$85-90% для relevantТехническая поддержка, knowledge workers
HybridЛюбая$$$90-95%Production chatbots, AI assistants

Начинать с Window Memory (самый простой). Если пользователи жалуются на 'забывчивость' - добавить Summary. Если нужна точность для конкретных фактов - добавить Vector. Hybrid - для production AI-ассистентов. Redis идеален для session storage: O(1) доступ к последним сообщениям, TTL на устаревшие сессии, pub/sub для streaming.

Memory в чатботе - это про сохранение всей истории сообщений. Чем длиннее буфер, тем умнее бот.

Memory - это управление компромиссом между context window, стоимостью и релевантностью. Hybrid-подход (Window + Summary + Vector) почти всегда даёт лучшее качество при меньшей стоимости, чем простое расширение буфера.

Интуиция от человеческой памяти: «помнить больше = понимать лучше». У LLM не так: лишние сообщения в контексте размывают attention, добавляют шум при retrieval и линейно растят стоимость. После 20-30 ходов чистый буфер начинает проигрывать summary-стратегии по точности ответа, не только по цене.

Hybrid Memory комбинирует три источника контекста. Какой из них отвечает за 'модель помнит факт из сообщения #5 при обработке сообщения #150'?

LLM запоминает разговор между сессиями - как человек после встречи

Модель stateless по архитектуре. Любая память между сессиями - инженерная надстройка: база данных + Redis + вектора. Без этого каждая сессия - первое знакомство

ChatGPT 'помнит' прошлые разговоры потому что OpenAI хранит их в базе и подгружает релевантное в системный промпт. Это RAG над историей чатов, а не встроенная память модели. Сама модель не изменилась - изменился контекст, который ей передали

Ключевые выводы

  • LLM API stateless - каждый вызов начинается с нуля, 'память' - ответственность backend
  • Buffer Memory: полная история, идеально для коротких задач, дорого и медленно для длинных разговоров
  • Window (sliding) Memory: последние N сообщений - разумный default для 80% чатботов
  • Summary Memory: gpt-4o-mini сжимает историю по порогу - сохраняет суть, теряет нюансы
  • Vector (episodic) Memory: text-embedding-3-small + HNSW = RAG по собственной истории, entity extraction сверху
  • Hybrid (Window + Summary + Vector) - production standard; Redis для session storage, PostgreSQL с pgvector для persistence

Вопросы для размышления

  • В каком сценарии чатбота Buffer Memory оправдан даже при 50+ сообщениях - и что это говорит о задаче?
  • Как entity extraction поверх vector memory меняет качество ответов по сравнению с 'сырыми' векторами сообщений?
  • MemGPT позволяет LLM самому решать что запомнить. Какие failure modes у такой архитектуры?

Что дальше

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

  • Tool Calling — Как LLM вызывает функции - function calling, tool use, structured actions
  • Agent Fundamentals — От чатбота к агенту - planning, reasoning, tool use в цикле
  • Caching & Optimization — Как кешировать ответы и снизить стоимость memory-heavy чатботов

Связанные уроки

  • aie-04-tokens-context-window — Context window limit - причина зачем нужна память
  • aie-09-embeddings — Vector memory строится на similarity search по embeddings
  • aie-16-tool-calling — Memory + tool use = полноценный персистентный агент
  • aie-17-agent-fundamentals — Долгосрочная память - ключевой компонент агента
  • aut-07-attention-memory — Working vs long-term memory - та же архитектурная дилемма
  • prob-17 — Summary memory - аппроксимация истории как Марков-процесс
  • db-19-redis
Memory для чатботов: как LLM помнит контекст - buffer, summary, vector memory

0

1

Войти