Files
rag/docs/curl测试手册.md
lacerate551 858ee40e5b chore: 同步项目状态
- main.py: 去掉 emoji 避免 GBK 编码崩溃
- docs/curl测试手册.md: 更新模型名和测试日期
- docs/代码审查报告_2026-06-05.md: 删除过期报告
- docs/main分支独有功能说明.md: 新增
- docs/出题系统逻辑.md: 新增
2026-06-19 15:25:57 +08:00

51 KiB
Raw Blame History

RAG API curl 测试手册

基于 后端对接规范.md,所有 curl 命令均在生产模式 (APP_ENV=prod) 下验证通过。

测试日期2026-06-10最近更新| 生产服务器:47.116.16.222 | 服务地址:http://127.0.0.1:5001

当前部署模型:qwen-turboDashScope| 嵌入模型:bge-base-zh-v1.5(本地 CPU| Rerankqwen3-rerankDashScope 云端 API

目录


1. 基础信息

认证方式

生产模式 (APP_ENV=prod) 下无需认证 Header直接放行。用户信息使用默认值

{"user_id": "backend-caller", "username": "后端调用", "role": "user", "department": ""}

中文编码注意

Windows bash 中 curl 传递中文 JSON 需使用文件方式:

# 方式一:使用临时文件(推荐)
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

检查服务运行状态。

curl -s http://localhost:5001/health

响应示例

{
  "bm25_index": "动态按需加载",
  "knowledge_base": "多向量库模式 (按集合提供服务)",
  "mode": "Agentic RAG",
  "status": "ok"
}

验证结果 通过


3. 问答接口

POST /rag

知识库问答SSE 流式返回)。

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 格式

