SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-21

Типы памяти агента: классификация и стоимость хранения

Разбираем семантическую, эпизодическую и процедурную память агентов. Сравниваем затраты на хранение и повторное встраивание данных для каждого типа памяти при работе на VPS.

Три типа памяти агента

Типы памяти агента делятся на три категории, и каждая из них по-разному влияет на затраты на оборудование: семантическая память хранит факты, эпизодическая память хранит события, а процедурная память хранит инструкции по выполнению задач. В таблице ниже дано определение каждого типа с примером для сервера. Всё, что следует далее, — это обычно не документируемая часть: стоимость хранения и стоимость восстановления каждого типа памяти.

ChartThe three agent memory types, with one server example of each
The data behind this chart
[
  {
    "label": "Semantic",
    "what_it_holds": "Facts the agent should treat as currently true",
    "server_example": "The database listens on 10.8.0.4:5432 and the nightly dump runs at 03:15 UTC"
  },
  {
    "label": "Episodic",
    "what_it_holds": "A record of one past event or session",
    "server_example": "On 2026-08-11 the deploy failed because the disk was full, and rotating logs fixed it"
  },
  {
    "label": "Procedural",
    "what_it_holds": "How to carry out a task, as steps the agent can run",
    "server_example": "The restore runbook: stop the service, load the dump, run migrations, start the service"
  }
]

Эти названия заимствованы из психологии человека, и это заимствование носит условный характер. Такое разделение оправдано практическими соображениями: эти три вида памяти имеют разные объемы и разные способы восстановления, поэтому их объединение в одном векторном хранилище снижает эффективность работы каждого из них.

Семантическая память имеет небольшой объем, и вам потребуется редактировать ее вручную

Несколько сотен фактов о ваших серверах занимают всего несколько десятков килобайт текста. Проблема не в хранении, а в исправлении данных. Ошибочный факт в семантической памяти будет присутствовать в каждом ответе агента, поэтому система должна позволять находить факт по имени, изменять его и гарантировать, что старое значение удалено.

Это указывает на использование хранилища с ключами: таблицы Postgres с первичным ключом или каталога небольших файлов markdown в git. Оба варианта позволяют выполнить один запрос, увидеть значение и отредактировать его на месте. Поиск по сходству (similarity search) не дает такой возможности, так как вы извлекаете данные по подобию, а не по ключу. Задача «изменить порт базы данных» превращается в «найти каждый фрагмент, где упоминается порт базы данных», и вы не можете быть уверены, что нашли их все. Храните факты по ключам. Выполняйте их эмбеддинг, если вам также нужен нечеткий поиск, но считайте копию с ключом единственным источником истины.

Устаревшие факты не сообщают о себе сами. Порт меняется, а запись остается, поэтому агент продолжает отвечать числом, которое было верным в июне. Политика устаревания и очистки памяти агента — это вторая часть данной страницы, и ее гораздо проще спроектировать, пока таблица еще невелика.

Почему эпизодическая память растет бесконечно

Эпизодическая память — это лог, а логи имеют свойство расти. Каждый сеанс, каждый вызов инструмента и каждая неудачная команда являются потенциальным эпизодом. Агент, записывающий по одной строке за каждый шаг, за месяц создаст гораздо больше записей, чем кто-либо сможет прочитать. Дисковое пространство — не единственный расходный ресурс: каждый добавленный в индекс эпизод увеличивает объем данных, которые необходимо просматривать при поиске.

Определите правила хранения данных в день создания таблицы, пока удаление записей не требует затрат. Два вопроса помогут решить большинство проблем. Во-первых, что стоит записывать: краткое содержание сеанса обычно стоит, а полный вывод команды ls -la — как правило, нет. Во-вторых, сколько времени должен храниться каждый тип эпизодов: например, необработанные эпизоды — 30 дней, а сводки сеансов — год.

Добавьте в каждую строку эпизода метку времени created_at и столбец source. Без created_at вы не сможете удалять данные по возрасту. Без source вы не сможете удалить все записи, поступившие из одного некорректного источника, что критически важно в тот день, когда выяснится, что веб-страница или тикет записывали инструкции прямо в память.

DELETE FROM episodes WHERE created_at < now() - interval '30 days';

Запускайте это по таймеру systemd, а затем следите за тем, как меняется количество строк и размер таблицы. Политика хранения, которую никто не исполняет, — это просто комментарий в коде.

psql -d agentmem -c "SELECT count(*) FROM episodes;"
psql -d agentmem -c "SELECT pg_size_pretty(pg_total_relation_size('episodes'));"

Процедурная память должна храниться в репозитории

Процедурная память — это то, как агент выполняет задачу: shell-скрипт, файл навыков или runbook с пронумерованными шагами. Это код, а код должен находиться там, где ему положено: в git-репозитории с поддержкой ревью, версионированием и читаемыми diff.

