SSD Nodes Learn 🎉 VPS mula $5.50/buwan
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-13

mem0 sa VPS: RAM, Docker Compose, TLS at Ollama

Alamin ang totoong RAM ng mem0: humigit-kumulang 1 GB para sa 3 container, 2 GB VPS kung remote ang model, at 8 GB para sa local Ollama setup.

Magkano talaga sa RAM ang self-hosting ng mem0 sa isang VPS

Ang self-hosting ng mem0 ay nangangahulugang pagpapatakbo ng tatlong container: ang FastAPI memory server, Postgres na may pgvector extension, at Next.js dashboard. Ang mem0 ay memory layer para sa mga agent. Ipo-post mo rito ang isang conversation, kukunin ng language model ang mga permanenteng fact mula rito, at ise-save ang mga iyon bilang vectors para makuha ng susunod na query ang mga nauugnay na fact.

Maglaan ng humigit-kumulang 1 GB resident memory para sa tatlong container, at 3 hanggang 4 GB disk pagkatapos ma-build ang mga image. Kayang patakbuhin ito nang maayos ng isang 2 GB VPS kapag nasa ibang machine ang language model. Kapag tumatakbo ang model sa parehong machine sa pamamagitan ng Ollama, ito ang kumokonsumo ng halos lahat ng resources: ang isang 8B model na naka-quantise sa 4 bits ay nangangailangan ng humigit-kumulang 6 GB nang mag-isa, kaya nagsisimula sa 8 GB ang fully local setup.

Huwag kunin ang mga numerong iyon mula sa isang blog post, kabilang na ang artikulong ito. Sukatin ang stack na aktuwal mong binuo.

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

Ang docker stats ay nagpi-print ng resident memory bawat container. Ang docker system df -v ay nagpi-print ng disk na ginagamit ng bawat image at bawat volume.

Hindi pareho ang steady state at peak usage. Kino-compile ng docker compose up -d --build ang Next.js dashboard, at ang Node build na iyon ang may pinakamataas na memory usage sa buong installation. Sa isang 1 GB VPS, pinatitigil ito ng kernel out-of-memory killer, at nagtatapos ang build sa exit code 137. Kumpirmahin muna ang sanhi bago ka maghanap ng Docker bug:

dmesg -T | grep -i "killed process"

Kung masyadong maraming component ang server para sa kailangan mo, may mas maliliit na option. Ang local agent memory store na walang server at memory na direktang nasa loob ng Claude Code ay parehong hindi nangangailangan ng database. Bumalik dito kapag kailangan nang magbasa ng parehong memory ang maraming agent o maraming machine.

Kailangan ba ang Neo4j para sa graph memory ng mem0?

Hindi. Kung sinasabi ng isang guide na magdagdag ka ng Neo4j container, mas luma ang guide na iyon kaysa sa code.

Dati, ang graph memory sa mem0 ay nangangahulugan ng external graph database na kino-configure gamit ang graph_store key at may enable_graph na naka-set sa true. Inalis ng bagong memory algorithm, na inilabas noong April 2026, ang dalawang key mula sa open source SDK. Tumatakbo na ngayon ang entity extraction sa loob ng ordinaryong add path, at isinusulat ang mga entity sa pangalawang pgvector collection na ipinangalan sa pangunahing collection at nilagyan ng _entities. Walang migration na kailangang patakbuhin. Magsisimulang gumana ang built-in entity linking sa susunod na add call.

Kapag inalis ang graph store, hindi na kailangan ang JVM container, ang heap nito, at ilang daang megabytes ng image. Sa isang 2 GB VPS, maaaring ito ang magtakda kung tatakbo ang system o mag-swap.

Narito nang malinaw ang mawawala sa iyo. Dati, may relations field ang mga search result na naglilista ng mga edge sa pagitan ng mga entity. Wala na ang field na iyon. Ngayon, itinataas ng mga entity match ang posisyon ng memory sa pinagsamang score, at wala nang structure na maaari mong i-traverse. Kung ginagamit ng application mo ang mga relationship na iyon, hindi na ini-store ng mem0 ang mga ito. Kailangan mong magpanatili ng sarili mong graph database sa labas ng mem0 at punan ito gamit ang sarili mong code.

