Refactor OpenViking Memory API and User Management

- Updated API authentication headers to use `X-API-Key` for both admin and user APIs.
- Modified the account creation process to directly create user-specific accounts without requiring an admin workspace.
- Enhanced user creation to return account-specific details, including `admin_user_id`.
- Introduced new endpoints for retrieving task status and user profiles, allowing for more flexible user data management.
- Updated search functionality to include additional parameters such as `level` and `score_threshold`.
- Improved the handling of user keys in the storage layer to associate them with specific accounts.
- Added tests to validate the new user account creation process and search functionalities, ensuring proper integration with the OpenViking service.
- Included new documentation to reflect changes in API usage and expected request/response formats.
This commit is contained in:
2026-05-27 16:09:28 +08:00
parent a89807b174
commit 70cda923b2
13 changed files with 543 additions and 165 deletions

113
README.md
View File

@ -5,7 +5,7 @@ Memory Gateway 是一个轻量级记忆网关项目,用统一的 HTTP API 把
- OpenViking负责会话归档、长期记忆抽取、按 `user_id / session_id` 隔离的语义检索。
- EverOS负责用户画像、episodic memory、profile 查询等补充记忆能力。
当前重点模块是 `memory_system_api`。它不是 OpenViking 的替代品,而是一个更窄的业务网关:上层只面对 user、user key、session 和 message网关内部固定使用 OpenViking `admin` 工作区
当前重点模块是 `memory_system_api`。它不是 OpenViking 的替代品,而是一个更窄的业务网关:上层只面对 user、user key、session 和 message网关内部为每个业务用户创建独立的 OpenViking admin account
## 核心模型
@ -28,21 +28,14 @@ Memory Gateway 是一个轻量级记忆网关项目,用统一的 HTTP API 把
如果没有先创建 user或者 `user_key` 与数据库里的 `user_id` 不匹配,`messages``commit``extract``tasks``search``profile` 都会返回 `401`
第一次创建业务 user 时,如果 SQLite 里还没有 OpenViking `admin` 工作区记录,网关会先调用 OpenViking
创建业务 user 时,网关直接为该用户创建一个独立 OpenViking account。默认 `account_id``<user_id>_account``admin_user_id` 是传入的 `user_id`
```http
POST /api/v1/admin/accounts
{"account_id": "admin", "admin_user_id": "admin"}
{"account_id": "<user_id>_account", "admin_user_id": "<user_id>"}
```
随后创建具体用户:
```http
POST /api/v1/admin/accounts/admin/users
{"user_id": "<user_id>", "role": "user"}
```
后续创建第二、第三个用户时,网关直接调用 `/api/v1/admin/accounts/admin/users`。所有返回的 `user_id / user_key`、创建过的 `session_id`、commit 返回的 `task_id / archive_uri` 都写入 SQLite不放在进程内缓存里。
网关不再调用 `/api/v1/admin/accounts/admin/users`。所有返回的 `admin_user_id / user_key`、创建过的 `session_id`、commit 返回的 `task_id / archive_uri` 都写入 SQLite不放在进程内缓存里。
### 鉴权
@ -59,12 +52,12 @@ OpenViking 内部调用遵循:
| OpenViking 场景 | 鉴权 |
|---|---|
| Admin API例如创建 account/user | `X-API-Key: <openviking root key>` |
| 普通用户 API例如 session/message/commit/task/search | `Authorization: Bearer <openviking user key>` |
| 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 路径 `viking://user/<user_id>/memories/``use_llm=true` 的智能搜索会同时传 `session_id``target_uri: viking://user/<user_id>/<session_id>`,用于结合当前 session context
OpenViking session 由请求里的 `session_id` 创建和提交。`/memory-system/search` 的 OpenViking 分支固定调用 OpenViking `/api/v1/search/search``target_uri` 可选,默认是 `viking://user/memories`,并默认传 `level: 2``score_threshold: 0.8`
## 安装
@ -127,7 +120,7 @@ storage:
先启动 OpenViking 和 EverOS再启动 Memory System API
```bash
python -m memory_system_api.server --config config.yaml --host 127.0.0.1 --port 1934
python -m memory_system_api.server --config config.yaml --host 0.0.0.0 --port 1934
```
如果 `server.api_key` 非空,所有请求还要加:
@ -144,6 +137,12 @@ Base URL
http://127.0.0.1:1934/memory-system
```
下面的示例默认先设置:
```bash
API=http://127.0.0.1:1934/memory-system
```
| 方法 | 路径 | 作用 | User key |
|---|---|---|---|
| `GET` | `/health` | 检查 OpenViking 和 EverOS 健康状态 | 不需要 |
@ -152,9 +151,9 @@ http://127.0.0.1:1934/memory-system
| `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` | `/openviking/tasks/{task_id}` | 查询 OpenViking 后台任务状态 | 需要 |
| `GET/POST` | `/openviking/tasks/{task_id}` | 查询 OpenViking 后台任务状态 | 需要 |
| `POST` | `/search` | 同时搜索 OpenViking 和 EverOS 记忆 | 需要 |
| `GET` | `/users/{user_id}/profile` | 查询 EverOS profile | 需要 |
| `GET/POST` | `/users/{user_id}/profile` | 查询 EverOS profile,并补充 OpenViking 用户记忆搜索结果 | 需要 |
## API 详情
@ -163,7 +162,7 @@ http://127.0.0.1:1934/memory-system
检查两个后端是否可访问。
```bash
curl -sS http://127.0.0.1:1934/memory-system/health
curl -sS "$API/health"
```
返回字段:
@ -176,7 +175,7 @@ curl -sS http://127.0.0.1:1934/memory-system/health
### `POST /users`
创建新的 OpenViking user,并把返回的 `user_id / user_key` 保存到本地 SQLite。
创建新的 OpenViking admin account,并把返回的 `admin_user_id / user_key` 保存到本地 SQLite。
请求体:
@ -187,9 +186,9 @@ curl -sS http://127.0.0.1:1934/memory-system/health
示例:
```bash
curl -sS -X POST http://127.0.0.1:1934/memory-system/users \
curl -sS -X POST "$API/users" \
-H "Content-Type: application/json" \
-d '{"user_id": "userA"}'
-d '{"user_id":"userA"}'
```
返回中的 `account.result.user_key` 是后续业务调用要传的 `user_key`
@ -200,8 +199,8 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/users \
"account": {
"status": "ok",
"result": {
"account_id": "admin",
"user_id": "userA",
"account_id": "userA_account",
"admin_user_id": "userA",
"user_key": "..."
}
}
@ -229,7 +228,7 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/users \
```bash
USER_KEY="..."
curl -sS -X POST http://127.0.0.1:1934/memory-system/messages \
curl -sS -X POST "$API/messages" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
@ -260,7 +259,7 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/messages \
示例:
```bash
curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/commit \
curl -sS -X POST "$API/sessions/sessionA1/commit" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
@ -277,7 +276,7 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/commit \
参数同 commit
```bash
curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/extract \
curl -sS -X POST "$API/sessions/sessionA1/extract" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
@ -291,7 +290,7 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/extract
```http
GET /api/v1/sessions/{session_id}/context
Authorization: Bearer <user_key>
X-API-Key: <user_key>
```
同时用同一个 `query` 调用 EverOS `/api/v1/memories/search`,返回相关 episodic/profile/raw message 记忆。适合在回答用户问题前,把“当前 session 工作记忆”和“EverOS 相关记忆”一起取回。
@ -314,7 +313,7 @@ Authorization: Bearer <user_key>
POST 示例:
```bash
curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/context \
curl -sS -X POST "$API/sessions/sessionA1/context" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
@ -324,12 +323,6 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/context
}'
```
GET 示例:
```bash
curl -sS "http://127.0.0.1:1934/memory-system/sessions/sessionA1/context?user_id=userA&user_key=$USER_KEY&query=我喜欢喝什么?&limit=10"
```
返回字段:
| 字段 | 含义 |
@ -338,11 +331,11 @@ curl -sS "http://127.0.0.1:1934/memory-system/sessions/sessionA1/context?user_id
| `items` | EverOS 搜索命中的精简记忆结果,含 `source_backend: "everos"` |
| `backends` | 两个后端的精简诊断信息,不重复返回完整 OpenViking context 或 EverOS `original_data` |
### `GET /openviking/tasks/{task_id}`
### `GET/POST /openviking/tasks/{task_id}`
查询 OpenViking 后台任务状态,例如 commit 返回的任务。
Query 参数
请求体
| 参数 | 类型 | 必需 | 说明 |
|---|---|---:|---|
@ -353,7 +346,7 @@ Query 参数:
示例:
```bash
curl -sS -X POST "http://127.0.0.1:1934/memory-system/openviking/tasks/${TASK_ID}" \
curl -sS -X POST "$API/openviking/tasks/${TASK_ID}" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
@ -372,15 +365,18 @@ curl -sS -X POST "http://127.0.0.1:1934/memory-system/openviking/tasks/${TASK_ID
|---|---|---:|---|
| `user_id` | string | 是 | 用户 ID |
| `user_key` | string | 是 | `/users` 返回的 user key |
| `session_id` | string/null | 否 | 会话 ID`use_llm=true` 时会作为 OpenViking search 的 session context |
| `session_id` | string/null | 否 | 会话 ID用于 EverOS 过滤和鉴权身份 |
| `query` | string | 是 | 查询文本 |
| `use_llm` | bool | 否 | `false` 使用 OpenViking find + EverOS hybrid`true` 使用 OpenViking search + EverOS agentic |
| `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 http://127.0.0.1:1934/memory-system/search \
curl -sS -X POST "$API/search" \
-H "Content-Type: application/json" \
-d '{
"user_id": "userA",
@ -388,7 +384,10 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/search \
"session_id": "sessionA1",
"query": "我喜欢喝什么?",
"use_llm": false,
"limit": 10
"limit": 10,
"level": 2,
"score_threshold": 0.8,
"target_uri": "viking://user/memories"
}'
```
@ -400,16 +399,34 @@ curl -sS -X POST http://127.0.0.1:1934/memory-system/search \
| `items` | 合并后的记忆结果,含 `source_backend` |
| `backends` | 两个后端的精简诊断信息例如命中数量、query plan 或查询过滤条件;不再回传完整原始命中和 `original_data` |
### `GET /users/{user_id}/profile`
### `GET/POST /users/{user_id}/profile`
读取 EverOS profile。该接口需要 `user_key`,用于确认调用方属于该 user。
读取用户画像。该接口需要 `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 "http://127.0.0.1:1934/memory-system/users/userA/profile?user_key=$USER_KEY"
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
@ -449,7 +466,13 @@ curl -sS -X POST "$API/search" \
OpenViking commit 返回 `task_id` 后,轮询到 `completed` 再搜索长期 memory
```bash
curl -sS "$API/openviking/tasks/<task_id>?user_id=userA&user_key=$USER_KEY&session_id=sessionA1"
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"
}'
```
## 开发检查