Если хранить runbook в виде встроенных фрагментов, вы получите лишь приблизительную копию. Поиск возвращает фрагменты с наивысшим рейтингом, поэтому агент может выполнить шаг 2 и шаг 5, в то время как шаг 3 не будет найден, и ничто не зафиксирует, какая версия процедуры была запущена. В git git log отвечает на оба этих вопроса. Стоимость хранения при этом практически равна нулю, что является еще одной причиной не платить за это по ценам векторных баз данных.

Реальная стоимость векторного представления на диске

ChartVector storage in pgvector, at 4 bytes per dimension plus an 8 byte header
The data behind this chart
[
  {
    "label": "bge-small-en-v1.5 (384 dims)",
    "bytes_per_vector": 1544,
    "mib_per_100k_rows": 147.2
  },
  {
    "label": "bge-base-en-v1.5 (768 dims)",
    "bytes_per_vector": 3080,
    "mib_per_100k_rows": 293.7
  },
  {
    "label": "bge-large-en-v1.5 (1024 dims)",
    "bytes_per_vector": 4104,
    "mib_per_100k_rows": 391.4
  },
  {
    "label": "text-embedding-3-small (1536 dims)",
    "bytes_per_vector": 6152,
    "mib_per_100k_rows": 586.7
  },
  {
    "label": "text-embedding-3-large (3072 dims)",
    "bytes_per_vector": 12296,
    "mib_per_100k_rows": 1172.6
  }
]

pgvector хранит vector как 4 байта на каждое измерение плюс 8 байт заголовка, поэтому расчет фиксирован, и его можно выполнить до загрузки данных. Один вектор размерностью 384 занимает 1544 байт, что делает 100,000 фрагментов равными 147.2 МиБ векторных данных. Тот же корпус с размерностью 3,072 занимает 1172.6 МиБ при 12296 байт на строку. Текст тот же, а объем хранилища почти в восемь раз больше.

Это только векторный столбец. Текст фрагмента, первичный ключ, накладные расходы на строку и индекс добавляются сверху, причем про индекс часто забывают. HNSW (hierarchical navigable small world, графовый индекс, который строит pgvector) хранит собственную копию векторов, которые он связывает, поэтому индексированное хранилище будет занимать значительно больше, чем удвоенные значения, приведенные выше. Измеряйте свои показатели, а не гадайте.

SELECT pg_size_pretty(pg_total_relation_size('memories')) AS total,
       pg_size_pretty(pg_relation_size('memories_embedding_idx')) AS idx;

RAM определяет, будет ли поиск быстрым, так как граф быстро обходится только тогда, когда он находится в оперативной памяти. Когда индекс становится больше объема памяти, который может выделить Postgres, поиск начинает считываться с диска, и задержка возрастает. У процесса построения есть свой лимит, maintenance_work_mem, и когда граф перерастает его, процесс сообщает об этом и замедляется:

NOTICE:  hnsw graph no longer fits into maintenance_work_mem after 61440 tuples
HINT:  Increase maintenance_work_mem to speed up builds.

Есть два способа уменьшить размер одного и того же корпуса. Выберите модель поменьше: 384 измерения стоят в четыре раза меньше, чем 1,536, а для поиска по собственным заметкам разница в точности часто незначительна. Либо используйте хранение с половинной точностью: тип halfvec занимает 2 байта на измерение плюс те же 8 байт заголовка, что почти вдвое сокращает объем столбца и его индекса.

Перед выбором модели стоит учесть одно ограничение. По состоянию на август 2026 года столбец vector может быть проиндексирован при размерности до 2,000, поэтому вектор размерностью 3,072 будет принят столбцом, но отклонен индексом:

ERROR:  column cannot have more than 2000 dimensions for hnsw index

Индексы halfvec поддерживают до 4,000 измерений, поэтому стандартное решение — индексировать приведение типа:

CREATE INDEX ON memories USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);

Когда pgvector эффективнее отдельного сервиса памяти

Если на сервере уже работает Postgres, векторы — это один пакет и одна инструкция.

psql -V
sudo apt install postgresql-16-pgvector
CREATE EXTENSION vector;

Число в имени пакета соответствует мажорной версии Postgres, например 16 для Ubuntu 24.04, поэтому ознакомьтесь с psql -V перед вводом команды.

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

Переходите на выделенный сервис памяти, если выполняется одно из следующих условий. Поисковая нагрузка конкурирует с вашим приложением и требует отдельной машины. Несколько агентов на разных хостах используют общую память. Или вам необходима логика извлечения и дедупликации, которую предоставляет готовый продукт, что является аргументом в пользу самостоятельно развернутого сервера памяти Mem0. Для одного агента и корпуса данных объемом в несколько миллионов чанков pgvector на уже работающем сервере проще в обслуживании и надежнее. Выбор самого движка и требования каждого из них к оперативной памяти описаны в запуске векторной базы данных на VPS.

