feat: 入库改为独立页面,更新 API 说明文档与 Agent skill

- 新增 Ingest.vue 独立入库页(文本/文件/批量 + 任务进度列表),移除入库 Drawer
- 导航栏去掉「入库进度」,新增「文档入库」入口;知识库页「入库」跳转独立页
- API 说明页接口清单与后端对齐(补齐用户管理/上传批量/任务重试删除/reingest 等,修正鉴权标注)
- 更新 qmdsearch-agent skill 与 api-examples(鉴权说明、会话 token、新端点示例)
This commit is contained in:
2026-08-04 20:50:53 +08:00
parent 224eac0048
commit db568740c5
7 changed files with 843 additions and 381 deletions
+28 -16
View File
@@ -25,8 +25,8 @@ metadata: {"clawdbot":{"emoji":"📚"}}
- `QMDSEARCH_BASE_URL`:服务基地址,例如 `http://localhost:8000` 或 NAS 地址 `http://<nas-ip>:8000`
- `QMDSEARCH_TOKEN`Bearer Token。通过 `POST {BASE}/api/v1/auth/login`(用户名 + 密码)获取;session TTL 12h,失效后重新登录。
> 所有变更类请求(上传 / 删除)与检索请求都必须在 Header 携带 `Authorization: Bearer <token>`。
> 当前代码实现中,查询类只读接口(文档列表 / 详情 / 类目 / 统计 / 健康)同样要求 Bearer(与登录态绑定),请始终携带 token 以避免 `1005` 未认证
> 变更类请求(上传 / 删除 / 重试 / 用户管理)必须携带 `Authorization: Bearer <token>`。
> 查询类只读接口(检索 / 文档列表 / 详情 / 下载 / 类目 / 统计 / 健康 / 任务状态)免登录,无需携带 token
## 统一约定
@@ -40,7 +40,7 @@ metadata: {"clawdbot":{"emoji":"📚"}}
curl -X POST {BASE}/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"<password>"}'
# → {"code":0,"data":{"token":"<JWT>","username":"admin","role":"admin","must_change_password":false},"message":"ok"}
# → {"code":0,"data":{"token":"<session-token>","username":"admin","role":"admin","must_change_password":false},"message":"ok"}
```
`must_change_password=true` 时,登录成功但调用其他接口会返回 `1006`,需先 `POST /api/v1/auth/password` 改密。
@@ -96,7 +96,6 @@ curl {BASE}/api/v1/documents/tasks/<task_id>
```bash
curl -X POST {BASE}/api/v1/search \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query":"如何配置 Redis 缓存","top_k":5,"summarize":false}'
```
@@ -111,18 +110,31 @@ curl -X POST {BASE}/api/v1/search \
## 6. 其他管理接口(按需)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/documents` | 文本入库(202 + task_id |
| POST | `/documents/upload` | 文件入库(202 + task_id |
| GET | `/documents/tasks/{task_id}` | 任务状态(done / failed |
| GET | `/documents?limit=&offset=` | 文档列表(分页游标) |
| GET | `/documents/{doc_id}` | 文档详情(L1 + L2/L3 + chunks 数) |
| GET | `/documents/{doc_id}/file` | 下载原始文件 |
| DELETE | `/documents/{doc_id}` | 删除文档(幂等) |
| GET | `/knowledge/categories` | 知识分类类目集 |
| GET | `/knowledge/stats` | 统计(四层点数 + 类目分布) |
| GET | `/health` | 健康检查 |
| 方法 | 路径 | 说明 | 鉴权 |
|------|------|------|------|
| POST | `/documents` | 文本入库(202 + task_id | Bearer |
| POST | `/documents/upload` | 文件入库(202 + task_id | Bearer |
| POST | `/documents/upload-batch` | 批量文件入库(202,逐文件建任务) | Bearer |
| GET | `/documents/tasks` | 入库任务列表(按时间降序) | Bearer |
| GET | `/documents/tasks/{task_id}` | 任务状态(done / failed | 免登录 |
| POST | `/documents/tasks/{task_id}/retry` | 重试入库任务(返回新 task_id | Bearer |
| DELETE | `/documents/tasks/{task_id}` | 删除入库任务(幂等) | Bearer |
| GET | `/documents?limit=&offset=` | 文档列表(分页游标) | 免登录 |
| GET | `/documents/{doc_id}` | 文档详情(L1 + L2/L3 + chunks 数) | 免登录 |
| GET | `/documents/{doc_id}/file` | 下载原始文件 | 免登录 |
| POST | `/documents/{doc_id}/reingest` | 重新摘要入库(读原文件→删旧→重跑) | Bearer |
| DELETE | `/documents/{doc_id}` | 删除文档(幂等) | Bearer |
| GET | `/knowledge/categories` | 知识分类类目集 | 免登录 |
| GET | `/knowledge/stats` | 统计(四层点数 + 类目分布) | 免登录 |
| GET | `/health` | 健康检查 | 免登录 |
| POST | `/auth/logout` | 退出登录 | Bearer |
| POST | `/auth/password` | 修改自己的密码 | Bearer |
| GET | `/auth/me` | 当前用户信息(脱敏) | Bearer |
| GET | `/auth/users` | 用户列表(脱敏) | Bearer + admin |
| POST | `/auth/users` | 创建用户 | Bearer + admin |
| PATCH | `/auth/users/{username}` | 更新用户角色 / 启用状态 | Bearer + admin |
| POST | `/auth/users/{username}/password` | 重置指定用户密码 | Bearer + admin |
| DELETE | `/auth/users/{username}` | 删除用户 | Bearer + admin |
## 错误码速查
@@ -36,11 +36,32 @@ curl -s -X POST {BASE}/api/v1/documents/upload \
curl -s {BASE}/api/v1/documents/tasks/<task_id>
```
### 检索
### 批量文件上传(202,逐文件建任务)
```bash
curl -s -X POST {BASE}/api/v1/documents/upload-batch \
-H "Authorization: Bearer <token>" \
-F "files=@a.pdf" -F "files=@b.md"
```
### 列出入库任务 / 重试 / 删除任务
```bash
curl -s -H "Authorization: Bearer <token>" "{BASE}/api/v1/documents/tasks?limit=20"
curl -s -X POST -H "Authorization: Bearer <token>" {BASE}/api/v1/documents/tasks/<task_id>/retry
curl -s -X DELETE -H "Authorization: Bearer <token>" {BASE}/api/v1/documents/tasks/<task_id>
```
### 重新摘要入库(读原文件 → 删旧 → 重跑)
```bash
curl -s -X POST -H "Authorization: Bearer <token>" {BASE}/api/v1/documents/<doc_id>/reingest
```
### 检索(免登录)
```bash
curl -s -X POST {BASE}/api/v1/search \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query":"如何配置 Redis 缓存","top_k":5,"summarize":false}'
```
@@ -120,6 +141,13 @@ class QMDSearchClient:
headers=self._headers(), files=files, data=data, timeout=60)
return self._ok(resp)["task_id"]
def upload_batch(self, paths: list[str]) -> dict:
"""批量上传多个文件:返回 {tasks:[{filename,task_id}], failed:[{filename,error}]}"""
files = [("files", open(p, "rb")) for p in paths]
resp = requests.post(f"{self.base}/api/v1/documents/upload-batch",
headers=self._headers(), files=files, timeout=60)
return self._ok(resp)
# ---- 轮询 ----
def wait_task(self, task_id: str) -> dict:
deadline = time.time() + self.poll_timeout
@@ -165,6 +193,6 @@ if __name__ == "__main__":
## 三、响应结构速记
- 文本 / 文件入库 `202``data = {task_id, status:"pending"[, saved_path]}`
- 文本 / 文件 / 批量入库 `202``data = {task_id, status:"pending"[, saved_path]}`;批量返回 `{tasks, failed}`
- 任务 `done``data.result = {document_id, summary:{l1_summary,l2_outline,l3_content_outline,level}, category, chunks_count, tags, category_confidence, deduplicated}`
- 检索 → `data = {query, hits:[{text,doc_id,title,section_path,score,doc_summary}], routed_categories, fallback, extracted_info, summary?}`