从零做了一个 AI 面试陪练工具,聊聊全过程
一个学 Java 后端的大学生,用 AI Coding 从零开发了一个 AI 面试陪练工具,和大家聊聊全过程踩坑与收获
作者:MuYi | Java 后端学习者
项目地址:https://gitee.com/MuYi-2025/interview-assistance-system
前言
大家好,我是一名正在找 Java 后端实习的大学生。
最近秋招/春招季,身边同学都在忙着刷八股、改简历、投递记录。我发现大家面临的问题出奇地一致:
- 八股背了就忘,看的时候觉得都会,面试一问就卡壳
- 简历写完不知道质量如何,找学长看又不好意思总麻烦人家
- 投了几十家公司,根本记不清哪家到什么阶段了
于是我花了些时间,做了一个AI 面试教练(Interview Copilot),用 LLM 来帮助大家系统化地准备面试。
写这篇文章,一方面是分享这个工具的使用方法,另一方面也聊聊我在开发过程中的一些思考和收获。
一、这个工具能做什么?
先上功能清单:
| 功能 | 说明 |
|---|---|
| 面试模拟 | 从题库抽题,逐题作答,AI 实时评分 + 反馈 |
| 简历诊断 | 上传 PDF,AI 从六个维度分析简历质量 |
| 岗位匹配 | 粘贴 JD,AI 分析简历匹配度和改进建议 |
| 场景出题 | 根据你的技能标签,AI 生成真实业务场景题 |
| 题库管理 | 批量导入面试题,支持 JSON/CSV/TXT |
| 投递记录 | 管理求职进度,状态筛选 + 统计概览 |
核心思路很简单:把面试准备这件事,从"散装学习"变成"系统化训练"。
二、为什么用 LLM 而不是传统方案?
做这个项目之前,我也想过用传统的规则引擎来做面试评分。但很快就发现了问题:
面试题的回答是开放式的。
比如问"HashMap 的底层原理",你可以说"数组 + 链表 + 红黑树",也可以说"通过 key 的 hashCode 定位桶,冲突时用链表,链表过长转红黑树"。两种回答都对,但深度不同。
用传统方案很难评判这种差异,而 LLM 天然擅长这个。它能:
- 理解回答的语义,而不是做关键词匹配
- 从准确性、完整性、表达清晰度多个维度打分
- 给出具体的改进建议,而不是泛泛的"答得不错"
这就是为什么选择 LLM 作为核心引擎。
三、架构设计
项目采用前后端分离架构,整体分为三层:
┌─────────────────────────────────────────────┐ │ Vue 3 前端 (Element Plus) │ │ 首页 │ 简历管理 │ 面试练习 │ 题库 │ 投递记录 │ └──────────────────┬──────────────────────────┘ │ HTTP / SSE(流式传输) ┌──────────────────▼──────────────────────────┐ │ FastAPI 后端 (Python) │ │ 用户管理 │ 简历分析 │ 面试引擎 │ 投递记录 │ └──────────────────┬──────────────────────────┘ │ ┌──────────────────▼──────────────────────────┐ │ 基础设施层 │ │ DeepSeek LLM │ 百炼向量模型 │ ChromaDB │ │ JSON 文件存储 │ pdfplumber PDF 解析 │ └─────────────────────────────────────────────┘技术选型考量
| 组件 | 选择 | 为什么 |
|---|---|---|
| LLM | DeepSeek | 性价比高,OpenAI 兼容接口,切换成本低 |
| 向量模型 | 阿里云百炼 text-embedding-v4 | 中文语义理解好,同样是 OpenAI 兼容接口 |
| 向量库 | ChromaDB | 轻量级,无需额外部署服务,本地文件即可运行 |
| 后端 | FastAPI | Python 生态 + 异步支持 + 自动 API 文档 |
| 前端 | Vue 3 + Element Plus | 组件丰富,上手快,适合快速开发 |
| 数据存储 | JSON 文件 | 简历、面试记录这类文本数据量不大,JSON 文件足够用,省去数据库部署 |
关于数据存储多说两句。一开始我尝试过用 MySQL 存面试记录,但发现一个尴尬的问题:面试记录里有大量的文本(问题、回答、反馈、报告),这些内容塞进 MySQL 的 TEXT 字段并不优雅,而且对于个人工具来说,部署一个 MySQL 服务太重了。
最终决定全部用 JSON 文件存储,配合目录结构来组织数据,简洁且可移植。这也是很多 CLI 工具(如 VS Code 的配置、npm 的 package-lock.json)采用的方案。
四、核心流程详解
4.1 面试模拟流程
这是整个项目最核心的功能,流程如下:
用户选择难度和题数 │ ▼ 无放回随机抽题(random.sample) │ ▼ ┌─→ 展示第 N 题 ←─────────────────┐ │ │ │ │ ▼ │ │ 用户作答 │ │ │ │ │ ▼ │ │ SSE 流式评分(LLM 逐 token 输出)│ │ │ │ │ ▼ │ │ 显示评分 + 反馈 │ │ │ │ │ └── 还有下一题?── 是 ────────┘ │ │ │ 否 │ ▼ │ SSE 流式生成综合报告 │ │ │ ▼ │ 保存到 JSON 文件 │ (题目、回答、评分、报告)关于抽题算法:最初用random.choice()循环抽题,但发现题库较小时重复率很高。后来改成random.sample()做无放回抽样,一次抽好 N 道题,天然不重复。这是一个很典型的"小优化解决大问题"的例子。
关于流式传输:LLM 生成完整报告可能需要 10-30 秒。如果用传统的同步请求,用户盯着 loading 转圈,体验很差。改用 SSE(Server-Sent Events)后,用户能实时看到文字一个个"蹦"出来,等待感大幅降低。
实现方式并不复杂:
后端(FastAPI):
defevent_stream():forchunkinllm.stream(prompt):ifchunk.content:yieldf"data:{json.dumps({'chunk':chunk.content})}\n\n"returnStreamingResponse(event_stream(),media_type="text/event-stream")前端(Vue 3 fetch):
constresponse=awaitfetch(url,{method:'POST',body:...})constreader=response.body.getReader()while(true){const{done,value}=awaitreader.read()if(done)break// 解析 SSE 数据,追加到显示区域}4.2 简历诊断流程
上传 PDF → pdfplumber 提取文本 │ ▼ LLM 六维度诊断(流式) - 基本信息完整性 - 技术栈匹配度 - 项目经历质量 - 成果量化程度 - 排版与表达 - 整体竞争力 │ ▼ 自动提取技能清单 (用于后续场景出题) │ ▼ 保存报告 + 技能 → 可下载 Markdown关于 PDF 解析:用的是 pdfplumber,纯 Python 库,不需要安装额外依赖。它能很好地处理大多数简历的排版,提取出干净的文本。遇到扫描版 PDF(纯图片)会提取失败,这种情况下会提示用户。
4.3 RAG 场景出题
这个功能结合了向量检索和LLM 生成:
用户技能标签:["Java", "Spring", "MySQL"] │ ▼ 对每个技能,用向量模型在题库中检索最相关的 3 道题 │ ▼ 将检索到的题目作为参考,连同技能标签一起发给 LLM │ ▼ LLM 生成结合实际项目场景的面试题这比单纯让 LLM 出题效果好很多,因为有了题库的"锚点",生成的题目更有针对性,不会跑偏。
向量检索的实现用 ChromaDB + 阿里云百炼的 embedding 模型:
fromchromadbimportPersistentClientfromlangchain_openaiimportOpenAIEmbeddings# 初始化embeddings=OpenAIEmbeddings(model="text-embedding-v4")client=PersistentClient(path="chroma_db")collection=client.get_or_create_collection("questions")# 检索query_vector=embeddings.embed_query("Java 集合框架")results=collection.query(query_embeddings=query_vector,n_results=3)4.4 投递记录管理
这个功能相对简单,就是对 JSON 文件的 CRUD 操作。但有一个设计细节值得说一下:状态流转。
投递状态有标准的流转顺序:
未投递 → 已投递 → 测评 → 笔试 → 一面 → 二面 → 三面 → 终面 → offer / 已终止同时还需要处理历史数据中的旧状态名称(比如"笔试进行中"要映射到"笔试"),所以单独抽了一个normalize_status()函数来做状态归一化。
五、开箱即用,5 分钟跑起来
这个项目的另一个目标是低门槛。不想让大家为了用一个工具先折腾半天环境。
准备工作
- Python 3.10+
- Node.js 18+
- DeepSeek API Key(去 platform.deepseek.com 注册获取)
- 阿里云百炼 API Key(去 dashscope.console.aliyun.com 获取)
3 步启动
# 第 1 步:配置环境变量cp.env.example .env# 编辑 .env,填入两个 API Key# 第 2 步:启动后端pipinstall-rrequirements.txt python main.py# → http://localhost:8000/docs 自带 API 文档# 第 3 步:启动前端cdfrontendnpminstallnpmrun dev# → http://localhost:5173打开浏览器,创建用户,上传简历,开始练习。就是这么简单。
不需要安装数据库,不需要配置 Docker,不需要申请额外的云服务。两个 API Key + 两个命令,搞定一切。
如果你不想用 Web 界面,也可以直接python main.py --cli走命令行交互。
六、开发过程中的一些感悟
6.1 从"能用"到"好用"的距离
项目的第一版是纯 CLI 的,能跑通核心流程,但体验很原始。
后来加了 Web 界面后,才发现"能用"和"好用"之间差了很多东西:
- 流式传输:LLM 生成需要时间,用户盯着 loading 圈会焦虑。改成流式输出后,用户能看到内容在"生长",心理感受完全不同。
- Markdown 渲染:LLM 输出的是 Markdown 格式的文本,直接显示就是一堆
##和**。用 md-editor-v3 的预览组件渲染后,报告的可读性提升了一个档次。 - 报告下载:分析完一份简历后,用户可能想保存或分享。加了"下载为 Markdown"按钮后,这个需求就闭环了。
这些都不是"核心功能",但每一个都能让用户多用几次。
6.2 关于数据存储的取舍
一开始我用 MySQL 存面试记录,后来改成了 JSON 文件。这个过程让我理解了一个道理:
技术选型要看场景,不要看"正确性"。
MySQL 是"正确"的关系型数据库,但对于一个个人工具来说:
- 面试记录主要是文本数据,不适合塞进关系表
- 部署 MySQL 对于小工具来说太重了
- JSON 文件可读、可编辑、可版本控制、可直接复制备份
后来我把这个思路也用在了其他项目上:小工具用文件,大系统用数据库,别一开始就上重型方案。
6.3 Prompt Engineering 比代码更重要
这个项目里,真正"写代码"的时间可能只占 40%,剩下 60% 都在调 prompt。
举个例子,评分 prompt 经历了三个版本:
V1(太简单):
请给这个面试回答打分。
→ 输出格式不统一,分数解析困难。
V2(加了维度):
请从准确性、完整性、表达清晰度三个维度打分,每项 0-10 分。
→ 格式统一了,但反馈太泛,像"准确性不错,建议提升完整性"。
V3(加了约束):
请从三个维度打分,每个维度给出分数后,必须指出回答中具体的亮点和不足,并给出改进建议。格式:准确性:X 分 - …
→ 反馈具体了,能指出"你提到了红黑树但没说明触发条件"。
Prompt 就是和 AI 沟通的"代码",它的质量直接决定了输出质量。这个认知对我帮助很大,不仅在这个项目里,后来做其他 LLM 相关的尝试时,都会先花时间打磨 prompt。
6.4 关于"重复造轮子"
做这个项目的过程中,我也犹豫过:市面上不是有类似的工具吗?为什么还要自己做?
后来想通了:造轮子不是为了替代别人的轮子,而是为了理解轮子是怎么转的。
通过这个项目,我学到了:
- RAG 架构:向量检索 + LLM 生成的结合方式
- SSE 流式传输:前后端如何实现实时数据流
- PDF 文本提取:pdfplumber 的使用和局限性
- 前端状态管理:Pinia 在实际项目中的用法
- API 设计:RESTful 接口的规划和文档化
这些经验是看再多教程也换不来的。
七、未来计划
目前项目已经覆盖了面试准备的基本场景,后续还打算:
- 面试历史回顾:查看过去的面试记录,跟踪进步轨迹
- 更多题型支持:目前主要是八股文,后续加入算法题、系统设计题
- 面试报告对比:多次练习后,对比不同时间的得分趋势
- 导出更多格式:支持导出 PDF 格式的报告
写在最后
这个项目是我学习后端开发过程中的一个实践。它不完美,但对我而言意义重大——从"学知识"到"做东西",这个跨越只有动手了才能完成。
如果你也在准备面试,或者对 LLM 应用开发感兴趣,欢迎试试这个工具,也欢迎提 issue 和 PR。
- 项目地址:https://gitee.com/MuYi-2025/interview-assistance-system
- GitHub:https://github.com/Y-MuYi/Interview-Copilot.git
觉得有用的话,点个 Star 支持一下吧!
如果这篇文章对你有帮助,欢迎点赞、收藏、转发。有问题也可以在评论区交流~
