Память LLM: мой подход

Память LLM: мой подход

viktorprogger

Disclaimer: описание составлено спонтанно и немного сумбурно, за что прошу прощения. Если будет интересно - перепишу более корректно и полно.


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

Начну с самого интересного: что она принесет.

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

Само собой, это если я смогу довести ее до полностью рабочего состояния 😄

А теперь - по порядку.

Для исторической справки - вот основные подходы к созданию памяти LLM

Часть скучная и нудная, за мякоткой стоит пролистать дальше.

1. In-memory, он же - "контекстное окно". Весь диалог пересылается LLM при каждом новом сообщении. Это стандарт индустрии, присутствует начиная с самых примитивных версий Chatgpt и до новейших harness агентов.

2. RAG. Можно взять огромный документ, разбить его на небольшие кусочки текста, по каждому кусочку построить числовой вектор, отражающий направленность смысла этой части, и при запросе пользователя сравнивать вектор запроса с векторами документов. Так мы получаем из БД части текста, максимально близкие по смыслу к вопросу пользователя. Но это не память в буквальном понимании этого слова. Скорее доступ к библиотеке, но с кучей оговорок и условностей. 

3. Текстовый поиск по файлам (привет, OpenClaw) и БД (привет, Hermes). Мне кажется очевидным, что с ростом объема данных у такой памяти начнется деменция. Но надо подождать ещё как минимум полгода, прежде чем эта проблема станет очевидной в массах.

4. memGPT. Интересный концепт, но во главе угла стоит LLM: она принимает все решения: когда записать в память, когда что оттуда достать, какой слой памяти использовать. Это даёт низкую точность, низкую скорость и высокую стоимость.

5. Менее популярные опенсорс-проекты. Основное отличие всего, что я видел - снова все строится вокруг LLM, где она должна принимать решения. Самое интересное на первый взгляд - это мемзеро (mem-0): они используют связку из KV-хранилища, векторной БД и графовой БД. Но, как оказалось, у них есть та же болячка: они просто собирают данные и на авось скармливают LLM, получая на выходе просто набор текста, векторов и примитивный граф связей. Хотя разработчики под эту систему даже денег на YCombinator подняли.

6. Самое неинтересное - продукты за закрытыми дверями: openai, google и пр. Никто не знает, что и как они внедряют, но вроде что-то делают.


Итак, я пришел к выводу, что можно и лучше, и в опенсорсе. Но что же именно?

Главная идея - что память агента должна работать схожим с человеческой образом. То есть:

  • Должна быть активна всегда: перед получением ответа надо достать воспоминания, а все, что попало на вход от пользователей - запомнить. Это не опция и не выбор.
  • Выстраивать ассоциативные связи.
  • Со временем и количеством должна помогать лучше, а не хуже.
  • Понимать текущий контекст как в примитивных случаях (связный диалог на одну тему), так и в комплексных (10+ участников, несколько параллельных тем обсуждения, частые отсылки местоимениями или по временным меткам, включая "когда произошло Х").

Для этого я реализовал несколько подходов, схожих с памятью человека:

  • понимание текущего контекста по одному сообщению и метаданным
  • затухание неиспользуемых связей с усилением активных
  • дедупликация сущностей и их разделение (несколько копий одной сущности с разными названиями vs несколько разных сущностей с одним названием)
  • разрешение анафор ("оно того стоило?")
  • фоновая обработка данных (аналог сна у человека: более глубокий анализ накопленного за день)

Возможно, есть что-то ещё, что я не вспомнил сразу.


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

Поэтому ещё один плюс - приватность из коробки: LLM не получит воспоминания, недоступные кому-то из присутствующих в чате. Ее можно будет использовать и в корпоративном сегменте, и у себя дома.


Сложности

  • В первую очередь - внедрение. Агент, использующий такую память, должен уметь с ней работать: LLM учили, что она всегда находится в контексте диалога с пользователем. Другие сценарии использования ее "ломают". Но, допустим, как запущу память - так и агента соответствующего сделаю 😁 Это куда проще задача. Уже в каком-то смысле начата.
  • Не получится забубенить тонну информации. Это не RAG, это память для ассистента а-ля человеческая. Для поиска по книгам и документам надо использовать соответствующий инструмент. То же и про вычисление по структурным данным (таблицы, счета, программный код и т.п.).
  • Неизвестно, как она поведет себя на объемах данных в миллионы сообщений и больше. Я начал писать тестовый датасет чата на пару тысяч сообщений, и уверен, что с ним проблем не возникнет: только найдутся баги, которые можно исправить. Это даёт гарантию на работу с десятками тысяч сообщений и хорошую уверенность с сотнями тысяч. Что же будет дальше - увидим только на практике. В какой-то момент нужно будет включать шардирование. А еще наберут огромный вес "божественные узлы": например, в нашем чате "программирование" и PHP будут иметь невероятное количество связей, но грузить все эти ассоциации на каждый запрос бессмысленно. На небольших объемах отфильтровать лишнее намного проще.
  • Система сильно полагается на временные связи. Это значит, что для нормальной обработки последовательного текста все равно надо подавать сообщения по одному, при желании проставив явные временные метки.
  • Пока что она медленная. Когда основные датасеты будут стабильно проходить - займусь оптимизацией, и смогу сильно сократить как минимум "горячий путь" (когда сообщение приходит прямо в чате; "холодный" - это постобработка накопленных данных)

Чем это решение лучше других

Описанное полагается в первую очередь на математику: считаем косинусное сходство и центроиды векторов, увеличиваем и уменьшаем веса графовых связей, запоминаем не "важное" по мнению LLM, а повторяемое. LLM тоже используется: для переводов (я сначала все перевожу на английский для унификации), извлечения сущностей (NER) и определения интента (есть смысл в сообщении или нет). Плюс более сложные сценарии в "ночном режиме" тоже требуют принятия сложных решений. Сейчас я для всего беру gpt-4o-mini, а потом можно будет в некоторых сценариях использовать специализированные быстрые решения (например, GLiNER).

Что дальше?

  1. Сейчас я пишу большой датасет в виде лога чата, растянутого на 2-3 года и состоящего из пары тысяч сообщений. Это позволит проверить память абсолютно во всех возможных сценариях. Когда он будет целиком проходить все тесты - можно будет сказать, что эта память на 100% рабочая.
  2. Написание первых агентов. Разные задачи требуют разного агентского окружения. Я бы даже сказал, разные субличности. Поэтому 1 агент будет просто отвечать в чате, другой - кодить, третий - разбирать файлы и строить аналитические отчеты. И у всех у них будет единая память и единая базовая личность. Под нее я пока хочу сделать домовенка Кузю, кстати 😄

Report Page