SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-28

Self-hosting mem0: установка на VPS и требования к RAM

Узнайте, как развернуть mem0 на собственном VPS. Инструкция включает настройку Docker Compose, привязку к localhost, использование TLS и интеграцию с Ollama. Реальные затраты памяти.

Реальные затраты оперативной памяти при self-hosting mem0 на VPS

Self-hosting mem0 подразумевает запуск трех контейнеров: сервера FastAPI для работы с памятью, базы данных Postgres с расширением pgvector и панели управления на Next.js. mem0 — это уровень памяти для агентов. Вы отправляете в него диалог, языковая модель извлекает из него устойчивые факты, которые сохраняются в виде векторов, чтобы при последующем запросе можно было получить релевантные данные.

Закладывайте примерно 1 GB оперативной памяти для трех контейнеров и от 3 до 4 GB дискового пространства после сборки образов. VPS с 2 GB RAM комфортно справляется с этой задачей, если языковая модель работает на другом узле. Если модель запущена на том же сервере через Ollama, она потребляет основные ресурсы: модель с 8B параметров, квантованная до 4 бит, требует около 6 GB RAM, поэтому для полностью локальной сборки потребуется от 8 GB.

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

docker compose ps
docker stats --no-stream
docker system df -v

docker stats выводит объем резидентной памяти для каждого контейнера. docker system df -v показывает объем дискового пространства, занимаемый каждым образом и томом.

Стабильное состояние — это не пиковая нагрузка. docker compose up -d --build компилирует панель управления Next.js, и этот процесс сборки на Node является самым ресурсоемким этапом всей установки. На VPS с 1 GB RAM механизм OOM-killer (out-of-memory killer) ядра принудительно завершает процесс, и сборка заканчивается ошибкой exit code 137. Подтвердите причину, прежде чем искать ошибку в Docker:

dmesg -T | grep -i "killed process"

Если сервер кажется избыточным решением для ваших задач, существуют более компактные варианты. локальное хранилище памяти агента без использования сервера и память, работающая внутри самого Claude Code позволяют обойтись без базы данных. Возвращайтесь к этому руководству, когда нескольким агентам или нескольким машинам потребуется доступ к одним и тем же данным памяти.

Нужен ли Neo4j для графовой памяти mem0?

Нет. Если в руководстве указано добавить контейнер Neo4j, значит, это руководство устарело.

Ранее графовая память в mem0 подразумевала использование внешней графовой базы данных, настроенной через ключ graph_store с параметром enable_graph, установленным в true. Новый алгоритм памяти, выпущенный в апреле 2026, исключил оба этих ключа из SDK с открытым исходным кодом. Извлечение сущностей теперь выполняется в рамках стандартного пути добавления данных, а сами сущности записываются во вторую коллекцию pgvector, название которой совпадает с основной с добавлением суффикса _entities. Процедура миграции не требуется. Встроенная связка сущностей начинает работать при следующем вызове добавления.

Отказ от графового хранилища позволяет не запускать JVM-контейнер, экономя его heap и несколько сотен мегабайт образа. На VPS с 2 GB оперативной памяти это определяет разницу между нормальной работой и уходом в swap.

Ниже перечислены возможности, от которых вы отказываетесь. Результаты поиска ранее содержали поле relations, в котором перечислялись ребра между сущностями. Это поле удалено. Совпадения сущностей теперь повышают позицию памяти в общем рейтинге, при этом структура, по которой можно было бы перемещаться, отсутствует. Если ваше приложение использовало эти связи, mem0 больше их не хранит; в таком случае вам потребуется собственная графовая база данных вне mem0, наполняемая вашим кодом.

Файл compose в репозитории предназначен для разработки

