跳到主内容
快讯直播
AI智模界
教程

用 AI 搭一套带评分标准的面试题库

这套流程能做出什么

走完这篇教程,你会得到一份可以直接拿进面试间的题库文件(JSON 或 CSV),每道题都长这样:

  • 题目本身:一句能直接念出口的话,比如"请讲一次你负责的系统在线上出现性能问题,你是怎么定位并解决的"
  • 考察维度:对应你岗位能力模型里的哪一格,比如"故障排查"
  • 难度分档:1 到 5
  • 加分要点:候选人说到哪些具体行为、数据、决策,说明他确实做过
  • 扣分信号:哪些回答方式说明他只是听过、没做过
  • 评分锚点:1 分、3 分、5 分分别对应什么样的回答水平,每档一句话
  • 追问链:2 到 3 个往下挖的问题,防止候选人用套话蒙混

一个人对着 JD 手写这些内容,一个岗位三十道题,通常要花掉大半天到两天。用 AI 生成初稿、人来定稿,时间能压到一两个小时,而且评分标准的颗粒度往往比匆忙手写的更细。

需要说清楚的是:AI 负责"出题 + 起草评分标准",人负责"判断这套标准对不对"。把 AI 产出的东西直接当标准答案用,是这套流程里成本最高的错误。

前置条件清单

动手前,确认这几样都在手边:

1. 一份真实的岗位 JD,越具体越好。描述里如果只有"负责相关业务开发",AI 也只能出泛泛的题。

2. 一个可调用的大模型 API Key,以及对应的调用地址。模型名、计费方式、参数上限以官方文档当前版本为准。

3. Python 环境(3.9 以上比较省事),能 pip install 装包。

4. 一个表格工具:Excel、飞书表格、Google Sheets 都行,用于人工评审。

5. 一位懂这个岗位的评审人,哪怕就是你自己。评分标准必须由懂业务的人过一遍。

6. 合规底线清单。涉及性别、年龄、婚育、籍贯、宗教、健康状况的问题一律不要,这类内容在很多地区会直接带来法律风险。

第 1 步:把 JD 翻译成能力维度表

先别急着让 AI 出题。第一步是人工定出考察维度,这是整个题库的骨架。

把 JD 丢给 AI,让它提炼 5 到 8 个能力维度,然后你自己删改。最后产出一张这样的表,存成 dimensions.csv

```csv

dimension,weight,description

故障排查,0.25,能从监控、日志、链路数据中定位线上问题根因

系统设计,0.25,能给出有取舍的架构方案并说明边界条件

协作沟通,0.15,能推动跨团队事项落地,处理分歧

代码质量,0.15,对可测试性、可维护性有稳定习惯

业务理解,0.10,能把技术方案和业务指标挂钩

学习迁移,0.10,能把新领域的方法迁移到当前问题

```

权重加起来等于 1。这张表决定了后面每一道题为什么存在,也是最后算总分的依据。

维度数量控制在 8 个以内。维度一多,每个维度出的题就少,评分的信度反而下降。

第 2 步:约定题库的数据结构

在写 prompt 之前先定字段。字段定得越死,后面解析和入库越省事。建议用这套:

字段类型说明
idstring形如 fault-003,前段是维度缩写
dimensionstring考察维度,必须来自维度表
difficultyint1-5
questionstring题干,可直接朗读
strong_pointsstring[]加分要点,3-5 条
weak_signalsstring[]扣分信号,3-5 条
scoring_anchorsobject键为 "1" / "3" / "5",值为描述
followupsstring[]追问,2-3 个
time_minutesint建议用时

为什么要留 weak_signals?因为面试里更常见的情况是"听起来很流畅,但一追问就空了"。提前把"空"长什么样写下来,面试官才有统一的判断依据。

第 3 步:写出题 Prompt,把评分标准一起要出来

这是整篇教程里最值得反复打磨的一段。可以直接复制下面这个模板,把方括号里的内容替换掉:

```text

你是一位资深【岗位名称】面试官,正在为【级别,如:三年经验】候选人设计面试题。

岗位背景:

【JD 摘要,两三句话】

本次考察维度:{dimension}

维度说明:{description}

请设计 {n} 道面试题,要求:

1. 全部采用行为面试法,问候选人"过去实际做过什么"。

禁止出现"你会怎么做""你怎么看""如果……"这类假设性问题。

2. 输出一个 JSON 数组,每个元素包含字段:

  • question:题干,口语化,能直接念出来
  • difficulty:1 到 5 的整数
  • strong_points:3 到 5 条,每条不超过 20 字,描述候选人回答里出现的具体行为、数字或决策
  • weak_signals:3 到 5 条,描述可观察到的空泛回答特征
  • scoring_anchors:对象,必须包含 "1"、"3"、"5" 三档,每档一句话,

描述候选人达到什么程度给这个分

  • followups:2 到 3 个追问,用于核实细节
  • time_minutes:建议面试时长,整数

3. 评分锚点只能写可观察的行为或结果。

禁止使用"优秀""良好""思路清晰""有深度"这类无法验证的词。

一档锚点里至少要包含一个动作动词或一个可量化的结果。

4. 不要涉及性别、年龄、婚育、籍贯、宗教、健康等个人特征。

5. 已有题目如下,新题不要与之重复:

{existing_questions}

只输出 JSON,不要任何解释文字。

```