Ang compose file sa repo ay para sa development

server/docker-compose.yaml ang nagde-declare ng name: mem0-dev, at talagang iyon ang ginagawa nito. Basahin muna ito bago patakbuhin, dahil may limang setting dito na mali para sa isang server.

  • Nagbu-build ito mula sa server/dev.Dockerfile at mina-mount ang checkout mo sa ibabaw ng image gamit ang .:/app, kaya pinapatakbo ng container ang anumang nasa directory na iyon sa halip na ang na-build mo.
  • Ang command nito ay rm -rf /app/packages && pip install -q --force-reinstall --no-deps mem0ai && alembic upgrade head && uvicorn main:app --reload. Muli nitong ini-install ang mem0ai mula sa PyPI sa bawat pagsisimula, kaya maaaring magbago ang version na pinapatakbo ng server sa isang restart na hindi mo itinuring na upgrade.
  • Dahil sa parehong pip step, mabibigo ang restart kapag walang outbound network bago pa man tumakbo ang uvicorn. Dahil dito, down ang memory server mo kapag hindi maabot ang PyPI.
  • Sinisimulan ng --reload ang file watcher ng uvicorn. Ginagamit ito upang i-restart ang process kapag nag-edit ka ng code, pero kumokonsumo ito ng memory at nagdadagdag ng second process na walang kapaki-pakinabang na ginagawa sa production. May --reload din ang production Dockerfile sa CMD nito, kaya mao-override mo ang command sa alinmang paraan.
  • Ang mga published port ay "8888:8000", "8432:5432" at "3000:3000". Kapag walang address sa unahan ang isang published port, naka-bind ito sa 0.0.0.0. Dahil dito, sumasagot ang Postgres sa public internet sa port 8432 sa sandaling magsimula ang stack.

Nararapat ng huling puntong ito ang sarili nitong babala. Inilalagay ng Docker ang sarili nitong rules bago ang chain na mina-manage ng ufw, kaya hindi isinasara ng ufw deny 8432 ang published container port. Ipinapaliwanag sa Direktang pag-publish ng Docker ng mga port lampas sa ufw ang mga kasangkot na rules.

Isang compose file para sa aktuwal na server

Magtrabaho sa loob ng server/, panatilihin kung nasaan ang init-db.sh, at palitan ang docker-compose.yaml ng sumusunod.

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

Mahalaga rito ang limang pagbabago, at may dahilan ang bawat isa.

Nagsisimula sa 127.0.0.1 ang bawat entry ng ports, kaya ang kernel ay tatanggap lamang ng mga connection na iyon mula mismo sa server. Lahat ng galing sa labas ay dadaan sa reverse proxy, na siyang tanging may hawak ng certificate.

Walang ports block ang Postgres. Kumokonekta rito ang mem0 container sa pamamagitan ng mem0_network gamit ang service name, kaya walang pakinabang ang pag-publish ng 8432 at nagbubukas lamang ito ng port. Gamitin ang docker compose exec postgres psql -U postgres kapag kailangan mo ng shell.

Inilipat ang history mula sa ./history bind mount papunta sa named volume. Itinatali ng bind mount ang data sa isang path at isang uid sa host na ito, samantalang ang named volume ay isang object na maaaring i-snapshot at ilipat ng Docker. Ipinapaliwanag ng Named volumes kumpara sa bind mounts kung kailan angkop ang bawat isa.

Inaalis ng command ang --reload at pinananatili ang alembic upgrade head. Panatilihin ang migration step na ito. Kung wala ito, magbo-boot ang app gamit ang database na walang mga table, kaya mabibigo ang bawat request sa unang query.

Ang NEXT_PUBLIC_API_URL ang URL na tinatawagan ng browser mo, kaya dapat itong public HTTPS address at hindi http://mem0:8000. Ini-inline ng Next.js ang bawat NEXT_PUBLIC_ value kapag nagbu-build, kaya kailangan ang docker compose up -d --build mem0-dashboard kapag binabago ito. Kapag plain restart lamang ang ginawa, mananatiling naka-embed ang lumang value sa JavaScript at maling host ang tatawagan ng dashboard.

