Mem0 实战(一):Docker Compose 自托管部署,接 OpenAI-compatible 网关、pgvector 与 502/405 排错

Mem0 是给 LLM 应用和 Agent 用的长期记忆层。它不替代大模型,也不替代普通数据库;它负责把对话里值得长期保留的信息抽取出来,写入可检索的记忆库,后续再按用户、会话或 Agent 维度召回。

官方对 Mem0 的定位也是 “AI agents and apps 的 memory layer”。它适合放在这些场景里:

  • AI 助手需要跨会话记住用户偏好,例如语言风格、常用工具、长期目标。
  • 客服、销售、教育类 Agent 需要记住历史交互,不希望每次都让用户重复背景。
  • 多 Agent 系统里,每个 Agent 需要保留自己的经验和任务上下文。
  • 业务系统已经有文档知识库,但还需要一层“用户长期事实 / 偏好 / 历史行为”的个性化记忆。

不适合的场景也要先说清楚:如果只是做文档问答,优先看 RAGFlow、LlamaIndex、LangChain 这类 RAG 链路;如果只是存结构化业务数据,直接用数据库;如果只是把最近十轮对话塞回 prompt,用普通 conversation buffer 就够了。Mem0 的价值在于“跨会话、可检索、可更新”的长期记忆。

本文记录一次自托管 Mem0 的部署方式和配置方式:Docker Compose 启动 API、Dashboard、PostgreSQL + pgvector,用 Nginx 对外暴露,再接 OpenAI-compatible 模型网关。文中所有域名、Key、Provider 名和模型名都已经脱敏,照抄时替换成自己的即可。

环境

项目 示例值
部署方式 Docker Compose
运行目录 /data/mem0
对外域名 https://<mem0-domain>
API 本机端口 127.0.0.1:18888 -> 8000
Dashboard 本机端口 127.0.0.1:13000 -> 3000
PostgreSQL/pgvector 127.0.0.1:18432 -> 5432
LLM Provider OpenAI-compatible
Chat 模型 <CHAT_MODEL>
Embedding 模型 text-embedding-3-small

先确认机器上有这些基础命令:

docker --version
docker compose version
git --version
nginx -v

Mem0 自托管部署结构

