docs: 更新出题批题后端对接指南 v1.2 — 同步实际行为

- 移除20题上限说明,改为无上限+50题警告
- 修正文件/向量库不存在时的响应格式(total=0,非404)
- 添加认证模式说明(生产模式直接放行)
- 添加智能出题接口文档(/exam/generate-smart)
- 添加填空题student_answer格式校验说明
- 更新错误码表,移除不存在的FILE_NOT_FOUND
- 添加Q5/Q6常见问题
- 响应示例修正status_code为2020
This commit is contained in:
User
2026-07-03 12:40:47 +08:00
parent c709360c7c
commit 2fbf1b85f9

View File

@@ -8,6 +8,11 @@
| `/exam/generate-smart` | POST | 生成题目AI 自动分析文档结构出题) | 120秒 | | `/exam/generate-smart` | POST | 生成题目AI 自动分析文档结构出题) | 120秒 |
| `/exam/grade` | POST | 批阅答案 | 60秒 | | `/exam/grade` | POST | 批阅答案 | 60秒 |
> **2026-07-03 变更**
> 1. 移除出题总题数 20 道上限,超过 50 道时返回警告(不影响出题)
> 2. 填空题批阅增加 `student_answer` 格式校验(必须为字符串列表)
> 3. 认证错误状态码修正(仅 `DEV_MODE=true` 时生效,见 [认证说明](#认证模式说明)
>
> **2026-06-05 变更**`/exam/grade` 请求字段 `question_content` 已重命名为 `content`(破坏性变更)。详见 [出题批阅接口变更说明2026-06-05](出题批阅接口变更说明2026-06-05.md)。 > **2026-06-05 变更**`/exam/grade` 请求字段 `question_content` 已重命名为 `content`(破坏性变更)。详见 [出题批阅接口变更说明2026-06-05](出题批阅接口变更说明2026-06-05.md)。
--- ---
@@ -27,9 +32,10 @@ Content-Type: application/json
|------|------|------|------| |------|------|------|------|
| `file_path` | string | ✅ | 文档路径(相对于 documents 目录) | | `file_path` | string | ✅ | 文档路径(相对于 documents 目录) |
| `collection` | string 或 string[] | ✅ | 向量库名称,支持数组(按优先级顺序检索,找到文件即停止) | | `collection` | string 或 string[] | ✅ | 向量库名称,支持数组(按优先级顺序检索,找到文件即停止) |
| `question_types` | object | ✅ | 题型及数量 | | `question_types` | object | ✅ | 题型及数量**无上限**(超过 50 道时服务端返回警告但仍正常出题) |
| `difficulty` | int | ❌ | 难度等级 1-5默认 3 | | `difficulty` | int | ❌ | 难度等级 1-5默认 3 |
| `request_id` | string | ❌ | 请求ID相同ID返回缓存结果幂等性 | | `request_id` | string | ❌ | 请求ID相同ID返回缓存结果幂等性 |
| `exclude_stems` | string[] | ❌ | 排除已有题目的题干列表,避免重复出题(最多 100 条) |
**请求示例:** **请求示例:**
@@ -64,12 +70,15 @@ Content-Type: application/json
{ {
"success": true, "success": true,
"status": "success", "status": "success",
"status_code": 2011, "status_code": 2020,
"message": "出题成", "message": "出题成",
"data": { "data": {
"request_id": "uuid-xxx", "request_id": "uuid-xxx",
"total": 10, "total": 10,
"source_chunks_used": 25, "source_chunks_used": 25,
"requested_types": {"single_choice": 3, "fill_blank": 2},
"actual_types": {"single_choice": 3, "fill_blank": 2},
"warnings": [],
"questions": [ "questions": [
{ {
"question_type": "single_choice", "question_type": "single_choice",
@@ -89,7 +98,8 @@ Content-Type: application/json
}, },
"source_trace": { "source_trace": {
"document_name": "薪酬制度.docx", "document_name": "薪酬制度.docx",
"chunks_count": 3 "page_numbers": [1],
"sources": [{"chunk_id": "...", "page": 1, "section": "...", "snippet": "..."}]
} }
} }
] ]
@@ -97,17 +107,30 @@ Content-Type: application/json
} }
``` ```
**失败响应:** **⚠️ 文件/向量库不存在时的响应:**
`file_path` 在指定 `collection` 中找不到,或 `collection` 不存在时,接口**不会返回错误**,而是返回空结果:
```json ```json
{ {
"success": false, "success": true,
"status": "failed", "status": "success",
"error_code": "FILE_NOT_FOUND", "status_code": 2020,
"message": "文件不存在" "message": "出题成功",
"data": {
"request_id": null,
"total": 0,
"questions": [],
"requested_types": {"single_choice": 1},
"actual_types": {},
"warnings": ["single_choice: 请求 1 道,实际生成 0 道"]
}
} }
``` ```
> **后端注意**:必须检查 `data.total` 是否 > 0 来判断出题是否成功,不能仅依赖 `success` 字段。
```
### 2.3 返回字段说明 ### 2.3 返回字段说明
**RAG 服务返回的字段(后端需存储):** **RAG 服务返回的字段(后端需存储):**
@@ -148,11 +171,63 @@ Content-Type: application/json
| 错误码 | HTTP | 说明 | | 错误码 | HTTP | 说明 |
|--------|------|------| |--------|------|------|
| `FILE_NOT_FOUND` | 404 | 指定文件不存在 | | `MISSING_PARAMS` | 400 | 缺少必填参数file_path / collection / question_types |
| `COLLECTION_NOT_FOUND` | 404 | 指定向量库不存在 | | `INVALID_PARAMS` | 400 | 参数校验失败题型无效、难度越界、总题数≤0 等) |
| `NO_CONTENT` | 400 | 文件内容为空,无法出题 | | `EXAM_ERROR` | 500 | 出题过程异常LLM 调用失败、解析错误等) |
| `LLM_ERROR` | 500 | LLM 调用失败 |
| `PARSE_ERROR` | 500 | 解析失败 | > **注意**:文件不存在或向量库不存在时,不会返回错误码,而是返回 `success=true` + `total=0` + `warnings`(见上方说明)。后端应检查 `total > 0`。
### 2.6 智能出题接口(/exam/generate-smart
与 `/exam/generate` 的区别:不需要传 `question_types`AI 自动分析文档后决定题型和数量。
```
POST /exam/generate-smart
Content-Type: application/json
```
**请求体字段说明:**
| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `file_path` | string | ✅ | 文档路径 |
| `collection` | string 或 string[] | ✅ | 向量库名称 |
| `difficulty` | int | ❌ | 难度等级 1-5默认 3 |
| `max_total` | int | ❌ | AI 出题总数上限,不传则不限制 |
| `exclude_stems` | string[] | ❌ | 排除已有题目的题干列表 |
| `request_id` | string | ❌ | 请求ID |
**请求示例:**
```json
{
"file_path": "111/卷烟货源组织管理办法.docx",
"collection": "111",
"difficulty": 3,
"max_total": 10,
"request_id": "smart-uuid-xxx"
}
```
**响应:**`/exam/generate` 格式相同,额外包含 `ai_analysis` 字段AI 分析结果)。
---
### 认证模式说明
RAG 服务支持两种认证模式,由环境变量 `DEV_MODE` 控制:
| 模式 | DEV_MODE | 认证行为 |
|------|----------|----------|
| **生产模式** | `false` | 认证网关**直接放行**,不校验 Header。权限由后端服务完全控制 |
| **开发模式** | `true` | 支持 `Authorization: Bearer mock-token-admin` 模拟登录,无 Header 时使用默认测试用户 |
**当前服务器为生产模式**`DEV_MODE=false`),因此:
- `Authorization` Header 会被忽略
- 不会返回 `401 UNAUTHORIZED``403 FORBIDDEN`
- 后端服务应自行完成用户认证和权限校验,再调用 RAG 出题/批阅接口
> 开发模式下,认证错误会返回正确的业务状态码(`UNAUTHORIZED=4001`、`FORBIDDEN=4002`HTTP 状态码分别为 401/403。
--- ---
@@ -182,6 +257,12 @@ Content-Type: application/json
| `student_answer` | any | ✅ | 学生答案 | 学生提交 | | `student_answer` | any | ✅ | 学生答案 | 学生提交 |
| `max_score` | number | ✅ | 满分 | 后端数据库 | | `max_score` | number | ✅ | 满分 | 后端数据库 |
> **填空题 `student_answer` 格式要求**2026-07-03 新增校验):
> - 必须为 **字符串数组**,如 `["答案1", "答案2"]`
> - 不是列表(如传了字符串 `"答案1"`)→ 该题直接得 0 分,`grading_status` 为 `"failed"`
> - 列表中某项不是字符串(如传了数字 `123`)→ 该题直接得 0 分
> - 校验失败不影响其他题目的正常批阅
**请求示例:** **请求示例:**
```json ```json
@@ -366,8 +447,11 @@ Content-Type: application/json
| 错误码 | HTTP | 说明 | | 错误码 | HTTP | 说明 |
|--------|------|------| |--------|------|------|
| `INVALID_ANSWER_FORMAT` | 400 | 答案格式不正确 | | `MISSING_PARAMS` | 400 | 缺少 answers 字段 |
| `GRADING_ERROR` | 500 | 批阅过程出错 | | `INVALID_PARAMS` | 400 | answers 非数组、question_type 无效等 |
| `GRADE_ERROR` | 500 | 批阅过程出错 |
> **填空题格式错误不返回错误码**:当 `student_answer` 格式不合法时,该题返回 `grading_status: "failed"` + `score: 0`,但接口整体仍返回 `success: true`。后端应检查每道题的 `grading_status` 字段。
--- ---
@@ -464,8 +548,23 @@ Content-Type: application/json
- 设置 60 秒超时 - 设置 60 秒超时
- 主观题较多时适当延长 - 主观题较多时适当延长
### Q5: 出题数量有上限吗?
2026-07-03 起,出题接口**不再限制总题数**。服务端会在请求数超过 50 道时记录警告日志,但不影响出题。建议:
- 单次出题不超过 30 道LLM 生成耗时与题数成正比30 道约需 5-8 分钟)
- 超过 30 道建议分批调用
- 设置 120 秒以上超时
### Q6: 填空题学生答案传错了会怎样?
2026-07-03 起,填空题增加了格式校验:
- `student_answer` 不是列表 → 该题得 0 分,`grading_status = "failed"`
- 列表中某项不是字符串 → 该题得 0 分
- 校验失败不影响同一请求中其他题目的批阅
- 接口整体仍返回 `success: true`,需检查每道题的 `grading_status`
--- ---
**文档版本**: v1.1 **文档版本**: v1.2
**更新时间**: 2026-05-17 **更新时间**: 2026-07-03
**相关文档**: [后端对接规范.md](./后端对接规范.md) **相关文档**: [后端对接规范.md](./后端对接规范.md)