Восходящий ИИ: как внешняя память заменяет рекуррентность. Детальный разбор механизмов MSP, Qwen‑Agent и индустриальных решений
1. Статичность LLM как архитектурная данность
Прежде чем переходить к механизмам, необходимо предельно чётко зафиксировать исходную проблему, чтобы дальнейшее описание MSP воспринималось не как абстрактная идея, а как инженерно обусловленное решение.
В работах по геометрии эмбеддингов и исследованиях внутренней размерности (intrinsic dimensionality) было экспериментально показано:
- **Пространство эмбеддингов LLM статично:** главные компоненты (PC), полученные методом PCA на различных текстовых корпусах, совпадают более чем на 95%, что указывает на стабильность геометрии пространства независимо от входных данных.
- **Эффективная размерность значительно ниже номинальной:** в ряде исследований показано, что intrinsic dimensionality часто лежит в диапазоне 50–150 против 384–4096 номинальных измерений (зависит от слоя, модели и датасета), что говорит о жёсткой концентрации информации.
- **Распределение векторов крайне анизотропно:** среднее попарное косинусное сходство достигает ~0.85–0.90 (соответствует метрикам анизотропии в работах Ethayarajh, 2019 и последующих исследованиях), а норма векторов почти идеально равна единице. Все векторы лежат на поверхности гиперсферы, но сконцентрированы в её ограниченных областях.
- **Единственная наблюдаемая динамика — эффект «снежного кома»:** накопление контекстных токенов смещает результирующий вектор ответа, но не меняет саму геометрию пространства.
Из этого следует, что в архитектуре Transformer отсутствует какой-либо механизм внутреннего состояния, сохраняющегося между вызовами. Модель — это большая математическая функция, принимающая последовательность токенов и возвращающая распределение вероятностей следующего токена. Никакого скрытого вектора, который бы переходил из одной сессии в другую, не предусмотрено.
Возникает вопрос: если мы хотим получить систему, способную к размышлению во времени, накоплению опыта и адаптации поведения на основе предыдущих взаимодействий — где должен располагаться механизм, обеспечивающий такую рекуррентность?
## 2. MSP как внешний функциональный аналог рекуррентности: послойное устройство и операционный цикл
> **Важно:** далее под «рекуррентностью» понимается не внутреннее скрытое состояние модели, а циклическое обновление внешнего контекста, обеспечивающее непрерывность поведения системы во времени.
MSP (Memory-State-Processing) — архитектурная концепция, в которой рекуррентное поведение системы возникает не из внутреннего скрытого состояния модели, а из внешней структуры, состоящей из трёх слоёв памяти и четырёхфазного рабочего цикла. Рассмотрим каждый слой и фазу отдельно, на уровне конкретных структур данных и операций.
### 2.1 Эпизодическая память
**Назначение:** хранить хронологию событий — «что происходило» в хронологическом порядке.
Структура записи:
**Физическое хранение:**
- В простейшем случае — JSON-файл или SQLite-таблица с индексом по `session_id + timestamp`.
- В продвинутых реализациях — векторная база (Chroma, Pinecone, Qdrant, FAISS), где каждая запись имеет embedding, полученный либо эмбеддером модели, либо лёгким энкодером (например, `all-MiniLM-L6-v2`).
**Ключевая особенность:** эпизодическая память растёт линейно с числом шагов агента. Без механизма консолидации она быстро приведёт к переполнению контекстного окна и деградации внимания на длинных дистанциях. Именно поэтому вводится следующий слой и фаза консолидации.
### 2.2 Семантическая память
**Назначение:** хранить факты и знания, извлечённые из эпизодов или предоставленные извне, без привязки к конкретному моменту времени.
**Структура записи (фактоид):**
**Процесс консолидации (детально):**
- **Триггер:** агент завершает сессию, либо накоплено `N` новых эпизодов (N — конфигурируемый порог, например, 20).
- **Сбор:** все эпизоды с момента последней консолидации объединяются в один текстовый блок.
- **Запрос к LLM (или отдельной модели-экстрактору):** «Из следующей истории диалога извлеки все устойчивые факты о пользователе, его предпочтениях и контексте задачи. Для каждого факта укажи степень уверенности (0-1). История: `{text}`».
- **Дедупликация:** каждый извлечённый кандидат сравнивается по embedding-близости с уже существующими фактоидами. Если косинусное сходство > 0.95 — факт считается дубликатом и не добавляется (или обновляется существующий).
- **Запись:** новые фактоиды сохраняются в векторную базу.
**Результат:** семантическая память растёт логарифмически, а не линейно, храня сжатое смысловое ядро всей истории взаимодействий.
### 2.3 Процедурная память
**Назначение:** хранить знания о том, «как действовать» — доступные инструменты, системные инструкции, поведенческие шаблоны.
**Состав процедурной памяти:**
- **System prompt:** неизменяемая (или редко изменяемая) системная инструкция, задающая роль агента и базовые правила.
- **Зарегистрированные инструменты:** список доступных функций/инструментов, каждый со своей JSON-схемой для function calling.
- **Поведенческие паттерны:** шаблоны «если произошло X, следует вызвать инструмент Y» (в Qwen‑Agent это неявно закодировано в способности модели к планированию, но может быть вынесено в явный rule-движок).
**Ключевое отличие:** процедурная память меняется редко и, как правило, административно, а не автоматически. Она задаёт «скелет» поведения агента.
### 2.4 Рабочая память (Working Memory)
**Назначение:** активный контекст, который модель «видит» прямо сейчас.
**Формирование рабочей памяти для каждого вызова LLM:**
- Берётся `system prompt` из процедурной памяти.
- Добавляются последние `K` эпизодов из эпизодической памяти (K — параметр, например, последние 10 шагов).
- Выполняется **Retrieve**: из семантической памяти извлекаются фактоиды, релевантные текущему запросу. Используется embedding запроса → косинусное сходство с embedding'ами фактоидов → top-M по сходству.
- Формируется финальный промпт:
Именно этот промпт подаётся на вход LLM.
### 2.5 Операционный цикл: Write → Consolidate → Retrieve → Inject
Теперь, имея четыре слоя памяти, можно детально описать, как они взаимодействуют в течение одного шага агента. Это и есть та самая рекуррентная петля, которая заменяет внутреннее состояние.
**Шаг 0. Инициализация**
Загружается система: процедурная память, пустая (или сохранённая) эпизодическая и семантическая память. Приходит первый запрос пользователя.
**На каждом шаге t:**
- **Retrieve (Поиск и формирование контекста)**
- Вычисляется embedding запроса.
- Векторный поиск по эпизодической памяти: `top_k_episodes`.
- Векторный поиск по семантической памяти: `top_m_facts`.
- Из процедурной памяти извлекаются `system_prompt` и схемы инструментов.
- Собирается промпт (см. 2.4).
- **Inject (Вызов модели)**
- Сформированный промпт подаётся в LLM через API.
- Модель возвращает текстовый ответ или `tool_call`.
- **Execution (Исполнение, если был tool call)**
- Фреймворк вызывает соответствующий инструмент (code_interpreter, web_search, API по MCP и т.п.).
- Возвращается результат выполнения.
- **Write (Запись в эпизодическую память)**
- Текущий шаг сохраняется как новый эпизод. При использовании векторной базы вычисляется embedding.
- **Consolidate (Консолидация) — асинхронно или по условию**
- Запускается каждые N шагов или по завершении сессии.
- LLM-экстрактор извлекает факты, проходит дедупликация, новые фактоиды сохраняются в семантическую память.
- **Переход к шагу t+1**
- Цикл повторяется с обновлённой рабочей и семантической памятью.
**Почему это рекуррентность**
В классической RNN рекуррентность описывается как:
`h_t = f(x_t, h_{t-1})`
В архитектуре с MSP:
h_t = LLM(Retrieve(MSP_{t-1}, x_t))
MSP_t = Write(MSP_{t-1}, x_t, h_t)
MSP_{t+1} = Consolidate(MSP_t)
**Важно:** это архитектурная, а не строгая математическая эквивалентность. В отличие от RNN, где `h_t` — непрерывный вектор фиксированной размерности, состояние MSP дискретно, явно наблюдаемо, модифицируемо и обновляется с задержкой, определяемой инфраструктурой памяти. Функция `LLM` статична, а динамика полностью определяется операциями над MSP. Это и есть вынос рекуррентности наружу.
3. Глубокая архитектура Qwen‑Agent: как MSP воплощается в коде
**Примечание:** примеры кода и имена классов упрощены для наглядности и соответствуют архитектуре Qwen-Agent v0.1–v0.2. Актуальные методы могут отличаться в новых версиях. Рекомендуется сверяться с официальным репозиторием.
### 3.1 Компонент Memory (эпизодическая память)
Класс `Memory` управляет двумя хранилищами:
- `history` — список сообщений текущей сессии (эпизодическая память в оперативном виде).
- `rag` — компонент для работы с документами (семантическая память).
Метод `get_memory()` реализует фазу **Retrieve** и формирует рабочую память, комбинируя историю и RAG-чанки с учётом лимита токенов. Запись (**Write**) происходит неявно через `session.add_message()`. Консолидация в базовой версии не автоматизирована, но архитектура позволяет добавить её как post-processing модуль.
### 3.2 RAG как семантическая память
Класс `RAG` реализует:
- Парсинг документов (PDF, DOCX, MD, TXT) с настраиваемым размером чанка и перекрытием.
- Индексацию через embedding (DashScope text-embedding-v2 или локальные модели) и сохранение в FAISS/Chroma/DashVector.
- Гибридный поиск (sparse BM25 + dense cosine similarity) при вызове `rag.retrieve(query)`.
### 3.3 Инструменты как процедурная память
Базовый класс `BaseTool` содержит `name`, `description`, JSON-схему параметров и метод `call()`. При инициализации `Assistant` описания всех инструментов автоматически инжектируются в system prompt. Qwen‑Agent также поддерживает MCP (Model Context Protocol), транслируя схемы внешних сервисов в формат `BaseTool`.
### 3.4 Планировщик (Agent / Assistant)
Цикл работы `Assistant` точно реализует петлю Write → Retrieve → Inject:
python
### 3.5 Контекст-менеджмент
При превышении `max_token` применяются стратегии: FIFO-обрезка старых сообщений или опциональная LLM-суммаризация. Параметр обычно выставляется как `LLM_CONTEXT_SIZE - RESERVED_FOR_RESPONSE`.
## 4. Детальный разбор решений крупных игроков: внутренняя кухня
### 4.1 OpenAI: Agents SDK и Session как persist-слой
В OpenAI Agents SDK (2025) память реализована как pluggable-абстракция:
- `Session` управляет списком сообщений и их сохранением между вызовами.
- `Memory`-компоненты поддерживают семантические факты, автоматически подмешиваемые в system prompt.
- Бэкенд памяти заменяем: SDK работает с InMemory, Redis, векторными БД или OpenAI Conversations API через единый интерфейс.
### 4.2 Google: Vertex AI Agent Memory
В составе Vertex AI Agent Builder / ADK доступен управляемый сервис памяти:
- Работает поверх Cloud Spanner (реляционная часть) и Vertex AI Vector Search.
- Разделяет `Memory Session` (эпизоды) и `Memory Fact` (семантика).
- Предоставляет встроенный LLM-экстрактор фактов и гибридный поиск. Агент взаимодействует с памятью через `memory_tool`, получая возможность явно запрашивать сохранение или поиск контекста.
### 4.3 Anthropic: MCP и mcp-agent
MCP — это протокол подключения внешних ресурсов, а не хранилище. Однако референсный `mcp-server-memory` реализует семантическую память в виде графа знаний (`create_entities`, `create_relations`, `search_nodes`). В связке с `SessionMemory` из `mcp-agent` получается полноценная MSP-петля, где эпизодическая и семантическая память разделены, но доступны через стандартный протокол.
### 4.4 Microsoft: AutoGen и Memory Banks как агенты
В экосистеме AutoGen 0.4+ и смежных проектах (например, Magentic-One) память часто моделируется как активный агент:
- `MemoryAgent` подписывается на события системы, сохраняет эпизоды и запускает экстракцию фактов.
- Реализуются банки: Episodic, Semantic, Short-Term (кольцевой буфер), Procedural.
- Используется паттерн Whiteboard: агенты читают/пишут в общее состояние через Pub/Sub. Векторный поиск реализуется через `sqlite-vec` или Azure AI Search.
### 4.5 LangChain / LangGraph
`LangGraph` явно моделирует граф состояний (`StateGraph`). Состояние сохраняется между шагами через checkpointing (SQLite/Postgres). Библиотека `LangMem` автоматически извлекает релевантные воспоминания из Store, добавляет их в состояние, а после вызова агента сохраняет новые факты. Процедурная память управляется через динамические system prompt'ы и инструменты.
### 4.6 Letta (бывшая MemGPT)
Letta строит агентную среду как ОС памяти:
- **Core Memory (RAM):** блоки персонажа и пользователя фиксированной длины. Агент может читать и перезаписывать их через `core_memory_append/replace`.
- **Recall Memory (Cache):** очередь последних событий.
- **Archival Memory (Cold Storage):** бесконечная векторная база с поиском по релевантности.
Агент управляет памятью программно, вызывая инструменты памяти как обычные функции. Это максимальная степень экстернализации: LLM сама решает, какое состояние ей нужно для следующего шага.
## 5. Механика внешней рекуррентности в действии: сквозной пример
**Задача:** агент поддержки помогает пользователю, который периодически возвращается с новыми вопросами. Агент должен помнить контекст из прошлых сессий.
**Сессия 1 (день 1).** Пользователь: «У меня проблема с установкой Python-пакета».
- Retrieve: память пуста. Рабочая память = system_prompt + запрос.
- Inject → LLM вызывает `web_search`.
- Write: эпизоды (user_msg, tool_call, tool_result, agent_response) сохранены.
- Consolidate: извлекаются факты: «Пользователь на Windows 11, Python 3.11», «Ошибка при установке пакета X». Фактоиды сохранены в семантическую память.
**Сессия 2 (день 14).** Пользователь: «Привет, у меня снова проблема с тем же самым скриптом».
- Retrieve: векторный поиск находит фактоиды и фрагменты прошлой сессии (косинусное сходство ~0.88).
- Inject: в промпт добавляется контекст из памяти.
- LLM отвечает не с нуля: «В прошлый раз мы решали проблему с пакетом X на Windows 11. Эта ошибка всё ещё возникает?»
- Write: новый эпизод добавляется. Связь между сессиями поддерживается через семантические фактоиды.
Рекуррентность проявляется в том, что состояние переходит из сессии 1 в сессию 2, хотя между ними прошло две недели, и никакое контекстное окно не могло бы это удержать.
## 6. Ограничения и риски архитектуры MSP
Внешняя рекуррентность не бесплатна. При проектировании MSP-систем необходимо учитывать:
- **Latency и стоимость:** каждый шаг требует вычисления эмбеддингов, векторного поиска и вызова LLM. Консолидация добавляет фоновые inference-запросы.
- **Дрейф консолидации:** LLM-экстрактор может сжимать нюансы, терять контекстные зависимости или галлюцинировать факты. Требуется валидация confidence-скоринга и периодическая перепроверка.
- **Retrieval misses:** косинусное сходство ≠ семантическая релевантность в сложных, многозначных или ироничных контекстах. Гибридный поиск и reranking частично решают проблему, но не устраняют её полностью.
- **Безопасность и изоляция:** внешняя память становится поверхностью атаки. Инъекции через результаты инструментов, утечка PII, несанкционированная модификация фактоидов или prompt leakage требуют отдельного контура валидации, шифрования и RBAC.
- **Масштабирование состояния:** при десятках тысяч сессий векторные базы требуют шардирования, TTL-политик и стратегий eviction. Без этого стоимость хранения и поиска растёт нелинейно.
MSP оправдан там, где ценность долгосрочного контекста, персонализации и непрерывного обучения превышает накладные расходы на его поддержку. Для stateless-чатов, коротких сессий или задач с жёстким SLA по задержкам классический контекстный стек часто остаётся оптимальным выбором.
## 7. Заключение
Transformer не запоминает. Он вычисляет. Но если вынести состояние наружу, структурировать его в эпизоды, факты и процедуры, а затем замкнуть цикл Retrieve → Inject → Write → Consolidate, статическая функция превращается в систему, способную накапливать опыт, адаптироваться и «думать» во времени.
MSP — это не замена архитектуры моделей. Это инженерный мост между статичной математикой внимания и динамикой реального мира. Qwen‑Agent, LangGraph, Letta, MCP и облачные SDK уже реализуют этот паттерн в production. Вопрос больше не в том, «возможна ли внешняя рекуррентность», а в том, как грамотно управлять её стоимостью, точностью и безопасностью.
Именно здесь заканчивается эпоха «промпт-инжиниринга» и начинается эпоха инженерии состояний.
---
Рекомендуемые источники для углубления
- Ethayarajh, K. (2019). *How Contextual are Contextualized Word Representations?* (метрики анизотропии)
- Ansuini et al. (2019). *Intrinsic Dimensionality of Deep Learning Models*
- Aghajanyan et al. (2021). *Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning*
- Letta (MemGPT) Architecture Paper & Docs: `letta.com/docs`
- Model Context Protocol Specification: `modelcontextprotocol.io`
- LangGraph & LangMem Documentation: `python.langchain.com`