Ang mga secret ay nasa .env, at hindi dapat ilantad sa internet ang .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

Itakda ang POSTGRES_PASSWORD, JWT_SECRET, at ADMIN_API_KEY. Iwanang hindi nakatakda ang AUTH_DISABLED=false. Tumpak ang pangalan nito sa ipinapatupad ng flag na iyon: kapag naka-enable ito, ibinibigay ng server ang lahat ng memory na hawak nito sa sinumang makakaabot sa port. Itakda ang MEM0_TELEMETRY=false kung ayaw mong ipadala upstream ang onboarding event.

Inihahambing ang ADMIN_API_KEY sa X-API-Key header gamit ang secrets.compare_digest, at nilalaktawan ng match ang lahat ng database lookup. Root credential ito para sa buong API. Tratuhin ito gaya ng root credential: huwag ilagay sa shell history, git, o i-paste sa prompt. Direktang naaangkop dito ang Compose env files at kung saan lumalabas ang mga secret mula sa mga ito at pag-iwas na mapasama ang API keys sa context ng agent, dahil mga agent ang tumatawag sa server na ito.

Ang mga value na nilo-load mula sa env_file ay napupunta sa container environment, at buong ipinapakita ng docker inspect ang mga ito. Mababasa ang mga ito ng sinumang kabilang sa docker group, at ang sinumang kabilang sa docker group ay epektibong may root access sa host.

Ilagay ang TLS sa harap ng API sa halip na buksan ang 8888

Sumasagot ang API sa 127.0.0.1:8888 at ang dashboard sa 127.0.0.1:3000. Tinatapos ng nginx ang TLS (transport layer security) sa 443 at ipinapasa ang request sa dalawang ito.

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;
    }
}

Mas mahalaga ang proxy_read_timeout kaysa sa unang tingin. Naka-block ang isang add call habang binabasa ng language model ang conversation at kumukuha ng mga fact. Ang lokal na 8B model na tumatakbo sa CPU ay madalas na lumalagpas sa default na 60 segundo ng nginx. Pagkatapos, makikita ng caller ang 504 Gateway Time-out habang gumagana pa ang model at naitatala pa rin ang memory. Magkakaroon ka ng memory na sinabing nabigo kahit naisulat naman ito.

Isara ang iba pang connection gamit ang default deny na ufw policy, at panatilihing bukas ang 22 at 443. I-issue ang certificate gamit ang certbot sa Ubuntu 24.04 na nasa likod ng nginx. Kung ginagamit na ng server ang Traefik para i-route ang ilang Compose app sa iba pang application, idagdag ang mem0 sa router na iyon sa halip na mag-install ng pangalawang proxy.

Smoke test: magdagdag ng isang memory at basahin ito muli

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

Ang wastong response ay isang JSON object na may listahang results, kung saan ang bawat entry ay naglalaman ng id, ng na-extract na memory text, at ng "event": "ADD". ADD events lamang ang ibinabalik ng kasalukuyang algorithm. Inalis ang UPDATE at DELETE events, kaya hindi bug ang kawalan ng mga ito.

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

Dapat bumalik nang may score ang fact tungkol sa Postgres 17. Ipasok ang identifier sa loob ng filters, gaya ng ipinapakita. Gumagana pa rin ang top-level na user_id, at nilalagyan ito ng server ng log na Top-level user_id in /search is deprecated. Use filters={...} instead. sa bawat paggamit.

Maglinis pagkatapos upang hindi maapektuhan ng test data ang mga totoong search:

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

Kung mas kaunti ang mga row na ibinabalik ng search kaysa sa inaasahan mo, suriin muna ang mga default bago sisihin ang retrieval. Sa kasalukuyang release, ang top_k ay default na 20, mula sa dating 100, at ang threshold ay default na 0.1 sa halip na none, kaya awtomatikong sinasala ang mahihinang match. Kapag gumagana na ito gamit ang curl, ang parehong endpoint ang ikokonekta mo sa isang agent, direkta man o sa pamamagitan ng isang MCP server na tumatakbo sa parehong VPS.

