SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-28

VPSでmem0をセルフホストするRAMと構成

mem0をVPSで動かす実測のRAM目安を解説します。3コンテナは約1GB、Ollamaの4bit 8Bモデルは約6GB、全ローカル構成は8GBからです。Compose、localhost bind、TLS、Neo4j不要の現行構成も紹介します。

VPS 上で mem0 をセルフホストする場合に実際に必要な RAM

mem0 をセルフホストするには、3 つのコンテナを実行します。FastAPI のメモリサーバー、pgvector 拡張機能を有効にした Postgres、Next.js のダッシュボードです。mem0 はエージェント向けのメモリ層です。会話を mem0 に送ると、言語モデルがその会話から長期的に保持すべき事実を抽出します。抽出した事実はベクトルとして保存され、後続のクエリで関連する事実を取得できます。

3 つのコンテナに必要な常駐メモリは、おおよそ 1 GB と見積もってください。イメージのビルド後に必要なディスク容量は 3 から 4 GB です。言語モデルを別の場所で実行する場合、2 GB の VPS で問題なく動作します。同じサーバー上で Ollama を使ってモデルを実行すると、他の要素よりもモデルが大幅に多くのリソースを消費します。4 ビットに量子化した 8B モデルだけで約 6 GB を必要とするため、すべてをローカルで実行する構成は 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 のビルド中がインストール全体で最もメモリを消費します。1 GB の VPS ではカーネルの out-of-memory killer がビルドを停止し、ビルドは exit code 137 で終了します。Docker のバグを疑う前に、原因を確認してください。

dmesg -T | grep -i "killed process"

サーバーが必要以上に大掛かりだと感じる場合は、より小規模な選択肢があります。サーバーをまったく使わないローカルエージェントメモリストア と Claude Code 自体に保存するメモリ は、どちらもデータベースを使用しません。複数のエージェントまたは複数のマシンで同じメモリを読み取る必要が生じたら、ここに戻ってください。

mem0 のグラフメモリに Neo4j は必要ですか?

いいえ。Neo4j コンテナの追加を指示しているガイドがある場合、そのガイドは現在のコードより古いものです。

以前の mem0 では、グラフメモリは外部グラフデータベースを意味し、graph_store キーの下で設定し、enable_graph を true に設定していました。2026 年 4 月にリリースされた新しいメモリアルゴリズムでは、オープンソース SDK から両方のキーが削除されました。エンティティ抽出は通常の add 処理内で実行され、エンティティはメインのコレクション名に _entities を付加した名前の、2 番目の pgvector コレクションに書き込まれます。実行する移行処理はありません。組み込みのエンティティリンクは、次回の add 呼び出しから機能します。

グラフストアを削除すると、JVM コンテナ、そのヒープ、および数百 MB のイメージが不要になります。2 GB の VPS では、これは正常に動作するか、スワップが発生するかの違いになります。

失われる機能を明確に説明します。以前は検索結果に、エンティティ間のエッジを列挙する relations フィールドが含まれていました。このフィールドはなくなりました。現在は、エンティティの一致によって統合スコア内のメモリの順位が上がりますが、たどれる構造はありません。アプリケーションでそれらの関係をたどっていた場合、mem0 は関係を保持しなくなります。その場合は、mem0 の外部に独自のグラフデータベースを用意し、自分のコードからデータを登録して管理します。

リポジトリ内の compose ファイルは開発用の compose ファイルです。

server/docker-compose.yaml は name: mem0-dev を宣言しており、その設定どおりに動作します。実行する前に内容を確認してください。サーバーで使うには、5 つの問題があります。

  • server/dev.Dockerfile からビルドし、.:/app でチェックアウトしたディレクトリをイメージにマウントします。そのため、コンテナはビルドした内容ではなく、そのディレクトリにある内容を実行します。
  • コマンドは rm -rf /app/packages && pip install -q --force-reinstall --no-deps mem0ai && alembic upgrade head && uvicorn main:app --reload です。起動するたびに PyPI から mem0ai を再インストールします。そのため、アップグレードしたつもりのない再起動で、サーバーが実行するバージョンが変わる可能性があります。
  • 同じ pip の処理により、外部ネットワークに接続できない状態で再起動すると、uvicorn が起動する前に失敗します。PyPI に到達できないため、メモリサーバーが停止したままになります。
  • --reload は uvicorn のファイルウォッチャーを起動します。これはコードを編集したときにプロセスを再起動するための機能です。本番環境では有用な処理を行わないまま、メモリと 2 つ目のプロセスを消費します。本番用の Dockerfile も CMD に --reload を含んでいるため、どちらの場合もコマンドを上書きします。
  • 公開ポートは "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

ここで重要なのは 5 つの変更です。それぞれに理由があります。

すべての ports エントリは 127.0.0.1 で始まるため、カーネルはこれらの接続を同一ホストからのものだけ受け付けます。外部からの通信はすべてリバースプロキシ経由で到達します。証明書を保持するのもリバースプロキシだけです。

Postgres には ports ブロックがありません。mem0 コンテナはサービス名を使って mem0_network 経由で接続するため、8432 を公開しても利点はなく、開放ポートが 1 つ増えるだけです。シェルが必要な場合は docker compose exec postgres psql -U postgres を使用します。

履歴の保存先を ./history bind mount から名前付き volume に変更します。bind mount では、このホスト上の 1 つのパスと 1 つの uid にデータが固定されます。一方、名前付き volume は Docker が snapshot を作成して移動できるオブジェクトです。名前付き volume と bind mount の比較 では、それぞれを使うべき場面を説明しています。

このコマンドでは --reload を削除し、alembic upgrade head を残します。この migration 手順は残してください。これがないと、アプリはテーブルのないデータベースに対して起動し、すべてのリクエストが最初のクエリで失敗します。

NEXT_PUBLIC_API_URL はブラウザーが呼び出す URL なので、http://mem0:8000 ではなく公開 HTTPS アドレスにする必要があります。Next.js はすべての NEXT_PUBLIC_ の値をビルド時に埋め込むため、変更するには docker compose up -d --build mem0-dashboard が必要です。単に再起動しただけでは、JavaScript に古い値が埋め込まれたままになり、ダッシュボードは誤ったホストを呼び出します。

Secrets は .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 全体に対する root 認証情報です。root 認証情報として扱ってください。shell の履歴に残さず、git に保存せず、プロンプトに貼り付けないでください。Compose の env ファイルと、そこから Secret が漏れる場所およびAPI key を agent のコンテキストから除外する方法がそのまま適用されます。このサーバーの呼び出し元は agent だからです。

env_fileから読み込んだ値はコンテナの環境変数に格納され、docker inspectですべて表示されます。dockerグループのメンバーはそれらを読み取れます。dockerグループのメンバーは、ホスト上で実質的に root と同等の権限を持ちます。

API を直接公開せず、TLS を前段に置く

API は 127.0.0.1:8888 で応答し、ダッシュボードは 127.0.0.1:3000 で応答します。nginx は 443 で TLS (transport layer security) を終端し、両方へ転送します。

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 呼び出しは、言語モデルが会話を読み取り、事実を抽出している間、ブロックします。CPU 上で動作するローカルの 8B モデルは、nginx のデフォルトである 60 秒を定期的に超えます。その場合、呼び出し元には 504 Gateway Time-out が返りますが、モデルは処理を続け、メモリへの書き込みも行われます。結果として、失敗したと通知されたメモリが残ります。

残りの通信は デフォルト拒否の ufw ポリシー で閉じ、22 と 443 だけを開放します。証明書は nginx の背後にある Ubuntu 24.04 で certbot を使用 して発行します。すでに 複数の Compose アプリを Traefik でルーティング している場合は、2 つ目のプロキシをインストールせず、そのルーターに mem0 を追加します。

スモークテスト: メモリを 1 件追加して読み戻す

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"}'

正常なレスポンスは、results リストを含む JSON オブジェクトです。各エントリには 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 に関する事実は、スコア付きで返されるはずです。次の例のように、識別子を 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 のデフォルト値が 100 から 20 に変更されています。また、threshold のデフォルト値は none ではなく 0.1 であるため、関連性の低い一致は自動的に除外されます。curl で動作を確認できたら、これらと同じエンドポイントをエージェントに接続します。直接接続することも、同じ VPS 上で実行する MCP server 経由で接続することもできます。

OpenAI key を一切使わずに mem0 を実行する

最初にブロッカーを確認します。最初の5分以内にここで止まります。サーバーイメージには固定された provider ライブラリだけが含まれており、/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 は /v1 で OpenAI 互換 API を提供し、/v1/chat/completions と /v1/embeddings に対応しています。また、mem0 の openai provider は openai_base_url を受け付けます。その key を Ollama に向けると、provider が実際に openai であるため、組み込みチェックを通過します。変わるのはアドレスだけです。

同じ Compose プロジェクトに Ollama を追加します。

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

トップレベルの volumes: key の下に ollama_models: を追加し、chat model を1つ、embedding model を1つ pull します。

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

VPS で Ollama を直接実行する 場合のように、Ollama がホスト上で systemd unit としてすでに実行されている場合は、コンテナから 127.0.0.1:11434 を指定しないでください。mem0 コンテナ内では、127.0.0.1 は mem0 コンテナ自身を指します。mem0 service に extra_hosts: ["host.docker.internal:host-gateway"] を指定し、Ollama が bridge から到達できるアドレスで待ち受けるように systemd drop-in で Environment="OLLAMA_HOST=0.0.0.0:11434" を設定します。ファイアウォールでは 11434 を閉じたままにします。

何も設定する前にモデルの embedding 次元数を確認する

この手順で、検索が機能するかどうかが決まります。

mem0 の pgvector store は、vector vector(1536) の固定された vector width で table を作成します。これは embedding_model_dims のデフォルト値が1536で、OpenAI の text-embedding-3-small の幅だからです。nomic-embed-text は768個の値を返します。mem0 内ではこの2つの数値を比較しないため、最初の insert 時に 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']))"

このコマンドは、collection で使用する必要がある幅を表示します。設定をファイルに書き込みます。shell の quoting を使って Postgres password を貼り付けると、本番環境に typo が入りやすいためです。

{
  "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"

2つ目の呼び出しで設定を読み戻します。これにより、書き込みが反映されたことを確認できます。その後、上記の smoke test をもう一度実行します。

この JSON には分かりにくい点が4つあります。どれも間違えると問題が発生します。

api_key は ollama という文字列で、Ollama はその値を無視します。空にはできません。key が設定されていない場合、OpenAI client library はリクエストをプロセス外へ送る前に error を発生させるためです。空でない文字列なら何でも使用できます。

embedding_model_dims は vector store に設定します。embedder には embedding_dims を意図的に設定しません。mem0 は embedding_dims を設定した場合に限り、OpenAI の dimensions parameter を送信します。Matryoshka truncation を実装していない backend は、この parameter を完全に拒否します。table の作成時に幅を設定し、embedder は変更しないでください。

collection_name は新しい設定です。mem0 は CREATE TABLE IF NOT EXISTS を指定して table を作成します。そのため、異なる幅を既存の collection に指定しても何も起こりません。古い vector(1536) column が残り、すべての insert が失敗します。幅を変更する場合は、新しい collection name を使用するか、古い table を手動で削除します。

openai_base_url の host は Compose の service name である ollama です。localhost ではありません。コンテナ同士は、共有 network 上で service name により相互に名前解決します。

完全にローカルで実行する場合のコスト

品質については正しく見積もってください。mem0 が公開している benchmark score は、抽出に最先端の model を使って測定されています。そのため、VPS 上の8B model で同じ結果が出ると考えず、上限の目安として扱ってください。小型の model は曖昧な fact を生成しやすく、JSON を要求しても prose を返すことがあります。その場合、error なしで add call が空の results list を返すことがあります。

もう1つのコストは速度です。CPU のみで抽出すると、add call ごとに数秒かかります。保存するすべての message でこの処理が発生します。要求した JSON の後まで model が長く出力すると、さらに遅くなります。そのため、num_predict で応答を制限する と、1回の add call の実行時間に上限を設定できます。この latency が問題になる場合は、GPU を接続した VPS が現実的な解決策です。8B model に CPU core を追加しても、期待するほど改善しません。マシンを変更するより model を変更する方が安価です。VPS 上の Nemotron 3.5 Lightning なら、pull する tag、必要な RAM、CPU のみで実用的な速度になるかを確認できます。

何を選んでも、1つのルールは変わりません。1つの collection 内で embedding model を混在させないでください。幅が同じでも、異なる2つの model が生成する vector は比較できません。insert は成功し、search は rows を返します。しかし、その rows は誤っており、どこにも error は報告されません。

バックアップ: データベースは1つではなく2つある

mem0 のバックアップで最も多いミスは、単一のデータベースだけをダンプすることです。init-db.sh はデフォルトの postgres データベースと並んで mem0_app を作成し、両者には異なるデータが格納されます。postgres データベースにはメモリに相当する pgvector コレクションが格納されます。mem0_app にはユーザー、セッション、API キー、リクエストログが格納されます。セルフホストのアプリケーションは、それぞれ独自の方法で状態を分割します。そのため、同じ役割を果たす 2 つの写真サーバーでもバックアップコマンドは異なります。ダンプを信頼する前に、アプリケーションが何を保存しているかを確認してください。その対極にあるのが、90 年代のビデオ店として再構築された Jellyfin ライブラリのような構成です。これはカタログ全体を別のサービスから読み込むため、独自の設定をコピーするだけで済みます。一方、mem0 では両方のデータベースが必要です。そうしないと、リストアしても使いものになりません。

postgres だけを復元するとメモリは戻りますが、すべてのアカウントと API キーが失われます。そのため、メモリを読み取るための認証ができません。roles とともに、両方を1つのコマンドでダンプします。

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

履歴ボリュームは 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."} が add で表示される場合、リクエストにそれらのフィールドが1つもありませんでした。検索はそのフィールドだけを対象にフィルタリングするため、メモリにはスコープを指定する必要があります。

HTTP 400 とともに LLM provider 'ollama' is not bundled in this image が表示される場合は、"provider": "ollama" を送信しています。openai_base_url を Ollama に向けた状態で "provider": "openai" を使用してください。

Postgres から expected 1536 dimensions, not 768 が表示される場合、コレクションの作成時と embedder の返却時でベクトルの幅が異なります。ベクトルストアに embedding_model_dims を設定し、新しい collection_name を使用してください。

モデル変更後に検索結果として意味のない行が返る場合があります。どこにもエラーがない場合でも、幅が一致しているためデータベースは正常と判断します。しかし、同じ文でもモデルが異なる位置に配置します。新しいコレクションを作成し、データを再度追加してください。

Ollama への接続中に mem0 のログで Connection refused が表示される場合、多くは openai_base_url 内の 127.0.0.1 を意味します。コンテナ内では、そのアドレスはコンテナ自身を指します。Ollama がホスト上で動作している場合は、サービス名またはホストゲートウェイを使用してください。

add の実行時に nginx から 504 Gateway Time-out が表示される場合、モデルの処理時間が proxy_read_timeout を超えています。値を引き上げ、リクエストを再試行する前にメモリが書き込まれていないか確認してください。

docker compose up --build 中に exit code 137 が表示される場合、out-of-memory killer が dashboard のビルドを停止しています。swap を追加するか、より大きなマシンでイメージをビルドしてレジストリに push してください。

error: port 3000 is already in use はリポジトリの make up ターゲットが出力しています。このターゲットは、3000 または 8888 が使用中の場合に起動を拒否します。lsof -iTCP:3000 -sTCP:LISTEN で使用元を確認してください。

FAQ

グラフメモリで mem0 を実行する場合、Neo4j はまだ必要ですか?

いいえ。2026 年 4 月にリリースされた新しいメモリアルゴリズムでは、オープンソース SDK から graph_store と enable_graph の設定キーが削除されました。エンティティの抽出は通常の add 処理中に実行され、<collection_name>_entities という名前の 2 番目の pgvector コレクションに書き込まれます。そのため、外部のグラフデータベース、追加のコンテナ、移行手順は不要です。代わりに、検索結果の relations フィールドはなくなりました。エンティティはメモリのランキングを上げるだけで、たどれるエッジを提供しません。これらの関係をたどっていたアプリケーションでは、mem0 の外部に独自のグラフストアが必要です。

セルフホストの mem0 サーバーを実行できる最小の VPS はどの程度ですか?

言語モデルを別の場所でホストする場合、API コンテナ、Postgres、ダッシュボードには RAM 2 GB と空きディスク容量約 4 GB で十分です。最も厳しいのは初回ビルドです。Next.js ダッシュボードのコンパイルには、実行時より多くのメモリが必要だからです。1 GB の環境では、ビルドが exit code 137 で強制終了されます。Ollama を同じサーバーで実行する場合は、モデルを基準にサイジングしてください。4-bit 量子化の 8B モデルだけで約 6 GB 必要なので、8 GB を見込んでください。

OpenAI API key なしで mem0 を実行できますか?

はい。Ollama の OpenAI 互換エンドポイントを使用できます。"provider": "ollama" の設定は失敗します。サーバーイメージに含まれるライブラリが openai、anthropic、gemini だけで、HTTP 400 が返されるためです。代わりに "provider": "openai" は維持し、llm と embedder の両方に、空でない任意の api_key を指定して "openai_base_url": "http://ollama:11434/v1" を設定します。Ollama は key を無視します。プロバイダーは実際には openai なので、組み込みのプロバイダーチェックも通過します。

ローカルの embedding model に切り替えた後、mem0 が結果を返さないのはなぜですか?

pgvector のテーブルが固定幅で作成されているためです。embedding_model_dims のデフォルト値は 1536 ですが、nomic-embed-text は 768 を返すため、Postgres は expected 1536 dimensions, not 768 で insert を拒否します。mem0 は CREATE TABLE IF NOT EXISTS を使用してテーブルを作成するため、既存のコレクションでは数値だけを変更しても効果がありません。embedding_model_dims にモデルの実際の幅を設定し、/v1/embeddings を呼び出して返される値の個数を数え、その幅を確認してください。同時に、vector store に新しい collection_name を指定します。