我用 Go 写了个 AI 面试官:出题、追问、打分全自动(上篇)


📮 本系列首发于公众号「GO语言入门之路」,共三篇:上篇(本文)讲状态机与核心提示词设计,下篇讲简历解析与多轮记忆,第三篇讲网页版 SSE 实战。

金九银十刚过去,后台收到不少读者的留言:刷了三个月八股文,一到面试被追问「为什么」「那在高并发下呢」就露馅。

问题不在题量不够,而在没有人逼你往深处挖。于是我用 Go 写了一个「AI 模拟面试教练」:你输入目标岗位,它生成面试计划、按 plan 逐题提问,答得浅就追问,面试结束输出一份结构化的评分报告。

这篇文章是这个系列的上篇,讲清楚产品设计和核心代码。下篇接简历解析与多轮记忆。

一、为什么这不是一个「一问一答」的 chatbot

很多人第一反应是:这不就是一个循环调大模型的 while 循环吗?真不是。区别在于它有一个面试状态机,每一轮要同时做三件事:

  • 按计划推进:面试题不是现场随便出的,开场前已经生成好一份面试计划(plan),后面每问一题都对照 plan;
  • 动态决策:用户答完一轮后,先做一次「评估」,判断这一题是挖到位了,还是该追问一层;
  • 持续记录:评估结果结构化地存下来,面试结束才能聚合成分维度评分,而不是笼统一句「表现不错」。

对话流大概长这样:

输入岗位 → 生成面试计划(能力维度+题目清单)
     ↓
按 plan 提问 → 用户作答 → 评估(置信度+关键点覆盖度)
     ↓               ↓
        深度不够 → 基于原题追问一轮
        深度达标 → 记录评分 → 下一题
     ↓
全部问完 → 聚合输出评分报告(Markdown)

这个状态机的实现只有薄薄一层 Go 代码,难的在提示词设计,下面逐个讲。

二、出题:先建能力模型,再生成面试计划

AI 面试官最容易翻车的地方,是题目东一榔头西一棒子,问完 GMP 又问 React。解法是先建一个岗位能力模型(rubric),把岗位拆成维度,再让模型按维度出题。

以「高级后端工程师」为例,rubric 长这样:

能力维度 权重 考察要点 出题深度
Go 语言内核 25% GMP 调度、GC、channel 底层 能讲清原理 + 能分析取舍
并发与性能 20% 锁、原子操作、pprof 调优 有真实调优案例
分布式系统 20% 一致性、幂等、限流熔断 能设计 + 能扛追问
工程化 20% 微服务治理、可观测性 落地经验
系统设计 15% 高并发架构、容量估算 完整的权衡过程

有了 rubric,出题的 system prompt 就非常具体了(关键片段):

const planPrompt = `你是资深技术面试官。目标岗位:%s。
请输出面试计划(JSON):每个能力维度 1~2 题,每题包含
题目、考察要点(checkpoints, 3~5条)、评分标准。
要求:题目由浅入深;checkpoints 必须具体、可验证,
不许出现"考察基础"这类空话。`

注意这里要求模型自己列出 checkpoints——它们是后面「追问判断」的依据,等于把评分标准提前从模型嘴里「套」了出来。

三、追问:判断回答深浅的两把尺子

追问是面试官的灵魂,也是这个 Agent 和普通 chatbot 最大的分水岭。判断逻辑在 system prompt 里,核心是两把尺子:

信号 含义 追问动作
自评置信度 让模型给自己这个回答打 1~5 分,低于阈值说明它自己都觉得虚 <3 分 → 必追问
关键点覆盖度 对照该题 checkpoints,用户命中了几条 覆盖率 <60% → 追问缺失点
追问过的题 同一题最多追问 2 轮,防止无限套娃 已追问 2 次 → 直接下一题

评估用的提示词(关键片段):