Стоимость повторного встраивания (re-embedding) при смене модели

Векторы, полученные с помощью разных моделей, несовместимы. Вы не можете встраивать новые данные с помощью новой модели, оставляя старые записи без изменений. Смешанная таблица выдаст бессмысленные результаты, так как расстояние, вычисленное между двумя разными системами координат, не имеет физического смысла. Смена модели означает необходимость повторного встраивания (re-embedding) всего корпуса данных.

Эти затраты состоят из четырех частей: токены (оплата API или время CPU/GPU на вашем собственном оборудовании), время выполнения процесса, место на диске для хранения обоих столбцов одновременно во время заполнения, а также перестроение индекса в конце. Безопасный порядок действий: добавить новый столбец, заполнить его порциями, переключить запросы на него, а затем удалить старый столбец и его индекс.

Измеряйте скорость на своем оборудовании, а не полагайтесь на опубликованные цифры, так как встраивание только на CPU на небольшом VPS работает значительно медленнее, чем та же модель на GPU. Замерьте время для одного репрезентативного фрагмента, а затем умножьте на общий объем корпуса.

ollama pull nomic-embed-text
time curl -s http://localhost:11434/api/embed \
  -d '{"model": "nomic-embed-text", "input": "one representative chunk of your corpus"}' > /dev/null

Локальная модель встраивания также размещает свои веса на том же диске, что и хранилище данных, а статья где Ollama хранит загруженные модели объясняет, куда расходуется это место.

Одно требование делает всё это возможным: храните исходный текст рядом с каждым вектором. Хранилище, содержащее только векторы, невозможно подвергнуть повторному встраиванию, так как не останется данных для подачи в новую модель. Если вы не можете ответить на вопрос «какой текст породил эту строку», ваш путь миграции — это полная пересборка из первоисточника, где эти тексты хранились изначально.

На что обращать внимание при заполнении памяти

По мере заполнения хранилища меняется не только стоимость. Старые факты теряют актуальность, а прошлые эпизоды вытесняют полезные результаты — это снова возвращает нас к проблеме очистки. Хранилище памяти также является доступным для записи входом, определяющим будущее поведение агента, поэтому любой источник, имеющий право записи, может впоследствии управлять действиями агента. Если в память попадает текст с веб-страниц или из тикетов, ознакомьтесь с разделом как работает отравление памяти агента, прежде чем расширять список источников, имеющих право записи. Объем извлекаемых данных также напрямую влияет на расход токенов при каждом запросе, и именно с этого начинается обеспечение предсказуемости расходов агента.

FAQ

Нужна ли векторная база данных для памяти агента?

Для фактов — нет. Семантическая память невелика, и вам нужно иметь возможность корректировать её по имени. С этой задачей лучше справляется таблица с ключами или каталог файлов в формате markdown в git: вы можете просмотреть конкретное значение и отредактировать его. Векторные представления (embeddings) оправдывают затраты, когда поиск по смыслу выполняется в корпусе данных, который слишком велик для простого перечисления; обычно это эпизодическая память и документы. Если вы уже используете Postgres, CREATE EXTENSION vector позволяет решить эту задачу без добавления еще одного сервиса для обслуживания.

Сколько дискового пространства потребуется для хранилища памяти агента?

Объем векторов предсказуем: 4 байта на измерение плюс 8 байт заголовка в pgvector. При 768 измерениях это 293.7 МиБ на 100 000 строк, а при 384 измерениях — 147.2 МиБ. Добавьте к этому текст фрагментов, накладные расходы на хранение строк и индекс HNSW, который хранит собственную копию векторов. Закладывайте как минимум двойной объем от размера векторов и измеряйте реальные показатели с помощью pg_total_relation_size.

Где должна храниться процедурная память?

В репозитории git в виде скриптов или файлов навыков, которые агент запускает напрямую. Процедура требует точного воспроизведения и истории версий, а поиск по сходству не обеспечивает ни того, ни другого. При поиске по фрагментам руководства вы получите наиболее подходящие части, что может привести к ситуации, когда шаг 2 и шаг 5 найдены, а шаг 3 отсутствует; при этом не будет зафиксировано, какая именно версия была выполнена.

Какова стоимость смены модели эмбеддингов?

Полная переиндексация корпуса, так как векторы, полученные с помощью разных моделей, нельзя сравнивать между собой. Учитывайте затраты на токены или время работы GPU, место на диске для одновременного хранения старых и новых столбцов, а также время на перестроение индекса. Добавьте новый столбец, выполните заполнение порциями, переключите запросы, а затем удалите старый столбец. Все это возможно только при условии, что исходный текст сохранен рядом с каждым вектором.

#agent-memory#semantic-memory#episodic-memory#pgvector#storage