Files
my-springboot-project/docs/AI流式问答与出题接口-前端使用指南.md

34 KiB
Raw Permalink Blame History

AI 流式问答与出题接口 - 前端使用指南

适用范围:知识库问答、会话管理、题目生成、答案批改
Base URLhttp://localhost:8080/api
认证方式Authorization: Bearer <JWT Token>
接口版本v2.17.0
更新时间2026-06-05


目录

  1. 快速开始
  2. AI 流式问答接口
  3. AI 会话管理接口
  4. 题目生成接口
  5. 题目批改接口
  6. 答题记录接口
  7. 前后端字段对照表
  8. 常见问题 FAQ
  9. 附录cURL 完整示例

一、快速开始

1.1 认证流程

所有接口(登录接口除外)均需携带 JWT Token

POST /api/auth/login
Content-Type: application/json

{
  "username": "admin",
  "password": "123456"
}

响应

{
  "code": 200,
  "data": {
    "token": "eyJhbGciOiJIUzUxMiJ9...",
    "user": {
      "id": 1,
      "username": "admin",
      "role": 1
    }
  }
}

后续所有接口请求头需添加:

Authorization: Bearer <token>

1.2 接口总览

模块 接口 方法 功能
流式问答 /ai/chat/stream POST 发起 AI 流式问答
中断问答 /ai/chat/stop?sessionId=xxx POST 中断流式回答
会话列表 /ai/sessions?page=1&pageSize=10 GET 获取当前用户的会话列表
会话详情 /ai/session/{sessionId} GET 获取指定会话的消息记录
消息引用 /ai/message/{messageId}/references GET 获取某条消息的引用列表
消息文件来源 /ai/message/{messageId}/sources GET 获取某条消息引用的文件来源(去重)
会话引用 /ai/session/{sessionId}/references GET 获取会话的全部引用
删除会话 /ai/session/{sessionId} DELETE 删除单个会话及相关数据
批量删除会话 /ai/sessions DELETE 批量删除多个会话
生成题目 /exam/generate POST 根据文档生成题目(异步)
生成试卷 /exam/paper/generate POST 动态生成试卷
开始考试 /exam/paper/{paperId}/start POST 获取试卷题目
考试结果 /exam/record/{recordId}/result GET 获取批阅结果
正式考试批改 /exam/record/{recordId}/grade POST 正式考试提交并批改
批改答案 /exam/grade POST 批改学生答案(通用)
查询答题记录 /exam/answers/query POST 查询用户答题记录
考试记录列表 /exam/records?type=practice GET 获取考试/练习记录列表

二、AI 流式问答接口

2.1 发起流式问答

接口POST /api/ai/chat/stream
Content-Typeapplication/json
返回类型text/event-stream (Server-Sent Events)

请求体

字段 类型 必填 说明
message string 用户提问内容
session_id string 会话ID不传则自动生成传空字符串 "" 也会自动生成
id string 自定义请求ID用于追踪

请求示例

{
  "message": "请介绍一下知识库管理系统",
  "session_id": "sess_1780410472658_9qg9a9hhp"
}

内部逻辑说明

  • 后端自动获取用户可访问的知识库(collections),无需前端传递
  • 后端自动从数据库加载该会话的历史消息作为上下文
  • 流式返回过程中finish 事件到达时会自动保存:
    • 用户提问 → context_messagerole=user
    • AI 回答 → context_messagerole=assistant含 answer、images 等)
    • 引用切片 → context_reference(自动从 RAG 获取 preview 字段)
    • 图片 → context_image(保留 score 字段)

流式事件类型

事件 type 说明 是否入库
start 对话开始事件
connected RAG 服务连接成功
thinking AI 思考中
searching 知识库检索中
sources 检索到的候选来源信息 仅前端展示,不写入数据库
chunk 流式内容片段 前端拼接显示
result / finish 最终完整结果(最重要) 存入数据库
error 错误信息

finish 事件核心字段