Patakbuhin ang mem0 nang walang anumang OpenAI key

Unahin ang blocker dahil makakaharap mo ito sa unang limang minuto. May fixed set ng provider libraries ang server image, at tinatanggihan ng /configure ang anumang wala sa mga ito:

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.

Hindi mo kailangang mag-rebuild ng anuman. Nagsisilbi ang Ollama ng OpenAI-compatible API sa /v1, na sumusuporta sa /v1/chat/completions at /v1/embeddings, at tumatanggap ang openai provider ng mem0 ng openai_base_url. Ituro ang key na iyon sa Ollama at papasa ang bundled check dahil tunay na openai ang provider. Ang address lang ang nagbabago.

Idagdag ang Ollama sa parehong Compose project:

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

Idagdag ang ollama_models: sa ilalim ng top-level na volumes: key, pagkatapos ay mag-pull ng isang chat model at isang embedding model:

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

Kung tumatakbo na ang Ollama sa host bilang systemd unit, gaya ng direktang pagpapatakbo ng Ollama sa isang VPS, huwag ituro ang container sa 127.0.0.1:11434. Sa loob ng mem0 container, ang 127.0.0.1 ay ang mem0 container. Bigyan ang mem0 service ng extra_hosts: ["host.docker.internal:host-gateway"], itakda ang Environment="OLLAMA_HOST=0.0.0.0:11434" sa isang systemd drop-in upang makinig ang Ollama sa address na maaabot ng bridge, at panatilihing naka-block ang 11434 sa firewall.

Itanong sa model ang embedding dimension nito bago mag-configure ng anuman

Tinutukoy ng hakbang na ito kung gagana ang retrieval.

Gumagawa ang pgvector store ng mem0 ng table na may fixed vector width na vector vector(1536) dahil ang default ng embedding_model_dims ay 1536, ang width ng text-embedding-3-small ng OpenAI. Nagbabalik ang nomic-embed-text ng 768 values. Walang bahagi ng mem0 ang nagko-compare sa dalawang numerong ito, kaya sa Postgres unang lumilitaw ang mismatch sa unang insert:

expected 1536 dimensions, not 768

Huwag ding basta pagkatiwalaan ang numerong nasa paragraph na ito. Itanong sa model:

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']))"

Ipinapakita nito ang width na kailangang gamitin ng collection mo. Isulat ang configuration sa isang file dahil kapag nag-paste ng Postgres password gamit ang shell quoting, madaling mapunta sa production ang mga 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"

Binabasa ng ikalawang call ang configuration, at ito ang check na nagpapatunay na naisulat ito nang tama. Pagkatapos, ulitin ang smoke test sa itaas.

May apat na detail sa JSON na hindi agad halata, at may masisira sa bawat isa kapag mali ang pagkaka-configure.

Ang api_key ay string na ollama, at binabalewala ng Ollama ang value nito. Hindi ito maaaring walang laman dahil nagkakaroon ng error ang OpenAI client library bago pa umalis sa process ang anumang request kapag walang nakatakdang key. Gumagana ang anumang non-empty string.

Ang embedding_model_dims ay inilalagay sa vector store, at sadyang walang embedding_dims sa embedder. Ipinapadala ng mem0 ang OpenAI dimensions parameter lamang kapag itinakda mo ang embedding_dims, at tahasang tinatanggihan ng mga backend na hindi nagpapatupad ng Matryoshka truncation ang parameter na iyon. Itakda ang width kung saan ginagawa ang table, at huwag baguhin ang embedder.

Bago ang collection_name. Ginagawa ng mem0 ang table gamit ang CREATE TABLE IF NOT EXISTS, kaya walang epekto ang pagturo ng ibang width sa dati nang collection: nananatili ang lumang vector(1536) column, at nabibigo ang bawat insert. Kailangan ng bagong collection name kapag binago ang width, o maaari mong manual na i-drop ang lumang table.

Ang host sa openai_base_url ay ang Compose service name na ollama, hindi localhost. Nire-resolve ng mga container ang isa’t isa gamit ang service name sa shared network nila.

Ang kapalit ng ganap na local na path