const evalPrompt = `评估用户对面试题的回答。
题目checkpoints: %s;用户回答: %s。
按 JSON 输出:confidence(1-5 自评)、
coverage(命中checkpoints比例0-1)、
hitPoints(命中的要点)、missed(缺失要点)、
suggestion(一句话改进建议)。
只输出 JSON。`

追问时把 missed 要点喂回去:「你刚才没提到 %s,能结合你的项目展开讲讲吗?」——追问是有方向的,不是复读机式地说「再详细点」。

四、打分:用 JSON Schema 锁死输出格式

面试结束要出报告,最大的坑是模型输出格式漂移:这次给你 JSON,下次塞两句解释,解析直接崩。用 response_format + JSON Schema 把输出锁成合法的 JSON,Go 侧用 struct 一一对应解析。

评分报告的 schema 设计:

字段 类型 说明
dimensions array 各能力维度:name / score(0-100) / comment
weakPoints array 薄弱点清单
suggestions array 可执行的改进建议
overall number 总分

Go 侧的解析和渲染(关键片段):

type Report struct {
    Dimensions []struct {
        Name    string `json:"name"`
        Score   int    `json:"score"`
        Comment string `json:"comment"`
    } `json:"dimensions"`
    WeakPoints  []string `json:"weakPoints"`
    Suggestions []string `json:"suggestions"`
    Overall     int      `json:"overall"`
}
// 解析后直接渲染成 Markdown 表格,落盘 report.md

SDK 用的是官方 openai-go(2026-11-02 从官方 GitHub releases 核对的最新版本 v3.91.1,要求 Go 1.26+,核对自 go.mod)。国内模型走 OpenAI 兼容端点,换 baseURL 和模型名即可,代码不用动。

五、跑起来的效果

命令行版的完整交互大概是这样:

$ go run ./cmd/coach
目标岗位: 高级后端工程师
[Q1/Go语言内核] GMP 模型里为什么要有 P 这一层?
> (你的回答……)
[追问] 你说本地队列减少全局锁竞争,那 P 上的队列满了会怎样?
[Q2/并发与性能] 你项目里出现过哪些 goroutine 泄漏?怎么发现的?
……
面试结束。生成报告: report.md

report.md 就是按维度打分 + 薄弱点 + 建议的 Markdown,可以直接贴进笔记软件对照着补。

六、总结与预告

这篇文章的核心就三件事:先用 rubric 建能力模型生成面试计划,再用「置信度 + 关键点覆盖度」两把尺子决定追问还是放行,最后用 JSON Schema 锁死评分报告的格式。整套状态机加提示词,不到 300 行 Go 代码。

下篇接入简历解析:面试官先读你的简历,再针对性出题——「你简历里写了做过百万级 QPS 网关,那我们来聊聊它的限流设计」。

相关阅读:AI 面试官先读简历再出题:Go 简历解析实战(下篇) · AI 面试官网页版实战:Go + SSE 流式输出(三)

版本说明

  • openai-go:v3.91.1(2026-11-02 核对自 github.com/openai/openai-go 的 releases 页;module 路径 github.com/openai/openai-go/v3,要求 Go 1.26+,核对自仓库 go.mod;官方文档:pkg.go.dev/github.com/openai/openai-go/v3)
  • 安装命令:go get github.com/openai/openai-go/v3@v3.91.1

本文系 AI 辅助生成,内容已经人工核对,如有错误欢迎评论区留言指正。

🛒 站长推荐(京东联盟)

以上链接含京东联盟推广代码;通过链接购买本站可能获得少量佣金,不影响你的购买价格。

📮 关注公众号「GO语言入门之路」
GO语言入门之路 公众号二维码

每周更新 Go + AI 应用开发实战:AI 面试官完整项目、MCP、Agent 工程化,完整源码随文章首发。

微信扫码,或搜索「GO语言入门之路」关注,第一时间获取系列更新与源码,不再错过任何一篇。

wx

关注公众号

©2017-2026 鲁ICP备17023316号-1 Powered by Hugo · 隐私政策