Spaces:
Sleeping
Sleeping
| # Smart Quiz AI 接口规范 | |
| **版本**: v2.2 | |
| **日期**: 2026-04-01 | |
| **状态**: Draft | |
| **描述**: 本文档详细定义了 Smart Quiz 后端与 AI 服务端的新版交互标准,重点增强了可追溯性、数据结构规范性和错误处理机制。 | |
| --- | |
| ## 1. 变更摘要 (Change Log) | |
| 1. **全局**: 所有响应新增 `meta` 字段(模型信息、耗时、Token 消耗)。 | |
| 2. **Quiz 生成**: | |
| - 移除 `options[].is_correct`。 | |
| - 新增 `question_id`。 | |
| - 新增 `correct_answers` 数组(支持单选、多选、判断)。 | |
| - 明确短答题必须返回 `explanation`。 | |
| 3. **错误处理**: 标准化 4xx/5xx 响应结构,引入 `error.type` 和 `error.reason`。 | |
| 4. **Quiz 评分**: 新增 `per_question_feedback`,提供每题得分与理由。 | |
| 5. **新增recipe 评分**: | |
| 智能出题变更:取消原 configurations 下的 questionCount和 questionTypes,新增configurations.recipe 对象。 | |
| 若生成了 SHORT_ANSWER 题,除了必备的 explanation 外,响应选项中还要支持返回带有评分标准的 rubric(json)。 | |
| 智能判卷变更:在请求的 userAnswers 每一项数组元素中,新增支持附加可选字段 rubric: Object。在给主观题打分时,会把出题接口接收到的这条 rubric 传过去 | |
| 6. **单题即时判题流程补充**: | |
| submit 升级为单题提交时,后端调用 grade 接口可仅传 1 条 `userAnswers`;最后一题完成后再触发一次整卷汇总调用,生成全局 `feedbackSummary/recommendations`。 | |
| --- | |
| ## 2. 通用规范 | |
| ### 2.1 Meta 信息 (Traceability) | |
| 所有 API 成功响应(2xx)必须包含 `meta` 字段,用于监控模型表现和成本。 | |
| **响应结构示例**: | |
| ```json | |
| { | |
| "data": { ... }, | |
| "meta": { | |
| "model": "gpt-4-turbo", // 模型名称 | |
| "model_version": "2024-04-09",// 模型版本日期 | |
| "prompt_version": "v2.1", // Prompt 版本 | |
| "temperature": 0.4, // 采样温度 | |
| "tokens_used": 1250, // 总 Token 消耗 (Prompt + Completion) | |
| "latency_ms": 3500 // 服务端处理耗时 (ms) | |
| } | |
| } | |
| ``` | |
| --- | |
| ## 3. 接口详情 | |
| ### 3.1 智能出题 (Generate Quiz) | |
| **变更点**: 数据结构重构,强化校验能力。 | |
| - **URL**: `{AI_SERVICE_URL}/ai/quiz/generate` | |
| - **Method**: `POST` | |
| - **Auth**: `Authorization: Bearer {API_KEY}` | |
| **请求参数 (Request)**: | |
| ```json | |
| { | |
| "requestId": "req_unique_id_123", | |
| "context": { | |
| "courseId": 101, | |
| "moduleId": 5, | |
| "topics": ["if-else", "loops"] | |
| }, | |
| "configurations": { | |
| "recipe": { | |
| "SINGLE_CHOICE": 3, | |
| "TRUE_FALSE": 0, | |
| "MULTIPLE_CHOICE": 1, | |
| "SHORT_ANSWER": 1 | |
| }, | |
| "language": "EN" | |
| } | |
| } | |
| ``` | |
| **请求参数说明 (Request Fields)**: | |
| | 字段名 | 类型 | 必选 | 描述 | | |
| | :------------------------ | :-------- | :--- | :------------------------ | | |
| | `requestId` | `String` | 是 | 溯源 ID,用于日志追踪 | | |
| | `context` | `Object` | 是 | 教学上下文信息 | | |
| | `context.courseId` | `Integer` | 是 | 课程 ID (Traceability) | | |
| | `context.moduleId` | `Integer` | 否 | 模块 ID (Traceability) | | |
| | `context.topics` | `Array` | 否 | 精确的主题列表 | | |
| | `configurations` | `Object` | 是 | 生成配置 | | |
| | `configurations.recipe` | `Object` | 是 | 题目生成配方 (题型: 题数) | | |
| | `configurations.language` | `String` | 是 | 题目语言 (CN/EN) | | |
| **字段备注 (Field Notes)**: | |
| - `configurations.recipe`: | |
| - 规定 AI 应该生成的具体题型及与其对应的题目数量。AI 模型需严格遵守该配置出题,对于不需要生成的题型可传 0 甚至省略其键。后端负责将教师设定好的配比翻译为配方。 | |
| - `context.topics`: | |
| - **后端生成逻辑**: 若指定 `moduleId`,系统自动检索该模块下所有 **Unit** 的标题作为主题列表;若未指定或模块无单元,默认为 `["general"]`。 | |
| - **传输处理**: 数组元素会被拼接为逗号分隔的字符串 (e.g., "Variables, Data Types") 传递给 AI 模型。 | |
| **响应 (Response)**: | |
| ```json | |
| { | |
| "data": { | |
| "questions": [ | |
| { | |
| "question_id": "ai_q_8f9a2", // [新增] 唯一标识 | |
| "type": "SHORT_ANSWER", | |
| "content": "Explain polymorphism in OOP.", | |
| "options": [], | |
| "correct_answers": ["Ability to take many forms"], | |
| "explanation": "Polymorphism allows objects to be treated as instances of their parent class.", | |
| "rubric": { // [新增] 题目专门的评分标准(可选) | |
| "keywords": ["inherit", "override", "many forms"], | |
| "max_score": 10 | |
| } | |
| }, | |
| { | |
| "question_id": "ai_q_7b3c1", | |
| "type": "MULTIPLE_CHOICE", | |
| "content": "Select mutable types.", | |
| "options": [ | |
| { "label": "A", "content": "List" }, | |
| { "label": "B", "content": "Tuple" }, | |
| { "label": "C", "content": "Dictionary" } | |
| ], | |
| "correct_answers": ["A", "C"] | |
| } | |
| ] | |
| }, | |
| "meta": { ... } | |
| } | |
| ``` | |
| **字段校验规则 (Backend Validation)**: | |
| 1. **SINGLE_CHOICE**: `correct_answers` 长度必须为 **1**。 | |
| 2. **MULTIPLE_CHOICE**: `correct_answers` 长度必须 **≥ 1**。 | |
| 3. **TRUE_FALSE**: 必须包含 2 个选项 (True/False),且 `correct_answers` 长度为 **1**。 | |
| 4. **SHORT_ANSWER**: `options` 为空,必须包含有效 `explanation`(作为参考答案)。 | |
| --- | |
| ### 3.2 智能判卷 (Grade Quiz) | |
| **变更点**: 增加逐题反馈详情,并支持单题即时判题与完卷汇总。 | |
| - **URL**: `{AI_SERVICE_URL}/ai/quiz/grade` | |
| - **Method**: `POST` | |
| - **Auth**: `Authorization: Bearer {API_KEY}` | |
| **请求参数 (Request)**: | |
| ```json | |
| { | |
| "requestId": "req_unique_id_456", | |
| "quizContext": { | |
| "title": "Python Quiz", | |
| "totalScore": 10.0, | |
| "maxScore": 100.0 | |
| }, | |
| "userAnswers": [ | |
| { | |
| "questionId": "501", | |
| "questionContent": "What is Python?", | |
| "userChoiceLabel": "A", | |
| "correctChoiceLabel": "A", | |
| "isCorrect": true | |
| } | |
| ] | |
| } | |
| ``` | |
| **请求参数说明 (Request Fields)**: | |
| | 字段名 | 类型 | 必选 | 描述 | | |
| | :------------------------------ | :------- | :--- | :------------------------------- | | |
| | `requestId` | `String` | 是 | 溯源 ID | | |
| | `quizContext` | `Object` | 是 | 测验背景信息 | | |
| | `userAnswers` | `Array` | 是 | 用户作答数据,用于生成针对性建议 | | |
| | `userAnswers[].questionId` | `String` | 是 | 题目唯一标识(后端用于回写对应题目) | | |
| | `userAnswers[].questionContent` | `String` | 是 | 题目内容文本 | | |
| | `userAnswers[].userChoiceLabel` | `String` | 否 | 客观题:用户选择的选项标签 | | |
| | `userAnswers[].correctChoiceLabel` | `String` | 否 | 客观题:标准答案选项标签 | | |
| | `userAnswers[].isCorrect` | `Boolean`| 否 | 客观题:后端预判是否正确 | | |
| | `userAnswers[].userTextAnswer` | `String` | 否 | 用户对主观题的回答文本 | | |
| | `userAnswers[].referenceAnswer` | `String` | 否 | 标准/参考答案 | | |
| | `userAnswers[].rubric` | `Object` | 否 | (可选) 评分标准(如需精细评分) | | |
| #### 3.2.1 单题即时判题调用约定 | |
| - 后端在学生每提交一道题时调用本接口,`userAnswers` 数组长度固定为 `1`。 | |
| - 客观题与主观题都允许走 AI 评分与说明生成。 | |
| - `per_question_feedback[].question_id` 必须回传并可映射到入参中的 `userAnswers[].questionId`。 | |
| #### 3.2.2 完卷汇总调用约定 | |
| - 当最后一题提交完成后,后端会再次调用本接口做整卷汇总。 | |
| - 此时 `userAnswers` 为整卷全量答案,用于生成全局 `feedbackSummary/recommendations`。 | |
| **完卷汇总请求示例(全量 `userAnswers`)**: | |
| ```json | |
| { | |
| "requestId": "req_quiz_final_789", | |
| "quizContext": { | |
| "title": "Python Quiz", | |
| "totalScore": 80.0, | |
| "maxScore": 100.0 | |
| }, | |
| "userAnswers": [ | |
| { | |
| "questionId": "501", | |
| "questionContent": "What is Python?", | |
| "userChoiceLabel": "A", | |
| "correctChoiceLabel": "A", | |
| "isCorrect": true | |
| }, | |
| { | |
| "questionId": "502", | |
| "questionContent": "Explain MVC.", | |
| "userTextAnswer": "Model View Controller...", | |
| "referenceAnswer": "Design pattern...", | |
| "rubric": { | |
| "keywords": ["Model", "View", "Controller", "Separation of concerns"], | |
| "max_score": 10 | |
| } | |
| } | |
| ] | |
| } | |
| ``` | |
| #### 3.2.3 职责边界与失败处理 | |
| - AI 负责输出每题分数与说明(`score`、`reasoning`)。 | |
| - 后端对外响应中的 `isCorrect`(客观题)由标准答案稳定比对生成,避免波动。 | |
| - 当 AI 超时/5xx 时,不应阻止后端保存用户答案;后端可将该题标记为待补判并允许重试。 | |
| **响应 (Response)**: | |
| ```json | |
| { | |
| "data": { | |
| "overall_score": 85, | |
| "feedback_summary": "Good understanding of OOP concepts.", | |
| "per_question_feedback": [ // [新增] 逐题反馈 | |
| { | |
| "question_id": "ai_q_8f9a2", | |
| "score": 10, | |
| "reasoning": "Correct. Class is indeed the blueprint." | |
| }, | |
| { | |
| "question_id": "ai_q_9c4d2", | |
| "score": 5, | |
| "reasoning": "Partially correct. You missed the edge case." | |
| } | |
| ], | |
| "recommendations": [ ... ] | |
| }, | |
| "meta": { ... } | |
| } | |
| ``` | |
| --- | |
| ### 3.3 智能提示 (Generate Hint) | |
| 后端调用此接口请求 AI 对单道题目生成解题提示(不泄露答案)。 | |
| - **URL**: `{AI_SERVICE_URL}/ai/quiz/hint` | |
| - **Method**: `POST` | |
| - **Auth**: `Authorization: Bearer {API_KEY}` | |
| **请求参数 (Request)**: | |
| ```json | |
| { | |
| "requestId": "req_unique_id_789", | |
| "questionContext": { | |
| "content": "Which keyword stops a loop?", | |
| "options": [ | |
| { "label": "A", "content": "stop" }, | |
| { "label": "B", "content": "break" } | |
| ] | |
| }, | |
| "type": "HINT" | |
| } | |
| ``` | |
| **请求参数说明 (Request Fields)**: | |
| | 字段名 | 类型 | 必选 | 描述 | | |
| | :------------------------ | :------- | :--- | :------------- | | |
| | `requestId` | `String` | 是 | 溯源 ID | | |
| | `questionContext` | `Object` | 是 | 题目上下文 | | |
| | `questionContext.content` | `String` | 是 | 题目文本 | | |
| | `questionContext.options` | `Array` | 是 | 选项列表 | | |
| | `type` | `String` | 是 | 请求类型: HINT | | |
| **响应参数 (Response)**: | |
| ```json | |
| { | |
| "data": { | |
| "hint": "Think about the command that completely terminates the execution." | |
| }, | |
| "meta": { | |
| "model": "gpt-4-turbo", | |
| "tokens_used": 50, | |
| "latency_ms": 800 | |
| } | |
| } | |
| ``` | |
| **响应字段说明 (Response Fields)**: | |
| | 字段名 | 类型 | 描述 | | |
| | :---------- | :------- | :---------------- | | |
| | `data.hint` | `String` | AI 生成的提示文本 | | |
| --- | |
| ## 4. 标准错误处理 (Error Handling) | |
| 当 AI 服务无法完成请求时,必须返回标准化的错误结构(非 2xx/200 OK)。 | |
| **错误响应结构**: | |
| ```json | |
| { | |
| "code": 422, | |
| "error": { | |
| "type": "INVALID_GENERATION", // 错误大类 | |
| "reason": "multiple_correct_answers_for_single_choice", // 具体原因 | |
| "details": "Question ai_q_8f9a2 has 2 correct answers." // 可选详情 | |
| }, | |
| "meta": { ... } // 即使失败也尽量返回 meta 以排查 tokens | |
| } | |
| ``` | |
| **标准错误码对照表**: | |
| | HTTP Status | error.type | 场景描述 | 处理建议 | | |
| | :---------- | :------------------- | :----------------------------------------------- | :------------------------------------------- | | |
| | **422** | `INVALID_GENERATION` | AI 生成内容不符合 Schema (如单选多答、JSON 损坏) | 后端可尝试重试 (Retry) 1-2 次 | | |
| | **429** | `RATE_LIMIT` | 超出并发或 Token 配额 | 后端需进行指数退避重试 (Exponential Backoff) | | |
| | **500** | `MODEL_ERROR` | 模型服务内部崩溃 | 记录日志,向前端返回通用错误 | | |
| | **504** | `TIMEOUT` | 生成超时 (如 > 60s) | 视场景重试或降级处理 | | |
| **常见 422 reason**: | |
| - `json_parse_error`: 输出不是有效的 JSON。 | |
| - `missing_field`: 缺少必填字段(如 `correct_answers`)。 | |
| - `schema_violation`: 数据结构违规(如单选题给了 2 个答案)。 | |
| --- | |
| ## 5. 待办事项 (Future Work) | |
| 以下功能规划在后续版本实现: | |
| 1. **Difficulty Target**: 基于 Bloom's Taxonomy 的难度分级控制。 | |
| 2. **Grading Rubric**: 支持自定义评分标准(Rubric)。 | |
| 3. **Advanced Trace**: 关联 Session/User/Attempt 上下文。 | |
| 4. **Pedagogy Hint Strategy**: 提供渐进式提示策略(Scaffolding)。 | |
| 5. **User Content Summary**: 自动生成用户上传内容的摘要。 | |