«Не вижу прайс», "Нет исходных данных" - и все это в одном чате. Или зачем я сделал двойную память для своего ИИ-ассистента.

«Не вижу прайс», "Нет исходных данных" - и все это в одном чате. Или зачем я сделал двойную память для своего ИИ-ассистента.

Стандартная схема обещает простую победу: подключаем локальную #llm , вешаем векторную базу (ChromaDB/Pinecone), добавляем #rag — и получаем «умного» #ai ассистента. На практике оказывается, что один только долгосрочный контекст не спасает внутри длинного диалога.

Пользователь задаёт уточняющий вопрос на 45-м сообщении, а #бот отвечает «не вижу сумму» или начинает галлюцинировать.

Причина банальна: лимит токенов обрезает историю, а векторный поиск теряет последовательность.

Я потратил пару месяцев на отладку и пришёл к архитектурному решению, которое реально работает в проде: разделил память на два независимых контура. Оперативная "STM" держит нить диалога, долгосрочная "MNEMOS" - про нее я уже писал ранее накапливает опыт между сессиями.

Вместе они убирают 90% проблем с потерей контекста и снижают количество правок вручную.

Почему одной памяти недостаточно

Долгосрочная база знаний отлично справляется с задачей «учиться на всех диалогах». Но внутри одного треда из 50 и более сообщений возникает классическая проблема character limit:

- Прайс-лист загружается в начале диалога, но на 20-м сообщении выпадает из окна контекста

- Векторная БД ищет смысл, а не порядок. Ассистент путается в датах и позициях.

- Результат: «какой курс?», «опишите подробнее», «не вижу сумму». Это не баги модели, это архитектурный пробел.

MNEMOS про это не знает — он оперирует Q&A-парами и тематическими коллекциями. Для оперативной памяти внутри треда нужна отдельная система. Я назвал её STM.

Как устроена двойная архитектура

Решение строится на трёх слоях оперативной памяти, которые собираются в единый промпт перед каждым вызовом LLM:

Слой 1: Якоря вместо автосохранений

Якорь — это короткая заметка, которая всегда висит в system_prompt. Она содержит текущую тему диалога и ключевые данные. Система ставит их автоматически:

- каждые ~3000 символов (страховка);

- при резкой смене темы (основной триггер);

- при обновлении данных (после расчётов или поиска).

Это не просто метки, а save points. Если #контекст потеряется из-за лимита, STM найдёт ближайший якорь и восстановит нить. Чем чаще якоря — тем меньше потеря информации.

Слой 2: Порядок важнее семантики

Для истории диалога важна именно хронология, а не смысловое сходство. Поэтому я использую прямой SQL-запрос к таблицеchat_history: берём последние N строк, сканируем назад и обрезаем ровно по лимиту токенов. Это гарантирует, что пользователь видит логичную последовательность без «провалов» в середине треда.

Слой 3: Интеллектуальный поиск внутри треда

Когда пользователю нужно уточнить данные, которые выпали из окна, LLM не гадает. Она пишет маркер SEARCH_HISTORY: ЛДСП цена.

Парсер перехватывает его, делает мгновенный #sql LIKE-поиск по всей истории диалога и инжектит найденные строки обратно в промпт для второго прохода модели.

Почему SQL, а не векторы?Для таблицы на 100–500 строк запрос выполняется за 1–5 мс. Никакого оверхеда индексов, никакой потери точности. Полностью покрывает потребность в поиске по текущему треду.

Чем это отличается от MemGPT и Letta

Аналоги оперируют единой моделью памяти (core/archival/recall) с ручным управлением жизненным циклом. Мой подход строже:

-Разделение ответственности:STM очищается при смене треда (контекст месяца давности не нужен в новом чате). MNEMOS живёт вечно.

-Авто-размещение якорей: Не требует ручной настройки agent'а. Триггеры работают по длине, смене темы и обновлению данных.

Что это даёт клиентам и бизнесу

Переход на двойную память дал измеримый эффект в продакшене:

-Снижение доли «человек в контуре»: Ассистент сам достает данные из истории, не спрашивает повторных уточнений и не галлюцинирует на цифрах.

-Стабильность сложных расчётов: Прайс-листы, курсы валют и спецификации теперь фиксируются в якорях и сохраняются до конца сессии.

-Экономия времени поддержки: Цикл самообучения (Sufler → fail → ЛИКБЕЗ) сокращает время на дообучение моделей. Ошибки не повторяются, потому что система хранит антипаттерны и подтягивает верные примеры.

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

Архитектура включает модули

microgoals.py, chat_history.py, experience_bank/ ,research.py и кастомный ассемблер промптов.

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

Полный разбор архитектуры, схемы взаимодействия доступны в моей серии статей: 3.STM + МНЕМОС: двойная память AI-ассистента

Если вы уже экспериментировали с dual-memory в проде или сталкивались с проблемами очистки состояния — делитесь опытом в комментариях.

Какие триггеры для якорей работали стабильнее всего на ваших проектах?

Где SQL LIKE начал тормозить, а где векторы оказались избыточны?