这张图里有两条路径要分清:

  • 页面访问走 /,Nginx 转到 Dashboard。
  • API 访问走 /api/*,Nginx 转到 Mem0 API,并把 /api 前缀去掉。

一、目录和 Compose

建议把运行态目录和源码目录分开。运行态目录只放 Compose、.env、数据卷挂载说明,源码放到 install/repo,以后升级、回滚和排查会清楚很多。

mkdir -p /data/mem0
mkdir -p /data/mem0/install
cd /data/mem0/install

# 第一次部署时 clone 源码;已有 repo 时只拉最新代码。
if [ -d repo/.git ]; then
  git -C repo pull --ff-only
else
  git clone https://github.com/mem0ai/mem0.git repo
fi

# 回到运行态目录,后续 compose 和 .env 都放这里。
cd /data/mem0

把这个最小化的 Compose 写到 /data/mem0/compose.yaml。不同版本的 Mem0 目录可能略有变化,build.context 按你实际 clone 下来的路径调整即可。

cd /data/mem0

[ -f compose.yaml ] && cp -a compose.yaml "compose.yaml.before.$(date +%Y%m%d%H%M%S)"

cat > compose.yaml <<'YAML'
name: mem0

services:
  postgres:
    image: pgvector/pgvector:pg17
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    ports:
      - "127.0.0.1:${POSTGRES_HOST_PORT}:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data

  mem0:
    build:
      context: /data/mem0/install/repo/server
    restart: unless-stopped
    env_file:
      - .env
    depends_on:
      - postgres
    ports:
      - "127.0.0.1:${MEM0_API_HOST_PORT}:8000"

  mem0-dashboard:
    build:
      context: /data/mem0/install/repo/server/dashboard
    restart: unless-stopped
    environment:
      NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
      API_INTERNAL_URL: ${API_INTERNAL_URL}
    depends_on:
      - mem0
    ports:
      - "127.0.0.1:${MEM0_DASHBOARD_HOST_PORT}:3000"

volumes:
  postgres-data:
YAML

几个细节:

  • 三个端口都绑定 127.0.0.1,不要直接暴露到公网。
  • Compose project 固定为 mem0,后续 docker compose ps、日志、重启都好认。
  • Dashboard 前端会把 NEXT_PUBLIC_API_URL 打进构建产物,改了这个值以后要重建 dashboard。

二、.env 怎么填

.env 里放运行参数和密钥,权限建议收紧到 0600。下面这段可以直接复制,先把占位符替换成自己的值。

cd /data/mem0

[ -f .env ] && cp -a .env ".env.before.$(date +%Y%m%d%H%M%S)"

cat > .env <<'ENV'
MEM0_API_HOST_PORT=18888
MEM0_DASHBOARD_HOST_PORT=13000
POSTGRES_HOST_PORT=18432

OPENAI_API_KEY=<MODEL_GATEWAY_API_KEY>
OPENAI_BASE_URL=https://<OPENAI_COMPATIBLE_BASE_URL>/<gateway-api-prefix>

POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<POSTGRES_PASSWORD>
POSTGRES_COLLECTION_NAME=memories

ADMIN_API_KEY=<MEM0_ADMIN_API_KEY>
JWT_SECRET=<JWT_SECRET>
AUTH_DISABLED=false
APP_DB_NAME=mem0_app

MEM0_DEFAULT_LLM_MODEL=<CHAT_MODEL>
MEM0_DEFAULT_EMBEDDER_MODEL=text-embedding-3-small

DASHBOARD_URL=https://<mem0-domain>
NEXT_PUBLIC_API_URL=https://<mem0-domain>/api
API_INTERNAL_URL=http://mem0:8000
ENV

chmod 600 .env

这里最容易填错的是 OPENAI_BASE_URL。如果模型网关是 OpenAI-compatible 风格,通常要填公共前缀,不要填完整的 /chat/completions/embeddings endpoint。Mem0 侧调用 chat 和 embedding 时会在 base url 后面走对应接口。

改完 .env 后不要只保存文件,要按变更类型重启对应服务。先做 Compose 语法检查:

cd /data/mem0
docker compose config >/tmp/mem0-compose-config.out && echo compose_config_ok

首次启动,或者改了 Dockerfile、依赖、源码,用:

docker compose up -d --build
docker compose ps

如果只是改了后端运行时变量,例如 OPENAI_API_KEYOPENAI_BASE_URLMEM0_DEFAULT_LLM_MODELMEM0_DEFAULT_EMBEDDER_MODELJWT_SECRET,重建整个前端没有意义,重建或重建并重启 API 即可:

cd /data/mem0
docker compose up -d --force-recreate mem0
docker compose ps
docker compose logs --tail=100 mem0

如果改了 Dashboard 会在构建时读取的变量,例如 NEXT_PUBLIC_API_URLNEXT_PUBLIC_INSTANCE_NAME,要重建 Dashboard:

cd /data/mem0
docker compose up -d --build --force-recreate mem0-dashboard
docker compose ps
docker compose logs --tail=100 mem0-dashboard

如果改的是 POSTGRES_PASSWORD,要特别小心:PostgreSQL 数据目录已经初始化以后,单改 .env 不会自动修改已有数据库用户密码。生产环境不要直接删 volume。完整改密命令放在后面的“六、502 排错一:PostgreSQL 密码里的特殊字符”里。

服务起来后,至少做三类检查:

cd /data/mem0
docker compose ps

# API 健康检查。
curl -sS http://127.0.0.1:18888/auth/setup-status

# Dashboard 健康检查。
curl -sS http://127.0.0.1:13000/api/health

期望能看到三个容器:

mem0-mem0-1
mem0-mem0-dashboard-1
mem0-postgres-1

三、Nginx 反向代理

如果你的 Nginx 会 include /etc/nginx/conf.d/*.conf,可以直接写入下面这个配置;如果 include 目录不同,把 NGINX_MEM0_CONF 换成你的实际路径。

MEM0_DOMAIN='<mem0-domain>'
NGINX_MEM0_CONF='/etc/nginx/conf.d/mem0.conf'

[ -f "${NGINX_MEM0_CONF}" ] && \
  cp -a "${NGINX_MEM0_CONF}" "${NGINX_MEM0_CONF}.before.$(date +%Y%m%d%H%M%S)"

cat > "${NGINX_MEM0_CONF}" <<NGINX
server {
    listen 80;
    server_name ${MEM0_DOMAIN};

    client_max_body_size 50m;

    location ^~ /api/auth/refresh {
        proxy_pass http://127.0.0.1:13000;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:18888/;
        proxy_http_version 1.1;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }

    location / {
        proxy_pass http://127.0.0.1:13000;
        proxy_http_version 1.1;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }
}
NGINX

nginx -t
systemctl reload nginx

/api/ 这一段的 proxy_pass http://127.0.0.1:18888/; 末尾有 /,作用是把外部路径里的 /api/ 前缀去掉。也就是说:

https://<mem0-domain>/api/auth/setup-status

会转成后端的:

http://127.0.0.1:18888/auth/setup-status

如果你用的是 Mem0 自带 Dashboard,要额外注意上面这个 /api/auth/refresh 例外。这个路径不是普通后端 API,而是 Dashboard 自己的 Next.js API route,用来把 refresh token 写进 HttpOnly cookie。它需要放在通用 /api/ 规则前面,保留在 Dashboard 上,不能被转到 Mem0 后端。

location ^~ /api/auth/refresh {
    proxy_pass http://127.0.0.1:13000;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
}

如果你是手工修改已有 Nginx 配置,改完也要先检查再 reload:

nginx -t
systemctl reload nginx

四、初始化和页面配置

第一次打开 Dashboard 时,按页面提示创建管理员。后续模型配置可以在页面里填,也可以通过默认配置和数据库里的 settings.config_overrides 控制。

OpenAI-compatible Provider 的核心信息是:

Provider: OpenAI
Base URL: https://<OPENAI_COMPATIBLE_BASE_URL>/<gateway-api-prefix>
LLM model: <CHAT_MODEL>
Embedding model: text-embedding-3-small
API Key: <MODEL_GATEWAY_API_KEY>

注意这里和 RAGFlow 的 Provider 配置思路类似:Base URL 放公共前缀,模型名和 embedding 模型分别填,不要把完整 chat 或 embedding endpoint 塞进 Base URL。

五、部署后验证

Mem0 部署后的验证顺序

先验证本机服务,不要一上来就从浏览器排查。

cd /data/mem0
docker compose config >/tmp/mem0-compose-config.out && echo compose_config_ok
docker compose ps

API 健康检查:

curl -sS http://127.0.0.1:18888/auth/setup-status

未初始化时通常会看到:

{"needsSetup":true}

Dashboard 健康检查:

curl -sS http://127.0.0.1:13000/api/health

再验证 Nginx 到 API 的转发:

curl -sS -H 'Host: <mem0-domain>' \
  http://127.0.0.1/api/auth/setup-status

最后再做一次真正的记忆写入和检索。接口路径以你当前版本的 /api/docs 为准,常见形态如下:

curl -sS -X POST 'https://<mem0-domain>/api/memories/' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: <MEM0_ADMIN_API_KEY>' \
  -d '{
    "messages": [
      {"role": "user", "content": "User likes hiking on weekends."}
    ],
    "user_id": "demo-user"
  }'

再搜这条记忆:

curl -sS -X POST 'https://<mem0-domain>/api/search/' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: <MEM0_ADMIN_API_KEY>' \
  -d '{
    "query": "What outdoor activity does the user like?",
    "user_id": "demo-user"
  }'

如果返回结果里能看到刚才写入的 hiking on weekends,说明 API、LLM、embedding、pgvector 这几段链路已经闭合。

测试完记得删掉测试记忆:

curl -sS -X DELETE 'https://<mem0-domain>/api/memories/<MEMORY_ID>' \
  -H 'X-API-Key: <MEM0_ADMIN_API_KEY>'

六、502 排错一:PostgreSQL 密码里的特殊字符

我遇到的第一个现象是页面 Quick Test 报:

Test failed (502): Upstream provider error.

但看日志时,模型网关的 chat 和 embedding 请求都有 200 返回,所以问题不在“模型网关完全不可达”。

继续看 Mem0 API 日志,会看到类似这样误导性很强的错误:

failed to resolve host 'postgres': [Errno -8] Servname not supported for ai_socktype

这里表面像 Docker DNS 解析不了 postgres,但真正的问题可能是 PostgreSQL 密码里包含了 URL 保留字符。部分 Mem0/pgvector 初始化代码会拼出这种连接串:

postgresql://<user>:<password>@postgres:5432/postgres

如果 <password> 里有 @:/#? 这类字符,又没有 URL encode,psycopg 解析连接串时就可能把密码的一部分误认为 host、port 或路径,最后抛出看起来像 DNS 或 service name 的错误。

先不要急着改源码,先用 PostgreSQL 和容器网络命令把范围缩小。下面这些命令都在 Mem0 所在机器执行:

cd /data/mem0

# 1. Postgres 容器本身是否健康。
docker compose ps postgres
docker compose exec -T postgres pg_isready -U postgres -d postgres

# 2. 从 API 容器里解析 postgres 这个 Docker service 名。
docker compose exec -T mem0 getent hosts postgres

# 3. 直接用 psql 连数据库,确认用户名、库名和密码本身可用。
docker compose exec -T postgres psql -U postgres -d postgres -c '\conninfo'

# 4. 确认 pgvector 扩展存在。
docker compose exec -T postgres psql -U postgres -d postgres \
  -c "select extname, extversion from pg_extension where extname = 'vector';"

# 5. 看 Mem0 已经创建了哪些表,确认应用库是否初始化过。
docker compose exec -T postgres psql -U postgres -d mem0_app \
  -c "select schemaname, tablename from pg_tables where schemaname = 'public' order by tablename;"

如果 pg_isreadygetent hosts postgrespsql '\conninfo' 都正常,但 Mem0 API 日志仍然报 failed to resolve host 'postgres'Servname not supported for ai_socktype,这时就不要再按 Docker DNS 排查了,重点看应用里拼出来的 PostgreSQL URI。

可以用这个小脚本只检查密码是否含 URL 保留字符,不把密码打印出来:

cd /data/mem0
python3 - <<'PY'
from pathlib import Path

reserved = set(":/?#[]@!$&'()*+,;=")
password = ""
for line in Path(".env").read_text().splitlines():
    if line.startswith("POSTGRES_PASSWORD="):
        password = line.split("=", 1)[1]
        break

print("POSTGRES_PASSWORD exists:", bool(password))
print("POSTGRES_PASSWORD has URL reserved chars:", any(ch in reserved for ch in password))
PY

如果确认是密码字符导致连接串解析异常,或者想把数据库密码换成不含 URL 保留字符的新密码,按下面顺序处理。

先用 PostgreSQL CLI 修改数据库用户密码:

cd /data/mem0
docker compose exec -T postgres psql -U postgres -d postgres \
  -c "ALTER USER postgres WITH PASSWORD '<NEW_POSTGRES_PASSWORD>';"

预期输出:

ALTER ROLE

ALTER USER 在 PostgreSQL 里会落到 role 变更上,所以返回 ALTER ROLE 表示密码修改成功。

然后再改 .env

POSTGRES_PASSWORD=<NEW_POSTGRES_PASSWORD>

改完重启会连接 PostgreSQL 的服务:

cd /data/mem0
docker compose up -d --force-recreate mem0
docker compose ps
docker compose logs --tail=100 mem0

如果你的 Compose 把 PostgreSQL 容器的 POSTGRES_PASSWORD 作为环境变量传入,也可以顺手重建 Postgres 容器,但不要删除 volume:

cd /data/mem0
docker compose up -d --force-recreate postgres mem0
docker compose ps

最后验证新密码能连上。不要把真实密码写进命令历史;可以临时用环境变量:

cd /data/mem0
read -rsp 'New Postgres password: ' PGPASSWORD
echo
export PGPASSWORD

docker compose exec -T -e PGPASSWORD postgres \
  psql -h 127.0.0.1 -U postgres -d postgres -c '\conninfo'

unset PGPASSWORD

如果这是一次性测试环境,并且确认数据可以丢,才考虑重建 volume。生产环境不要用删除 volume 的方式处理密码问题;这会直接丢 PostgreSQL 数据。

修复思路是:构造连接串时对 user、password、dbname 做 URL encode。示例代码:

from urllib.parse import quote

POSTGRES_CONNECTION_STRING = (
    f"postgresql://{quote(POSTGRES_USER, safe='')}:{quote(POSTGRES_PASSWORD, safe='')}"
    f"@{POSTGRES_HOST}:{int(POSTGRES_PORT)}/{quote(POSTGRES_DB, safe='')}"
)

config = {
    "vector_store": {
        "provider": "pgvector",
        "config": {
            "host": POSTGRES_HOST,
            "port": int(POSTGRES_PORT),
            "dbname": POSTGRES_DB,
            "user": POSTGRES_USER,
            "password": POSTGRES_PASSWORD,
            "collection_name": POSTGRES_COLLECTION_NAME,
            "connection_string": POSTGRES_CONNECTION_STRING,
        },
    },
}

如果你使用的 Mem0 版本已经修复了这块,不需要改源码;如果仍然报这个错,先检查 .env 里的 POSTGRES_PASSWORD 是否包含 URL 保留字符,再看当前版本是否把 connection_string 原样拼接了。

修完以后重建 API:

cd /data/mem0
docker compose up -d --build mem0
docker compose logs -f mem0

然后重复验证数据库和 API:

cd /data/mem0
docker compose exec -T postgres pg_isready -U postgres -d postgres
curl -sS http://127.0.0.1:18888/auth/setup-status
docker compose logs --tail=100 mem0

七、502 排错二:GPT-5 风格模型不接受 top_p

第二个现象仍然是 Quick Test 报 502,但后端日志里可以看到另一个特征:

TypeError: 'NoneType' object is not subscriptable

继续看模型网关返回体,真实原因是模型不接受请求里的 top_p。有些网关会用 HTTP 200 包一层错误结构,OpenAI SDK 收到后没有正常的 choices,Mem0 后续再取 choices[0] 就变成了 NoneType

Mem0 的 LLM 配置里有一个关键项:

{
  "llm": {
    "provider": "openai",
    "config": {
      "model": "<CHAT_MODEL>",
      "is_reasoning_model": true
    }
  }
}

这个 is_reasoning_model 不是普通 .env 变量。它属于 Mem0 的运行时 LLM config。设置为 true 后,Mem0 会按 reasoning model 的方式组织参数,避免继续带上不兼容的 top_p

如果你希望默认按模型名判断,可以在服务端默认配置里这样写:

"llm": {
    "provider": "openai",
    "config": {
        "api_key": OPENAI_API_KEY,
        "temperature": 0.2,
        "model": DEFAULT_LLM_MODEL,
        "is_reasoning_model": DEFAULT_LLM_MODEL.lower().startswith("gpt-5"),
    },
},

如果已经通过 Dashboard 保存过配置,还要检查数据库里的覆盖配置。示例:

查看当前配置:

docker compose exec -T postgres psql -U postgres -d mem0_app \
  -c "select id, config_overrides from settings;"

is_reasoning_model 写进 LLM config:

docker compose exec -T postgres psql -U postgres -d mem0_app \
  -c "update settings
      set config_overrides = jsonb_set(
        coalesce(config_overrides, '{}'::jsonb),
        '{llm,config,is_reasoning_model}',
        'true'::jsonb,
        true
      );"

如果同时要确认模型名:

docker compose exec -T postgres psql -U postgres -d mem0_app \
  -c "update settings
      set config_overrides = jsonb_set(
        coalesce(config_overrides, '{}'::jsonb),
        '{llm,config,model}',
        '\"<CHAT_MODEL>\"'::jsonb,
        true
      );"

改完重启 API:

cd /data/mem0
docker compose restart mem0

再跑一次创建记忆和搜索记忆。如果日志里 /embeddings/chat/completions 都是正常返回,并且 pgvector 有写入,说明这段修好了。

八、登录 405:PUT /api/auth/refresh 被转到了后端 API

还有一个容易被误判成账号密码问题的坑:登录接口 POST /api/auth/login 返回 200,但页面仍然停在登录页,浏览器控制台看到:

PUT https://<mem0-domain>/api/auth/refresh 405 (Method Not Allowed)
Allow: POST

这个 405 的关键不是密码错,而是请求打错了服务。

Dashboard 登录成功后,会先调用后端 /auth/login 拿到 access_tokenrefresh_token,然后用:

PUT /api/auth/refresh

把 refresh token 交给 Dashboard 自己的 Next.js route,让它写入 HttpOnly cookie。这个 PUT 在 Dashboard 上是合法的。

但如果 Nginx 写了一个很宽的规则:

location /api/ {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://127.0.0.1:18888;
}

/api/auth/refresh 会被转成后端 API 的 /auth/refresh。后端 FastAPI 只定义了:

@router.post("/refresh", response_model=TokenResponse)
def refresh(...):
    ...

所以浏览器发 PUT,后端返回 405 Method Not Allowed,响应头里会带:

Allow: POST

验证方法:

# 直连 Dashboard,PUT 应该是 200,并返回 set-cookie。
curl -sS -D - -o /tmp/refresh-dashboard.out \
  -X PUT 'http://127.0.0.1:13000/api/auth/refresh' \
  -H 'Content-Type: application/json' \
  -d '{"refresh_token":"dummy"}'

# 直连后端,PUT 会是 405,POST 才会进入业务校验。
curl -sS -D - -o /tmp/refresh-api.out \
  -X PUT 'http://127.0.0.1:18888/auth/refresh' \
  -H 'Content-Type: application/json' \
  -d '{"refresh_token":"dummy"}'

修复就是上一节提到的 Nginx 例外:location ^~ /api/auth/refresh 走 Dashboard,其他 /api/* 继续走后端 API。

修完后再测:

curl -sS -D - -o /tmp/refresh-nginx.out \
  -X PUT 'http://127.0.0.1/api/auth/refresh' \
  -H 'Host: <mem0-domain>' \
  -H 'Content-Type: application/json' \
  -d '{"refresh_token":"dummy"}'

期望结果:

HTTP/1.1 200 OK
set-cookie: mem0_refresh_token=...

同时确认普通后端 API 仍然走后端:

curl -sS -H 'Host: <mem0-domain>' \
  http://127.0.0.1/api/auth/setup-status

这条应该仍然返回后端的 setup 状态,例如:

{"needsSetup":false}

九、Mem0 和 RAGFlow 的配置差异

这两个工具都可能要配置 OpenAI-compatible 模型网关,但它们解决的问题不一样。

对比项 Mem0 RAGFlow
核心目标 长期记忆 文档知识库 RAG
主要数据 用户偏好、历史事实、会话记忆 PDF、Word、网页、表格、扫描件等文档
典型入口 Memory API / SDK / Agent 集成 Dataset、Chat app、OpenAI-compatible Chat API
向量库用途 检索记忆 检索文档 chunk
模型配置重点 LLM + embedding + memory config Provider、默认模型、Dataset 解析
常见坑 reasoning 模型参数、pgvector 连接串 Base URL 拼接、embedding endpoint、Dataset 未绑定 Chat

简单理解:

  • RAGFlow 解决“我有一批文档,怎么让模型基于文档回答,并给出引用”。
  • Mem0 解决“这个用户或 Agent 以前说过什么、偏好是什么、长期事实是什么,怎么在后续对话里自动想起来”。

所以它们可以同时存在。RAGFlow 管知识库,Mem0 管个性化记忆;业务系统或 Agent 在生成回答前,分别从 RAGFlow 取文档依据,从 Mem0 取用户记忆。

快速参考

关键地址:

Dashboard: https://<mem0-domain>/
API:       https://<mem0-domain>/api
API Docs:  https://<mem0-domain>/api/docs

关键 .env

OPENAI_API_KEY=<MODEL_GATEWAY_API_KEY>
OPENAI_BASE_URL=https://<OPENAI_COMPATIBLE_BASE_URL>/<gateway-api-prefix>
MEM0_DEFAULT_LLM_MODEL=<CHAT_MODEL>
MEM0_DEFAULT_EMBEDDER_MODEL=text-embedding-3-small
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_COLLECTION_NAME=memories
NEXT_PUBLIC_API_URL=https://<mem0-domain>/api
API_INTERNAL_URL=http://mem0:8000

开工前检查:

docker --version
docker compose version
git --version
nginx -v

源码目录初始化或更新:

mkdir -p /data/mem0
mkdir -p /data/mem0/install
cd /data/mem0/install

# 第一次部署时 clone 源码;已有 repo 时只拉最新代码。
if [ -d repo/.git ]; then
  git -C repo pull --ff-only
else
  git clone https://github.com/mem0ai/mem0.git repo
fi

关键文件落盘后再启动:

cd /data/mem0

# compose.yaml 和 .env 按正文示例写入后,先检查配置。
docker compose config >/tmp/mem0-compose-config.out && echo compose_config_ok

# 首次启动或源码变更后启动。
docker compose up -d --build
docker compose ps

常用检查命令:

cd /data/mem0
docker compose config >/tmp/mem0-compose-config.out && echo compose_config_ok
docker compose ps
docker compose logs -f mem0

.env 后按变更范围重启:

# 后端运行时变量,例如 OPENAI_API_KEY、OPENAI_BASE_URL、默认模型。
docker compose up -d --force-recreate mem0

# Dashboard 构建期变量,例如 NEXT_PUBLIC_API_URL。
docker compose up -d --build --force-recreate mem0-dashboard

# 代码、依赖或 Dockerfile 变更。
docker compose up -d --build mem0 mem0-dashboard

PostgreSQL 改密:

cd /data/mem0
docker compose exec -T postgres psql -U postgres -d postgres \
  -c "ALTER USER postgres WITH PASSWORD '<NEW_POSTGRES_PASSWORD>';"
# 预期输出: ALTER ROLE

Nginx 405 例外:

location ^~ /api/auth/refresh {
    proxy_pass http://127.0.0.1:13000;
}

排错顺序可以直接复制下面这段。先把 MEM0_DOMAINMEM0_ADMIN_API_KEY 改成你的值:

cd /data/mem0

MEM0_DOMAIN='<mem0-domain>'
MEM0_ADMIN_API_KEY='<MEM0_ADMIN_API_KEY>'
MEM0_DEMO_USER='demo-user'

# 1. 检查 Compose 配置是否能正常渲染。
docker compose config >/tmp/mem0-compose-config.out && echo compose_config_ok

# 2. 检查容器状态。
docker compose ps

# 3. 检查 Mem0 API 本机端口。
curl -sS "http://127.0.0.1:18888/auth/setup-status"

# 4. 检查 Dashboard 本机端口。
curl -sS "http://127.0.0.1:13000/api/health"

# 5. 检查 Nginx Host 转发到 API 是否正常。
curl -sS -H "Host: ${MEM0_DOMAIN}" \
  "http://127.0.0.1/api/auth/setup-status"

# 6. 通过外部域名写入一条测试记忆。
curl -sS -X POST "https://${MEM0_DOMAIN}/api/memories/" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ${MEM0_ADMIN_API_KEY}" \
  -d "{
    \"messages\": [
      {\"role\": \"user\", \"content\": \"User likes hiking on weekends.\"}
    ],
    \"user_id\": \"${MEM0_DEMO_USER}\"
  }"

# 7. 搜索刚才写入的测试记忆。
curl -sS -X POST "https://${MEM0_DOMAIN}/api/search/" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ${MEM0_ADMIN_API_KEY}" \
  -d "{
    \"query\": \"What outdoor activity does the user like?\",
    \"user_id\": \"${MEM0_DEMO_USER}\"
  }"

# 8. 如果上一步返回里有测试记忆 id,测试完删除它。
MEMORY_ID='<MEMORY_ID_FROM_SEARCH_RESULT>'
curl -sS -X DELETE "https://${MEM0_DOMAIN}/api/memories/${MEMORY_ID}" \
  -H "X-API-Key: ${MEM0_ADMIN_API_KEY}"

易错点:

  • OPENAI_BASE_URL 填公共前缀,不要填完整 /chat/completions
  • is_reasoning_model=true 不是 .env 自动生效项,它要进入 Mem0 的 LLM runtime config。
  • PostgreSQL 密码包含特殊字符时,连接串里的用户名、密码、库名要 URL encode。
  • Dashboard 的 NEXT_PUBLIC_API_URL 改了以后要重建前端。
  • API、Dashboard、Postgres 端口默认只监听 127.0.0.1,公网入口交给 Nginx 或 LB。

参考:

posted @ 2026-07-09 15:16  Hello_worlds  阅读(45)  评论(0)    收藏  举报