{
  "type": "finish",
  "answer": "根据【参考资料】...完整的AI回答内容其中包含 [ref:文档名_86] 这样的引用标记。",
  "duration_ms": 75512,
  "citations": [
    {
      "chunk_id": "文档名_86",
      "chunk_index": 86,
      "source": "文档名.docx",
      "collection": "dept_1_kb",
      "doc_type": "other",
      "section": "3.1 权重计算公式",
      "chunk_type": "text",
      "page": 1,
      "score": 0.838,
      "preview": "【系统自动从 RAG 接口获取的目标切片完整正文】",
      "content": {
        "stem": "切片摘要内容",
        "data": {}
      }
    }
  ],
  "images": [
    {
      "image_id": "49d2910b.jpg",
      "path": "/api/image/49d2910b.jpg/data",
      "source": "来源文档.docx",
      "page": 1,
      "chunk_type": "image",
      "description": "图片描述",
      "score": 0.85,
      "collection": "dept_1_kb"
    }
  ]
}

重要说明

  • answer 中的 [ref:chunk_id] 标记:前端需解析为可点击链接,点击后跳转/展示对应引用信息
  • preview 字段:后端写入 context_reference 表时,会自动调用 RAG 预览接口 GET /documents/{collection}/{source}/preview?chunk_index=N&context=0 填充该字段;若接口报错,则填入错误信息
  • context_message.answer 字段保留完整的 [ref:chunk_id] 标记文本

answer 字段引用标记解析

前端需解析 [ref:chunk_id] 为可点击元素:

"市场状态 = Σ(二级指标均值 × 权重)[ref:文档名_86]。
此外一级指标合计权重不低于70%[ref:文档名_93]。"

前端 JavaScript 调用示例fetch + ReadableStream

// 发起流式问答
async function chatStream(message, sessionId, token) {
  const response = await fetch('/api/ai/chat/stream', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + token
    },
    body: JSON.stringify({ message, session_id: sessionId })
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  let fullAnswer = '';

  while (true) {
    const { value, done } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split('\n');
    buffer = lines.pop() || '';  // 保留未完成的行

    for (const line of lines) {
      if (!line.startsWith('data:')) continue;
      try {
        const data = JSON.parse(line.slice(5).trim());
        handleEvent(data);  // 分发到事件处理器
      } catch (e) {
        console.warn('解析失败:', line);
      }
    }
  }
}

// 事件处理器(前端自行实现 UI 更新)
function handleEvent(data) {
  switch (data.type) {
    case 'chunk':
      // 实时拼接显示到对话框
      fullAnswer += data.content;
      // renderAnswer(fullAnswer);
      break;
    case 'finish':
      // 对话完成,拿到完整 answer、citations、images
      console.log('完整回答:', data.answer);
      console.log('引用列表:', data.citations);
      console.log('图片列表:', data.images);
      break;
    case 'error':
      console.error('AI 错误:', data.message);
      break;
  }
}

为什么不用 EventSourceEventSource 只能 GET 请求,且无法自定义请求头(无法传 Token。推荐使用 fetch + ReadableStream 方式。

2.2 中断流式问答

接口POST /api/ai/chat/stop?sessionId=sess_xxx

响应

{
  "success": true,
  "message": "已中断AI回答"
}

三、AI 会话管理接口

统一响应结构(Map

{
  "success": true,
  "data": [...],
  "total": 10,
  "page": 1,
  "pageSize": 10,
  "pages": 1
}

3.1 获取用户会话列表

接口GET /api/ai/sessions?page=1&pageSize=10

查询参数

参数 类型 必填 默认值 说明
page int 1 页码
pageSize int 10 每页数量

响应 data 元素字段ChatSession

字段 类型 说明
id long 数据库主键
sessionId string 会话唯一ID
userId long 用户ID
createTime datetime 创建时间

3.2 获取会话详情(消息记录)

接口GET /api/ai/session/{sessionId}?page=1&pageSize=20

权限检查:后端自动校验该会话是否属于当前用户

响应 data 元素字段ChatMessage

字段 类型 说明
id long 消息ID
conversationId long 会话ID数据库主键
role string user / assistant
content string 用户提问原文role=user或 AI 回答内容role=assistant 时通常与 answer 一致)
messageType string rag
isFinished int 1=完成
answer string AI 完整回答(含 [ref:chunk_id] 标记),仅 role=assistant 时有值
images string(JSON数组) 图片列表JSON 字符串,需前端解析)
durationMs long 耗时(毫秒)
createTime datetime 创建时间

