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

这张图里有两条路径要分清:
- 页面访问走
/,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_KEY、OPENAI_BASE_URL、MEM0_DEFAULT_LLM_MODEL、MEM0_DEFAULT_EMBEDDER_MODEL、JWT_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_URL、NEXT_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。
五、部署后验证

先验证本机服务,不要一上来就从浏览器排查。
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_isready、getent hosts postgres、psql '\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_token 和 refresh_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_DOMAIN、MEM0_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。
参考:
- Mem0 官方文档:https://docs.mem0.ai/introduction
- Mem0 GitHub:https://github.com/mem0ai/mem0
- Mem0 Open Source setup:https://docs.mem0.ai/open-source/setup

浙公网安备 33010602011771号