模板里那句"已有题目如下"很关键。分批生成时把前面批次的题干回传,能明显压低重复率。

第 4 步:批量生成并结构化落盘

按维度循环调用,一次出一个维度的题,比一次性要求"给我全部题"稳定得多。下面是一段可用的脚本:

```python

import json

import os

import time

from openai import OpenAI # 以官方文档当前版本为准

client = OpenAI(

api_key=os.environ["LLM_API_KEY"],

base_url=os.environ.get("LLM_BASE_URL"),

)

MODEL = os.environ["LLM_MODEL"]

PROMPT_TEMPLATE = open("prompt.txt", encoding="utf-8").read()

def generate(dimension: str, description: str, n: int, existing: list[str]) -> list[dict]:

prompt = PROMPT_TEMPLATE.format(

dimension=dimension,

description=description,

n=n,

existing_questions="\n".join(existing) or "(暂无)",

)

resp = client.chat.completions.create(

model=MODEL,

messages=[{"role": "user", "content": prompt}],

temperature=0.8,

response_format={"type": "json_object"},

)

text = resp.choices[0].message.content.strip()

text = text.removeprefix("``json").removeprefix("`").removesuffix("``")

data = json.loads(text)

return data if isinstance(data, list) else data.get("questions", [])

def main():

dims = [

{"name": "故障排查", "description": "能从监控、日志中定位根因"},

{"name": "系统设计", "description": "能给出有取舍的架构方案"},

]

results, existing = [], []

for d in dims:

for attempt in range(3):

try:

items = generate(d["name"], d["description"], 6, existing)

for i, item in enumerate(items, 1):

item["id"] = f"{d['name']}-{i:03d}"

item["dimension"] = d["name"]

results.extend(items)

existing.extend(x["question"] for x in items)

break

except Exception as exc: # JSON 截断、网络抖动都落这里

print(f"{d['name']} 第 {attempt + 1} 次失败:{exc}")

time.sleep(3)

with open("question_bank.jsonl", "w", encoding="utf-8") as f:

for item in results:

f.write(json.dumps(item, ensure_ascii=False) + "\n")

print(f"共生成 {len(results)} 道题")

if __name__ == "__main__":

main()

```

几个细节值得留意:

  • temperature 调高一点(0.7 到 1.0),题目多样性会更好;生成评分锚点时反而可以调低。
  • 明确要求 JSON 输出模式,能省掉大量解析麻烦。不同服务商对这个参数的支持方式不一样,以官方文档当前版本为准。
  • 解析失败就重试,别让一次网络抖动毁掉整批任务。

第 5 步:机器初筛,把明显不合格的挑出来

生成完先跑一遍自动检查,减少人工评审的负担:

```python

import json

from difflib import SequenceMatcher

REQUIRED = ["id", "dimension", "difficulty", "question",

"strong_points", "weak_signals", "scoring_anchors",

"followups", "time_minutes"]

def similar(a: str, b: str) -> float:

return SequenceMatcher(None, a, b).ratio()

def check(path: str):

items = [json.loads(line) for line in open(path, encoding="utf-8")]

problems = []

for i, item in enumerate(items):

missing = [k for k in REQUIRED if k not in item]

if missing:

problems.append((item.get("id", i), f"缺字段:{missing}"))

anchors = item.get("scoring_anchors", {})

if set(anchors) < {"1", "3", "5"}:

problems.append((item.get("id", i), "评分锚点不全"))

for level, desc in anchors.items():

if len(str(desc)) < 8:

problems.append((item.get("id", i), f"{level} 档描述过短"))

if not 1 <= item.get("difficulty", 0) <= 5:

problems.append((item.get("id", i), "难度越界"))

for i in range(len(items)):

for j in range(i + 1, len(items)):

r = similar(items[i]["question"], items[j]["question"])

if r > 0.75:

problems.append((items[i]["id"], f"与 {items[j]['id']} 相似度 {r:.2f}"))

for pid, msg in problems:

print(pid, msg)

print(f"共 {len(problems)} 条待处理")

check("question_bank.jsonl")

```

相似度阈值 0.75 只是个起点,跑一批之后按实际情况调。

第 6 步:人工评审,重点看评分标准

自动检查只能拦住格式问题,内容质量必须人来判。建议逐题问四个问题:

1. 这个问题在面试里问得出口吗? 有的 AI 题干又长又书面,念出来很别扭,改成口语。

2. 评分锚点能不能区分出"做过"和"没做过"? 比如 5 分档写"能说出完整方案",这个太虚。改成"能说出具体采用了哪种方案、当时对比过的另一种方案是什么、最终效果指标怎么变的"。

3. 加分要点是不是在描述行为? 出现"思路清晰""表达流畅"就删掉,换成"能主动说出方案被否决的原因"。

4. 难度分布合理吗? 六道题全是最难的,面试前三十分钟就把候选人打崩了,拿不到有效信息。

导出成 CSV 给面试官用:

```python

import csv

import json

items = [json.loads(line) for line in open("question_bank.jsonl", encoding="utf-8")]

with open("interview_sheet.csv", "w", newline="", encoding="utf-8-sig") as f:

w = csv.writer(f)

w.writerow(["题号", "维度", "难度", "题目", "1分锚点", "3分锚点", "5分锚点",

"追问1", "追问2", "建议时长", "实得分", "备注"])

for it in items:

a = it["scoring_anchors"]

fu = it["followups"] + [""] * (2 - len(it["followups"]))

w.writerow([it["id"], it["dimension"], it["difficulty"], it["question"],

a["1"], a["3"], a["5"], fu[0], fu[1],

it["time_minutes"], "", ""])

```

utf-8-sig 这个编码别写错,否则用 Excel 打开会乱码。

第 7 步:用真实面试数据回流校准

题库不是一次做完就锁死的。面了十几个人之后,把每题的打分汇总起来看两件事:

  • 均分和标准差。所有候选人都拿 4 分的题,区分度接近零,考虑替换或降级为暖场题。
  • 和总分的相关性。某题得分和最终录用结论明显不相关的,说明它可能没考察到真正重要的东西。

```python

import pandas as pd

df = pd.read_csv("scores.csv") # 列:candidate_id, question_id, dimension, score

stats = df.groupby("question_id")["score"].agg(["mean", "std", "count"])

stats = stats[stats["count"] >= 5].sort_values("std")

print(stats.head(10)) # 标准差小的排前面,优先复查

```

加权总分的算法也一并固化下来,避免每个面试官口径不同:

```python

WEIGHTS = {"故障排查": 0.25, "系统设计": 0.25, "协作沟通": 0.15,

"代码质量": 0.15, "业务理解": 0.10, "学习迁移": 0.10}

def weighted_score(rows):

"""rows: [{'dimension': ..., 'score': 1-5}, ...]"""

per_dim = {}

for r in rows:

per_dim.setdefault(r["dimension"], []).append(r["score"])

total, wsum = 0.0, 0.0

for dim, scores in per_dim.items():

w = WEIGHTS.get(dim, 0)

total += (sum(scores) / len(scores)) * w

wsum += w

return round(total / wsum, 2) if wsum else 0.0

```

常见坑与排错

AI 出的题全是"你会怎么设计一个 XXX"

这是模型偷懒的默认姿势。这类问题候选人可以凭想象回答,面试官无法验证真假。在 prompt 里明确禁止假设句,并加一条"题干里必须出现'请讲一次''描述一个你亲自参与的'这类引导语"。

评分标准写成"优秀 / 良好 / 一般"

同样要在 prompt 里硬性约束:"每档锚点必须包含至少一个动作动词或可量化结果"。生成后可以用脚本扫一遍,出现"清晰""深入""优秀"等词就标红。

JSON 解析老失败

常见原因是模型输出被 token 上限截断,或者前面加了一段解释文字。应对方式:要求只输出 JSON;开启 JSON 输出模式;把单次生成的题目数降到 5 到 8 道;解析失败时重试而不是硬解析。

题目之间高度重复

分批生成时务必把已有题干回传给模型;生成完再跑一次相似度检查。同一个维度下相似度超过阈值的,保留分更高的那道。

难度全部堆在中间

在 prompt 里显式给出分布要求,比如"难度 1-5 的题目数量分别为 1、2、2、1、0"。

把 AI 的答案要点当成标准答案

模型对具体技术事实可能存在错误表述。评分锚点里如果涉及具体协议、具体算法细节,必须由懂这个领域的评审人核对。一份标注"待评审"的题库,比一份看起来完备但没人看过的题库安全得多。

合规问题漏网

建一个关键词黑名单(婚育、年龄、籍贯、宗教等),生成后自动扫一遍,再人工过一遍。这一步不能省。

下一步建议

做版本管理。题库按岗位和级别分目录,每次改动留记录。面试官反馈某道题问不出东西,能追溯到是哪一版加的。

接向量检索去重。题目数量上到几百道以后,字符串相似度就不够用了。把题干转成向量存进向量库,新增题目先做一次近邻检索。

把评分表接进面试记录。面试官当场在表格里打分、填备注,数据自然沉淀下来,第 7 步的统计就不用再手工整理。

做面试官打分校准。找一段录制的模拟回答,让几位面试官各自打分,看彼此偏差有多大。偏差大的维度,回头改评分锚点。

扩展到其他题型。同一套结构可以套到笔试题、案例分析题、take-home 作业的评分表上。真正通用的不是题目,是"可观察行为 + 分档锚点"这套写法。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。