注意ChatMessage 实体中已移除 sources 字段。引用信息需通过 /ai/message/{messageId}/references 接口单独获取。

3.3 获取消息引用列表

接口GET /api/ai/message/{messageId}/references?docName=xxx

查询参数

参数 类型 必填 说明
docName string 按文档名称过滤引用

响应 data 元素字段ChatReference

字段 类型 说明
id long 引用记录ID
messageId long 关联的消息ID
chunkId string 切片唯一标识 {docName}_{chunkIndex}
chunkIndex int 切片序号
collection string 向量库名称
docName string 文档名称
docType string 文档类型
page int 页码
section string 章节/段落位置
chunkType string text / image / table
excerpt string 切片摘要内容
preview string 目标切片完整正文(系统自动从 RAG 获取,失败则填错误信息)
score decimal 相关性评分 0-1
createTime datetime 创建时间

3.4 获取消息文件来源列表(去重)

接口GET /api/ai/message/{messageId}/sources

用途:对同一条消息的引用按文档名做去重汇总,用于展示"参考文档列表"侧栏

响应 data 元素字段

字段 类型 说明
docName string 文档名称(去重后的唯一标识)
docType string 文档类型
referenceCount int 该文档被引用的次数
pages string 页码范围,如 "5""1-10"

响应示例

{
  "success": true,
  "data": [
    {
      "docName": "薪酬制度.docx",
      "docType": "other",
      "referenceCount": 5,
      "pages": "1-8"
    },
    {
      "docName": "考核办法.docx",
      "docType": "other",
      "referenceCount": 3,
      "pages": "3"
    }
  ],
  "total": 2
}

3.5 获取会话全部引用

接口GET /api/ai/session/{sessionId}/references

用途:返回整个会话中所有 AI 回答的引用汇总,字段与单条消息引用接口一致

3.6 删除单个会话

接口DELETE /api/ai/session/{sessionId}

删除指定会话及其所有消息和引用数据。后端自动校验会话所属权。

3.7 批量删除会话

接口DELETE /api/ai/sessions

请求体

["sess_xxx1", "sess_xxx2", "sess_xxx3"]

响应

{
  "success": true,
  "message": "会话批量删除成功",
  "deletedCount": 3
}

四、题目生成接口

本模块接口统一响应结构(Result<T>

{
  "code": 200,
  "message": "操作成功",
  "data": { ... }
}

4.1 生成题目(异步)

接口POST /api/exam/generate
Content-Typeapplication/json

请求体字段

字段 类型 必填 说明
file_id Long 二选一 文件ID系统自动从 knowledge_file 表查询向量库信息(推荐
file_path string 二选一 文件路径(如 dept_1_kb/薪酬制度.docx
collection string file_path 必填 向量库名称(使用 file_path 时必须提供)
question_types object 指定题型及数量;不传则使用 AI 智能生成模式
question_scores object 自定义题型分数配置
difficulty int 难度等级 1-5默认 3
request_id string 请求ID用于幂等性

question_types 可选值

题型 key 说明
单选题 single_choice 四个选项单选
多选题 multiple_choice 四个选项多选
判断题 true_false 对/错两选
填空题 fill_blank 按空格填写答案,支持同义词
简答题 subjective 开放回答,由 LLM 评分

请求示例:指定题型模式

{
  "file_id": 1,
  "question_types": {
    "single_choice": 3,
    "multiple_choice": 2,
    "true_false": 2,
    "fill_blank": 2,
    "subjective": 1
  },
  "difficulty": 3,
  "request_id": "gen_req_001"
}

请求示例:智能生成模式(推荐)

不提供 question_types 参数时,系统调用 AI 智能出题接口,自动根据文档内容判断题型和数量:

{
  "file_id": 1,
  "difficulty": 3
}

响应示例(成功)

{
  "code": 200,
  "message": "收到请求",
  "data": {
    "requestId": "gen_req_001",
    "fileId": 1,
    "fileMatchStatus": "success",
    "matchedCollection": "dept_1_kb",
    "documentName": "薪酬制度.docx",
    "collectionFilled": true,
    "asyncTaskStarted": true,
    "nextStep": "请通过文件状态接口查询生成进度",
    "status": "success"
  }
}

响应示例(文件验证失败)

{
  "code": 400,
  "message": "文件不存在,请确认 file_id 是否正确",
  "data": {
    "status": "error",
    "errorType": "FILE_VALIDATION_ERROR",
    "errorDetail": "文件不存在",
    "suggestion": "请检查 file_id 是否正确、文件是否已删除、或文件是否已完成向量化"
  }
}

fileMatchStatus 可能值

说明 HTTP 状态码
success 文件验证通过,启动异步任务 200
FILE_NOT_FOUND 文件不存在 400
FILE_DELETED 文件已被删除 400
NOT_VECTORIZED 文件尚未完成向量化 400
PARAM_MISSING 参数不完整 400
INTERNAL_ERROR 服务器内部错误 500

4.2 轮询题目生成进度

接口GET /api/file/{fileId}

关键字段

字段 说明
processStatus 文件处理状态(如 INDEXED
examStatus 题目生成状态UNGENERATED / GENERATING / GENERATED / FAILED
processMessage 生成详情,包含题目数量和 AI 分析结果

examStatus 流转

UNGENERATED ──► GENERATING ──► GENERATED
                       │
                       └──────► FAILED

轮询策略建议:初始间隔 2-3 秒;超时 5-10 分钟examStatus 达到终态则停止。

4.3 生成试卷

接口POST /api/exam/paper/generate

请求体

{
  "single_choice_count": 5,
  "multiple_choice_count": 3,
  "true_false_count": 2,
  "fill_blank_count": 2,
  "subjective_count": 1,
  "difficulty": 3,
  "include_personal": false,
  "file_ids": [1, 2, 3]
}

响应 data 字段ExamPaperGenerateResponse

字段 类型 说明
paperId string 试卷ID
paperTitle string 试卷标题
totalScore decimal 总分
questionCount int 题目总数
generatedAt datetime 生成时间
questions array 题目列表

五、题目批改接口

5.1 批改答案(日常练习 / 模拟考 / 正式考试通用)

接口POST /api/exam/grade

请求体字段

字段 类型 必填 说明
request_id string 请求ID
type / answerType string practice / mock_exam / formal_exam
record_id string 正式考试记录ID提供时走正式考试提交/批改分支
paper_id string 试卷ID
session_id string 会话ID
answers array 答案列表

answers 数组元素字段

字段 类型 必填 说明
question_id string 题目ID
question_type string single_choice / multiple_choice / true_false / fill_blank / subjective
question_content object 题目内容(含 stem / options / answer 等)
student_answer any 学生提交的答案
max_score number 满分

请求示例

{
  "request_id": "grade_req_001",
  "answer_type": "practice",
  "answers": [
    {
      "question_id": "q_001",
      "question_type": "single_choice",
      "question_content": {
        "stem": "根据公司规定,员工薪资由哪几部分组成?",
        "data": {
          "options": [
            { "key": "A", "content": "基本工资+奖金" },
            { "key": "B", "content": "基本工资+绩效奖金+津贴补贴" }
          ]
        },
        "answer": "B"
      },
      "student_answer": "B",
      "max_score": 5.0
    },
    {
      "question_id": "q_002",
      "question_type": "multiple_choice",
      "question_content": {
        "stem": "以下哪些属于绩效奖金的评定因素?",
        "data": { "options": [...] },
        "answer": ["A", "B", "D"]
      },
      "student_answer": ["A", "B"],
      "max_score": 4.0
    },
    {
      "question_id": "q_003",
      "question_type": "true_false",
      "question_content": {
        "stem": "公司规定员工每月绩效奖金上限为工资的20%。",
        "answer": "F"
      },
      "student_answer": "T",
      "max_score": 2.0
    },
    {
      "question_id": "q_004",
      "question_type": "fill_blank",
      "question_content": {
        "stem": "员工薪资由___、___和___三部分组成。",
        "data": { "blank_count": 3 },
        "answer": [["基本工资"], ["绩效奖金", "绩效"], ["津贴补贴", "补贴"]]
      },
      "student_answer": ["基本工资", "绩效奖金", "交通补贴"],
      "max_score": 6.0
    },
    {
      "question_id": "q_005",
      "question_type": "subjective",
      "question_content": {
        "stem": "请简述公司薪酬制度的核心原则。",
        "data": {
          "scoring_points": [
            { "point": "公平性", "weight": 0.3 },
            { "point": "激励性", "weight": 0.3 },
            { "point": "竞争力", "weight": 0.2 },
            { "point": "合法性", "weight": 0.2 }
          ]
        },
        "answer": "公司薪酬制度遵循公平、激励、竞争、合法四大原则..."
      },
      "student_answer": "我认为公司的薪酬制度应该公平公正...",
      "max_score": 10.0
    }
  ]
}

响应 data 字段ExamGradeResponse

字段 类型 说明
success boolean 是否成功
totalScore decimal 得分
totalMaxScore decimal 满分
scoreRate decimal 得分率(百分比)
results array 每题批改结果

results 元素字段

字段 类型 说明
questionId string 题目ID
questionType string 题型
score decimal 本题得分
maxScore decimal 本题满分
correct / isCorrect boolean 是否答对
studentAnswer any 学生答案
correctAnswer any 正确答案
feedback string 批改反馈

批阅规则

题型 批阅方式 得分规则
单选题 精确匹配 正确得满分,错误得 0
多选题 集合比对 全对满分,少选一半,错选得 0
判断题 精确匹配 正确得满分,错误得 0
填空题 多答案匹配 每空独立评分,支持同义词匹配
简答题 LLM 评分 根据得分点评分,不超过 max_score

5.2 正式考试提交并批改

接口POST /api/exam/record/{recordId}/grade

路径参数recordId正式考试记录ID

请求体ExamSaveRequest

{
  "answers": [
    {
      "question_id": "q_001",
      "question_type": "single_choice",
      "answer": "B"
    }
  ]
}

六、答题记录接口

6.1 开始考试(获取题目)

接口POST /api/exam/paper/{paperId}/start

系统自动查找或创建考试记录,返回试卷题目内容。

6.2 获取考试结果

接口GET /api/exam/record/{recordId}/result

权限检查:后端校验该记录是否属于当前用户

响应 data 字段

字段 类型 说明
recordId string 记录ID
paperId string 试卷ID
paperTitle string 试卷标题
status string submitted
totalScore decimal 得分
totalMaxScore decimal 满分
scoreRate decimal 得分率
submitTime datetime 提交时间
answers array 每题结果

6.3 查询用户答题记录

接口POST /api/exam/answers/query

请求体UserAnswerQueryRequest

字段 类型 必填 说明
paper_id string 二选一 按试卷ID查询
session_id string 二选一 按会话ID查询
answer_type string 过滤类型practice / mock_exam / formal_exam
page int 页码,默认 1
page_size int 每页数量,默认 20

请求示例

{
  "paper_id": "paper_abc123",
  "answer_type": "practice",
  "page": 1,
  "page_size": 20
}

6.4 获取考试记录列表

接口GET /api/exam/records?type=practice

查询参数

参数 类型 必填 默认值 说明
type string practice practice / mock_exam / formal_exam

分支逻辑

  • type=practice → 返回日常练习答题记录(UserAnswerQueryResponse
  • type=mock_examformal_exam → 返回试卷考试记录列表(List<ExamRecordResponse>

七、前后端字段对照表

7.1 ChatReference 引用字段映射

后端字段 前端字段AI返回 类型 说明
chunkId chunk_id string 切片唯一标识 {docName}_{chunkIndex}
chunkIndex chunk_index int 切片序号
collection collection string 向量库名称
docName source / doc_name string 文档名称
docType doc_type string 文档类型
page page int 页码
section section string 章节/段落位置
chunkType chunk_type string text / image / table
excerpt content.stem string 切片摘要
preview —(系统自动填充) string 目标切片完整正文,由后端从 RAG 预览接口获取,失败则填错误信息
score score decimal 相关性评分 0-1
createTime datetime 创建时间

7.2 ChatMessage 消息字段映射

后端字段 前端字段 类型 说明
id message_id long 消息唯一ID
conversationId conversation_id long 会话数据库主键ID
role role string user / assistant
content content string 用户提问原文 / AI 回答
answer answer string AI 完整回答(含 [ref:chunk_id] 标记role=assistant 有效
messageType message_type string rag
isFinished is_finished int 1=完成
images images string(JSON数组) 图片列表JSON 字符串,前端需 JSON.parse
durationMs duration_ms long 耗时(毫秒)
createTime create_time datetime 创建时间

已移除字段sources。引用信息需通过 /ai/message/{messageId}/references 接口获取。

7.3 Image 图片字段映射context_image 表)

后端字段 前端字段AI返回 类型 说明
imageId image_id string 图片标识
path path / url string 图片访问路径,如 /api/image/xxx/data
source source string 来源文档
page page int 页码
section section string 章节位置
chunkType chunk_type string 切片类型image
description description string 图片描述
score score decimal 相关性评分(保留
collection collection string 向量库名称

已移除字段filenamesize_bytesformatpage_endtypefull_description


八、常见问题 FAQ

Q1: answer 中的 [ref:chunk_id] 标记如何解析?

:前端需要在渲染 answer 时,使用正则匹配 \[ref:([^\]]+)\],将其替换为可点击的引用链接:

const renderAnswer = (answer) => {
  const regex = /\[ref:([^\]]+)\]/g;
  return answer.replace(regex, (match, chunkId) => {
    return `<a class="ref-link" data-chunk-id="${chunkId}">[引用]</a>`;
  });
};

Q2: 流式问答如何处理?为什么不用 EventSource

:由于 EventSource 只能 GET 请求,且无法自定义请求头(无法传 Token推荐使用 fetch + ReadableStream 方式:

const response = await fetch('/api/ai/chat/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + token
  },
  body: JSON.stringify({ message, session_id: sessionId })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let fullAnswer = '';

while (true) {
  const { value, done } = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop() || '';

  for (const line of lines) {
    if (!line.startsWith('data:')) continue;
    const dataStr = line.slice(5).trim();
    if (!dataStr) continue;
    try {
      const data = JSON.parse(dataStr);
      if (data.type === 'chunk') {
        fullAnswer += data.content;
        // renderAnswer(fullAnswer);  // 更新 UI
      } else if (data.type === 'finish') {
        console.log('引用:', data.citations);
        console.log('图片:', data.images);
      }
    } catch (e) {
      console.warn('解析失败:', dataStr);
    }
  }
}

Q3: 题目生成接口为什么是异步的?如何获取生成结果?

:题目生成需要调用 AI LLM 进行内容理解和题目构造,耗时较长(通常 10-60 秒)。使用异步方式可避免前端超时等待。

获取结果方式:

  1. 调用 POST /api/exam/generate 提交任务,得到 fileId
  2. 轮询 GET /api/file/{fileId} 检查 examStatus 字段
  3. examStatus 变为 GENERATED 时,通过题目列表接口查看题目

Q4: citations 和 sources 有什么区别?

  • citationsfinish 事件中AI 回答中真正引用到的切片。会写入 context_reference 表,可通过引用列表接口查询
  • sources(流式事件中):检索阶段命中的候选来源文档。仅用于前端展示不写入数据库context_message 表也没有 sources 字段

Q5: context_reference.preview 字段是怎么来的?

:当 citations 写入 context_reference 表时,后端会对每条引用自动调用 RAG 预览接口:

GET /documents/{collection}/{source}/preview?chunk_index=N&context=0

获取该切片的完整正文写入 preview 字段。若接口调用失败,preview 填入错误信息(如"预览获取失败: ...")。前端可直接展示 preview 内容,无需再调用 RAG 接口。

Q6: 同一会话多次提问,如何区分不同消息的引用?

context_reference 表通过 messageId 字段关联到具体消息。每个消息的引用列表独立。可通过:

  • /ai/message/{messageId}/references — 查询某条消息的引用
  • /ai/session/{sessionId}/references — 查询整个会话的所有引用

Q7: context_image 表中的 score 字段有什么用?

:保留 score 字段用于记录 AI 返回的图片相关性评分0-1。前端可根据 score 排序展示图片,或过滤低分图片。


九、附录cURL 完整示例

以下示例均需替换 <token> 为实际登录获取的 JWT Token

9.1 登录获取 Token

curl -X POST "http://localhost:8080/api/auth/login" \
     -H "Content-Type: application/json" \
     -d '{"username":"admin","password":"123456"}'

9.2 发起流式问答

curl -X POST "http://localhost:8080/api/ai/chat/stream" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{"message":"市场状态评价指标体系中一级指标有哪些","session_id":""}' \
     --no-buffer

9.3 中断流式问答

curl -X POST "http://localhost:8080/api/ai/chat/stop?sessionId=sess_xxx" \
     -H "Authorization: Bearer <token>"

9.4 获取会话列表

curl -X GET "http://localhost:8080/api/ai/sessions?page=1&pageSize=10" \
     -H "Authorization: Bearer <token>"

9.5 获取会话详情

curl -X GET "http://localhost:8080/api/ai/session/sess_1780410472658_9qg9a9hhp" \
     -H "Authorization: Bearer <token>"

9.6 获取消息引用列表

curl -X GET "http://localhost:8080/api/ai/message/178/references" \
     -H "Authorization: Bearer <token>"

9.7 获取消息文件来源列表(去重)

curl -X GET "http://localhost:8080/api/ai/message/178/sources" \
     -H "Authorization: Bearer <token>"

9.8 删除单个会话

curl -X DELETE "http://localhost:8080/api/ai/session/sess_1780410472658_9qg9a9hhp" \
     -H "Authorization: Bearer <token>"

9.9 批量删除会话

curl -X DELETE "http://localhost:8080/api/ai/sessions" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '["sess_xxx1","sess_xxx2"]'

9.10 生成题目(指定题型)

curl -X POST "http://localhost:8080/api/exam/generate" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
       "file_id": 1,
       "question_types": {
         "single_choice": 3,
         "multiple_choice": 2,
         "true_false": 2,
         "fill_blank": 2,
         "subjective": 1
       },
       "difficulty": 3,
       "request_id": "gen_req_001"
     }'

9.11 生成题目(智能模式)

curl -X POST "http://localhost:8080/api/exam/generate" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{"file_id":1,"difficulty":3}'

9.12 轮询题目生成状态

curl -X GET "http://localhost:8080/api/file/1" \
     -H "Authorization: Bearer <token>"

9.13 生成试卷

curl -X POST "http://localhost:8080/api/exam/paper/generate" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
       "single_choice_count": 5,
       "multiple_choice_count": 3,
       "true_false_count": 2,
       "fill_blank_count": 2,
       "subjective_count": 1,
       "difficulty": 3,
       "include_personal": false
     }'

9.14 批改答案(日常练习)

curl -X POST "http://localhost:8080/api/exam/grade" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
       "request_id": "grade_req_001",
       "answer_type": "practice",
       "answers": [
         {
           "question_id": "q_001",
           "question_type": "single_choice",
           "question_content": {
             "stem": "题目内容...",
             "data": { "options": [...] },
             "answer": "B"
           },
           "student_answer": "B",
           "max_score": 5.0
         }
       ]
     }'

9.15 开始考试(获取题目)

curl -X POST "http://localhost:8080/api/exam/paper/paper_xxx/start" \
     -H "Authorization: Bearer <token>"

9.16 获取考试结果

curl -X GET "http://localhost:8080/api/exam/record/record_xxx/result" \
     -H "Authorization: Bearer <token>"

9.17 查询答题记录

curl -X POST "http://localhost:8080/api/exam/answers/query" \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{"paper_id":"paper_xxx"}'

9.18 获取考试记录列表

# 日常练习
curl -X GET "http://localhost:8080/api/exam/records?type=practice" \
     -H "Authorization: Bearer <token>"

# 正式考试
curl -X GET "http://localhost:8080/api/exam/records?type=formal_exam" \
     -H "Authorization: Bearer <token>"

文档版本v2.17.0
最后更新2026-06-05
适用代码版本:与当前 Spring Boot 后端(AIChatController / ExamController)同步