Files
QMDSearch/skills/qmdsearch-agent/SKILL.md
T
kplam 83eb8d0dd0 feat: 新增 QMDSearch Agent Skill 包与下载入口
- 新增 skills/qmdsearch-agent(SKILL.md + references/api-examples.md),文档化
  AI Agent 鉴权、文本/文件上传入库(异步轮询)与分层检索调用方式
- 打包 QMDSearch-Agent-Skill.zip 至 app/static/agent-skill/
- 后端新增 GET /agent-skill 免登录下载路由(随 ./app 卷挂载,restart 即生效)
- 前端 API 说明页新增「AI Agent Skill 下载」卡片,链接至 /agent-skill
2026-08-01 00:11:05 +08:00

146 lines
6.6 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.
---
name: qmdsearch-agent
description: 通过 QMDSearch REST API 让 AI Agent 上传文档(文本/文件)并执行分层检索查询。配置服务地址与 Bearer Token 后,即可在对话中入库知识库并检索答案。
metadata: {"clawdbot":{"emoji":"📚"}}
---
# QMDSearch Agent 接入 Skill
本 skill 指导 AI Agent 调用 **QMDSearch**(面向 AI Agent 的分层信息检索服务)的 HTTP API,完成两类核心操作:
1. **上传文档**:把文本或文件送入知识库(异步入库,自动三级总结 + 向量化)。
2. **查询 / 检索**:对知识库做分层语义检索,返回最相关原文 chunk。
## 何时使用
- 用户希望把一份文档 / 笔记 / 网页内容加入知识库 → 调用上传接口。
- 用户就知识库内容提问 → 调用检索接口。
- 用户想确认文档是否入库成功 → 轮询任务状态。
- 需要列出 / 删除知识库文档、查看统计 → 调用对应只读 / 管理接口。
## 前置配置(必须)
启用前先确定:
- `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` 未认证。
## 统一约定
- 路径前缀:`{BASE}/api/v1`
- 响应体:`{ "code": 0, "data": {...}, "message": "ok" }``code=0` 成功;`1xxx` 客户端错误;`2xxx` 服务端错误。
- 入库是**异步**的:上传返回 `202 + task_id`,需轮询 `GET /documents/tasks/{task_id}` 直到 `status=done`(或 `failed`)。
## 1. 获取 Token
```bash
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"}
```
`must_change_password=true` 时,登录成功但调用其他接口会返回 `1006`,需先 `POST /api/v1/auth/password` 改密。
## 2. 上传文档(文本)
`POST {BASE}/api/v1/documents`JSON body `{text, title?, source?, metadata?}`
```bash
curl -X POST {BASE}/api/v1/documents \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"text":"QMDSearch 支持 L1/L2/L3 分层检索……", "title":"QMDSearch 介绍", "source":"notes"}'
# → 202 {"code":0,"data":{"task_id":"<uuid>","status":"pending"},"message":"ok"}
```
- `text` 必填且非空;`title` / `source` 可选;`metadata``dict[str,str]`
- 相同 `sha256(text)` 会命中**去重**,直接复用旧文档(`data``deduplicated=true`)。
## 3. 上传文件
`POST {BASE}/api/v1/documents/upload``multipart/form-data`
- `file`:必填,支持 `.txt .md .html .htm .pdf .docx`
- `title` / `source`:可选(默认取原文件名)
- `metadata`:可选 JSON 字符串
```bash
curl -X POST {BASE}/api/v1/documents/upload \
-H "Authorization: Bearer <token>" \
-F "file=@document.pdf" \
-F "source=manual"
# → 202 {"code":0,"data":{"task_id":"<uuid>","status":"pending","saved_path":"..."},"message":"ok"}
```
服务端按扩展名提取纯文本(PDF 扫描件自动 OCR 降级),再复用同一入库流水线。
## 4. 轮询入库任务
`GET {BASE}/api/v1/documents/tasks/{task_id}`(无需鉴权):
```bash
curl {BASE}/api/v1/documents/tasks/<task_id>
# done → {"code":0,"data":{"task_id":...,"status":"done","result":{...文档ID/总结/分类...},"created_at":...,"updated_at":...}}
# failed → {"code":0,"data":{"task_id":...,"status":"failed","error":"..."}}
```
建议:提交后每 12s 轮询,直到 `status∈{done,failed}``done``result.document_id` 即入库文档 ID。
## 5. 检索(查询)
`POST {BASE}/api/v1/search`JSON `{query, top_k?, summarize?}`
```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}'
```
返回 `data``{query, hits[], routed_categories[], fallback, extracted_info, summary?}`
每个 `hit``{text, doc_id, title, section_path, score, doc_summary}`
- `top_k`:返回条数(默认 `RETRIEVAL_FINAL_K`,通常 5)。
- `summarize=true`:额外返回 `summary`(对检索结果做 AI 总结)。
- `fallback=true`:走了全库兜底(未走类目路由),召回较广。
- `extracted_info`:query 解析出的关键词 / 实体 / 意图 / 命中类目。
## 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` | 健康检查 |
## 错误码速查
- `1001` 参数 / 格式错误(空文本、不支持的类型、弱密码、超大小)
- `1004` 资源不存在(task / doc 不存在)
- `1005` 未认证或凭证无效 / 账号已禁用
- `1006` 权限不足 / 首次登录须先改密
- `2000` 服务端内部错误(检索 / 入库 / 列表失败)
- `2001` 认证服务暂不可用
## Agent 最佳实践
1. **先登录拿 token**,缓存 12h,失效再用 `/auth/login` 刷新。
2. **上传走异步**:拿到 `task_id` 后轮询,不要在对话里阻塞等待,可告诉用户“正在入库,稍后查询”。
3. **去重友好**:重复提交同文本会自动复用,不必担心重复。
4. **大文件 / 批量**:逐文件上传并各自轮询;注意 `UPLOAD_MAX_SIZE_MB`(默认 20MB)。
5. **检索调参**:召回不足调大 `top_k`;需要摘要设 `summarize=true`;关注 `fallback` 判断是否需要改写 query。
6. **凭证安全**:token 等同会话,不要写入日志或外发。
完整请求 / 响应示例(含 Python 客户端封装)见 `references/api-examples.md`