Files
rag/docs/curl测试手册.md
lacerate551 8268071fdc docs: 模型切换至 mimo-v2.5 + 文档全面更新
- config.py: INTENT_MODEL 从 deepseek-v4-flash 切换至 mimo-v2.5
- config.py: get_intent_client() 从百炼 API 切换至 mimo API
- RAG系统完整指南.md: v4.0→v4.1,新增图片检索子系统、P0安全网、
  救援管线、五层缓存架构文档;替换所有旧模型名和API地址
- RAG数据流程.md: 完全重写,匹配实际代码逻辑
- curl测试手册.md: 更新模型名和Reranker配置
- MinerU模型部署指南.md: VLM_MODEL 更新为 mimo-v2.5
- 开发与系统模块说明.md: API地址和模型名更新
- 测试指南.md: API地址和模型名更新
2026-06-21 23:11:46 +08:00

2188 lines
51 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.
# RAG API curl 测试手册
> 基于 `后端对接规范.md`,所有 curl 命令均在生产模式 (`APP_ENV=prod`) 下验证通过。
>
> 测试日期2026-06-10最近更新| 生产服务器:`47.116.16.222` | 服务地址:`http://127.0.0.1:5001`
>
> 当前部署模型:`mimo-v2.5`xiaomimimo.com API| 嵌入模型:`bge-base-zh-v1.5`(本地 CPU| Rerank`xop3qwen8breranker`(讯飞云 API
## 目录
- [1. 基础信息](#1-基础信息)
- [2. 健康检查](#2-健康检查)
- [3. 问答接口](#3-问答接口)
- [4. 检索接口](#4-检索接口)
- [5. 向量库管理](#5-向量库管理)
- [6. 文档管理](#6-文档管理)
- [7. 切片管理](#7-切片管理)
- [8. 同步服务](#8-同步服务)
- [9. 反馈系统](#9-反馈系统)
- [10. FAQ 管理](#10-faq-管理)
- [11. 出题系统](#11-出题系统)
- [12. 图片服务](#12-图片服务)
- [13. 报告服务](#13-报告服务)
- [14. 知识库路由](#14-知识库路由)
- [15. 异步任务查询](#15-异步任务查询)
- [16. 认证系统](#16-认证系统)
- [17. 其他端点](#17-其他端点)
- [附录. 已知问题](#附录-已知问题)
---
## 1. 基础信息
### 认证方式
生产模式 (`APP_ENV=prod`) 下无需认证 Header直接放行。用户信息使用默认值
```json
{"user_id": "backend-caller", "username": "后端调用", "role": "user", "department": ""}
```
### 中文编码注意
Windows bash 中 curl 传递中文 JSON 需使用文件方式:
```bash
# 方式一:使用临时文件(推荐)
echo '{"query":"中文内容"}' > /tmp/test.json
curl -s -X POST http://localhost:5001/search -H "Content-Type: application/json" -d @/tmp/test.json
# 方式二:英文可直接传递
curl -s -X POST http://localhost:5001/search -H "Content-Type: application/json" -d '{"query":"hello"}'
```
### 通用响应格式
所有接口返回 JSON成功时 HTTP 200错误时返回对应 HTTP 状态码。
---
## 2. 健康检查
### GET /health
检查服务运行状态。
```bash
curl -s http://localhost:5001/health
```
**响应示例**
```json
{
"bm25_index": "动态按需加载",
"knowledge_base": "多向量库模式 (按集合提供服务)",
"mode": "Agentic RAG",
"status": "ok"
}
```
**验证结果**:✅ 通过
---
## 3. 问答接口
### POST /rag
知识库问答SSE 流式返回)。
```bash
echo '{"message":"三峡工程","chat_history":[]}' > /tmp/rag.json
curl -s -X POST http://localhost:5001/rag \
-H "Content-Type: application/json" \
-d @/tmp/rag.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `message` | string | ✅ | 用户消息 |
| `chat_history` | array | ✅(生产模式) | 对话历史 |
| `collections` | string[] | ❌ | 知识库列表,默认 `["public_kb"]` |
| `session_id` | string | ❌ | 会话 ID |
**chat_history 格式**
```json
[
{"role": "user", "content": "之前的问题"},
{"role": "assistant", "content": "之前的回答"}
]
```
**SSE 事件序列**
```
data: {"type": "start", "message": "正在检索知识库..."}
data: {"type": "sources", "sources": [...]}
data: {"type": "chunk", "content": "每个token"}
data: {"type": "finish", "answer": "完整回答[ref:chunk_id]", "sources": [...], "citations": [...]}
```
**finish 事件中 citations 结构**(引用溯源,用于前端跳转定位):
```json
{
"citations": [
{
"chunk_id": "3.docx_33",
"chunk_index": 33,
"source": "3.docx",
"collection": "public_kb",
"doc_type": "word",
"section": "第五篇 投入管理 > 一、零售终端建设投入标准",
"preview": "内容摘要...",
"content": "切片内容(截断 300 字)",
"chunk_type": "text",
"page": null,
"page_end": null
}
]
}
```
| citations 字段 | 说明 |
|------|------|
| `chunk_id` | 切片唯一标识,格式 `{文件名}_{序号}` |
| `chunk_index` | 全局切片序号(从 chunk_id 提取),用于文档预览跳转 |
| `source` | 来源文件名 |
| `collection` | 所属向量库名称,用于定位文档所在知识库 |
| `doc_type` | 文档类型:`pdf``word``excel` |
| `section` | 章节路径(已清洗,过滤掉正文内容) |
| `page` / `page_end` | 页码(仅 PDF |
| `bbox` / `bbox_mode` | 坐标定位(仅 PDF |
| `section_chunk_id` | 章节内段落序号(仅 Word |
**带 collections 参数**
```bash
echo '{"message":"三峡工程","chat_history":[],"collections":["public_kb"]}' > /tmp/rag.json
curl -s -X POST http://localhost:5001/rag \
-H "Content-Type: application/json" \
-d @/tmp/rag.json
```
> **⚠️ 重要**:指定知识库必须使用 `collections` 数组参数(如 `["dept_tech"]`),而非 `collection` 单数参数。
> 使用单数 `collection` 参数会被忽略,导致默认检索 `public_kb`。
**多向量库同时查询**
```bash
# 同时检索多个知识库
echo '{"message":"信息安全","collections":["dept_tech","public_kb"],"chat_history":[]}' > /tmp/rag.json
curl -s -X POST http://localhost:5001/rag \
-H "Content-Type: application/json" \
-d @/tmp/rag.json
```
**验证结果**:✅ 通过
---
### POST /chat
普通聊天模式(非知识库)。
```bash
echo '{"message":"你好","chat_history":[]}' > /tmp/chat.json
curl -s -X POST http://localhost:5001/chat \
-H "Content-Type: application/json" \
-d @/tmp/chat.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `message` | string | ✅ | 用户消息 |
| `chat_history` | array | ❌ | 对话历史 |
**响应示例**
```json
{
"answer": "你好!很高兴见到你~",
"mode": "chat",
"sources": [],
"web_searched": false
}
```
**验证结果**:✅ 通过
---
## 4. 检索接口
### POST /search
混合检索(向量 + BM25供 Dify 工作流调用。
```bash
echo '{"query":"三峡工程","top_k":3}' > /tmp/search.json
curl -s -X POST http://localhost:5001/search \
-H "Content-Type: application/json" \
-d @/tmp/search.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `query` | string | ✅ | 查询文本 |
| `top_k` | int | ❌ | 返回数量,默认 5 |
| `collections` | string[] | ❌ | 知识库列表,默认 `["public_kb"]` |
**响应示例**
```json
{
"contexts": ["综述\n三峡工程是国之重器..."],
"metadatas": [
{
"_collection": "public_kb",
"chunk_id": "三峡公报_1-15页.pdf_text_8",
"chunk_type": "text",
"collection": "public_kb",
"doc_type": "pdf",
"page": 5,
"page_end": 6,
"section": "三峡工程公报 > 综述",
"source": "三峡公报_1-15页.pdf",
"status": "active",
"version": "v1"
}
],
"scores": [0.9975]
}
```
**scores 说明**:相似度分数,范围 0-1越高越相关已从距离转换
**验证结果**:✅ 通过
---
## 5. 向量库管理
### GET /collections
获取向量库列表。
```bash
curl -s http://localhost:5001/collections
```
**响应示例**
```json
{
"collections": [
{
"created_at": "2026-06-02T21:35:43.839864",
"department": "",
"description": "所有人可访问的公开文档",
"display_name": "公开知识库",
"document_count": 824,
"name": "public_kb"
},
{
"created_at": "2026-06-04T06:15:52.556940",
"department": "",
"description": "",
"display_name": "dept_1_kb",
"document_count": 500,
"name": "dept_1_kb"
},
{
"created_at": "2026-06-10T03:04:20.619279",
"department": "",
"description": "",
"display_name": "resources",
"document_count": 0,
"name": "resources"
}
],
"total": 3
}
```
**验证结果**:✅ 通过
---
### POST /collections
创建新向量库。
```bash
echo '{"name":"test_kb","display_name":"测试库","department":"测试部","description":"测试描述"}' > /tmp/create.json
curl -s -X POST http://localhost:5001/collections \
-H "Content-Type: application/json" \
-d @/tmp/create.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `name` | string | ✅ | 向量库名称(字母、数字、下划线、连字符) |
| `display_name` | string | ❌ | 显示名称 |
| `department` | string | ❌ | 所属部门 |
| `description` | string | ❌ | 描述 |
**响应示例**
```json
{
"message": "向量库 'test_kb' 创建成功",
"name": "test_kb",
"success": true
}
```
**验证结果**:✅ 通过
---
### PUT /collections/\<name\>
修改向量库信息。
```bash
echo '{"display_name":"新名称","description":"新描述"}' > /tmp/update.json
curl -s -X PUT http://localhost:5001/collections/test_kb \
-H "Content-Type: application/json" \
-d @/tmp/update.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `display_name` | string | ❌ | 显示名称 |
| `description` | string | ❌ | 描述 |
**验证结果**:✅ 通过
---
### DELETE /collections/\<name\>
删除向量库。
```bash
curl -s -X DELETE http://localhost:5001/collections/test_kb
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `delete_documents` | boolean | ❌ | 是否删除文档源文件,默认 false |
**带参数示例**
```bash
curl -s -X DELETE "http://localhost:5001/collections/test_kb?delete_documents=true"
```
**验证结果**:✅ 通过
---
### GET /collections/\<kb_name\>/documents
获取向量库内的文档列表。
```bash
curl -s "http://localhost:5001/collections/public_kb/documents"
```
**响应示例**
```json
{
"collection": "public_kb",
"documents": [
{
"chunks": 69,
"source": "3.txt"
},
{
"chunks": 12,
"source": "1.txt"
}
],
"total": 10
}
```
**验证结果**:✅ 通过
---
### GET /collections/\<kb_name\>/chunks
获取向量库切片列表。
```bash
curl -s "http://localhost:5001/collections/public_kb/chunks?limit=2&offset=0"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `document_id` | string | ❌ | 过滤指定文档的切片 |
| `limit` | int | ❌ | 返回数量,默认 100 |
| `offset` | int | ❌ | 偏移量,默认 0 |
**响应示例**
```json
{
"collection": "public_kb",
"chunks": [
{
"id": "三峡公报_1-15页.pdf_text_0",
"document": "三峡公报_1-15页.pdf",
"content": "切片内容...",
"metadata": {
"chunk_id": "三峡公报_1-15页.pdf_text_0",
"chunk_type": "text",
"collection": "public_kb",
"page": 1,
"source": "三峡公报_1-15页.pdf",
"status": "active",
"version": "v1"
},
"score": null
}
],
"total": 150
}
```
**验证结果**:✅ 通过
---
### GET /collections/\<kb_name\>/documents/\<filename\>/versions
获取文档版本历史。
```bash
# URL 编码文件名中的特殊字符
curl -s "http://localhost:5001/collections/public_kb/documents/%E4%B8%89%E5%B3%A1%E5%85%AC%E6%8A%A5_1-15%E9%A1%B5.pdf/versions?limit=5"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `limit` | int | ❌ | 返回数量,默认 10 |
**响应示例**
```json
{
"success": true,
"document_id": "三峡公报_1-15页.pdf",
"collection": "public_kb",
"versions": [
{
"version": "v1",
"status": "active",
"effective_date": "2026-04-14T21:03:06",
"deprecated_date": null,
"chunk_count": 120
}
],
"total": 1
}
```
**验证结果**:✅ 通过
---
### POST /collections/\<kb_name\>/update-image-descriptions
更新图片切片描述(重新生成)。
```bash
curl -s -X POST "http://localhost:5001/collections/public_kb/update-image-descriptions"
```
**响应示例**
```json
{
"success": true,
"message": "图片描述更新完成",
"updated": 5
}
```
**验证结果**:✅ 通过
---
## 6. 文档管理
### GET /documents/list
获取文档列表。
```bash
curl -s "http://localhost:5001/documents/list?collection=public_kb"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `collection` | string | ❌ | 知识库名称(也可用 `kb_name`),默认返回全部 |
> **注意**:该接口不支持分页,返回指定知识库的全部文档列表。
**响应示例**
```json
{
"documents": [
{
"collection": "public_kb",
"filename": "三峡公报_1-15页.pdf",
"last_modified": "2026-04-14T21:03:06",
"path": "public_kb/三峡公报_1-15页.pdf",
"size": 2773520
}
],
"total": 8
}
```
**验证结果**:✅ 通过
---
### GET /documents/\<path\>/status
获取文档处理状态。
```bash
# URL 编码路径中的斜杠
curl -s "http://localhost:5001/documents/public_kb%2Ftest.txt/status"
```
**响应示例**
```json
{
"success": true,
"status": "active",
"chunk_count": 105,
"last_processed": null
}
```
**验证结果**:✅ 通过
---
### POST /documents/upload
上传单个文件。
```bash
echo "测试文档内容" > /tmp/test.txt
curl -s -X POST http://localhost:5001/documents/upload \
-F "file=@/tmp/test.txt" \
-F "collection=public_kb"
```
**表单字段**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `file` | file | ✅ | 上传文件 |
| `collection` | string | ✅ | 目标知识库(也可用 `kb_name` |
**响应示例**
```json
{
"success": true,
"status": "success",
"status_code": 2002,
"message": "文件上传成功,已保存并添加到向量库",
"data": {
"file": {
"filename": "test.txt",
"collection": "public_kb",
"path": "public_kb/test.txt",
"size": 18
},
"sync_status": "已保存并添加到向量库"
}
}
```
> **说明**:文件保存和向量化均为同步操作,响应时文件已处理完成。不包含 `task_id` 字段(异步任务系统仅 main 分支可用)。
>
> **同名文件处理**:上传同名文件时,旧版本的切片会被自动清理后覆盖,不会生成时间戳后缀文件。
**验证结果**:✅ 通过
---
### POST /documents/batch-upload
批量上传文件。
```bash
echo "文件1内容" > /tmp/file1.txt
echo "文件2内容" > /tmp/file2.txt
curl -s -X POST http://localhost:5001/documents/batch-upload \
-F "files=@/tmp/file1.txt" \
-F "files=@/tmp/file2.txt" \
-F "collection=public_kb"
```
**响应示例**
```json
{
"success": true,
"status": "success",
"status_code": 2003,
"message": "批量上传完成,成功 2/2 个文件",
"data": {
"total": 2,
"success_count": 2,
"results": [
{"filename": "file1.txt", "path": "public_kb/file1.txt", "status": "success"},
{"filename": "file2.txt", "path": "public_kb/file2.txt", "status": "success"}
]
}
}
```
> **说明**:批量上传为同步操作,响应时所有文件已处理完成。不包含 `task_id` 字段(异步任务系统仅 main 分支可用)。
>
> **同名文件处理**:与单文件上传相同,批量上传中遇到同名文件也会自动覆盖旧版本。
**验证结果**:✅ 通过
---
### PUT /documents/\<path\>
更新/替换文档。
```bash
echo "更新后的文档内容" > /tmp/updated.txt
curl -s -X PUT "http://localhost:5001/documents/public_kb%2Ftest.txt" \
-F "file=@/tmp/updated.txt"
```
**表单字段**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `file` | file | ✅ | 替换的文件 |
**响应示例**
```json
{
"success": true,
"message": "文件已更新"
}
```
**验证结果**:✅ 通过
---
### DELETE /documents/\<path\>
删除文档。
```bash
# URL 编码路径中的斜杠
curl -s -X DELETE "http://localhost:5001/documents/public_kb%2Ftest.txt"
```
**响应示例**
```json
{
"message": "文档已删除",
"success": true
}
```
**验证结果**:✅ 通过
---
### POST /collections/\<kb_name\>/documents/\<filename\>/deprecate
废弃文档版本。
```bash
curl -s -X POST "http://localhost:5001/collections/public_kb/documents/test.txt/deprecate"
```
**验证结果**:✅ 通过(接口存在)
---
### POST /collections/\<kb_name\>/documents/\<filename\>/restore
恢复文档版本。
```bash
curl -s -X POST "http://localhost:5001/collections/public_kb/documents/test.txt/restore"
```
**验证结果**:✅ 通过(接口存在)
---
### 🛠️ DEV GET /documents/\<path\>/preview
> **开发环境自用接口,后端组无需调用。**
> 仅供 dev-ui 内部前端实现引用溯源跳转使用。后端组可根据 `/rag` 返回的 `citations` 中的 `chunk_index`、`page`、`bbox` 等字段自行实现文档定位。
文档预览(支持按切片序号跳转),用于引用溯源点击后定位到文档中的具体位置。
```bash
# 跳转到指定切片(前后各取 2 个上下文切片)
curl -s "http://localhost:5001/documents/public_kb%2F1.docx/preview?chunk_index=33&context=2"
# 不指定 chunk_index返回前 5 个切片作为概览
curl -s "http://localhost:5001/documents/public_kb%2F1.docx/preview"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `chunk_index` | int | ✅ | 目标切片序号(来自 citations 的 `chunk_index` 字段) |
| `context` | int | ✅ | 上下文切片数,默认 2前后各取 2 个) |
**响应示例**
```json
{
"success": true,
"collection": "public_kb",
"source": "1.docx",
"total_chunks": 105,
"target_index": 33,
"chunks": [
{"id": "1.docx_31", "content": "...", "metadata": {...}, "is_target": false},
{"id": "1.docx_32", "content": "...", "metadata": {...}, "is_target": false},
{"id": "1.docx_33", "content": "...", "metadata": {...}, "is_target": true},
{"id": "1.docx_34", "content": "...", "metadata": {...}, "is_target": false},
{"id": "1.docx_35", "content": "...", "metadata": {...}, "is_target": false}
]
}
```
> **说明**`is_target: true` 的切片即为引用定位目标,前端可高亮显示并滚动到该位置。
---
## 7. 切片管理
### GET /documents/\<path\>/chunks
获取文档切片列表。
```bash
# URL 编码路径
curl -s "http://localhost:5001/documents/dept_hr%2F%E4%BA%BA%E5%91%98%E5%90%8D%E5%86%8C.txt/chunks"
```
> **注意**:该接口不支持分页或过滤参数,返回指定文档的全部切片。
**响应示例**
```json
{
"chunks": [
{
"document": "# 智启科技有限公司人员名册\n\n**更新日期**2024年6月...",
"id": "人员名册.txt_text_0",
"metadata": {
"chunk_id": "人员名册.txt_text_0",
"chunk_index": 0,
"chunk_type": "text",
"collection": "dept_hr",
"doc_type": "other",
"page": 1,
"page_end": 1,
"preview": "# 智启科技有限公司人员名册...",
"section": "人员名册",
"source": "人员名册.txt",
"has_table": false,
"status": "active",
"version": "v1"
},
"status": "active",
"version": "v1"
}
],
"collection": "dept_hr",
"document_id": "dept_hr/人员名册.txt",
"success": true,
"total": 4
}
```
**切片字段说明**
| 字段 | 说明 |
|------|------|
| `id` / `chunk_id` | 切片唯一标识,格式:`{文件名}_{类型}_{序号}` |
| `document` | **切片完整内容**(重要:用于增删改查) |
| `chunk_type` | 切片类型:`text`(文本)、`table`(表格)、`image`(图片) |
| `source` | 来源文件名 |
| `page` / `page_end` | 起止页码 |
| `section` | 所属章节路径 |
| `preview` | 内容预览(截断版,用于列表展示) |
| `has_table` | 是否包含表格 |
**验证结果**:✅ 通过
---
### POST /chunks
新增切片。
```bash
echo '{"collection":"public_kb","content":"测试切片内容","metadata":{"section":"测试章节"}}' > /tmp/chunk.json
curl -s -X POST http://localhost:5001/chunks \
-H "Content-Type: application/json" \
-d @/tmp/chunk.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `collection` | string | ✅ | 向量库名称 |
| `content` | string | ✅ | 切片内容 |
| `metadata` | object | ❌ | 元数据 |
**验证结果**:✅ 通过
---
### PUT /chunks/\<id\>
修改切片。
```bash
echo '{"collection":"dept_hr","content":"更新后的内容"}' > /tmp/update_chunk.json
curl -s -X PUT "http://localhost:5001/chunks/人员名册.txt_text_0" \
-H "Content-Type: application/json" \
-d @/tmp/update_chunk.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `collection` | string | ✅ | 向量库名称 |
| `content` | string | ❌ | 新内容 |
| `metadata` | object | ❌ | 新元数据 |
**验证结果**:✅ 通过
---
### DELETE /chunks/\<id\>
删除切片。
```bash
curl -s -X DELETE "http://localhost:5001/chunks/人员名册.txt_text_0?collection=dept_hr"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `collection` | string | ✅ | 向量库名称 |
**验证结果**:✅ 通过
---
## 8. 同步服务
### POST /sync
触发文档同步(异步任务)。
```bash
curl -s -X POST http://localhost:5001/sync \
-H "Content-Type: application/json"
```
**响应示例**
```json
{
"success": true,
"status": "success",
"status_code": 2010,
"message": "同步完成",
"data": {
"result": {
"documents_processed": 20,
"documents_added": 3,
"documents_modified": 2,
"documents_deleted": 0,
"errors": []
}
}
}
```
> **说明**:此接口为**同步操作**,请求会阻塞直到同步完成(可能需要较长时间)。响应中 `data.result` 包含完整的同步结果。不包含 `task_id` 字段(异步任务系统仅 main 分支可用)。
>
> **冲突检测**:如果已有同步任务正在运行,返回 HTTP 409
> ```json
> {"error": "TASK_RUNNING", "message": "同步任务正在执行中,请等待完成"}
> ```
**验证结果**:✅ 通过
---
### GET /sync/status
获取同步状态。
```bash
curl -s http://localhost:5001/sync/status
```
**响应示例**
```json
{
"documents_tracked": 0,
"enabled": true,
"last_sync": null,
"monitoring": false
}
```
**验证结果**:✅ 通过
---
### GET /sync/history
获取同步历史。
```bash
curl -s http://localhost:5001/sync/history
```
**响应示例**
```json
{
"history": []
}
```
**验证结果**:✅ 通过
---
### GET /sync/changes
获取待同步变更。
```bash
curl -s http://localhost:5001/sync/changes
```
**响应示例**
```json
{
"changes": []
}
```
**验证结果**:✅ 通过
---
### POST /sync/start
启动文件监控。
```bash
curl -s -X POST http://localhost:5001/sync/start
```
**响应示例**
```json
{
"message": "文件监控已启动",
"status": "success",
"status_code": 2010
}
```
**验证结果**:✅ 通过
---
### POST /sync/stop
停止文件监控。
```bash
curl -s -X POST http://localhost:5001/sync/stop
```
**响应示例**
```json
{
"message": "文件监控已停止",
"status": "success",
"status_code": 2010
}
```
**验证结果**:✅ 通过
---
## 9. 反馈系统
### POST /feedback
提交反馈。
```bash
echo '{"session_id":"test-session","query":"测试问题","answer":"测试回答","rating":1,"reason":"测试原因"}' > /tmp/feedback.json
curl -s -X POST http://localhost:5001/feedback \
-H "Content-Type: application/json" \
-d @/tmp/feedback.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `session_id` | string | ✅ | 会话 ID |
| `query` | string | ✅ | 用户问题 |
| `answer` | string | ❌ | 系统回答(可为空) |
| `rating` | int | ✅ | 评分1=赞,-1=踩) |
| `reason` | string | ❌ | 原因 |
**响应示例**
```json
{
"faq_suggested": true,
"feedback_id": 7,
"success": true,
"suggestion_id": 6
}
```
**验证结果**:✅ 通过
---
### GET /feedback/list
获取反馈列表。
```bash
curl -s "http://localhost:5001/feedback/list?limit=5"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `limit` | int | ❌ | 返回数量,默认 100 |
| `rating` | int | ❌ | 按评分过滤1=赞,-1=踩) |
| `user_id` | string | ❌ | 按用户 ID 过滤 |
| `start_date` | string | ❌ | 起始日期 |
| `end_date` | string | ❌ | 结束日期 |
> **注意**:该接口不支持 `page`/`page_size` 分页,使用 `limit` 控制返回数量。
**响应示例**
```json
{
"feedbacks": [
{
"answer": "测试回答",
"created_at": "2026-05-04T01:45:35",
"id": 7,
"query": "测试问题",
"rating": 1,
"reason": "测试原因",
"session_id": "test-session",
"sources": [],
"user_id": ""
}
],
"success": true,
"total": 7
}
```
**验证结果**:✅ 通过
---
### GET /feedback/stats
获取反馈统计。
```bash
curl -s http://localhost:5001/feedback/stats
```
**响应示例**
```json
{
"stats": {
"avg_rating": 1.0,
"negative_count": 0,
"positive_count": 8,
"satisfaction_rate": 100.0,
"total_feedback": 8
},
"success": true
}
```
**验证结果**:✅ 通过
---
### GET /feedback/bad-cases
获取差评案例列表。
```bash
curl -s http://localhost:5001/feedback/bad-cases
```
**响应示例**
```json
{
"bad_cases": [],
"blacklisted_sources": [],
"success": true,
"suggestions": [
"补充到知识库(针对知识盲区)",
"添加到 Query Rewrite 规则(针对表达歧义)"
]
}
```
**验证结果**:✅ 通过
---
### GET /feedback/blacklist
获取切片黑名单。
```bash
curl -s http://localhost:5001/feedback/blacklist
```
**响应示例**
```json
{
"blacklist": [],
"count": 0,
"success": true,
"usage": "在检索时过滤这些来源以提升回答质量"
}
```
**验证结果**:✅ 通过
---
## 10. FAQ 管理
### GET /faq
获取 FAQ 列表。
```bash
curl -s "http://localhost:5001/faq?limit=5"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `status` | string | ❌ | 按状态过滤(如 `approved``draft` |
| `limit` | int | ❌ | 返回数量,默认 50 |
**响应示例**
```json
{
"faqs": [
{
"answer": "根据参考资料...",
"avg_rating": 1.0,
"created_at": "2026-04-19T11:27:15",
"frequency": 1,
"id": 1,
"question": "C类吸烟区域",
"source_documents": null,
"status": "approved",
"updated_at": "2026-04-19T11:27:15"
}
],
"success": true,
"total": 3
}
```
**验证结果**:✅ 通过
---
### POST /faq
创建新 FAQ。
```bash
curl -s -X POST http://localhost:5001/faq \
-H "Content-Type: application/json" \
-d "{\"question\":\"FAQ question\",\"answer\":\"FAQ answer\"}"
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `question` | string | ✅ | 问题内容 |
| `answer` | string | ✅ | 答案内容 |
**响应示例**
```json
{
"faq_id": 7,
"message": "FAQ已创建请通过 /faq/<id>/approve 接口确认后生效",
"status": "draft",
"success": true
}
```
**验证结果**:✅ 通过
---
### PUT /faq/\<id\>
修改 FAQ。
```bash
curl -s -X PUT "http://localhost:5001/faq/7" \
-H "Content-Type: application/json" \
-d "{\"question\":\"updated question\",\"answer\":\"updated answer\"}"
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `question` | string | ❌ | 新问题内容 |
| `answer` | string | ❌ | 新答案内容 |
**响应示例**
```json
{
"message": "FAQ更新成功",
"success": true,
"sync_status": "skipped"
}
```
**验证结果**:✅ 通过
---
### DELETE /faq/\<id\>
删除 FAQ。
```bash
curl -s -X DELETE "http://localhost:5001/faq/7"
```
**响应示例**
```json
{
"message": "FAQ删除成功",
"success": true
}
```
**验证结果**:✅ 通过
---
### GET /faq/suggestions
获取 FAQ 建议列表。
```bash
curl -s "http://localhost:5001/faq/suggestions?status=pending&limit=5"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `status` | string | ❌ | 按状态过滤,默认 `pending` |
| `limit` | int | ❌ | 返回数量,默认 50 |
**响应示例**
```json
{
"success": true,
"suggestions": [
{
"answer": "",
"avg_rating": 1.0,
"created_at": "2026-04-29T20:49:38",
"frequency": 2,
"id": 5,
"query": "test",
"status": "pending"
}
],
"total": 3
}
```
**验证结果**:✅ 通过
---
### POST /faq/suggestions/\<id\>/approve
批准 FAQ 建议(需 admin 角色)。
```bash
curl -s -X POST "http://localhost:5001/faq/suggestions/6/approve" \
-H "Content-Type: application/json" \
-d '{}'
```
**请求体**(可选,用于修改答案):
```json
{"answer": "管理员修改后的答案"}
```
**注意**:必须传递请求体(至少空对象 `{}`),否则返回 400 错误。
**验证结果**:✅ 通过
---
### POST /faq/suggestions/\<id\>/reject
拒绝 FAQ 建议(需 admin 角色)。
```bash
curl -s -X POST "http://localhost:5001/faq/suggestions/6/reject" \
-H "Content-Type: application/json" \
-d '{}'
```
**验证结果**:✅ 通过
---
### POST /faq/\<id\>/approve
直接批准 FAQ非从建议列表
```bash
curl -s -X POST "http://localhost:5001/faq/1/approve" \
-H "Content-Type: application/json" \
-d '{}'
```
> **注意**:此端点与 `POST /faq/suggestions/<id>/approve` 不同,后者用于审批用户提交的 FAQ 建议。
**验证结果**:✅ 通过(路由存在)
---
## 11. 出题系统
### 出题架构说明v2
v2 重构后采用 **4 阶段出题架构**,确保题目质量和多样性:
| 阶段 | 说明 | 改进点 |
|------|------|--------|
| Phase 1 | 文档结构分析 | 按章节分组,统计内容量 |
| Phase 2 | 知识点规划 | 全局唯一,避免跨章节重复 |
| Phase 3 | 精准出题 | 每个知识点单独检索,确保上下文充足 |
| Phase 4 | 质量校验 | 去重 + 数量校正,零重复率 |
**支持的题型**
| 题型 key | 中文名 | answer 格式 |
|----------|--------|-------------|
| `single_choice` | 单选题 | 单个选项字母(如 "B" |
| `multiple_choice` | 多选题 | 选项字母列表(如 ["A","B"] |
| `true_false` | 判断题 | 布尔值或字符串(如 true/"true" |
| `fill_blank` | 填空题 | 嵌套列表(如 [["答案1"],["答案2"]] |
| `subjective` | 简答题 | 参考答案字符串 |
---
### GET /exam/health
出题服务健康检查。
```bash
curl -s http://localhost:5001/exam/health
```
**响应示例**
```json
{
"service": "exam-api",
"status": "ok",
"version": "2.0"
}
```
**验证结果**:✅ 通过
---
### POST /exam/generate
生成考题(指定题型和数量)。
**特点**
- 需要手动指定 `question_types`(每种题型的数量)
- 适合有明确需求的场景(如"出 5 道单选题"
**入参校验**
- `question_types` 中每个题型必须属于: `single_choice`, `multiple_choice`, `true_false`, `fill_blank`, `subjective`
- 每种题型数量必须为非负整数
- `difficulty` 必须为 1-5 的整数
- **总题数上限 20 道**(所有题型数量之和不能超过 20
- 校验失败返回 HTTP 400error_code 为 `INVALID_PARAMS`
```bash
curl -s -X POST http://localhost:5001/exam/generate \
-H "Content-Type: application/json" \
-d '{"file_path":"public_kb/1.docx","collection":"public_kb","question_types":{"single_choice":5,"true_false":3,"fill_blank":2}}'
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `file_path` | string | ✅ | 文档路径(格式:`collection/filename` |
| `collection` | string 或 string[] | ✅ | 知识库名称,支持数组(按优先级排序) |
| `question_types` | object | ✅ | 题型数量配置 |
| `difficulty` | int | ❌ | 难度等级1-5默认 3 |
| `options` | object | ❌ | 附加选项(如 `max_source_chunks` |
| `request_id` | string | ❌ | 请求 ID幂等性 |
| `exclude_stems` | string[] | ❌ | 已有题目题干列表(跨调用去重,最多 100 条) |
> **注意**:生产模式(`DEV_MODE=false`)下无需传 `Authorization` header直接放行。开发模式下可传 `Authorization: Bearer mock-token-admin` 模拟管理员身份。
**question_types 配置示例**
```json
{
"single_choice": 5,
"multiple_choice": 2,
"true_false": 3,
"fill_blank": 2,
"subjective": 1
}
```
**响应示例**
```json
{
"success": true,
"status": "success",
"status_code": 2020,
"message": "出题成功",
"data": {
"questions": [
{
"content": {
"stem": "重购率的定义是下列哪一项?",
"answer": "B",
"data": {
"options": [
{"content": "选项A内容", "key": "A"},
{"content": "品规连续两周订货客户数/上周订货客户数*100%", "key": "B"}
]
},
"explanation": "重购率的定义是..."
},
"difficulty": 3,
"question_type": "single_choice",
"source_trace": {
"chunk_ids": ["1.docx_76"],
"document_name": "public_kb/1.docx",
"page_numbers": [1],
"sources": [...]
}
}
],
"request_id": null,
"source_chunks_used": 15,
"success": true,
"total": 10,
"requested_types": {"single_choice": 5, "true_false": 3, "fill_blank": 2},
"actual_types": {"single_choice": 5, "true_false": 3, "fill_blank": 2},
"warnings": []
}
}
```
> **说明**:此接口为**同步操作**,请求会阻塞直到出题完成(通常需要 30-60 秒)。响应中 `data` 直接包含完整出题结果。不包含 `task_id` 字段(异步任务系统仅 main 分支可用)。
>
> **注意**`warnings` 字段在某题型实际生成数量少于请求数量时返回提示信息。
**验证结果**:✅ 通过2026-06-05
---
### POST /exam/generate-smart
AI 智能出题 - 自动分析文件并决定题型和数量。
**特点**
- 不需要传 `question_types`AI 自动分析文档后决定
- 返回格式与旧端口完全兼容,额外包含 `ai_analysis` 字段
- 适合不想费脑子的场景
```bash
curl -s -X POST http://localhost:5001/exam/generate-smart \
-H "Content-Type: application/json" \
-d '{"file_path":"public_kb/1.docx","collection":"public_kb"}'
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `file_path` | string | ✅ | 文档路径(格式:`collection/filename` |
| `collection` | string 或 string[] | ✅ | 知识库名称,支持数组(按优先级排序) |
| `difficulty` | int | ❌ | 难度等级1-5默认 3 |
| `options` | object | ❌ | 附加选项 |
**响应示例**
```json
{
"success": true,
"status": "success",
"status_code": 2020,
"message": "AI 智能出题成功",
"data": {
"ai_analysis": {
"total_knowledge_points": 21,
"suitable_types": ["single_choice", "multiple_choice", "true_false", "subjective"],
"question_types": {
"single_choice": 8,
"multiple_choice": 6,
"true_false": 4,
"fill_blank": 0,
"subjective": 3
},
"reason": "文档包含21个知识点涵盖术语定义、流程步骤、数值标准..."
},
"questions": [...],
"request_id": null,
"source_chunks_used": 15,
"success": true,
"total": 16
}
}
```
> **说明**:此接口为**同步操作**,请求会阻塞直到出题完成。响应中 `data` 直接包含完整出题结果(含 `ai_analysis` 字段)。不包含 `task_id` 字段(异步任务系统仅 main 分支可用)。
**注意事项**
- 实际出题数量 ≤ min(文档知识点数, AI 推荐数量)
- 如果文档知识点较少,生成的题目数量会相应减少
- 生产模式下无需传 `Authorization` header
**支持的题型**
| 题型 key | 中文名 | 说明 |
|----------|--------|------|
| `single_choice` | 单选题 | content.answer 为单个选项字母 |
| `multiple_choice` | 多选题 | content.answer 为选项字母列表 |
| `true_false` | 判断题 | content.answer 为布尔值或字符串 |
| `fill_blank` | 填空题 | content.answer 为嵌套列表 |
| `subjective` | 简答题 | content.answer 为参考答案 |
**验证结果**:✅ 通过
---
### POST /exam/grade
批阅答案。
```bash
echo '{"answers":[{"question_id":"q1","question_type":"single_choice","content":{"answer":"B"},"student_answer":"B","max_score":2}]}' > /tmp/grade.json
curl -s -X POST http://localhost:5001/exam/grade \
-H "Content-Type: application/json" \
-d @/tmp/grade.json
```
**请求体**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `answers` | array | ✅ | 答案数组 |
**answers 数组元素**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `question_id` | string | ✅ | 题目 ID |
| `question_type` | string | ✅ | 题型 |
| `content` | object | ✅ | 题目内容(与出题接口返回的 `content` 字段结构一致,后端可直接透传) |
| `student_answer` | string/array | ✅ | 学生答案 |
| `max_score` | int | ✅ | 满分 |
> **注意**`question_type` 必须为以下值之一:`single_choice`, `multiple_choice`, `true_false`, `fill_blank`, `subjective`。传入无效类型返回 HTTP 400。
**响应示例**
```json
{
"success": true,
"status": "success",
"status_code": 2021,
"message": "批阅完成",
"data": {
"request_id": null,
"results": [
{
"question_id": "q1",
"score": 2,
"max_score": 2,
"grading_status": "success",
"details": {
"correct": true,
"student_answer": "B",
"correct_answer": "B",
"feedback": "正确!"
}
}
],
"score_rate": 100.0,
"success": true,
"total_max_score": 2,
"total_score": 2
}
}
```
> **说明**:此接口为**同步操作**,响应中 `data` 直接包含完整批阅结果。不包含 `task_id` 字段(异步任务系统仅 main 分支可用)。
**`grading_status` 取值说明**
- `success`:评分成功
- `failed`:评分失败(主观题 LLM 解析失败或超时),此时 `details` 包含 `error` 字段
> **注意**:当主观题缺少 `scoring_points` 评分标准时,`details.warnings` 会包含警告信息,评分结果仅供参考。
**验证结果**:✅ 通过2026-06-05
---
## 12. 图片服务
### GET /images/list
获取图片列表。
```bash
curl -s "http://localhost:5001/images/list?limit=5&offset=0"
```
**查询参数**
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `limit` | int | ❌ | 返回数量,默认 50 |
| `offset` | int | ❌ | 偏移量,默认 0 |
**响应示例**
```json
{
"images": [
{
"image_id": "0569dd285537",
"size_bytes": 169818,
"url": "/images/0569dd285537"
}
],
"limit": 5,
"offset": 0,
"total": 67
}
```
**验证结果**:✅ 通过
---
### GET /images/\<id\>
获取单张图片。
```bash
curl -s -o image.jpg http://localhost:5001/images/0569dd285537
```
**响应**返回图片文件HTTP 200
**验证结果**:✅ 通过
---
### GET /images/\<id\>/info
获取图片元数据。
```bash
curl -s "http://localhost:5001/images/0569dd285537/info"
```
**响应示例**
```json
{
"format": "JPEG",
"height": 1357,
"image_id": "0569dd285537",
"mode": "RGB",
"size_bytes": 169818,
"url": "/images/0569dd285537",
"width": 1023
}
```
**验证结果**:✅ 通过
---
### GET /images/stats
获取图片统计。
```bash
curl -s http://localhost:5001/images/stats
```
**响应示例**
```json
{
"format_counts": {
".jpg": 46,
".png": 21
},
"supported_formats": [".jpeg", ".gif", ".bmp", ".jpg", ".webp", ".png"],
"total_images": 67,
"total_size_bytes": 5394510,
"total_size_mb": 5.14
}
```
**验证结果**:✅ 通过
---
## 13. 报告服务
### GET /reports/weekly
获取周报。
```bash
curl -s http://localhost:5001/reports/weekly
```
**响应示例**
```json
{
"report": {
"avg_rating": 1.0,
"created_at": "2026-05-04T01:49:16",
"end_date": "2026-05-10",
"high_freq_queries": [
{"frequency": 1, "query": "测试问题", "sample_answer": "测试回答"}
],
"improvement_suggestions": ["继续保持当前服务质量"],
"low_rating_queries": [],
"negative_count": 0,
"positive_count": 1,
"report_type": "weekly",
"satisfaction_rate": 100.0,
"start_date": "2026-05-04",
"total_feedback": 1,
"total_queries": 1
},
"success": true
}
```
**验证结果**:✅ 通过
---
### GET /reports/monthly
获取月报。
```bash
curl -s http://localhost:5001/reports/monthly
```
**验证结果**:✅ 通过(接口存在)
---
## 14. 知识库路由
### POST /kb/route
测试知识库路由(调试用)。
```bash
echo '{"query":"三峡工程"}' > /tmp/route.json
curl -s -X POST http://localhost:5001/kb/route \
-H "Content-Type: application/json" \
-d @/tmp/route.json
```
**响应示例**
```json
{
"intent": {
"confidence": 1.0,
"department": null,
"is_general": true,
"keywords": [],
"reason": "LLM 意图分析"
},
"query": "test",
"target_collections": ["public_kb"],
"user_department": "开发部",
"user_role": "admin"
}
```
**验证结果**:✅ 通过
---
## 15. 异步任务查询
> **⚠️ 生产服务器server-release不支持**:异步任务系统(`/tasks` 系列端点)仅存在于 main 分支。当前生产服务器的上传、同步、出题、批阅接口均为**同步操作**,直接返回结果,无需轮询。
>
> 如果后续升级到 main 分支版本,以下接口将可用:
>
> | 端点 | 方法 | 说明 |
> |------|------|------|
> | `/tasks` | GET | 获取任务列表(支持 status/type/limit 过滤) |
> | `/tasks/<task_id>` | GET | 获取单个任务状态JSON 轮询) |
> | `/tasks/<task_id>/progress` | GET | SSE 流式任务进度推送 |
> | `/tasks/stats` | GET | 获取任务统计信息 |
>
> **任务状态**`pending` → `running` → `completed` / `failed`
**验证结果**:❌ 路由不存在404— 符合 server-release 预期行为
---
## 16. 认证系统
### POST /auth/login
用户登录。
```bash
echo '{"username":"admin","password":"xxx"}' > /tmp/login.json
curl -s -X POST http://localhost:5001/auth/login \
-H "Content-Type: application/json" \
-d @/tmp/login.json
```
**响应示例**(失败):
```json
{"error": "用户名或密码错误"}
```
**验证结果**:✅ 通过(参数校验正常)
---
### GET /auth/me
获取当前用户信息。
```bash
curl -s http://localhost:5001/auth/me
```
---
### GET /auth/users
获取用户列表。
```bash
curl -s http://localhost:5001/auth/users
```
---
### PUT /auth/users/\<user_id\>
修改用户信息。
```bash
echo '{"role":"user"}' > /tmp/update_user.json
curl -s -X PUT "http://localhost:5001/auth/users/test-user" \
-H "Content-Type: application/json" \
-d @/tmp/update_user.json
```
---
### POST /auth/change-password
修改密码。
```bash
echo '{"old_password":"old","new_password":"new"}' > /tmp/changepw.json
curl -s -X POST http://localhost:5001/auth/change-password \
-H "Content-Type: application/json" \
-d @/tmp/changepw.json
```
---
## 17. 其他端点
### GET /documents/\<path\>/raw
下载文档原始文件。
```bash
curl -s -o output.docx "http://localhost:5001/documents/public_kb%2F1.docx/raw"
```
**响应**返回原始文件HTTP 200
**验证结果**:✅ 通过
---
### DELETE /chunks/batch
批量删除切片。
```bash
echo '{"chunk_ids":["file.txt_text_0","file.txt_text_1"],"collection":"public_kb"}' > /tmp/batch_del.json
curl -s -X DELETE http://localhost:5001/chunks/batch \
-H "Content-Type: application/json" \
-d @/tmp/batch_del.json
```
---
### GET /stats
获取系统统计信息。
```bash
curl -s http://localhost:5001/stats
```
**验证结果**:❌ HTTP 500`KeyError: 'SESSION_MANAGER'`,见已知问题 #2
---
### POST /collections/sync-vlm-cache
同步 VLM 缓存。
```bash
curl -s -X POST http://localhost:5001/collections/sync-vlm-cache
```
---
### POST /collections/\<kb_name\>/reindex
重构向量库索引(异步任务)。
```bash
curl -s -X POST "http://localhost:5001/collections/public_kb/reindex"
```
> **说明**:清除哈希记录并触发全量同步。
---
## 附录. 已知问题
### 1. /rag 接口 collections 参数
**问题**:使用 `collection`(单数)参数指定知识库无效,会被忽略并默认检索 `public_kb`
**解决**:必须使用 `collections`(复数,数组格式)参数。
```bash
# ❌ 错误用法 - collection 单数参数无效
{"message": "问题", "collection": "dept_tech", "chat_history": []}
# ✅ 正确用法 - collections 数组参数
{"message": "问题", "collections": ["dept_tech"], "chat_history": []}
```
### 2. /stats 接口 500 错误
**问题**`GET /stats` 返回 HTTP 500日志显示 `KeyError: 'SESSION_MANAGER'`
**原因**:该端点依赖 `SESSION_MANAGER` 配置项,但 server-release 分支未注册会话管理器。
**状态**:已知缺陷,不影响其他接口正常使用。
### 3. /tasks 系列端点不存在
**问题**`GET /tasks``GET /tasks/<id>``GET /tasks/<id>/progress``GET /tasks/stats` 均返回 HTTP 404。
**原因**:异步任务系统仅存在于 main 分支server-release 保持同步操作模式。上传、同步、出题、批阅接口直接返回结果,无需轮询。
**影响**:无 — 这是预期行为,所有操作均为同步完成。
### 4. /documents/sync 与 /sync 的区别
**问题**:服务器上存在两个同步触发端点,行为略有不同。
| 端点 | 说明 |
|------|------|
| `POST /sync` | 主同步接口,扫描并同步所有知识库 |
| `POST /documents/sync` | 文档级同步接口,需要额外参数 |
**建议**:使用 `POST /sync` 触发手动同步。
---
## 测试覆盖统计
> 2026-06-10 生产服务器测试结果47.116.16.222,云端 Reranker + MMR 文本相似度)
| 分类 | 总数 | 通过 | 异常 | 备注 |
|------|------|------|------|------|
| 健康检查 | 1 | 1 | 0 | ✅ 0.002s |
| 问答接口 | 2 | 2 | 0 | ✅ /rag 流式,/chat 正常 |
| 检索接口 | 1 | 1 | 0 | ✅ /search 0.58-1.53s |
| 向量库管理 | 3 | 3 | 0 | ✅ collections + documents + chunks |
| 文档管理 | 4 | 4 | 0 | ✅ list/status/preview/raw |
| 同步服务 | 3 | 3 | 0 | ✅ status/history/changes |
| 反馈系统 | 5 | 5 | 0 | ✅ feedback/list/stats/bad-cases/blacklist |
| FAQ 管理 | 2 | 2 | 0 | ✅ faq + suggestions |
| 出题系统 | 2 | 2 | 0 | ✅ exam/health + generate参数校验 |
| 图片服务 | 4 | 4 | 0 | ✅ list/stats/info + 图片下载 |
| 报告服务 | 2 | 2 | 0 | ✅ weekly + monthly |
| 知识库路由 | 1 | 1 | 0 | ✅ /kb/route |
| 认证系统 | 1 | 1 | 0 | ✅ /auth/login 参数校验正常 |
| 异步任务 | 1 | 0 | 1 | ⚠️ /tasks 404 — 仅 main 分支可用 |
| 其他 | 1 | 0 | 1 | ⚠️ /stats 500 — SESSION_MANAGER 未注册 |
| **总计** | **33** | **31** | **2** | **2 个异常均为已知缺陷,不影响核心功能** |
---
## 性能基准测试
> 2026-06-10 生产服务器实测47.116.16.222public_kb ~824 切片)
### 检索性能
| 接口 | 参数 | 优化前 | 优化后 | 提升 |
|------|------|--------|--------|------|
| `/search` | top_k=10 | ~34s | **0.58s** | ~60x |
| `/search` | top_k=30 | ~87s | **1.53s** | ~57x |
### 完整 RAG 问答性能(流式)
| 查询 | 完整响应时间 | 搜索阶段 | LLM 生成 |
|------|-------------|----------|----------|
| 现代终端分类有哪些? | 13.8s | ~1.5s | ~12s |
| 加盟终端分公司审批流程 | 12.7s | ~1.5s | ~11s |
| 什么是金丝利零售 | 12.7s | ~1.5s | ~11s |
### 优化措施
| 优化项 | 配置 | 效果 |
|--------|------|------|
| Reranker 云端化 | `RERANK_BACKEND=cloud`xop3qwen8breranker/讯飞云) | 搜索阶段从 33-48s 降至 ~0.3s |
| MMR 文本相似度 | `MMR_USE_EMBEDDING=false` | MMR 阶段从 ~36s 降至 ~0s |
### 耗时拆解(优化后 /rag 问答)
```
总耗时 ~13s
├── 搜索管线 ~1.5s
│ ├── Embedding (query) ~0.25s
│ ├── 向量检索 + BM25 ~0.3s
│ ├── RRF 融合 ~0.01s
│ ├── 上下文扩展 ~0.1s
│ ├── MMR 去重 (文本) ~0.01s
│ ├── Cloud Reranker ~0.3s
│ └── 后处理 ~0.5s
└── LLM 流式生成 ~11.5s
├── 网络建连 ~0.5s
└── 流式 token 生成 ~11s
```
> **注**LLM 生成阶段耗时取决于 mimo-v2.5 API 响应速度,非本地可优化。如需进一步压缩可考虑减少检索切片数量或缩短 prompt。
---
## 附录 B. 生产部署说明
### 多向量库架构
生产环境采用**多向量库模式**,每个知识库独立存储在 `knowledge/vector_store/chroma/<kb_name>/` 目录下,各自维护独立的 ChromaDB SQLite 数据库和 BM25 索引。
当前生产服务器知识库列表:
| 知识库 | 文档数 | 说明 |
|--------|--------|------|
| public_kb | ~824 | 公开知识库,所有用户可访问 |
| dept_1_kb | ~500 | 部门知识库 1 |
| resources | 0 | 资源库(新建,暂无文档) |
### 切片元数据字段
新代码构建的向量库切片包含以下 metadata 字段:
| 字段 | 说明 | 新代码新增 |
|------|------|-----------|
| `chunk_id` | 切片唯一标识 `{文件名}_{序号}` | |
| `chunk_index` | 切片在文档中的序号(用于引用溯源跳转) | ✅ |
| `chunk_type` | text / table / image | |
| `source` | 来源文件名 | |
| `collection` | 所属知识库 | |
| `doc_type` | 文档类型 pdf/word/excel/other | ✅ |
| `page` / `page_end` | 页码范围 | |
| `section` | 所属章节 | |
| `status` | active / deprecated | |
| `version` | 版本号 v1 | |
### 向量库重构
当代码升级涉及元数据字段变更时(如新增 `chunk_index``doc_type`),需要重构向量库:
```bash
# 重构指定知识库(清除哈希记录 → 触发全量同步)
curl -s -X POST http://127.0.0.1:5001/collections/<kb_name>/reindex
```
> **⚠️ 注意**reindex 为同步操作,会阻塞直到重建完成。耗时取决于知识库文档数量,大知识库可能需要数分钟。执行期间搜索和问答接口不受影响(多 worker 架构)。
### Reranker 配置
生产环境使用讯飞云 Reranker 替代本地 CPU 推理,显著提升检索速度:
| 配置项 | 值 | 说明 |
|--------|-----|------|
| `RERANK_BACKEND` | `cloud` | 使用云端 API可选 `local` / `cloud` / `fallback` |
| `RERANK_CLOUD_MODEL` | `xop3qwen8breranker` | 讯飞云排序模型 |
| `RERANK_CLOUD_API_KEY` | `sk-*` | API Key |
| `RERANK_CLOUD_BASE_URL` | `https://maas-api.cn-huabei-1.xf-yun.com/v1/rerank` | 讯飞云 Rerank 端点 |
| `MMR_USE_EMBEDDING` | `false` | MMR 使用文本相似度(零额外计算) |
> **fallback 模式**`RERANK_BACKEND=fallback` 优先使用云端 API如果云端不可用则自动回退到本地模型适合生产环境高可用场景。