[
  {"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 结构(引用溯源,用于前端跳转定位):

{
  "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 文档类型:pdfwordexcel
section 章节路径(已清洗,过滤掉正文内容)
page / page_end 页码(仅 PDF
bbox / bbox_mode 坐标定位(仅 PDF
section_chunk_id 章节内段落序号(仅 Word

带 collections 参数

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

多向量库同时查询

# 同时检索多个知识库
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

普通聊天模式(非知识库)。

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 对话历史

响应示例

{
  "answer": "你好!很高兴见到你~",
  "mode": "chat",
  "sources": [],
  "web_searched": false
}

验证结果 通过


4. 检索接口

POST /search

混合检索(向量 + BM25供 Dify 工作流调用。

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"]

响应示例

{
  "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

获取向量库列表。

curl -s http://localhost:5001/collections

响应示例

{
  "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

创建新向量库。

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 描述

响应示例

{
  "message": "向量库 'test_kb' 创建成功",
  "name": "test_kb",
  "success": true
}

验证结果 通过


PUT /collections/<name>

修改向量库信息。

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>

删除向量库。

curl -s -X DELETE http://localhost:5001/collections/test_kb

查询参数

参数 类型 必需 说明
delete_documents boolean 是否删除文档源文件,默认 false

带参数示例

curl -s -X DELETE "http://localhost:5001/collections/test_kb?delete_documents=true"

验证结果 通过


GET /collections/<kb_name>/documents

获取向量库内的文档列表。

curl -s "http://localhost:5001/collections/public_kb/documents"

响应示例

{
  "collection": "public_kb",
  "documents": [
    {
      "chunks": 69,
      "source": "3.txt"
    },
    {
      "chunks": 12,
      "source": "1.txt"
    }
  ],
  "total": 10
}

验证结果 通过


GET /collections/<kb_name>/chunks

获取向量库切片列表。

curl -s "http://localhost:5001/collections/public_kb/chunks?limit=2&offset=0"

查询参数

参数 类型 必需 说明
document_id string 过滤指定文档的切片
limit int 返回数量,默认 100
offset int 偏移量,默认 0

响应示例

{
  "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

获取文档版本历史。

# 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

响应示例

{
  "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

更新图片切片描述(重新生成)。

curl -s -X POST "http://localhost:5001/collections/public_kb/update-image-descriptions"

响应示例

{
  "success": true,
  "message": "图片描述更新完成",
  "updated": 5
}

验证结果 通过


6. 文档管理

GET /documents/list

获取文档列表。

curl -s "http://localhost:5001/documents/list?collection=public_kb"

查询参数

参数 类型 必需 说明
collection string 知识库名称(也可用 kb_name),默认返回全部

注意:该接口不支持分页,返回指定知识库的全部文档列表。

响应示例

{
  "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

获取文档处理状态。

# URL 编码路径中的斜杠
curl -s "http://localhost:5001/documents/public_kb%2Ftest.txt/status"

响应示例

{
  "success": true,
  "status": "active",
  "chunk_count": 105,
  "last_processed": null
}

验证结果 通过


POST /documents/upload

上传单个文件。

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

响应示例

{
  "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

批量上传文件。

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"

响应示例

{
  "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>

更新/替换文档。

echo "更新后的文档内容" > /tmp/updated.txt
curl -s -X PUT "http://localhost:5001/documents/public_kb%2Ftest.txt" \
  -F "file=@/tmp/updated.txt"

表单字段

字段 类型 必需 说明
file file 替换的文件

响应示例

{
  "success": true,
  "message": "文件已更新"
}

验证结果 通过


DELETE /documents/<path>

删除文档。

# URL 编码路径中的斜杠
curl -s -X DELETE "http://localhost:5001/documents/public_kb%2Ftest.txt"

响应示例

{
  "message": "文档已删除",
  "success": true
}

验证结果 通过


POST /collections/<kb_name>/documents/<filename>/deprecate

废弃文档版本。

curl -s -X POST "http://localhost:5001/collections/public_kb/documents/test.txt/deprecate"

验证结果 通过(接口存在)


POST /collections/<kb_name>/documents/<filename>/restore

恢复文档版本。

curl -s -X POST "http://localhost:5001/collections/public_kb/documents/test.txt/restore"

验证结果 通过(接口存在)


🛠️ DEV GET /documents/<path>/preview

开发环境自用接口,后端组无需调用。 仅供 dev-ui 内部前端实现引用溯源跳转使用。后端组可根据 /rag 返回的 citations 中的 chunk_indexpagebbox 等字段自行实现文档定位。

文档预览(支持按切片序号跳转),用于引用溯源点击后定位到文档中的具体位置。

# 跳转到指定切片(前后各取 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 个)

响应示例

{
  "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

获取文档切片列表。

# URL 编码路径
curl -s "http://localhost:5001/documents/dept_hr%2F%E4%BA%BA%E5%91%98%E5%90%8D%E5%86%8C.txt/chunks"

注意:该接口不支持分页或过滤参数,返回指定文档的全部切片。

响应示例

{
  "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

新增切片。

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>

修改切片。

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>

删除切片。

curl -s -X DELETE "http://localhost:5001/chunks/人员名册.txt_text_0?collection=dept_hr"

查询参数

参数 类型 必需 说明
collection string 向量库名称

验证结果 通过


8. 同步服务

POST /sync

触发文档同步(异步任务)。

curl -s -X POST http://localhost:5001/sync \
  -H "Content-Type: application/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

{"error": "TASK_RUNNING", "message": "同步任务正在执行中,请等待完成"}

验证结果 通过


GET /sync/status

获取同步状态。

curl -s http://localhost:5001/sync/status

响应示例

{
  "documents_tracked": 0,
  "enabled": true,
  "last_sync": null,
  "monitoring": false
}

验证结果 通过


GET /sync/history

获取同步历史。

curl -s http://localhost:5001/sync/history

响应示例

{
  "history": []
}

验证结果 通过


GET /sync/changes

获取待同步变更。

curl -s http://localhost:5001/sync/changes

响应示例

{
  "changes": []
}

验证结果 通过


POST /sync/start

启动文件监控。

curl -s -X POST http://localhost:5001/sync/start

响应示例

{
  "message": "文件监控已启动",
  "status": "success",
  "status_code": 2010
}

验证结果 通过


POST /sync/stop

停止文件监控。

curl -s -X POST http://localhost:5001/sync/stop

响应示例

{
  "message": "文件监控已停止",
  "status": "success",
  "status_code": 2010
}

验证结果 通过


9. 反馈系统

POST /feedback

提交反馈。

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 原因

响应示例

{
  "faq_suggested": true,
  "feedback_id": 7,
  "success": true,
  "suggestion_id": 6
}

验证结果 通过


GET /feedback/list

获取反馈列表。

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 控制返回数量。

响应示例

{
  "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

获取反馈统计。

curl -s http://localhost:5001/feedback/stats

响应示例

{
  "stats": {
    "avg_rating": 1.0,
    "negative_count": 0,
    "positive_count": 8,
    "satisfaction_rate": 100.0,
    "total_feedback": 8
  },
  "success": true
}

验证结果 通过


GET /feedback/bad-cases

获取差评案例列表。

curl -s http://localhost:5001/feedback/bad-cases

响应示例

{
  "bad_cases": [],
  "blacklisted_sources": [],
  "success": true,
  "suggestions": [
    "补充到知识库(针对知识盲区)",
    "添加到 Query Rewrite 规则(针对表达歧义)"
  ]
}

验证结果 通过


GET /feedback/blacklist

获取切片黑名单。

curl -s http://localhost:5001/feedback/blacklist

响应示例

{
  "blacklist": [],
  "count": 0,
  "success": true,
  "usage": "在检索时过滤这些来源以提升回答质量"
}

验证结果 通过


10. FAQ 管理

GET /faq

获取 FAQ 列表。

curl -s "http://localhost:5001/faq?limit=5"

查询参数

参数 类型 必需 说明
status string 按状态过滤(如 approveddraft
limit int 返回数量,默认 50

响应示例

{
  "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。

curl -s -X POST http://localhost:5001/faq \
  -H "Content-Type: application/json" \
  -d "{\"question\":\"FAQ question\",\"answer\":\"FAQ answer\"}"

请求体

字段 类型 必需 说明
question string 问题内容
answer string 答案内容

响应示例

{
  "faq_id": 7,
  "message": "FAQ已创建请通过 /faq/<id>/approve 接口确认后生效",
  "status": "draft",
  "success": true
}

验证结果 通过


PUT /faq/<id>

修改 FAQ。

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 新答案内容

响应示例

{
  "message": "FAQ更新成功",
  "success": true,
  "sync_status": "skipped"
}

验证结果 通过


DELETE /faq/<id>

删除 FAQ。

curl -s -X DELETE "http://localhost:5001/faq/7"

响应示例

{
  "message": "FAQ删除成功",
  "success": true
}

验证结果 通过


GET /faq/suggestions

获取 FAQ 建议列表。

curl -s "http://localhost:5001/faq/suggestions?status=pending&limit=5"

查询参数

参数 类型 必需 说明
status string 按状态过滤,默认 pending
limit int 返回数量,默认 50

响应示例

{
  "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 角色)。

curl -s -X POST "http://localhost:5001/faq/suggestions/6/approve" \
  -H "Content-Type: application/json" \
  -d '{}'

请求体(可选,用于修改答案):

{"answer": "管理员修改后的答案"}

注意:必须传递请求体(至少空对象 {}),否则返回 400 错误。

验证结果 通过


POST /faq/suggestions/<id>/reject

拒绝 FAQ 建议(需 admin 角色)。

curl -s -X POST "http://localhost:5001/faq/suggestions/6/reject" \
  -H "Content-Type: application/json" \
  -d '{}'

验证结果 通过


POST /faq/<id>/approve

直接批准 FAQ非从建议列表

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

出题服务健康检查。

curl -s http://localhost:5001/exam/health

响应示例

{
  "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
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 配置示例

{
  "single_choice": 5,
  "multiple_choice": 2,
  "true_false": 3,
  "fill_blank": 2,
  "subjective": 1
}

响应示例

{
  "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_typesAI 自动分析文档后决定
  • 返回格式与旧端口完全兼容,额外包含 ai_analysis 字段
  • 适合不想费脑子的场景
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 附加选项

响应示例

{
  "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

批阅答案。

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。

响应示例

{
  "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

获取图片列表。

curl -s "http://localhost:5001/images/list?limit=5&offset=0"

查询参数

参数 类型 必需 说明
limit int 返回数量,默认 50
offset int 偏移量,默认 0

响应示例

{
  "images": [
    {
      "image_id": "0569dd285537",
      "size_bytes": 169818,
      "url": "/images/0569dd285537"
    }
  ],
  "limit": 5,
  "offset": 0,
  "total": 67
}

验证结果 通过


GET /images/<id>

获取单张图片。

curl -s -o image.jpg http://localhost:5001/images/0569dd285537

响应返回图片文件HTTP 200

验证结果 通过


GET /images/<id>/info

获取图片元数据。

curl -s "http://localhost:5001/images/0569dd285537/info"

响应示例

{
  "format": "JPEG",
  "height": 1357,
  "image_id": "0569dd285537",
  "mode": "RGB",
  "size_bytes": 169818,
  "url": "/images/0569dd285537",
  "width": 1023
}

验证结果 通过


GET /images/stats

获取图片统计。

curl -s http://localhost:5001/images/stats

响应示例

{
  "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

获取周报。

curl -s http://localhost:5001/reports/weekly

响应示例

{
  "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

获取月报。

curl -s http://localhost:5001/reports/monthly

验证结果 通过(接口存在)


14. 知识库路由

POST /kb/route

测试知识库路由(调试用)。

echo '{"query":"三峡工程"}' > /tmp/route.json
curl -s -X POST http://localhost:5001/kb/route \
  -H "Content-Type: application/json" \
  -d @/tmp/route.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 获取任务统计信息

任务状态pendingrunningcompleted / failed

验证结果 路由不存在404— 符合 server-release 预期行为


16. 认证系统

POST /auth/login

用户登录。

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

响应示例(失败):

{"error": "用户名或密码错误"}

验证结果 通过(参数校验正常)


GET /auth/me

获取当前用户信息。

curl -s http://localhost:5001/auth/me

GET /auth/users

获取用户列表。

curl -s http://localhost:5001/auth/users

PUT /auth/users/<user_id>

修改用户信息。

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

修改密码。

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

下载文档原始文件。

curl -s -o output.docx "http://localhost:5001/documents/public_kb%2F1.docx/raw"

响应返回原始文件HTTP 200

验证结果 通过


DELETE /chunks/batch

批量删除切片。

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

获取系统统计信息。

curl -s http://localhost:5001/stats

验证结果 HTTP 500KeyError: 'SESSION_MANAGER',见已知问题 #2


POST /collections/sync-vlm-cache

同步 VLM 缓存。

curl -s -X POST http://localhost:5001/collections/sync-vlm-cache

POST /collections/<kb_name>/reindex

重构向量库索引(异步任务)。

curl -s -X POST "http://localhost:5001/collections/public_kb/reindex"

说明:清除哈希记录并触发全量同步。


附录. 已知问题

1. /rag 接口 collections 参数

问题:使用 collection(单数)参数指定知识库无效,会被忽略并默认检索 public_kb

解决:必须使用 collections(复数,数组格式)参数。

# ❌ 错误用法 - 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 /tasksGET /tasks/<id>GET /tasks/<id>/progressGET /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=cloudqwen3-rerank 搜索阶段从 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 生成阶段耗时取决于 qwen-turbo API 响应速度,非本地可优化。当前已使用 qwen-turbo最快模型如需进一步压缩可考虑减少检索切片数量或缩短 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_indexdoc_type),需要重构向量库:

# 重构指定知识库(清除哈希记录 → 触发全量同步)
curl -s -X POST http://127.0.0.1:5001/collections/<kb_name>/reindex

⚠️ 注意reindex 为同步操作,会阻塞直到重建完成。耗时取决于知识库文档数量,大知识库可能需要数分钟。执行期间搜索和问答接口不受影响(多 worker 架构)。

Reranker 配置

生产环境使用 DashScope 云端 Reranker 替代本地 CPU 推理,显著提升检索速度:

配置项 说明
RERANK_BACKEND cloud 使用云端 API可选 local / cloud / fallback
RERANK_CLOUD_MODEL qwen3-rerank DashScope 云端排序模型
RERANK_CLOUD_API_KEY sk-* DashScope 标准 API Key
RERANK_CLOUD_BASE_URL https://dashscope.aliyuncs.com/compatible-api/v1/reranks OpenAI 兼容端点
MMR_USE_EMBEDDING false MMR 使用文本相似度(零额外计算)

fallback 模式RERANK_BACKEND=fallback 优先使用云端 API如果云端不可用则自动回退到本地模型适合生产环境高可用场景。