server/docker-compose.yaml объявляет name: mem0-dev, и это именно то, что он делает. Прочитайте его перед запуском, так как пять моментов в нем не подходят для сервера.

  • Он выполняет сборку из server/dev.Dockerfile и монтирует вашу рабочую копию поверх образа с помощью .:/app, поэтому контейнер запускает то, что находится в этой директории, а не то, что вы собрали.
  • Его команда — rm -rf /app/packages && pip install -q --force-reinstall --no-deps mem0ai && alembic upgrade head && uvicorn main:app --reload. Она переустанавливает mem0ai из PyPI при каждом запуске, поэтому версия, которую использует ваш сервер, может измениться во время перезагрузки, которую вы не планировали как обновление.
  • Тот же шаг с pip означает, что перезагрузка при отсутствии исходящего сетевого соединения завершится ошибкой еще до запуска uvicorn. Ваш сервер памяти окажется недоступен, так как PyPI был недосягаем.
  • --reload запускает механизм отслеживания файлов uvicorn. Он нужен для перезапуска процесса при редактировании кода, но в продакшене он лишь потребляет память и создает лишний процесс без какой-либо пользы. Продакшн-образ Dockerfile также содержит --reload в своем CMD, поэтому вы в любом случае переопределяете команду.
  • Опубликованные порты — "8888:8000", "8432:5432" и "3000:3000". Опубликованный порт без указания адреса привязывается к 0.0.0.0, поэтому Postgres начинает отвечать всему интернету на порту 8432 сразу после запуска стека.

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

Файл compose для реального сервера

Работайте внутри server/, сохраните init-db.sh на месте и замените docker-compose.yaml на следующее.

name: mem0

services:
  mem0:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    env_file: .env
    ports:
      - "127.0.0.1:8888:8000"
    networks: [mem0_network]
    volumes:
      - mem0_history:/app/history
    depends_on:
      postgres:
        condition: service_healthy
    command: >
      sh -c "alembic upgrade head &&
             uvicorn main:app --host 0.0.0.0 --port 8000"
    environment:
      - PYTHONUNBUFFERED=1
      - DASHBOARD_URL=https://mem0.example.com
      - APP_DB_NAME=mem0_app
      - AUTH_DISABLED=false
      - MEM0_TELEMETRY=false

  postgres:
    image: pgvector/pgvector:pg17
    restart: unless-stopped
    shm_size: "128mb"
    networks: [mem0_network]
    environment:
      - POSTGRES_USER=${POSTGRES_USER:-postgres}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -q -U ${POSTGRES_USER:-postgres}"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - postgres_db:/var/lib/postgresql/data
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh

  mem0-dashboard:
    build: ./dashboard
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    networks: [mem0_network]
    environment:
      - NEXT_PUBLIC_API_URL=https://mem0.example.com
      - API_INTERNAL_URL=http://mem0:8000
    depends_on:
      mem0:
        condition: service_started

volumes:
  postgres_db:
  mem0_history:

networks:
  mem0_network:
    driver: bridge

Здесь важны пять изменений, и у каждого есть причина.

Каждая запись ports начинается с 127.0.0.1, поэтому ядро принимает эти соединения только с самого сервера. Весь внешний трафик поступает через reverse proxy, который является единственным компонентом, хранящим сертификат.

У Postgres вообще нет блока ports. Контейнер mem0 обращается к нему по mem0_network через имя сервиса, поэтому публикация порта 8432 ничего не дает, кроме открытого порта. Используйте docker compose exec postgres psql -U postgres, если вам нужен доступ к оболочке.

История перемещается из bind mount ./history в именованный том. Bind mount привязывает данные к конкретному пути и uid на хосте, в то время как именованный том — это объект, который Docker может копировать и переносить. Именованные тома против bind mounts описывает, когда лучше использовать каждый из них.

Команда исключает --reload и оставляет alembic upgrade head. Обязательно сохраните этот шаг миграции. Без него приложение запустится с базой данных без таблиц, и каждый запрос будет завершаться ошибкой при первом же обращении.

NEXT_PUBLIC_API_URL — это URL, к которому обращается ваш браузер, поэтому он должен быть публичным HTTPS-адресом, а не http://mem0:8000. Next.js встраивает каждое значение NEXT_PUBLIC_ во время сборки, поэтому для его изменения требуется docker compose up -d --build mem0-dashboard. Обычный перезапуск сохранит старое значение, «запеченное» в JavaScript, и панель управления будет обращаться к неверному хосту.

Секреты хранятся в .env, и .env не должен попадать в интернет

cd server
cp .env.example .env
openssl rand -hex 32    # paste into JWT_SECRET
openssl rand -hex 32    # paste into ADMIN_API_KEY
chmod 600 .env

Установите POSTGRES_PASSWORD, JWT_SECRET и ADMIN_API_KEY. Оставьте AUTH_DISABLED=false. Название флага точно описывает его действие: при включении сервер передает все данные из своей памяти любому, кто имеет доступ к порту. Установите MEM0_TELEMETRY=false, если вы не хотите, чтобы событие онбординга отправлялось вышестоящему узлу.

ADMIN_API_KEY сравнивается с заголовком X-API-Key с помощью secrets.compare_digest, и совпадение позволяет пропустить все обращения к базе данных. Это корневые учетные данные для всего API. Относитесь к ним соответствующим образом: не сохраняйте их в истории оболочки, не добавляйте в git и не вставляйте в командную строку. Статьи Файлы окружения Compose и утечки секретов из них и как не допустить попадания API-ключей в контекст агента применимы напрямую, так как вызывающие стороны этого сервера — агенты.

Значения, загруженные из env_file, находятся в окружении контейнера, а docker inspect выводит их в полном объеме. Любой пользователь в группе docker может прочитать их, а любой пользователь в группе docker фактически обладает правами root на хосте.

Размещение TLS перед API вместо открытия порта 8888

API отвечает на 127.0.0.1:8888, а панель управления — на 127.0.0.1:3000. nginx выполняет TLS (transport layer security) termination на порту 443 и перенаправляет запросы к обоим сервисам.

server {
    listen 443 ssl;
    server_name mem0.example.com;

    ssl_certificate     /etc/letsencrypt/live/mem0.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mem0.example.com/privkey.pem;

    location ~ ^/(memories|search|configure|auth|api-keys|docs|openapi.json) {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 180s;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

proxy_read_timeout важнее, чем кажется на первый взгляд. Вызов add блокируется, пока языковая модель считывает диалог и извлекает факты. Локальная модель 8B на CPU часто работает дольше стандартного 60-секундного таймаута nginx, из-за чего вызывающая сторона получает 504 Gateway Time-out, хотя модель всё ещё продолжает обработку, а данные записываются в память. В итоге вы получаете запись в памяти, о неудаче которой вас уведомили.

Закройте остальные порты с помощью политики ufw по умолчанию deny, оставив открытыми только 22 и 443. Выпустите сертификат через certbot в Ubuntu 24.04 с nginx. Если сервер уже обслуживает другие приложения через маршрутизацию Traefik для нескольких Compose-приложений, добавьте mem0 в этот роутер вместо установки второго прокси-сервера.

Smoke-тест: добавление одной записи в память и её чтение

export MEM0_KEY='<the ADMIN_API_KEY from .env>'

curl -sS -X POST http://127.0.0.1:8888/memories \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d '{"messages":[{"role":"user","content":"I deploy with Docker Compose and I run Postgres 17."}],"user_id":"smoke"}'

Корректный ответ представляет собой JSON-объект со списком results, где каждая запись содержит id, извлечённый текст memory и "event": "ADD". Текущий алгоритм возвращает только события ADD. События UPDATE и DELETE были удалены, поэтому их отсутствие не является ошибкой.

curl -sS -X POST http://127.0.0.1:8888/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d '{"query":"which database do I run?","filters":{"user_id":"smoke"},"top_k":5}'

Факт о Postgres 17 должен вернуться с оценкой (score). Передайте идентификатор внутри filters, как показано в примере. Использование user_id верхнего уровня по-прежнему работает, и сервер записывает Top-level user_id in /search is deprecated. Use filters={...} instead. в логи при каждом таком обращении.

Удалите тестовые данные после завершения, чтобы они не влияли на реальные результаты поиска:

curl -sS -X DELETE "http://127.0.0.1:8888/memories?user_id=smoke" \
  -H "X-API-Key: $MEM0_KEY"

Если поиск возвращает меньше строк, чем ожидалось, проверьте значения по умолчанию, прежде чем искать проблему в механизме извлечения. В текущем релизе top_k по умолчанию равно 20 (ранее было 100), а threshold по умолчанию равно 0.1 вместо отсутствия фильтрации, поэтому слабые совпадения теперь отсеиваются автоматически. Как только это заработает через curl, эти же эндпоинты можно подключать к агенту — напрямую или через MCP-сервер, запущенный на том же VPS.

Запуск mem0 без ключа OpenAI

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

LLM provider 'ollama' is not bundled in this image. Bundled providers: openai, anthropic, gemini. To use another provider, install its Python package, rebuild the container, and extend BUNDLED_LLM_PROVIDERS in server/main.py.

Вам не нужно ничего пересобирать. Ollama предоставляет API, совместимый с OpenAI, по адресу /v1, поддерживая /v1/chat/completions и /v1/embeddings, а провайдер openai в mem0 принимает openai_base_url. Укажите этот ключ в настройках Ollama, и встроенная проверка будет пройдена, так как провайдер действительно является openai. Меняется только адрес.

Добавьте Ollama в тот же проект Compose:

  ollama:
    image: ollama/ollama
    restart: unless-stopped
    networks: [mem0_network]
    ports:
      - "127.0.0.1:11434:11434"
    volumes:
      - ollama_models:/root/.ollama

Добавьте ollama_models: в раздел верхнего уровня volumes:, затем загрузите одну модель для чата и одну модель для эмбеддингов:

docker compose up -d ollama
docker compose exec ollama ollama pull llama3.1:8b
docker compose exec ollama ollama pull nomic-embed-text

Если Ollama уже работает на хосте как systemd-юнит, как описано в запуске Ollama напрямую на VPS, не указывайте контейнеру адрес 127.0.0.1:11434. Внутри контейнера mem0 адрес 127.0.0.1 указывает на сам контейнер mem0. Предоставьте сервису mem0 extra_hosts: ["host.docker.internal:host-gateway"], установите Environment="OLLAMA_HOST=0.0.0.0:11434" в drop-in файле systemd, чтобы Ollama слушала адрес, доступный через bridge-сеть, и закройте порт 11434 на брандмауэре.

Узнайте размерность эмбеддингов модели перед настройкой

Этот шаг определяет, будет ли вообще работать поиск.

Хранилище pgvector в mem0 создает таблицу с фиксированной шириной вектора vector vector(1536), так как embedding_model_dims по умолчанию использует 1536 — размерность модели text-embedding-3-small от OpenAI. nomic-embed-text возвращает 768 значений. Внутри mem0 нет проверки на соответствие этих чисел, поэтому ошибка возникает со стороны Postgres при первой же попытке вставки:

expected 1536 dimensions, not 768

Не доверяйте числу из этого абзаца. Спросите модель:

curl -sS http://127.0.0.1:11434/v1/embeddings \
  -H "Content-Type: application/json" \
  -d '{"model":"nomic-embed-text","input":"dimension check"}' \
  | python3 -c "import json,sys; print(len(json.load(sys.stdin)['data'][0]['embedding']))"

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

{
  "vector_store": {
    "provider": "pgvector",
    "config": {
      "host": "postgres",
      "port": 5432,
      "dbname": "postgres",
      "user": "postgres",
      "password": "<POSTGRES_PASSWORD from .env>",
      "collection_name": "memories_local_768",
      "embedding_model_dims": 768
    }
  },
  "llm": {
    "provider": "openai",
    "config": {
      "model": "llama3.1:8b",
      "api_key": "ollama",
      "openai_base_url": "http://ollama:11434/v1",
      "temperature": 0.2
    }
  },
  "embedder": {
    "provider": "openai",
    "config": {
      "model": "nomic-embed-text",
      "api_key": "ollama",
      "openai_base_url": "http://ollama:11434/v1"
    }
  }
}
curl -sS -X POST http://127.0.0.1:8888/configure \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d @config.json

curl -sS http://127.0.0.1:8888/configure -H "X-API-Key: $MEM0_KEY"

Второй вызов считывает конфигурацию обратно — это проверка того, что запись прошла успешно. Затем повторите описанный выше тест.

Четыре детали в этом JSON не очевидны, и каждая из них приведет к сбою при неверной настройке.

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

embedding_model_dims применяется к векторному хранилищу, и для эмбеддера намеренно не задается embedding_dims. mem0 отправляет параметр OpenAI dimensions только если вы установили embedding_dims, а бэкенды, не поддерживающие усечение Matryoshka, сразу отклоняют этот параметр. Установите ширину при создании таблицы и не меняйте настройки эмбеддера.

collection_name — это новый параметр. mem0 создает таблицу с CREATE TABLE IF NOT EXISTS, поэтому указание другой ширины для существующей коллекции ничего не даст: старый столбец vector(1536) останется, и каждая вставка будет завершаться ошибкой. Для изменения ширины нужно либо создать новую коллекцию, либо удалить старую таблицу вручную.

Хост в openai_base_url — это имя сервиса в Compose ollama, а не localhost. Контейнеры находят друг друга по имени сервиса в общей сети.

Цена полностью локального решения

Будьте честны в оценке качества. Опубликованные результаты тестов mem0 были получены с использованием передовых моделей для извлечения данных, поэтому воспринимайте их как верхний предел, а не как прогноз для модели 8B на вашем VPS. Маленькая модель извлекает менее точные факты и иногда возвращает текст там, где требовался JSON, что проявляется в виде вызова add, возвращающего пустой список results без ошибок.

Вторая цена — скорость. Извлечение данных только на CPU занимает секунды на каждый вызов add, и каждое сохраняемое сообщение увеличивает это время. Модель, которая выдает лишний текст помимо запрошенного JSON, усугубляет проблему, поэтому ограничение ответа через num_predict устанавливает предел времени выполнения одного вызова add. Если задержка критична, единственным честным решением будет VPS с подключенным GPU. Увеличение количества ядер CPU для модели 8B помогает гораздо меньше, чем ожидается. Смена модели — более дешевый рычаг, чем смена оборудования, а Nemotron 3.5 Lightning на VPS дает вам тег для загрузки, требования к RAM и понимание того, достаточно ли быстрой будет работа только на CPU.

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

Резервное копирование: две базы данных, а не одна

Самая распространённая ошибка при резервном копировании mem0 — выгрузка только одной базы данных. init-db.sh создаёт базу данных mem0_app в дополнение к базе данных postgres по умолчанию, и они хранят разные данные. В базе данных postgres находятся коллекции pgvector, то есть воспоминания. В mem0_app хранятся пользователи, сеансы, API keys и журналы запросов. Каждое самостоятельно размещённое приложение по-своему разделяет состояние, поэтому два фотосервера с одинаковыми функциями всё равно требуют разных команд резервного копирования. Поэтому перед использованием дампа проверьте, какие данные сохраняет приложение. На другом конце этого диапазона находится, например, библиотека Jellyfin, перестроенная под видеопрокат 90-х, которая получает весь каталог из другого сервиса и поэтому обычно требует только копирования собственной конфигурации. Для mem0 нужны обе базы данных, иначе восстановление будет бесполезным.

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

docker compose exec -T postgres pg_dumpall -U postgres --clean \
  | gzip > "mem0-$(date +%F).sql.gz"

Том с историей (history volume) отделен от Postgres и требует собственного копирования:

docker run --rm -v mem0_mem0_history:/data -v "$PWD:/backup" \
  alpine tar czf /backup/mem0-history.tgz -C /data .

Docker добавляет префикс имени проекта к именам томов, поэтому уточните свои имена с помощью docker volume ls, прежде чем полагаться на mem0_mem0_history.

Выполняйте восстановление в пустой контейнер и проверяйте количество строк, прежде чем считать данные достоверными:

gunzip -c mem0-2026-08-03.sql.gz \
  | docker compose exec -T postgres psql -U postgres -d postgres

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

Типичные ошибки и сообщения, которые вы увидите

{"detail":"Authentication required. Provide a Bearer token or X-API-Key header."} означает, что заголовок отсутствует или написан с ошибкой. Имя заголовка — X-API-Key, а curl передает имена заголовков буквально.

{"detail":"At least one identifier (user_id, agent_id, run_id) is required."} при добавлении означает, что в запросе не было ни одного из них. Память должна быть привязана к чему-либо, так как фильтры поиска работают именно по этим полям.

LLM provider 'ollama' is not bundled in this image с кодом HTTP 400 означает, что вы отправили "provider": "ollama". Используйте "provider": "openai" с параметром openai_base_url, указывающим на Ollama.

expected 1536 dimensions, not 768 от Postgres означает, что коллекция была создана с одной размерностью, а эмбеддер возвращает другую. Установите embedding_model_dims в векторном хранилище и используйте новый collection_name.

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

Connection refused в логах mem0 при обращении к Ollama обычно означает 127.0.0.1 в openai_base_url. Внутри контейнера этот адрес указывает на сам контейнер. Используйте имя сервиса или host gateway, если Ollama запущена на хосте.

504 Gateway Time-out от nginx при добавлении означает, что модель отвечала дольше, чем proxy_read_timeout. Увеличьте это значение и проверьте, была ли память записана, прежде чем повторять запрос.

exit code 137 во время docker compose up --build означает, что OOM-killer (Out-of-Memory killer) остановил сборку панели управления. Добавьте swap или соберите образ на более мощной машине и отправьте его в реестр.

error: port 3000 is already in use возникает из цели make up в репозитории, которая отказывается запускаться, если порты 3000 или 8888 заняты. Найдите процесс, занимающий порт, с помощью lsof -iTCP:3000 -sTCP:LISTEN.

FAQ

Нужен ли мне по-прежнему Neo4j для работы mem0 с графовой памятью?

Нет. Новый алгоритм работы с памятью, выпущенный в апреле 2026 года, исключил ключи конфигурации graph_store и enable_graph из SDK с открытым исходным кодом. Извлечение сущностей теперь выполняется во время обычной операции добавления и записывается во вторую коллекцию pgvector с именем <collection_name>_entities. Таким образом, внешняя графовая база данных, дополнительный контейнер и этап миграции больше не требуются. Обратной стороной является то, что поле relations в результатах поиска больше не существует. Сущности теперь повышают рейтинг памяти, а не предоставляют ребра для обхода, поэтому приложению, которое ранее использовало эти связи, потребуется собственное графовое хранилище вне mem0.

Какой минимальный размер VPS нужен для запуска self-hosted сервера mem0?

Если языковая модель размещена на другом сервере, для контейнера API, Postgres и панели управления достаточно 2 GB оперативной памяти и около 4 GB свободного дискового пространства. Критическим моментом является первая сборка, так как компиляция панели управления Next.js потребляет больше памяти, чем её запуск, и на сервере с 1 GB памяти процесс сборки будет завершен с ошибкой exit code 137. Если на том же сервере работает Ollama, учитывайте размер модели: модель 8B с 4-битной квантованием требует примерно 6 GB памяти, поэтому планируйте использование 8 GB.

Можно ли запустить mem0 без API-ключа OpenAI?

Да, через совместимый с OpenAI эндпоинт Ollama. Установка "provider": "ollama" приведет к ошибке, так как образ сервера содержит только библиотеки openai, anthropic и gemini, и вернет HTTP 400. Вместо этого оставьте "provider": "openai" и установите "openai_base_url": "http://ollama:11434/v1" с любым непустым значением api_key как для llm, так и для embedder. Ollama игнорирует ключ, а встроенная проверка провайдера проходит успешно, так как провайдером действительно является openai.

Почему mem0 не возвращает результаты после переключения на локальную модель эмбеддингов?

Потому что таблица pgvector была создана с фиксированной шириной. embedding_model_dims по умолчанию имеет значение 1536, nomic-embed-text возвращает 768, и Postgres отклоняет вставку с ошибкой expected 1536 dimensions, not 768. mem0 создает таблицу с параметром CREATE TABLE IF NOT EXISTS, поэтому изменение только числа не влияет на существующую коллекцию. Установите embedding_model_dims в соответствии с реальной шириной вашей модели, подтвердите эту ширину, вызвав /v1/embeddings и подсчитав количество возвращаемых значений, и одновременно задайте для векторного хранилища новое имя collection_name.