面试复盘功能设计

面试复盘功能设计
AI Agent 工程实践教程 · 第 12 章
把模拟面试后的问题、回答、评分和建议沉淀成可复盘的产品功能。
第十二天:面试复盘功能设计
前面我们已经完成了学生端、后台管理、文件上传、知识库问答、Text-to-SQL 等能力。
今天要设计一个更贴近真实业务的 AI 功能:面试复盘。
这个功能不是简单地上传一个音频文件,也不是单纯做语音转文字。它的目标是把学生真实面试后的录音,结合学生简历,整理成一份可读、可追踪、可复盘的面试报告。
整体链路如下:
学生简历
↓
学生上传面试录音
↓
录音文件转文字
↓
ASR 分句整理成对话
↓
结合简历生成面试复盘
↓
学生和老师查看复盘结果
从系统视角看,它不是一个单点接口,而是一条完整的异步处理链路:
1. 为什么要做面试复盘
学生出去面试以后,常见问题是:
面试问了什么?
学生当时怎么回答的?
哪些地方回答得不好?
哪些问题和简历内容有关?
下次怎么优化?
老师怎么快速了解学生这次面试表现?
如果只靠学生口头描述,信息很容易丢失:
| 问题 | 影响 |
|---|---|
| 学生记不全问题 | 老师无法判断真实表现 |
| 学生复述不准确 | 容易漏掉关键追问 |
| 没有原始材料 | 无法对照分析 |
| 老师逐个听录音成本高 | 复盘效率低 |
| 学生不知道怎么改 | 下次面试仍然重复犯错 |
所以面试复盘功能要解决的核心问题是:
把一次真实面试沉淀成结构化资料,并自动给出可执行的优化方案。
2. 功能边界
面试复盘功能由学生自助上传触发。
这里的录音来源不是平台内模拟面试,而是学生出去真实面试时录下来的音频,所以不设计面试官模块,也不设计后台老师代上传录音。
功能范围如下:
| 模块 | 是否需要 |
|---|---|
| 学生简历上传 | 需要 |
| 学生面试录音上传 | 需要 |
| 录音转文字 | 需要 |
| ASR 分句整理为对话 | 需要 |
| AI 生成面试复盘 | 需要 |
| 后台查看学生复盘 | 需要 |
| 面试官管理 | 不包含 |
| 后台代上传录音 | 不包含 |
一句话概括:
学生上传自己的面试录音,系统自动转写、整理、分析,后台负责查看结果。
3. 用户角色和使用场景
3.1 学生端
学生端主要做三件事:
上传简历
上传面试录音
查看复盘结果
学生完整使用流程:
进入学生首页
↓
上传或更新简历
↓
点击“面试复盘”
↓
上传面试录音
↓
填写面试时间和备注
↓
等待系统转写和分析
↓
查看对话稿和复盘报告
学生上传录音时填写辅助信息:
| 字段 | 说明 |
|---|---|
| 面试时间 | 这场面试发生的时间 |
| 录音文件 | mp3、m4a、wav 等音频文件 |
| 复盘备注 | 学生自己补充的信息,比如公司、岗位、感觉不好的地方 |
3.2 后台老师端
后台老师主要做三件事:
查看学生简历
查看学生上传的面试录音
查看面试对话和 AI 复盘报告
后台不需要复杂操作,重点是信息清晰:
| 后台内容 | 作用 |
|---|---|
| 学生姓名、手机号 | 定位学生 |
| 简历 | 了解学生背景 |
| 面试录音 | 必要时回听原始材料 |
| 对话稿 | 快速看面试问答内容 |
| 说话人 | 区分不同发言人 |
| 复盘报告 | 快速知道问题和优化方案 |
4. 总体业务流程
面试复盘拆成五个阶段:
阶段一:学生资料准备
↓
阶段二:学生上传录音
↓
阶段三:语音识别转文字
↓
阶段四:对话结构化
↓
阶段五:生成复盘报告
用流程图表示:
这里采用“按钮提交 + 定时轮询”:
这张图里最重要的是两个边界:
| 边界 | 说明 |
|---|---|
| 上传录音 | 只保存文件和业务记录,不在上传接口里同步识别 |
| 开始转写 | 由页面按钮触发 ASR 任务,后端通过定时任务查询结果 |
5. 学生简历在复盘中的作用
面试复盘不能只看录音文本。
因为很多面试问题其实是围绕简历展开的,例如:
你简历上写了 RAG 项目,具体是怎么做的?
你说自己熟悉 Spring Boot,说一下你们项目里的权限怎么设计?
你这个项目里用到了 Milvus,它的作用是什么?
如果系统不知道学生简历内容,就很难判断回答是否充分。
所以简历在面试复盘中有三个作用:
| 作用 | 说明 |
|---|---|
| 背景补充 | 让 AI 知道学生写了哪些项目和技能 |
| 问题归因 | 判断面试官的问题是否来自简历 |
| 回答评估 | 判断学生回答是否和简历匹配 |
举例:
简历写了:熟悉 LangChain、RAG、向量数据库。
面试官问:你们知识库问答怎么做的?
学生回答:就是把文件传上去,然后 AI 回答。
AI 复盘结论:
这个回答过于表层,没有讲清楚文档解析、切分、向量化、召回、Prompt 拼接和模型生成流程。
复盘报告会要求学生补充 RAG 的完整链路。
6. 录音上传设计
学生端上传录音时,前端不直接把文件传给 AI 服务。
正确做法是:
前端获取上传凭证
↓
前端上传到对象存储
↓
前端把 objectKey 提交给后端
↓
后端保存面试复盘记录
这样做有几个好处:
| 好处 | 说明 |
|---|---|
| 文件存储统一 | 简历、作业、SOP、面试录音都走同一套上传逻辑 |
| 后端可控 | 后端校验 objectKey 是否属于当前学生 |
| 密钥安全 | 前端不接触 AI 服务密钥 |
| 可回听 | 后台生成临时下载地址播放录音 |
录音文件支持常见音频格式:
mp3
m4a
wav
aac
ogg
flac
webm
amr
录音文件统一存入学生面试复盘目录,后端负责校验文件归属:
只能访问当前学生自己的录音
只能上传允许的音频格式
不能访问非法文件路径
7. 语音转文字设计
学生上传录音以后,下一步就是 ASR,也就是 Automatic Speech Recognition,自动语音识别。
这里使用语音识别专用模型,而不是直接用多模态大模型。
原因是:
| 方案 | 作用 |
|---|---|
| ASR 专用模型 | 稳定完成长音频转写,生成带说话人的对话稿 |
| 大模型 | 在对话稿基础上做角色判断、问题分析和复盘报告 |
转写流程:
录音文件
↓
ASR 语音识别模型
↓
带说话人的分句结果
↓
保存 speaker + text 对话JSON
录音识别采用异步流程:
submit 提交识别任务
↓
query 查询识别结果
↓
保存识别结果
提交识别任务时,后端会把对象存储里的录音转换成临时可访问地址:
audio_object_key
↓
后端生成 presigned download url
↓
传给 ASR 服务
识别任务需要包含三类信息:
| 信息 | 说明 |
|---|---|
| 用户标识 | 用来标记是哪名学生的识别任务 |
| 录音地址 | 后端生成的临时下载地址 |
| 识别配置 | 开启标点、文本规整、分句和说话人识别 |
识别任务设计如下:
识别完成后,系统只提取复盘需要的内容:说话人和发言文本。
8. 从 ASR 分句到对话
语音识别模型返回的结果通常是一整段文本,或者一组带时间戳的分句。
但面试复盘需要的是更清晰的结构:
面试官:请你介绍一下你的项目。
学生:我做的是一个 AI 课程系统,里面有知识库问答和 Text-to-SQL。
面试官:你们知识库问答是怎么实现的?
学生:主要是文档上传以后切分,然后向量化,查询的时候做相似度召回。
所以要增加一个“对话整理”步骤。
系统不会把原始识别结果直接展示给学生。
面试复盘真正需要的是结构化对话:
谁在说
说了什么
这句话属于面试问题还是学生回答
输入:
ASR 分句结果
说话人聚类 speaker
学生简历
学生备注
输出:
[
{
"speaker": "1",
"text": "请你介绍一下你的项目。"
},
{
"speaker": "2",
"text": "我做的是一个 AI 课程系统,里面有知识库问答和 Text-to-SQL。"
}
]
这里要注意:speaker=1 不一定天然等于“面试官”,speaker=2 也不一定天然等于“学生”。
ASR 做的是说话人聚类,含义是:
| 字段 | 说明 |
|---|---|
speaker=1 |
第一类声音 |
speaker=2 |
第二类声音 |
speaker=3 |
第三类声音,可能是环境声、其他人、误分离 |
页面展示:
说话人 1:你现在还在这家公司吗?
说话人 2:离职了。
生成复盘报告时,系统会根据对话内容识别说话人角色:
9. 面试复盘报告设计
有了简历和带说话人的对话稿以后,才能生成真正有价值的复盘报告。
复盘报告包含以下部分:
| 模块 | 内容 |
|---|---|
| 面试概要 | 这场面试主要聊了什么 |
| 问题清单 | 面试官问了哪些问题 |
| 回答评价 | 学生回答得怎么样 |
| 简历关联 | 哪些问题来自简历 |
| 风险点 | 哪些回答暴露出知识短板 |
| 优化方案 | 下次怎么回答 |
| 推荐话术 | 给学生一版更好的回答 |
报告结构:
# 面试复盘报告
## 1. 面试概要
本次面试主要围绕 AI 课程系统、RAG 知识库问答、Text-to-SQL 和项目权限设计展开。
## 2. 高频问题
1. 请介绍一下你的项目
2. RAG 知识库问答怎么实现
3. 向量数据库在项目里起什么作用
4. Text-to-SQL 如何保证 SQL 安全
## 3. 回答表现
整体能讲出项目方向,但细节不足。尤其在 RAG 和 Text-to-SQL 部分,回答偏概念,没有结合项目里的真实流程。
## 4. 主要问题
- 回答缺少完整链路
- 技术细节不够具体
- 没有主动讲业务价值
- 对异常场景和安全控制说明不足
## 5. 优化方案
按照“业务背景 -> 技术方案 -> 关键难点 -> 结果价值”的结构回答项目问题。
## 6. 推荐回答
如果面试官问“你们知识库问答怎么做的”,推荐回答如下:
我们先把用户上传的文档做解析和切分,然后对文本块生成向量并存入 Milvus。
用户提问时,系统会先做向量召回,找到相关片段,再把问题和召回内容拼成 Prompt 发给大模型。
为了提升回答质量,我们还做了上下文压缩和来源保留,避免模型凭空编造。
10. 数据库表设计
面试复盘记录放在一张主表中。
这张表承载一条面试复盘从上传到生成报告的完整状态。
核心数据分为五组:
| 数据组 | 内容 |
|---|---|
| 学生信息 | 学生 ID、学生姓名、手机号 |
| 面试信息 | 面试时间、学生备注 |
| 录音信息 | 录音文件、文件大小、上传时间 |
| 转写信息 | 转写状态、对话稿、失败原因、完成时间 |
| 报告信息 | 报告状态、复盘报告、失败原因、完成时间 |
状态字段:
| 状态 | 说明 |
|---|---|
PENDING |
等待处理 |
PROCESSING |
处理中 |
SUCCESS |
处理成功 |
FAILED |
处理失败 |
转写结果:
| 内容 | 说明 |
|---|---|
| 对话稿 | 保存说话人和发言内容 |
| 转写状态 | 标记是否未开始、处理中、成功或失败 |
| 失败原因 | 转写失败时用于页面提示和后台排查 |
| 完成时间 | 记录转写任务完成时间 |
对话稿结构:
[
{
"speaker": "1",
"text": "你现在还在这家公司吗?"
},
{
"speaker": "2",
"text": "离职了。"
}
]
转写状态流转图:
11. 后端接口设计
11.1 学生端接口
学生端接口放在 studentFront 下。
接口:
| 接口 | 方法 | 说明 |
|---|---|---|
/student/interview-reviews |
GET |
查询我的面试复盘列表 |
/student/interview-reviews |
POST |
上传一条面试复盘录音 |
/student/interview-reviews/{id}/transcribe |
POST |
点击开始转写或重新转写 |
11.2 后台管理接口
后台先以查看为主。
接口:
| 接口 | 方法 | 说明 |
|---|---|---|
/api/interview-reviews |
GET |
分页查询学生面试复盘 |
/api/interview-reviews/{id}/transcribe |
POST |
后台提交转写或重新转写 |
后台列表展示:
| 字段 | 说明 |
|---|---|
| 学生姓名 | 来自学生表 |
| 手机号 | 来自学生表 |
| 面试时间 | 学生填写 |
| 录音文件 | 可播放 |
| 转写状态 | 是否转写完成 |
| 报告状态 | 是否生成报告 |
| 上传时间 | 记录创建时间 |
接口调用关系:
接口调用关系分为三段:
| 阶段 | 接口 | 结果 |
|---|---|---|
| 上传记录 | POST /student/interview-reviews |
保存 PENDING 记录 |
| 发起转写 | POST /student/interview-reviews/{id}/transcribe |
保存 taskId,状态变成 PROCESSING |
| 查看结果 | GET /student/interview-reviews / GET /api/interviewReviews |
学生和后台查看录音、状态和对话稿 |
12. 异步任务设计
语音转文字和复盘报告生成都不适合放在上传接口里同步执行。
原因:
音频文件可能很大
ASR 识别需要时间
大模型生成报告也需要时间
接口同步等待容易超时
用户体验不好
语音转写采用异步任务,不在上传接口里同步执行:
学生上传录音
↓
接口快速返回:PENDING
↓
学生或老师点击“开始转写”
↓
后端 submit ASR,状态改为 PROCESSING
↓
Spring Boot 定时任务轮询 query
↓
转写完成后保存对话 JSON
↓
前端轮询状态或刷新列表
系统使用 Spring Boot 定时任务查询转写结果:
每隔 1 分钟扫描 transcript_status = PROCESSING 的记录
↓
查询 ASR 结果
↓
识别完成,保存 transcript_dialogue_json,状态改为 SUCCESS
↓
识别失败,保存 transcript_error_message,状态改为 FAILED
定时任务核心规则:
开关未启用:直接跳过
没有 PROCESSING 记录:直接结束
ASR 还在处理:保持 PROCESSING
ASR 成功:保存 speaker/text JSON
ASR 失败:保存失败原因,状态改为 FAILED
13. AI 复盘 Prompt 设计
生成复盘报告时,输入不是一整段纯文本,而是结构化材料。
模型输入包含三部分:
| 输入材料 | 作用 |
|---|---|
| 学生简历 | 提供项目、技能和经历背景 |
| 面试对话稿 | 还原面试问题和学生回答 |
| 学生备注 | 补充公司、岗位、面试反馈等信息 |
复盘报告输出结构:
面试复盘报告
一、面试概要
二、面试问题清单
三、回答表现分析
四、简历相关问题分析
五、主要短板
六、下次优化方案
七、推荐回答话术
报告生成时必须遵守两个原则:
| 原则 | 说明 |
|---|---|
| 不编造 | 录音里没有出现的问题不能写进报告 |
| 改法具体 | 每条优化方案都要指向具体回答和改法 |
14. 前端页面设计
14.1 学生端页面
学生端顶部入口:
面试复盘
页面结构:
顶部:返回首页 / 页面标题
左侧:上传面试录音
- 面试时间
- 选择录音文件
- 复盘备注
- 上传按钮
右侧:我的复盘记录
- 面试时间
- 录音文件
- 转写状态
- 开始转写 / 重新转写
- 查看对话
详情页展示:
录音播放器
对话稿
AI复盘报告
学生端页面结构:
学生端页面拆成两块:
| 区域 | 内容 |
|---|---|
| 上传表单 | 面试时间、录音文件、复盘备注、上传按钮 |
| 录音列表 | 文件名、上传时间、转写状态、开始/重新转写、查看对话 |
14.2 后台页面
后台页面以管理和查看为主:
筛选区:
- 学生姓名
- 手机号
- 转写状态
- 报告状态
列表区:
- 学生信息
- 面试时间
- 录音播放
- 转写状态
- 开始转写 / 重新转写
- 查看对话
后台详情页分 Tab:
基础信息
录音播放
对话稿
复盘报告
15. 关键异常处理
这个功能涉及文件、第三方接口和大模型,异常处理必须提前设计。
| 异常 | 处理方式 |
|---|---|
| 音频格式不支持 | 上传时提示用户 |
| 文件过大 | 上传前限制大小 |
| ASR 提交失败 | 保存失败原因,允许重试 |
| ASR 长时间无结果 | 设置超时时间,转为失败 |
| 对话内容为空 | 不生成报告,提示录音质量可能有问题 |
| 大模型生成失败 | 保存失败原因,允许重试 |
| 简历不存在 | 仍可复盘,但报告提示缺少简历背景 |
| 无法区分说话人 | 对话稿中标记 UNKNOWN |
用户看到的提示要简单:
录音转写中,请稍后查看
录音识别失败,请重新上传或联系老师
复盘报告生成中,请稍后刷新
后台看到的信息要更详细:
ASR错误码
ASR错误信息
任务ID
失败时间
重试次数
16. 落地流程
功能按下面的顺序落地:
第一步:学生上传简历
第二步:学生上传面试录音
第三步:后台能播放录音
第四步:页面增加“开始转写”按钮
第五步:后端接入豆包 submit/query
第六步:Spring Boot 定时任务轮询 PROCESSING 记录
第七步:保存 speaker/text 对话 JSON
第八步:学生端和后台展示对话
第九步:生成 Markdown 复盘报告
本次不做:
逐字时间轴
点击文字跳转录音
复杂统计报表
多版本复盘报告
自动判断面试官/学生角色
主链路:
录音上传成功
↓
录音能播放
↓
录音能提交转写
↓
定时任务能拿到 speaker/text 对话
↓
学生和老师能看到对话
后端代码模块:
17. 最终效果
功能完成后,一条面试复盘记录包含:
学生是谁
学生简历是什么
什么时候面试
录音文件在哪里
面试录音转写状态是什么
speaker/text 对话是什么
AI 复盘报告是什么
老师和学生怎么改进
这时,面试复盘就不再是一个简单文件上传功能,而是一个完整的 AI 辅导流程。
它把原本散落的信息:
简历
录音
学生记忆
老师经验
整理成了结构化、可追踪、可复用的学习资料:
对话稿
问题清单
短板分析
优化方案
推荐回答
这就是面试复盘功能真正的价值。
最终数据从“录音”变成“可复盘资料”的过程如下:







