从 0 到 1 做一个 Android 面试官 Agent
这套文档做一件事: 带你从一个空文件夹开始, 做出一个能上线、有评测、有 CI 的 Android 模拟面试 Agent, 并且照着做就能跑通。
读者预设: 零开发背景。不需要你懂 Python、不需要你用过 Docker、不需要你有 GPU。用一台 Mac (或任何 Linux/Windows) 就能全程跟完。
每一章的 ✅ Checkpoint 里贴的输出, 全部是在真机上真的跑出来的, 不是编的。跑出来不一样的地方, 章节里会告诉你哪些差异是正常的。
一、最终做出来的是什么
一个网页版的"Android 面试官"。你点开始, 它出题; 你打字回答, 它当场判分、指出你漏了什么、然后根据你答得好不好决定下一步——答得好就追问深一层, 答得差就换个简单的题, 答完出一份带薄弱项和学习计划的报告。
它和"套一个提示词让 GPT 扮演面试官"的区别, 是这套文档真正想教的东西:
| 提示词版面试官 | 本项目 | |
|---|---|---|
| 题目来源 | 模型现编, 每次不一样, 可能编出错的题 | 自建知识库检索 + 黄金题库, 题目和答案要点都有出处 |
| 判分 | 模型说 7 分就 7 分 | 模型只判"要点命中没有", 分数由代码按权重算 |
| 流程 | 全靠模型自觉 | 显式状态机, 追问几层、什么时候降难度, 都是代码决定的 |
| 质量 | "我试了几次感觉还行" | 三层评测: 检索准确率、判分器与人的一致性、对话级 LLM Judge |
| 上线 | 跑在自己电脑上 | Docker 镜像 + Nginx + 健康检查 + CI 质量闸门 |
这个项目放简历上能打的点: 不是"我做过 RAG", 而是"我的检索 Recall@3 从 0.9333 提到 1.0000 是量出来的; 我的判分器和人工标注 MAE 是 0.833、顺序一致率 0.8, 这个数字挂在 CI 上, 掉了不许合并"。会说前半句的人很多, 能说出后半句的一百个里没几个。
二、文档目录与学习路线
请按顺序读。每一章的产出都是下一章的输入, 跳着读会在第 4 章开始卡住。
| 序号 | 文档 | 内容 | 预计耗时 |
|---|---|---|---|
| 00 | 项目总览与技术选型 | 成品长什么样、整体架构、每个技术选择的理由与代价 | 2 小时 |
| 01 | 环境搭建: uv 与项目骨架 | 装 Python、uv、建项目、配置分层、.env 与 .gitignore | 半天 |
| 02 | 语料体系: 从零建一个知识库 | 知识点大纲、Markdown + YAML 元数据规范、写 7 篇语料 | 1 天 |
| 03 | 黄金评测集与判分标准 | 15 道题的评测集、rubric 要点权重、故意留的陷阱题 | 半天 |
| 04 | RAG 第一步: 切分与入库 | 按标题切块、整句重叠、元数据落库、Chroma 持久化 | 1 天 |
| 05 | 混合检索: BM25 + 向量 + RRF | 两路召回、RRF 融合、精排、阈值、元数据过滤 | 1~2 天 |
| 06 | 检索评测: 用数字证明变好了 | Recall@K / MRR / nDCG@K、消融表、样本量陷阱 | 半天 |
| 07 | 面试官状态机与命令行版 | 六状态 FSM、判分器、追问与难度自适应、报告生成 | 2~3 天 |
| 08 | Web 服务: FastAPI + SSE + 鉴权 + 落库 | 接口设计、流式推送、API Key、SQLite、单文件前端 | 2~3 天 |
| 09 | 三层评估体系 | 判分器一致性 (MAE/一致率)、LLM Judge 双向消偏 | 1~2 天 |
| 10 | 模型微调与私有化部署 | 数据导出、Mac 上用 MLX、租卡 QLoRA、Ollama/GGUF | 2~3 天 |
| 11 | Docker 与上线 | 多阶段构建、compose、Nginx 与 SSE、数据卷、上云 | 1~2 天 |
| 12 | CI 建设与质量闸门 | GitHub Actions、离线测试策略、镜像构建验证 | 1 天 |
| 13 | 踩坑手册与面试话术 | 本项目真实踩的 20 个坑、怎么把项目讲成亮点 | 上线/面试前必读 |
总时长约 3~4 周 (每天 2~4 小时)。
三、跟读方式
- 每章都有 ✅ Checkpoint, 跑不出来就别往下走。 Checkpoint 不是装饰, 是"到这里为止你的代码是活的"的证据。第 5 章检索不对, 第 7 章的面试官一定选不出题, 但报错会出现在完全无关的地方。
- 代码全部给出, 但请手敲关键文件。 复制粘贴能跑通, 但学不会。
chunker.py、fsm.py、grader.py这三个建议一行行敲。 - 不要跳过评测章 (06 / 09)。 它们不产生新功能, 只产生数字。但没有数字, 你后面所有"我优化了一下"都是自我感觉。
- 花钱控制在 10 元以内。 全程可以用
OFFLINE=true离线跑通 (规则判分 + 假向量), 只在第 9 章测判分质量时需要真 API。用 DeepSeek 之类的国内低价模型, 十几次实验几块钱。
四、你需要准备什么
- 一台电脑, Mac / Linux / Windows 都行 (本文档在 macOS 26.5.1 / Apple M3 / 16GB 上验证)
- 不需要显卡。 第 10 章的微调给了三条不用自己有卡的路
- 一个 LLM API Key (可选, 第 7 章之后才用得上)
- 磁盘留出 5GB: embedding 模型 100MB, 但 Docker 镜像和 torch 加起来会占几个 G
五、这套文档的一个原则
凡是没量过的, 就说没量过; 量出来不好看的, 也照原样贴。
最典型的例子是 cross-encoder 精排。第 5 章讲了怎么接它, 第 6 章量了它 —— 结果是变差了:
| 模式 | Recall@3 | MRR | nDCG@3 |
|---|---|---|---|
| hybrid | 1.0000 | 0.9667 | 0.9647 |
| hybrid+rerank | 1.0000 | 0.9333 | 0.9443 |
按"业界最佳实践"这里应该写"加了精排 MRR 提升 3%"。但实测是掉的, 所以本项目的 USE_RERANK 默认是 false, 而文档里保留这张表和这段说明。第 6 章还会补一句同样重要的话: 这个评测集只有 15 题, 0.0334 的差距不到一题, 所以正确结论是"在这个数据集上没看出收益", 而不是"精排没用"。
这个原则很重要: 你将来接手的项目里, 一半的"性能优化"都是没量过的传说。学会区分"我知道"、"我以为"和"我量了但样本不够", 比多学一个框架值钱。
这套文档里被这个原则挡下来的结论有四个, 它们全都写进了正文而不是被删掉:
| 结论 | 出处 |
|---|---|
| cross-encoder 精排让 MRR 从 0.9667 掉到 0.9333, 所以默认关掉 | 第 6 章 |
| LoRA 微调修好了输出格式但没有修好判分正确性, 该模型没上线 | 第 10 章 |
mlx_lm fuse 合并 adapter 不是无损的 (要重新量化), 合完必须重新评估 |
第 10 章 |
| 检索指标不能当 CI 门禁 —— CI 装不了真 embedding 模型, 同一份代码 vector Recall@3 会从 1.0 掉到 0.7333 | 第 12 章 |
另外有两处明确标注了没有实测: 第 10 章的租卡 QLoRA 和 GGUF 转换, 第 12 章的 docker-build job。它们给的是官方文档加逐行推理, 但没有 Checkpoint —— 因为这套文档里的 Checkpoint 只贴真跑出来的东西。
准备好了就从 00-项目总览与技术选型 开始。