Skip to content

Latest commit

 

History

History
116 lines (80 loc) · 8.88 KB

File metadata and controls

116 lines (80 loc) · 8.88 KB

讲给面试官听:ResumeForge 项目讲解指南

这份文档帮你把项目讲清楚、讲出深度,而不是背功能清单。 原则:先讲"解决了什么真问题",再讲"怎么解决的",最后用 2-3 个能深挖的技术点证明工程能力。

一、30 秒电梯演讲

我做了一个本地优先的 AI 简历工作台,叫 ResumeForge(简历通)。 它解决的是求职者资料散、简历版本乱、AI 生成简历会编造经历这三个真实痛点。 技术上是 FastAPI + React + SQLite 的单机应用,前端运行时依赖只有 6 个,后端纯 Python 零编译。 核心设计是把"事实"和"表述"拆开管——AI 只负责把已确认的事实改写成漂亮的简历,改写不了事实本身, 所以它写出来的每一句话都能追溯到你的资料库。

二、它到底解决什么问题(5 分钟版)

求职期的数据是散的、乱的、危险的:

  1. 散:JD 在收藏夹,简历有七八版 简历-最终版2.docx,投递进度在备忘录,面试问题面完就忘。
  2. 乱:改了三版简历,不知道哪一版投给了哪家公司。
  3. 危险:AI 能把简历写漂亮,也能把你没做过的事写进去——面试官追问两句就露馅。

ResumeForge 的答案是围绕一条主线做闭环:

录入岗位 → 维护资料 → AI 生成 / 自行编写简历 → 导出投递
    ↑                                            ↓
    └── 面试深挖 / 模拟面试(检验) ← 求职进度 / 投递台(执行反馈)←┘

关键差异点在于它不做黑盒:匹配度不给你一个百分比(那会给你虚假的精确感),只给五类结论(已匹配 / 表达缺口 / 证据不足 / 真实缺口 / 待确认);生成结果会和资料库逐条比对,不一致就报警。

三、技术栈(一句话 + 表)

层 选型 为什么
前端 React 18 + TypeScript + Vite + Ant Design 5 运行时依赖只有 6 个,无 Redux / 无 Tailwind,状态用页面级 hook
后端 FastAPI + SQLAlchemy 2 + Alembic + Pydantic 2 异步、类型安全、可离线测试
存储 SQLite(本地优先) 单用户单机,零部署成本;多数据集 = 多个真实库文件
AI OpenAI 兼容协议 + Anthropic 原生,双协议 用户自带 Key,一个 Provider 接口切换
导出 服务端 PDF(fpdf2 嵌入中文字体)+ 浏览器打印 + Word(python-docx) 三种都复用同一套版式口径
浏览器自动化 自研 CDP 客户端(WebSocket) 驱动用户自己的 Chrome/Edge 投递,纯 Python 零编译

工程数据:2700+ 测试用例、后端覆盖率门槛 80%、19 个 Alembic 迁移、GitHub Actions 三平台 CI(Linux ×2 / Windows)。

四、架构一句话 + 分层

前后端严格三层,任何功能走同一条路:页面 → 路由 → 服务 → ORM → SQLite。前端从不直接拼 URL,后端路由从不写业务。