Maging makatotohanan tungkol sa quality. Sinukat ang mga inilathalang benchmark score ng mem0 gamit ang frontier models para sa extraction, kaya ituring ang mga ito bilang ceiling, hindi forecast para sa 8B model sa VPS mo. Mas malalabo ang facts na isinusulat ng maliit na model, at kung minsan ay prose ang ibinabalik nito kahit JSON ang hinihingi. Lumalabas ito bilang add call na nagbabalik ng walang laman na results list nang walang error.

Ang speed ang isa pang kapalit. Ang CPU-only extraction ay inaabot ng ilang segundo bawat add call, at binabayaran mo ang oras na iyon sa bawat mensaheng sine-save mo. Kung mahalaga ang latency, ang tapat na solusyon ay isang VPS na may nakakabit na GPU. Mas kaunti ang naitutulong ng pagdaragdag ng CPU cores sa 8B model kaysa sa inaasahan ng marami.

Anuman ang piliin mo, may isang patakarang dapat sundin: huwag paghaluin ang embedding models sa iisang collection. Ang dalawang magkaibang model na nagkataong pareho ang width ay gumagawa ng mga vector na hindi maikukumpara. Magtatagumpay ang insert, magbabalik ng rows ang search, at mali ang mga row nang walang anumang error na naiuulat.

Mga backup: dalawang database ang mayroon, hindi isa

Ang pinakakaraniwang pagkakamali sa pag-backup ng mem0 ay ang pag-dump ng iisang database. Gumagawa ang init-db.sh ng mem0_app kasabay ng default na postgres database, at magkaiba ang nilalaman ng mga ito. Nasa postgres database ang mga pgvector collection, na siyang mga memory. Nasa mem0_app naman ang mga user, session, API key, at request log.

Kung postgres lamang ang ire-restore, babalik ang mga memory pero mawawala ang lahat ng account at API key. Dahil dito, walang makaka-authenticate upang basahin ang mga ito. I-dump ang parehong database, pati ang roles, gamit ang isang command:

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

Hiwalay sa Postgres ang history volume at kailangan nito ng sarili nitong kopya:

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

Nilalagyan ng Docker ng project name ang mga volume name. Kaya kumpirmahin muna ang iyo gamit ang docker volume ls bago ipagpalagay na mem0_mem0_history ito.

I-restore ang mga ito sa isang scratch container at suriin ang row count bago mo paniwalaan ang resulta:

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

Ang backup na hindi mo pa kailanman na-restore ay isang palagay lamang. Kapag tama na ang mga dump, ilipat ang mga ito sa labas ng server gamit ang restic snapshot sa off-site storage, dahil walang napoprotektahan ang backup na nasa server na dapat nitong protektahan.

Mga failure mode at ang eksaktong strings na makikita mo

{"detail":"Authentication required. Provide a Bearer token or X-API-Key header."} ibig sabihin ay nawawala o mali ang spelling ng header. Ang pangalan nito ay X-API-Key, at literal na ipinapadala ng curl ang mga pangalan ng header.

{"detail":"At least one identifier (user_id, agent_id, run_id) is required."} sa isang add ay ibig sabihin na wala sa request ang alinman sa mga ito. Kailangang may scope ang isang memory, dahil eksaktong sa mga field na iyon nagfi-filter ang search.

LLM provider 'ollama' is not bundled in this image na may HTTP 400 ay ibig sabihin na nagpadala ka ng "provider": "ollama". Gamitin ang "provider": "openai" na nakaturo ang openai_base_url sa Ollama.

expected 1536 dimensions, not 768 mula sa Postgres ay ibig sabihin na ginawa ang collection sa isang width, pero ibang width ang ibinabalik ng embedder. Itakda ang embedding_model_dims sa vector store at gumamit ng bagong collection_name.

Nagbabalik ang search ng mga row na walang saysay pagkatapos magpalit ng model, kahit walang error saanman. Pareho pa rin ang width, kaya walang problema ang database, pero inilalagay ng dalawang model ang parehong sentence sa magkaibang posisyon. Magsimula ng bagong collection at mag-add muli.

Connection refused sa mem0 logs habang kumokonekta sa Ollama ay karaniwang ibig sabihin na 127.0.0.1 sa openai_base_url. Sa loob ng container, ang address na iyon ay ang container mismo. Gamitin ang service name, o ang host gateway kapag tumatakbo ang Ollama sa host.

504 Gateway Time-out mula sa nginx habang nag-a-add ay ibig sabihin na mas matagal kaysa proxy_read_timeout ang pagproseso ng model. Itaas ito, at tingnan kung naisulat na ang memory bago muling subukan ang request.

exit code 137 habang ginagawa ang docker compose up --build ay ang out-of-memory killer na humihinto sa pagbuo ng dashboard. Magdagdag ng swap, o buuin ang image sa mas malaking machine at i-push ito sa registry.

error: port 3000 is already in use ay nagmumula sa make up target ng repo, na tumatangging magsimula kapag ginagamit na ang 3000 o 8888. Hanapin ang owner gamit ang lsof -iTCP:3000 -sTCP:LISTEN.

FAQ

Kailangan ko pa ba ng Neo4j para patakbuhin ang mem0 na may graph memory?

Hindi. Inalis ng bagong memory algorithm, na inilabas noong April 2026, ang mga configuration key na graph_store at enable_graph mula sa open source SDK. Tumatakbo na ngayon ang entity extraction habang normal na nag-a-add at nagsusulat ito sa pangalawang pgvector collection na pinangalanang <collection_name>_entities. Kaya wala nang external graph database, dagdag na container, o migration step. Ang kapalit nito ay wala na ang field na relations sa search results. Pinapataas na ngayon ng mga entity ang ranking ng memory sa halip na magbigay ng edges na maaaring traversan. Kung may application na naglalakad sa mga relationship na iyon, kailangan nitong gumamit ng sarili nitong graph store sa labas ng mem0.

Ano ang pinakamaliit na VPS na kayang magpatakbo ng self-hosted mem0 server?

Kung naka-host sa ibang lugar ang language model, sapat na ang 2 GB RAM at humigit-kumulang 4 GB na libreng disk space para sa API container, Postgres, at dashboard. Pinakamabigat ang unang build dahil mas maraming memory ang ginagamit ng pag-compile ng Next.js dashboard kaysa sa aktuwal na pagpapatakbo nito. Sa 1 GB na server, napapatay ang build at lumalabas ang exit code 137. Kung Ollama ang tumatakbo sa parehong server, ibatay ang sizing sa model: ang 8B model na may 4-bit quantisation ay nangangailangan ng humigit-kumulang 6 GB nang mag-isa, kaya maglaan ng 8 GB.

Maaari ko bang patakbuhin ang mem0 nang walang OpenAI API key?

Oo, gamit ang OpenAI-compatible endpoint ng Ollama. Nabibigo ang pag-set ng "provider": "ollama" dahil ang server image ay naglalaman lamang ng openai, anthropic, at gemini libraries at nagbabalik ng HTTP 400. Sa halip, panatilihin ang "provider": "openai" at itakda ang "openai_base_url": "http://ollama:11434/v1" gamit ang anumang non-empty na api_key, para sa llm at embedder. Hindi ginagamit ni Ollama ang key. Nakapapasa ang bundled provider check dahil openai talaga ang provider.

Bakit walang ibinabalik na resulta ang mem0 pagkatapos kong lumipat sa local embedding model?

Dahil ginawa ang pgvector table gamit ang nakapirming width. Ang default ng embedding_model_dims ay 1536, habang 768 ang ibinabalik ng nomic-embed-text, kaya tinatanggihan ng Postgres ang insert at nagbabalik ng expected 1536 dimensions, not 768. Ginagawa ng mem0 ang table gamit ang CREATE TABLE IF NOT EXISTS, kaya walang epekto sa existing collection ang pagpapalit lamang ng numero. Itakda ang embedding_model_dims sa aktuwal na width ng iyong model. Kumpirmahin ang width na iyon sa pagtawag sa /v1/embeddings at pagbibilang ng mga value na ibinabalik nito. Kasabay nito, bigyan ang vector store ng bagong collection_name.