系列收官:把这个 Go 写的 AI 面试官改成你的 Agent(八)
📮 本系列首发于公众号「GO语言入门之路」,系列聚合目录。前文见 第四篇 ~ 第七篇:SQLite 记忆。
八篇了。从第一晚 200 行的命令行脚本,到今天飞书 + 网页双端、语音作答、7×24 部署、历史落库的完整产品——代码量翻了几倍,但有一个数字始终是零:核心状态机被改动的次数。
你可能根本不想做面试教练。没关系,这篇收官之作就是给你一把手术刀:fork 这个仓库,动哪几层、怎么动,把它改成属于你的垂直场景 Agent。
八篇演进回顾:加的一直是"外壳",不是"内脏"
先把全貌摆出来。回看整个系列,每篇新增的其实只有一类东西——I/O 适配层:
| 篇 | 新增能力 | 动的层 |
|---|---|---|
| 一 | CLI 核心:出题、追问、打分 | 状态机 + LLM 封装 |
| 二 | 简历 PDF 解析,针对性出题 | 状态机输入 + 一个新包 |
| 三 | Web 版 + SSE 流式点评 | web/ 适配层(新增) |
| 四 | 飞书机器人,长连接零公网 IP | bot/ 适配层(新增) |
| 五 | 语音作答(ASR) | bot/ + asr/(新增) |
| 六 | systemd 部署 + token 成本监控 | deploy/ + 计数器 |
| 七 | SQLite 历史落库 +「历史」指令 | store/(新增) |
这个演进的秘密在于第一篇文章立下的架构决定:internal/coach 状态机只依赖 llm.Client 接口,不认识 HTTP、不认识飞书、不认识麦克风。之后每接一个新端,都是"外面包一层、里面一行不动"。改造别人的 Agent 项目,先看它的状态机有没有被 I/O 污染——这是判断代码值不值得 fork 的第一标准。
四层解剖:你的改动落在哪一层
整个项目四层,自下而上:
- LLM 与存储底座:
internal/llm(openai-go v3 封装,JSON Schema/流式/用量统计)、internal/store(modernc.org/sqlite,纯 Go 无 CGO)、internal/asr。这层几乎不用动。 - 领域状态机:
internal/coach。计划 → 评估 → 追问 → 报告的状态流转,加上全部提示词(集中在prompts.go)。这是改造的主战场。 - 会话路由与指令:
internal/bot。IM 交互逻辑:谁正在面试、指令解析、列表序号缓存。 - I/O 适配:
internal/web、internal/bot/lark.go。换平台动这里。
依赖方向严格单向:上层可以知道下层,反过来不行。第七篇的 Store 接口定义在 bot 侧而不是 store 侧,也是同一个原则。
改造对照表:三个垂直场景各动哪几层
这是本篇的收藏点。三个典型 fork 方向,逐层标注改动量:
| 层 | 英语口语陪练 | 公务员结构化面试 | 技术 Quiz 刷题机 |
|---|---|---|---|
| coach/prompts.go | 全换:面试官→口语教练,评估尺子从"要点覆盖"换成"语法/流利度/用词" | 大改:换成结构化题型(综合分析/应急应变等),rubric 固定为评分标准 | 全换:去掉追问逻辑相关的评估项 |
| coach 状态机 | 不用动 | 不用动 | 小改:去掉追问分支 |
| Schema | 换字段(fluency/grammar/pronunciation) | 换字段(按公考评分要素) | 简化 |
| bot 指令 | 不用动 | 不用动 | 「历史」改名「错题本」即可 |
| ASR 语音 | 必需(已经是核心链路) | 可选 | 不需要 |
| store | 不用动 | 不用动 | 不用动 |
看出规律了吗:三个场景里 store、bot、状态机全部复用,要写的只有提示词和 JSON Schema。这正是"产品级 Agent"和"玩具 demo"的分水岭——demo 把提示词焊死在流程里,产品把领域知识集中在可替换的一层。
动手示例:把"技术面试官"改成"口语陪练"
以第一个场景为例,实际改动从 prompts.go 的评估提示词开始——评估尺子变了,追问判断的依据就跟着变:
// 改前(技术面试):评估依据是 checkpoints 覆盖度
// user := 面试题 / 考察要点 / 候选人回答 → confidence、coverage、missed…
// 改后(口语陪练):评估依据是语言质量三要素
const system = `你是严格的英语口语教练,只依据语言事实评估,不许给安慰分。`
user := fmt.Sprintf(`话题:%s
学员表达:%s
按 JSON 输出评估:fluency(流利度1-5)、grammar(语法准确度1-5)、
vocabulary(用词丰富度1-5)、errors(列出 3 处最需要改的错误)、
suggestion(一句可执行的练习建议)、depth_ok(本话题是否练到位)。只输出 JSON。`,
topic, speech)
配套做两件事:EvalSchema 换成新字段;ShouldFollowUp 的阈值从 coverage 换成三要素均分(比如 < 3.5 就追问"能不能换个说法再说一遍")。改完跑 go test ./internal/coach/——Mock 客户端会告诉你状态机有没有被改坏。
三个值得带走的设计决策
最后沉淀三条这个系列反复验证过的经验:
- 接口定义在消费侧。bot 定义 Store、定义 Interview,实现方单向依赖。换存储、换状态机都是新增而不是修改。
- 所有能力可选注入。meter 传 nil 就不统计用量,store 传 nil 就没有历史——每个功能都能独立关闭,调试和降级都简单。
- 副作用不许反噬主流程。落库失败附一行警告,报告照样发出;ASR 没配置就优雅拒绝语音。Agent 上线后最贵的故障都是"次要功能拖死主要功能"。
系列完结
八篇,从 coach new --pos 的第一行输出,到飞书里一句「历史」调出三周前的面试报告。完整代码正在 GO2AI-CN 组织下整理开源(仓库名:ai-interview-coach),开源后欢迎 fork 改造成你自己的 Agent。
这个系列到此完结。后续内容将转向 MCP 协议与 Agent 工程化的新系列——把面试教练里埋的伏笔(工具调用、记忆、多 Agent)一个个展开讲透。
相关阅读:系列聚合目录 · 上篇:状态机与核心提示词 · 第七篇:SQLite 记忆
版本说明
- openai-go:v3.97.0(2026-11-09 核对自 github.com/openai/openai-go 的 releases 页;module 路径
github.com/openai/openai-go/v3,要求 Go 1.26+) - modernc.org/sqlite:v1.61.1(2026-11-06 核对自 Go Module Proxy)
- larksuite/oapi-sdk-go/v3:v3.12.2(2026-11-05 核对自 GitHub tag 列表)
本文系 AI 辅助生成,内容已经人工核对,如有错误欢迎评论区留言指正。
- 《Go 程序设计语言》(Go 语言圣经,机械工业出版社) —— Go 官方团队出品,公认入门第一书
- 《Go 语言实战》(异步图书,人民邮电出版社) —— 实战导向,面试前巩固工程手感
- 《Go 语言编程之旅:一起用 Go 做项目》(博文视点,电子工业出版社) —— 项目驱动入门,从零写出完整应用
- Keychron K1Max 矮轴机械键盘(Mac/Win 双系统,QMK/VIA 开源改键) —— 轻薄矮轴 + 开源固件,程序员桌面常客
- 罗技 MX Master 3S 无线鼠标(Flow 跨屏,静音电磁滚轮) —— 人体工学设计,写代码一整天手不酸
以上链接含京东联盟推广代码;通过链接购买本站可能获得少量佣金,不影响你的购买价格。
每周更新 Go + AI 应用开发实战:AI 面试官完整项目、MCP、Agent 工程化,完整源码随文章首发。
微信扫码,或搜索「GO语言入门之路」关注,第一时间获取系列更新与源码,不再错过任何一篇。