React 页面  ──前端封装 api/*──▶  FastAPI 路由 api/*  ──▶  业务 services/*  ──▶  ORM models/*  ──▶  SQLite
(界面)        (统一请求层)        (参数校验/编排)       (纯逻辑,可离线测)      (表结构)

这条链路的两个工程价值:业务逻辑与框架解耦(services 层可以脱离 FastAPI 跑单测),契约集中(前后端枚举逐字镜像,改一处有测试兜住)。

五、四个可以深挖的亮点

挑 2-3 个你最有把握的展开。每个都能讲出"难点 → 方案 → 结果"。

亮点 1:防 AI 虚构 —— 事实与表述分离

  • 难点:大模型最危险的失败不是写不好,是编造。把一个没做过的项目写进简历,比排版难看严重得多。
  • 方案:单独建"事实台账"表,每条主张记录"原始事实 + 简历表述 + 承担程度 + 核实状态"。只有"已确认"的条目才进生成上下文;未确认说法进"禁止使用"清单;生成结果与资料库逐条比对,不一致给防虚构警告;正文有【待补】标记时导出被拦并指出位置。
  • 结果:AI 只能"改写事实",不能"创造事实"。这条是产品的灵魂,也是最能体现"我理解 LLM 边界"的地方。
  • 可追问点:为什么不让 AI 自己确认台账条目?→ 那等于让模型给自己发通行证。

亮点 2:自动投递的两层隔离(浏览器桥接 + 站点适配器)

  • 难点:自动投递要驱动真实浏览器、理解陌生招聘网站表单——这是最不可控、最易因站点改版而失效的环节。
  • 方案:把最不可测的两件事封在两层之后。浏览器桥接层(services/browser/)只管 CDP 传输和"页面什么时候真的就绪";站点适配器层(services/sites/)只认一个站点、提供选择器与流程。业务层只调"站点无关"接口,两层都能用假传输层离线测试——测试不需要真的联网或开浏览器。
  • 结果:站点改版只影响对应适配器文件;整条链路在没有招聘网站账号的 CI 里也能全绿。
  • 可追问点:怎么判断"页面加载好了"?→ 不信任 readyState(SPA 卡片是 XHR 异步渲染的),只认"目标选择器匹配到内容或明确无结果";"这一页是不是目标页"用"目标地址的每个查询参数都能在当前位置取到相同值"判,而不是地址整串相等。

亮点 3:单源判定 + 渐进式数据库迁移

  • 难点:一个规则在多处各写一遍,必然前后端漂移;加表加列会拒收用户手里的旧备份。
  • 方案:关键判断只留一份实现——投递准入 admission_of()、进度合并 resolve_status()、回收站 TRASH_SPECS 注册表;数据库用 Alembic 版本化迁移,升级前自动备份,旧备份先迁移再校验,所以"加表"不再是不兼容改动。
  • 结果:匹配度分析、投递服务、前端展示都读同一份结论,阈值不会漂移;19 个迁移每个都有"建表 / 幂等 / 可回滚"的测试钉住。

亮点 4:工程洁癖(可选的加分项)

  • 前端运行时依赖只有 6 个(antd 系 + dayjs + react 系 + router),没有状态管理库、没有 CSS 框架。
  • 后端依赖全部纯 Python 或有 wheel,首次安装零编译(Windows 新手不用装 Visual C++ Build Tools)。
  • 提示词独立成文件、版本化;发行包只从 git archive 出包并重新校验必需文件。

六、演进路线(体现"能长期维护一个项目")

从 0.1 到 0.10,四个多月、87 个提交,功能是沿主链逐渐长出来的,不是一次性堆上去:

版本 时间 里程碑
0.1–0.2 2026-08 基础骨架:资料、岗位、简历生成
0.3–0.5 2026-09 上旬 岗位文本/JD 规则解析、附件识别、一致性校验
0.6–0.8 2026-09 中 导出管线、搜索/收藏、写作增强、事实台账
0.9 2026-09-20 投递台、求职进度、模拟面试、面试深挖、版面诊断
0.10 2026-09-21 岗位采集筛选、批次可见性、跨平台 CI 全绿

讲演进时强调:每一版都有真实用户反馈驱动——CHANGELOG 里大量条目是"用户在 X 场景下发现 Y 失效,我复现后修掉"。这比"我会写代码"更有说服力。

七、高频追问与应答

面试官问 你的应答方向
为什么用 SQLite,不上 MySQL/PostgreSQL? 单用户本地工具,零部署成本是核心卖点;ORM 已隔离方言,未来切多用户只需补迁移与并发适配。
AI 会编造经历怎么办? 这正是核心设计——事实台账 + 逐条比对 + 导出闸门,见亮点 1。
单机应用有什么工程难度? 难点不在并发,在数据安全(备份/迁移/旧库兼容)和外部世界的不可控(招聘站点改版、浏览器行为),见亮点 2/3。
为什么不用无头浏览器(Playwright/Puppeteer)? 要投的是真实站点,需要真实浏览器与登录态;且驱动用户自己的 Chrome/Edge 更贴近真实投递环境。
项目有什么短板? 诚实说:前端 E2E 测试覆盖还不全、无多用户协作、站点适配器目前主要适配单一站点——并说明这是"单用户本地优先"定位下的取舍,以及下一步会补什么。

八、一句话总结(备用)

我做的不只是一个"套壳大模型"的工具,而是认真处理了 AI 落地时最难的两个问题——可信(不让它编造)和可靠(外部依赖层层隔离、数据迁移平滑无损)。这两个问题的解法,是我最能拿得出手的工程能力。


配套文档:项目导航图(功能→代码倒查)· 架构设计(数据流与决策记录)· CHANGELOG(每个版本的修复细节)。