Files
memory-gateway/README.md

781 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Memory Gateway
Memory Gateway 是一个轻量级记忆网关项目,用统一的 HTTP API 把上层应用接到两个记忆后端:
- OpenViking负责会话归档、长期记忆抽取、按 `user_id / session_id` 隔离的语义检索。
- EverOS负责用户画像、episodic memory、profile 查询等补充记忆能力。
当前重点模块是 `memory_system_api`。它不是 OpenViking 的替代品,而是一个更窄的业务网关:上层只面对 user、user key、session 和 message网关内部为每个业务用户创建独立的 OpenViking admin account。
## 核心模型
### 身份字段
| 字段 | 含义 | 是否自定义 | 备注 |
|---|---|---:|---|
| `user_id` | 真实终端用户 | 是 | 先通过 `/users` 创建后续写入、查询、commit 时使用 |
| `user_key` | OpenViking 返回的用户 key | 否 | `/users` 返回并写入 SQLite业务调用时随请求体或 query 传入 |
| `session_id` | 一次会话 ID | 是 | OpenViking session 容器,同时用于带 session context 的搜索 |
建议 ID 只使用字母、数字、`_``-``.``@`,不要使用空格、斜杠或中文。
### 先创建用户再使用
除健康检查外,业务调用分两步:
1. 调用 `POST /memory-system/users` 创建 OpenViking user。
2. 保存返回的 `user_key`后续写入消息、commit、extract、task、search、profile 都传 `user_id + user_key`,不需要传 `account_id`
如果没有先创建 user或者 `user_key` 与数据库里的 `user_id` 不匹配,`messages``commit``extract``tasks``search``profile` 都会返回 `401`
创建业务 user 时,网关直接为该用户创建一个独立 OpenViking account。默认 `account_id``<user_id>_account``admin_user_id` 是传入的 `user_id`
```http
POST /api/v1/admin/accounts
{"account_id": "<user_id>_account", "admin_user_id": "<user_id>"}
```
网关不再调用 `/api/v1/admin/accounts/admin/users`。所有返回的 `admin_user_id / user_key`、创建过的 `session_id`、commit 返回的 `task_id / archive_uri` 都写入 SQLite不放在进程内缓存里。
### 鉴权
Memory Gateway 有两类 key
| Key | 请求头 | 用途 | 是否必需 |
|---|---|---|---|
| Memory System API key | `X-API-Key` | 保护 Memory Gateway 服务本身 | 仅当 `server.api_key` 配置非空时需要 |
| OpenViking user key | 请求体/query 的 `user_key` | 校验具体用户并调用 OpenViking 普通用户 API | 除 `/health``/users` 外都需要 |
OpenViking 的 root key 配在服务端 `config.yaml` 中,由网关内部使用。调用方不需要也不应该在业务请求中传 OpenViking root key。
OpenViking 内部调用遵循:
| OpenViking 场景 | 鉴权 |
|---|---|
| Admin API例如创建 account | `X-API-Key: <openviking root key>` |
| 普通用户 API例如 session/message/commit/task/search | `X-API-Key: <openviking user key>` |
### Session 与搜索范围
OpenViking session 由请求里的 `session_id` 创建和提交。`/memory-system/search` 的 OpenViking 分支固定调用 OpenViking `/api/v1/search/search``target_uri` 可选,默认是 `viking://user/memories`,并默认传 `level: 2``score_threshold: 0.8`
## 本地三服务安装
Memory Gateway 需要先连上两个后端服务。默认本地端口约定:
| 服务 | 默认地址 | 作用 |
|---|---|---|
| OpenViking | `http://127.0.0.1:1933` | session、archive、long-term memory、resources、semantic search |
| EverOS EverCore | `http://127.0.0.1:1995` | profile、episodic memory、recall |
| Memory Gateway | `http://127.0.0.1:1934` | 对业务方暴露统一 `/memory-system` API |
### 安装 OpenViking
OpenViking 可以直接用 `pip install` 安装,不需要 clone 源码。Memory Gateway 只依赖它暴露 HTTP API 和一个服务端 root key
```bash
python -m venv /Users/tom/.venvs/openviking
source /Users/tom/.venvs/openviking/bin/activate
pip install -U pip
pip install openviking --upgrade --force-reinstall
```
如果本机已经有 OpenViking 源码或已安装的 `openviking-server`,可以跳过安装,直接确认 `openviking-server --help` 可用。
### 安装 EverOS / EverCore
Memory Gateway 使用 EverOS 里的 EverCore HTTP 服务。按 [EverOS / EverCore Quick Start](https://github.com/EverMind-AI/EverOS#evercore)
```bash
git clone https://github.com/EverMind-AI/EverOS.git /Users/tom/projects/EverOS
cd /Users/tom/projects/EverOS/methods/EverCore
# 需要 Docker 和 Python 3.12。
cp /Users/tom/projects/memory-gateway/everos.env.example .env
# 编辑 .env至少填入实际可用的 LLM_API_KEY 和 VECTORIZE_API_KEY。
docker compose up -d
uv sync
```
如果 EverOS 已经在本机存在,只需要进入 `methods/EverCore` 并补齐 `.env`
### 安装 Memory Gateway
```bash
cd /Users/tom/projects/memory-gateway
python -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e ".[dev]"
```
也可以用 `uv`
```bash
uv sync --extra dev
```
## 配置文件
### OpenViking 配置
Memory Gateway 仓库内提供 OpenViking 配置模板:
```bash
mkdir -p ~/.openviking
cp /Users/tom/projects/memory-gateway/openviking.ov.conf.example ~/.openviking/ov.conf
```
然后编辑 `~/.openviking/ov.conf`,至少替换:
| 占位符 | 含义 |
|---|---|
| `<OPENVIKING_ROOT_KEY>` | OpenViking root key必须和 Memory Gateway `config.yaml` 里的 `openviking.api_key` 一致 |
| `<EMBEDDING_PROVIDER>` / `<EMBEDDING_API_BASE>` / `<EMBEDDING_API_KEY>` / `<EMBEDDING_MODEL>` | OpenViking embedding provider 配置 |
| `<VLM_PROVIDER>` / `<VLM_API_BASE>` / `<VLM_API_KEY>` / `<VLM_MODEL>` | OpenViking VLM provider 配置 |
| `<RERANK_PROVIDER>` / `<RERANK_API_BASE>` / `<RERANK_API_KEY>` / `<RERANK_MODEL>` | OpenViking rerank provider 配置 |
配置好后先跑一次:
```bash
openviking-server doctor
```
`root_api_key` 只放在 OpenViking 和 Memory Gateway 的服务端配置里。业务调用方不要传 root key。
### EverOS / EverCore 配置
Memory Gateway 仓库内也提供 EverOS / EverCore 的 `.env` 模板。复制到 EverCore 目录:
```bash
cd /Users/tom/projects/EverOS/methods/EverCore
cp /Users/tom/projects/memory-gateway/everos.env.example .env
```
然后编辑 `.env`,至少填入 `LLM_API_KEY``LLM_MODEL``VECTORIZE_API_KEY``EMBEDDING_MODEL``RERANK_MODEL`。Docker 依赖地址默认使用模板里的本地 compose 端口;如果改过 EverCore 的 compose 配置,需要同步修改 `.env`
### Memory Gateway 配置
复制 Gateway 配置模板:
```bash
cd /Users/tom/projects/memory-gateway
cp config.example.yaml config.yaml
```
然后编辑 `config.yaml`
```yaml
server:
host: "127.0.0.1"
port: 1934
api_key: ""
openviking:
url: "http://127.0.0.1:1933"
api_key: "<OPENVIKING_ROOT_KEY>"
timeout: 30
verify_ssl: true
everos:
url: "http://127.0.0.1:1995"
api_key: ""
timeout: 180
verify_ssl: true
health_path: "/health"
storage:
sqlite_path: "./memory_system_api.sqlite3"
```
环境变量也可以覆盖部分配置:
| 环境变量 | 覆盖字段 |
|---|---|
| `MEMORY_SYSTEM_SERVER_API_KEY` | `server.api_key` |
| `MEMORY_SYSTEM_SERVER_HOST` | `server.host` |
| `MEMORY_SYSTEM_SERVER_PORT` | `server.port` |
| `OPENVIKING_URL` / `OPENVIKING_BASE_URL` | `openviking.url` |
| `OPENVIKING_API_KEY` | `openviking.api_key` |
| `EVEROS_URL` / `EVEROS_BASE_URL` | `everos.url` |
| `EVEROS_API_KEY` | `everos.api_key` |
| `MEMORY_SYSTEM_STORAGE_SQLITE_PATH` | `storage.sqlite_path` |
## 启动
按依赖顺序启动三个服务。
终端 1启动 OpenViking。
```bash
source /Users/tom/.venvs/openviking/bin/activate
openviking-server --config ~/.openviking/ov.conf
```
如果使用 Docker 方式运行 OpenViking确认对 Memory Gateway 暴露的是 `1933` 端口,避免和 Memory Gateway 的 `1934` 端口冲突。
终端 2启动 EverOS / EverCore。
```bash
cd /Users/tom/projects/EverOS/methods/EverCore
docker compose up -d
uv run python src/run.py --port 1995
```
终端 3启动 Memory Gateway。
```bash
cd /Users/tom/projects/memory-gateway
source .venv/bin/activate
python -m memory_system_api.server --config config.yaml --host 0.0.0.0 --port 1934
```
健康检查:
```bash
curl -sS http://127.0.0.1:1933/health
curl -sS http://127.0.0.1:1995/health
curl -sS http://127.0.0.1:1934/memory-system/health
```
如果 `server.api_key` 非空,所有请求还要加:
```bash
-H "X-API-Key: <memory-system-api-key>"
```
## API 总览
Base URL
```text
http://127.0.0.1:1934/memory-system
```
下面的示例默认先设置:
```bash
API=http://127.0.0.1:1934/memory-system
```
| 方法 | 路径 | 作用 | User key |
|---|---|---|---|
| `GET` | `/health` | 检查 OpenViking 和 EverOS 健康状态 | 不需要 |
| `POST` | `/users` | 在固定 `admin` 工作区创建 OpenViking user并保存 user key | 不需要 |
| `POST` | `/messages` | 写入一轮或半轮会话消息 | 需要 |
| `POST` | `/sessions/{session_id}/commit` | 提交会话,触发 OpenViking commit 和 EverOS flush | 需要 |
| `POST` | `/sessions/{session_id}/extract` | 立即触发 OpenViking extract | 需要 |
| `GET/POST` | `/sessions/{session_id}/context` | 查询 OpenViking 会话上下文,并用同一 query 搜索 EverOS 记忆 | 需要 |
| `GET/POST` | `/openviking/tasks/{task_id}` | 查询 OpenViking 后台任务状态 | 需要 |
| `GET` | `/memories` | 列出 OpenViking memory URI | 需要 |
| `GET` | `/memories/content` | 读取某条 memory 内容 | 需要 |
| `POST` | `/memories` | 创建、覆盖或追加写入 memory | 需要 |
| `DELETE` | `/memories` | 删除某条 memory URI | 需要 |
| `POST` | `/resources` | 上传本地文件或远程 URL 到 OpenViking resources | 需要 |
| `DELETE` | `/resources` | 删除 OpenViking resource URI | 需要 |
| `POST` | `/search` | 同时搜索 OpenViking 和 EverOS 记忆 | 需要 |
| `GET/POST` | `/users/{user_id}/profile` | 查询 EverOS profile并补充 OpenViking 用户记忆搜索结果 | 需要 |
## API 详情
### `GET /health`
检查两个后端是否可访问。
```bash
curl -sS "$API/health"
```
返回字段:
| 字段 | 含义 |
|---|---|
| `status` | `success``partial_success``failed` |
| `backends.openviking` | OpenViking 健康检查结果 |
| `backends.everos` | EverOS 健康检查结果 |
### `POST /users`
创建新的 OpenViking admin account并把返回的 `admin_user_id / user_key` 保存到本地 SQLite。
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 要创建的用户 ID |
示例:
```bash
curl -sS -X POST "$API/users" \
-H "Content-Type: application/json" \
-d '{"user_id":"userA"}'
```
返回中的 `account.result.user_key` 是后续业务调用要传的 `user_key`
```json
{
"status": "success",
"account": {
"status": "ok",
"result": {
"account_id": "userA_account",
"admin_user_id": "userA",
"user_key": "..."
}
}
}
```
### `POST /messages`
写入用户消息和/或助手消息。至少要传 `user_message``assistant_message` 其中一个。网关会先确保 OpenViking user/session 存在,再把消息写入 OpenViking session同时写入 EverOS。
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 已创建的用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `session_id` | string | 是 | 会话 ID |
| `user_message` | string/null | 否 | 用户消息 |
| `assistant_message` | string/null | 否 | 助手消息 |
| `timestamp` | int/null | 否 | 预留字段 |
| `metadata` | object | 否 | 预留字段 |
示例:
```bash
USER_KEY="..."
curl -sS -X POST "$API/messages" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"session_id": "sessionA1",
"user_message": "请记住:我喜欢拿铁。",
"assistant_message": "好的,我记住了。"
}'
```
### `POST /sessions/{session_id}/commit`
提交会话。OpenViking 会归档 session 并异步抽取长期记忆,通常会返回 `task_id`EverOS 会 flush 当前 session。
路径参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| `session_id` | string | 要提交的会话 ID |
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
示例:
```bash
curl -sS -X POST "$API/sessions/sessionA1/commit" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'"
}'
```
如果返回里有 OpenViking `task_id`,需要继续查询任务直到完成。
### `POST /sessions/{session_id}/extract`
立即触发 OpenViking extract只作用于 OpenViking不触发 EverOS flush。适合调试或明确要求“现在就抽取”的场景。
参数同 commit
```bash
curl -sS -X POST "$API/sessions/sessionA1/extract" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'"
}'
```
### `GET/POST /sessions/{session_id}/context`
查询一次会话的当前上下文。网关会调用 OpenViking
```http
GET /api/v1/sessions/{session_id}/context
X-API-Key: <user_key>
```
同时用同一个 `query` 调用 EverOS `/api/v1/memories/search`,返回相关 episodic/profile/raw message 记忆。适合在回答用户问题前,把“当前 session 工作记忆”和“EverOS 相关记忆”一起取回。
路径参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| `session_id` | string | 要查询的会话 ID |
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `query` | string | 是 | 用于 EverOS search 的查询文本 |
| `limit` | int | 否 | EverOS 记忆返回条数,默认 10范围 1 到 100 |
POST 示例:
```bash
curl -sS -X POST "$API/sessions/sessionA1/context" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"query": "我喜欢喝什么?",
"limit": 10
}'
```
返回字段:
| 字段 | 含义 |
|---|---|
| `context` | OpenViking `result`,包含 `latest_archive_overview``pre_archive_abstracts``messages``stats` |
| `items` | EverOS 搜索命中的精简记忆结果,含 `source_backend: "everos"` |
| `backends` | 两个后端的精简诊断信息,不重复返回完整 OpenViking context 或 EverOS `original_data` |
### `GET/POST /openviking/tasks/{task_id}`
查询 OpenViking 后台任务状态,例如 commit 返回的任务。
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `session_id` | string/null | 否 | 会话 ID传入后会按同一 session identity 查询 |
示例:
```bash
curl -sS -X POST "$API/openviking/tasks/${TASK_ID}" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"session_id": "sessionA1"
}'
```
### `GET /memories`
列出 OpenViking memory URI。网关会调用 OpenViking
```http
GET /api/v1/fs/ls?uri=viking://user/memories&recursive=true
X-API-Key: <user_key>
```
Query 参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `uri` | string | 否 | 要列出的 memory 根 URI默认 `viking://user/memories` |
| `recursive` | bool | 否 | 是否递归列出,默认 `true` |
示例:
```bash
curl -sS -G "$API/memories" \
--data-urlencode "user_id=userA" \
--data-urlencode "user_key=$USER_KEY" \
--data-urlencode "uri=viking://user/memories" \
--data-urlencode "recursive=true"
```
### `GET /memories/content`
读取某条 memory 内容。先用 `/memories``/search` 找到 `viking://user/memories/...` URI再读取
```bash
curl -sS -G "$API/memories/content" \
--data-urlencode "user_id=userA" \
--data-urlencode "user_key=$USER_KEY" \
--data-urlencode "uri=viking://user/memories/preferences/python.md"
```
### `POST /memories`
创建、覆盖或追加写入 memory。网关会调用 OpenViking `/api/v1/content/write`,写入后由 OpenViking 刷新语义和向量索引。
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `uri` | string | 是 | 目标 memory URI例如 `viking://user/memories/profile.md` |
| `content` | string | 是 | 要写入的 Markdown/text 内容 |
| `mode` | `create`/`replace`/`append` | 否 | 写入模式,默认 `create` |
| `wait` | bool | 否 | 是否等待索引刷新,默认 `true` |
覆盖修改:
```bash
curl -sS -X POST "$API/memories" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"uri": "viking://user/memories/preferences/python.md",
"content": "# Python 偏好\n\n用户偏好使用 Python 做数据分析,常用 pandas。",
"mode": "replace",
"wait": true
}'
```
追加补充时把 `mode` 改为 `append`;新增 memory 时可用默认的 `create`
### `DELETE /memories`
删除某条 memory。默认非递归删除如果 OpenViking 提示目标是目录或复合资源,再把 `recursive` 设为 `true`
```bash
curl -sS -X DELETE -G "$API/memories" \
--data-urlencode "user_id=userA" \
--data-urlencode "user_key=$USER_KEY" \
--data-urlencode "uri=viking://user/memories/preferences/python.md" \
--data-urlencode "recursive=false"
```
返回中的 `memory` 是 OpenViking 对应接口的原始响应。
### `POST /resources`
上传文件资源到 OpenViking。网关只调用 OpenViking不写 EverOS。
如果 `path` 是本地路径,文件必须能被 Memory System API 服务进程读取。网关会先调用 OpenViking `/api/v1/resources/temp_upload` 上传临时文件,取返回的 `temp_file_id`,再调用 `/api/v1/resources` 添加资源。
如果 `path``http://``https://` URL网关会直接调用 OpenViking `/api/v1/resources`,并把 URL 作为 `path` 传给 OpenViking。
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `path` | string | 是 | 本地文件路径,或 `http://` / `https://` URL |
| `to` | string | 是 | 目标 OpenViking resource URI |
| `reason` | string/null | 否 | 上传原因,透传给 OpenViking |
| `wait` | bool | 否 | 是否等待处理完成,默认 `true` |
| `directly_upload_media` | bool | 否 | 是否直接上传媒体,默认 `true` |
本地文件示例:
```bash
curl -sS -X POST "$API/resources" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"path": "/home/tom/memory-gateway/tests/大语言模型应用.pdf",
"to": "viking://resources/userA/files/大语言模型应用.pdf",
"reason": "userA 上传的文件",
"wait": true,
"directly_upload_media": true
}'
```
远程 URL 示例:
```bash
curl -sS -X POST "$API/resources" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"path": "https://example.com/images/photo.png",
"to": "viking://resources/userA/images/photo.png",
"reason": "userA 上传的远程图片",
"wait": true,
"directly_upload_media": true
}'
```
返回中的 `resource` 是 OpenViking `/api/v1/resources` 的原始响应,`backends.openviking` 保留调用状态和错误信息。
### `DELETE /resources`
删除 OpenViking resource URI。网关会调用 OpenViking
```http
DELETE /api/v1/fs?uri=<OPENVIKING_URI>&recursive=<true|false>
X-API-Key: <user_key>
```
Query 参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `uri` | string | 是 | 要删除的 OpenViking URI |
| `recursive` | bool | 否 | 是否递归删除,默认 `true` |
示例:
```bash
curl -sS -X DELETE -G "$API/resources" \
--data-urlencode "user_id=userA" \
--data-urlencode "user_key=$USER_KEY" \
--data-urlencode "uri=viking://resources/userA/files/大语言模型应用.pdf" \
--data-urlencode "recursive=true"
```
返回中的 `resource` 是 OpenViking `/api/v1/fs` 删除接口的原始响应。
### `POST /search`
同时查询 OpenViking 和 EverOS并合并结果。
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `session_id` | string/null | 否 | 会话 ID用于 EverOS 过滤和鉴权身份 |
| `query` | string | 是 | 查询文本 |
| `use_llm` | bool | 否 | 只影响 EverOS 检索方式:`false` 使用 hybrid`true` 使用 agentic |
| `limit` | int | 否 | 返回条数,默认 10范围 1 到 100 |
| `level` | int | 否 | OpenViking search level默认 2 |
| `score_threshold` | float | 否 | OpenViking 最低分数阈值,默认 0.8,范围 0 到 1 |
| `target_uri` | string | 否 | OpenViking 搜索范围,默认 `viking://user/memories` |
示例:
```bash
curl -sS -X POST "$API/search" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"session_id": "sessionA1",
"query": "我喜欢喝什么?",
"use_llm": false,
"limit": 10,
"level": 2,
"score_threshold": 0.8,
"target_uri": "viking://user/memories"
}'
```
返回字段:
| 字段 | 含义 |
|---|---|
| `status` | 总体状态 |
| `items` | 合并后的记忆结果,含 `source_backend` |
| `backends` | 两个后端的精简诊断信息例如命中数量、query plan 或查询过滤条件;不再回传完整原始命中和 `original_data` |
### `GET/POST /users/{user_id}/profile`
读取用户画像。该接口需要 `user_key`,用于确认调用方属于该 user。网关会读取 EverOS profile并用同一个 `query` 调 OpenViking `/api/v1/search/search`,固定传 `target_uri: viking://user/memories``level`
请求体:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
| `user_key` | string | 是 | `/users` 返回的 user key |
| `query` | string | 否 | OpenViking 搜索文本,默认 `用户画像` |
| `limit` | int | 否 | OpenViking 返回条数,默认 10范围 1 到 100 |
| `level` | int | 否 | OpenViking search level默认 2 |
示例:
```bash
curl -sS -X POST "$API/users/userA/profile" \
-H "Content-Type: application/json" \
-d '{
"user_key": "'"$USER_KEY"'",
"query": "我想喝东西",
"limit": 10,
"level": 2
}'
```
返回中的 `profile` 是 EverOS profile 原始结果,`items` 是 OpenViking 命中的用户记忆,`backends` 只保留两个后端的状态和计数诊断,不重复返回完整 EverOS profile 或 OpenViking 命中列表。
## 完整测试流程
```bash
API=http://127.0.0.1:1934/memory-system
curl -sS -X POST "$API/users" \
-H "Content-Type: application/json" \
-d '{"user_id":"userA"}'
USER_KEY="把上一步返回的 account.result.user_key 填到这里"
curl -sS -X POST "$API/messages" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"session_id": "sessionA1",
"user_message": "请记住:我在 sessionA1 喜欢拿铁,项目代号 alpha-session。",
"assistant_message": "好的。"
}'
curl -sS -X POST "$API/sessions/sessionA1/commit" \
-H "Content-Type: application/json" \
-d '{"user_id":"userA","user_key":"'"$USER_KEY"'"}'
curl -sS -X POST "$API/search" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"session_id": "sessionA1",
"query": "我喜欢喝什么?",
"limit": 10
}'
```
OpenViking commit 返回 `task_id` 后,轮询到 `completed` 再搜索长期 memory
```bash
curl -sS -X POST "$API/openviking/tasks/<task_id>" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
"user_key": "'"$USER_KEY"'",
"session_id": "sessionA1"
}'
```
## 开发检查
```bash
PYTHONPATH=/home/tom/memory-gateway pytest -q
python -m compileall -q memory_system_api plugins eval tests
```
## Hermes Plugin 状态
仓库里仍保留 Hermes memory provider`plugins/memory/memory_system`
注意Memory System API 已切换为 `user_id + user_key` 鉴权plugin 代码如需继续使用,需要同步传递这两个字段。