
1. 一次反直觉的评测结果当匹配分和人工判断背道而驰28 条 JD跑完 Agent 匹配打分再拉人工逐条评估最后算出来的 Spearman 相关系数是ρ -0.085。这个数字第一次出现在我面前的时候我盯着屏幕看了大概十秒钟脑子里只有一个念头要么数据错了要么我的 Agent 彻底跑偏了。ρ 接近 0 意味着两套排序几乎不相关而 -0.085 这个负值更微妙——它不是说“完全随机”而是隐约透出一种“越匹配的反而人工越不买账”的倾向。做过 LLM 应用评测的人都知道这种结果比直接报错还难受因为报错至少告诉你哪里断了而负相关是在说你精心设计的 Agent 匹配逻辑可能从一开始就在优化一个错误的目标。这篇文章不打算给你一个“标准答案”因为我自己也是在反复拆解这 28 条数据、重跑了好几轮 Prompt 之后才慢慢摸清楚问题出在哪。我会把整个评测的设计思路、Spearman 相关性分析的具体做法、Agent 匹配分的生成逻辑、以及最后定位到的几个核心坑点全部摊开来讲。如果你正在做 Agent 匹配、JD 解析、LLM 打分排序这类事情或者你手上也有一批“模型觉得很好但人觉得不行”的案例这篇应该能帮你少走一些弯路。先说清楚适用人群你需要对 LLM 的基本调用有概念知道什么是 Prompt、什么是结构化输出最好自己跑过一两个 Agent 项目。完全没接触过 LLM 的读者也能看懂思路但具体操作部分可能需要补一些前置知识。全文会围绕“为什么会出现负相关”这个核心问题展开而不是泛泛地讲 Agent 怎么做。2. 评测设计28 条 JD 和两套打分体系是怎么搭起来的2.1 为什么选 28 条 JD 而不是 100 条样本量的选择其实很讲究。我一开始想的是搞 100 条 JD数据量大、统计上更稳。但实际操作下来发现两个问题第一人工评估的成本太高100 条 JD 每条都要仔细读、逐项打分一个人做完至少要四五个小时中间注意力衰减严重后面的打分质量明显下降第二JD 的多样性比数量更重要28 条已经覆盖了技术、产品、运营、设计、数据五个方向每个方向 5 到 6 条基本能反映不同岗位类型的匹配特征。28 这个数字还有一个好处它足够小可以让我对每一条 JD 的匹配结果都做深度复盘。如果是一百条我可能只会看几个极端案例就下结论了。28 条的话每一条的分数、人工评语、Agent 输出我都能对一遍这对定位问题非常关键。提示做小样本评测时样本的“代表性”比“数量”重要得多。与其堆 100 条同质化 JD不如精心挑 30 条覆盖不同岗位类型、不同技能要求、不同经验层级的样本。2.2 Agent 匹配分的生成逻辑Agent 这边的匹配分我用的是一套比较典型的两阶段流程。第一阶段是 JD 解析把每条 JD 拆成结构化的字段岗位名称、核心技能要求、加分项、经验年限、学历要求、软技能关键词。第二阶段是候选人画像匹配把候选人的简历信息也做同样的结构化处理然后逐字段计算匹配度最后加权汇总成一个 0 到 100 的匹配分。具体来说技能匹配占 40% 权重经验年限占 20%学历占 10%软技能占 15%行业背景占 15%。这个权重分配是我根据常见招聘优先级拍的没有做严格的回归分析这也是后面出问题的一个隐患。Prompt 的设计大概是这样的MATCH_PROMPT 你是一个专业的招聘匹配助手。请根据以下 JD 要求和候选人信息计算匹配分数。 JD 信息 {jd_structured} 候选人信息 {candidate_structured} 请按以下维度打分每项 0-100 1. 技能匹配度候选人技能与 JD 要求的重合程度 2. 经验匹配度工作年限和项目经验的相关性 3. 学历匹配度学历背景是否符合要求 4. 软技能匹配度沟通、协作、领导力等 5. 行业匹配度过往行业与目标行业的相关性 输出 JSON 格式 {{skill_score: ..., experience_score: ..., education_score: ..., soft_skill_score: ..., industry_score: ..., total_score: ...}} 这个 Prompt 看起来没什么问题结构清晰、维度明确、输出格式也定义好了。但问题恰恰藏在这些“看起来没问题”的地方后面会详细拆。2.3 人工判断的评估标准人工这边我设计了一个五级量表1 分表示完全不匹配2 分表示不太匹配3 分表示一般4 分表示比较匹配5 分表示非常匹配。评估的时候不看 Agent 的分数避免锚定效应。每条 JD 我会先读一遍然后看候选人信息凭直觉给一个分再回头逐项检查有没有遗漏的关键点最后定分。为了减少个人偏见我还找了另一位同事独立评了一遍两个人不一致的地方拿出来讨论最终取共识分。28 条 JD 里有 6 条出现了明显分歧讨论之后有 4 条达成了共识剩下 2 条保留了两人的平均分。人工评估最大的挑战是“标准漂移”。前 10 条的时候我打分比较严格中间 10 条开始放松最后 8 条又因为疲劳变得随意。后来我强制自己每评 5 条就休息 10 分钟并且把评分标准打印出来放在旁边每评一条都对照一遍才把漂移控制住。2.4 Spearman 相关系数的计算过程Spearman 相关系数衡量的是两组排序之间的单调关系不要求线性假设适合这种“分数排序”的场景。计算步骤不复杂把 Agent 匹配分从高到低排序得到每个 JD 的排名把人工评分也从高到低排序得到对应的排名对每个 JD计算两个排名的差值 d代入公式 ρ 1 - (6 * Σd²) / (n * (n² - 1))我用 Python 的 scipy 库直接算的from scipy.stats import spearmanr agent_scores [85, 72, 91, 63, 78, ...] # 28 个 Agent 匹配分 human_scores [3, 4, 2, 5, 3, ...] # 28 个人工评分 rho, p_value spearmanr(agent_scores, human_scores) print(fSpearman rho: {rho:.3f}, p-value: {p_value:.3f})跑出来 rho -0.085p 值 0.667。p 值这么大意味着这个负相关在统计上并不显著换句话说我们不能说“Agent 和人工判断存在显著的负相关”只能说“两者之间没有检测到显著的正相关”。这个区别很重要因为如果 rho 是 -0.6 且 p 0.01那就是另一个性质的问题了。但即便统计上不显著-0.085 这个方向性仍然值得警惕。它至少说明 Agent 的排序和人工的排序之间没有任何有意义的正向关联这在一个“匹配”任务里是不可接受的。3. 拆解负相关五个可能的原因和逐一排查过程3.1 原因一Agent 在优化“字面匹配”而非“实质匹配”这是我最先怀疑的方向。Agent 做技能匹配的时候本质上是在做关键词重合度计算。JD 里写了“熟悉 Python、有数据分析经验”候选人简历里也有“Python”和“数据分析”Agent 就给高分。但人工看的时候会判断这个候选人的 Python 是用来做爬虫的数据分析是做报表的跟 JD 要的“用 Python 做统计建模”根本不是一回事。我挑了几条典型 JD 做验证。有一条 JD 是“数据科学家要求熟悉 A/B 测试、因果推断、Python 统计建模”候选人简历里写了“熟练使用 Python 进行数据清洗和可视化参与过 A/B 测试”。Agent 给了 82 分技能匹配度打了 90。但人工只给了 2 分因为候选人的 A/B 测试经验是“参与”而非“主导”而且没有因果推断的任何痕迹Python 统计建模更是完全没提。这就是典型的“字面匹配陷阱”。Agent 看到关键词就给分但人工会判断关键词背后的深度和相关性。3.2 原因二权重分配拍脑袋没有数据支撑前面提到我的权重是技能 40%、经验 20%、学历 10%、软技能 15%、行业 15%。这个分配完全是我凭感觉定的。实际跑下来发现学历和行业这两项在很多 JD 里根本不应该占那么高权重。比如有一条运营岗 JD明确写了“不限学历看重实操能力”但 Agent 还是按 10% 的权重给学历打分导致一个学历一般但实操经验丰富的候选人被拉低了总分。人工评估的时候学历这一项直接忽略给了高分。这一条的分差直接贡献了不小的排名差异。我后来做了一个简单的敏感性分析把学历权重从 10% 降到 0%把技能权重从 40% 提到 50%重新算了一遍 Spearmanrho 从 -0.085 变成了 0.12。虽然还是不高但至少方向转正了。这说明权重分配确实是一个影响因素但不是唯一因素。3.3 原因三Prompt 里的“打分维度”引导了错误注意力回头看我那个 Prompt五个维度技能、经验、学历、软技能、行业。这个框架本身没问题但问题在于每个维度的描述太笼统。“技能匹配度候选人技能与 JD 要求的重合程度”——什么叫“重合程度”是关键词重合还是能力重合还是项目经验重合LLM 拿到这种模糊描述最自然的反应就是做关键词匹配。而且五个维度并列打分LLM 会倾向于“每个维度都给一个中庸的分数”导致最终总分趋同。我看了 28 条 JD 的 Agent 总分分布标准差只有 8.3而人工评分的标准差是 1.2五级量表。Agent 的分数集中度太高区分度不够排序自然就和人工对不上。后来我把 Prompt 改成了“先判断候选人是否满足硬性门槛不满足直接给低分满足门槛后再按技能深度、项目相关性、经验匹配度三个维度打分”Agent 分数的标准差提升到了 14.6和人工的相关性也明显改善。3.4 原因四人工评估的“整体直觉” vs Agent 的“分项加总”人工评估的时候我发现自己经常是“先有整体判断再拆解原因”。看到一份简历前几行就能感觉到“这个人行不行”然后再去找证据支撑这个判断。而 Agent 是反过来的先算分项再加总。这两种认知路径的差异会导致系统性的排序偏差。举个例子有一条 JD 要求“有从 0 到 1 搭建数据平台的经验”。候选人 A 的各项技能都匹配但没有 0 到 1 的经验候选人 B 技能匹配度稍低但有完整的 0 到 1 经历。Agent 给 A 打了 78给 B 打了 74。但人工评估时B 的“0 到 1”经历是一个强信号直接给了 4 分A 只给了 3 分。这种“关键经历一票定乾坤”的判断Agent 的分项加总模型很难捕捉。3.5 原因五样本量小 评分粒度粗放大了噪声28 条 JD 做 Spearman 分析统计功效本身就不高。再加上人工评分是五级量表粒度很粗很多 JD 的人工分集中在 3 分和 4 分排序信息量有限。Agent 分数虽然是 0 到 100但实际分布也很集中。两组都缺乏区分度的数据做相关性分析结果很容易被少数几条极端案例带偏。我试过把人工评分改成 10 级量表重新评了一遍rho 变成了 0.05虽然还是接近 0但至少不是负的了。这说明评分粒度确实有影响但核心问题还是在于 Agent 和人工的判断逻辑不一致。4. 重跑与优化从 ρ-0.085 到 ρ0.43 的实操记录4.1 第一步重构 Prompt从“分项打分”到“门槛 深度”原来的 Prompt 是五个维度并列打分改版之后变成了三段式MATCH_PROMPT_V2 你是一个资深招聘专家。请按以下步骤评估候选人匹配度 第一步硬性门槛检查 - JD 中是否明确要求了学历、年限、证书等硬性条件 - 候选人是否满足这些硬性条件 - 如果不满足直接输出 total_score 为 20 分以下并说明原因。 第二步核心能力深度评估 - 针对 JD 中列出的每一项核心技能判断候选人是“精通”、“熟练”、“了解”还是“无经验”。 - 精通 90-100 分熟练 70-89 分了解 50-69 分无经验 0-49 分。 - 取所有核心技能得分的加权平均权重按 JD 中技能出现的顺序递减。 第三步关键经历匹配 - JD 中是否提到“从 0 到 1”、“主导”、“独立负责”等关键词 - 候选人是否有对应的经历有则加 10 分无则不加分。 输出 JSON 格式 {{gate_check: pass/fail, skill_scores: {{...}}, key_experience_bonus: ..., total_score: ...}} 这个改版的核心变化是把“硬性门槛”单独拎出来不满足直接压分技能评估从“重合度”改成“深度分级”增加了“关键经历加分项”。改完之后Agent 分数的区分度明显提升和人工评分的 rho 从 -0.085 提升到了 0.31。4.2 第二步用少量标注数据校准权重Prompt 改完之后我没有继续拍脑袋定权重而是拿 10 条 JD 做了人工标注然后用一个简单的网格搜索找最优权重组合。具体做法是对每条 JD人工给出每个维度的分数技能、经验、学历、软技能、行业用不同的权重组合计算总分看哪个组合和人工总分的 Spearman 最高在最优组合附近再做精细搜索最后找到的权重是技能 55%、经验 25%、学历 5%、软技能 10%、行业 5%。这个结果和我的直觉差别很大——学历和行业的权重被大幅压缩技能的权重被提高。用这个权重重新跑 28 条 JDrho 提升到了 0.38。注意权重校准一定要用独立于评测集的数据。我是从另外 10 条 JD 里做的标注避免过拟合到 28 条评测集上。4.3 第三步引入“对比排序”代替“绝对打分”绝对打分有一个天然缺陷LLM 对分数的校准能力很差同样一份简历今天打 75明天可能打 80。而排序任务相对更稳定。所以我尝试了一种新方法不直接给每个候选人打分而是让 Agent 对同一 JD 下的多个候选人做两两对比输出“A 比 B 更匹配”的判断然后用 Elo 评分系统算出每个人的相对分数。具体做法是COMPARE_PROMPT 请比较以下两位候选人与目标 JD 的匹配程度。 JD{jd_text} 候选人 A{candidate_a} 候选人 B{candidate_b} 请判断谁更匹配并说明理由。输出格式 {{winner: A or B, reason: ...}} 对每个 JD 下的候选人做多轮两两对比然后用 Elo 算法更新分数。这个方法跑下来rho 提升到了 0.43是目前最好的结果。而且我发现对比排序对 Prompt 的敏感度更低换几种不同的问法结果都比较稳定。4.4 优化前后的关键指标对比指标优化前优化后Spearman rho-0.0850.43Agent 分数标准差8.316.2人工-Agent 排序一致对数9/2819/28极端误判案例数62Prompt 稳定性重跑 3 次方差高低这个对比不是说 0.43 就万事大吉了。0.43 只能算“中等相关”离“高度一致”还有距离。但至少方向对了而且我知道继续优化的方向在哪里一是增加标注数据做更细的权重校准二是把对比排序和绝对打分结合起来用。5. 常见问题与排查技巧实录5.1 Agent 匹配分和人工判断相关性低先查什么遇到 rho 接近 0 或者为负不要急着改 Prompt。先按这个顺序排查检查数据对齐Agent 分数和人工评分是不是一一对应的有没有错位我一开始就犯过这个错把两条 JD 的分数搞反了导致 rho 算出来是负的。看分数分布Agent 分数的标准差是不是太小如果所有分数都挤在 70 到 85 之间排序信息量本身就不够。看极端案例挑出 Agent 给高分但人工给低分的案例逐条分析原因。通常看 5 条就能发现系统性问题。检查人工评分的一致性如果两个人独立评分的相关性都很低那说明人工标准本身就不稳定先解决人工评估的标准化问题。5.2 Prompt 改了但效果不稳定怎么办LLM 的输出本身就有随机性。同一个 Prompt 跑三次结果可能不一样。我的做法是把 temperature 调到 0 或 0.1减少随机性对每个 JD 跑三次取中位数作为最终分数如果三次结果的方差很大说明 Prompt 本身有歧义需要进一步明确还有一个技巧在 Prompt 里加入“请先思考再打分”的指令让 LLM 输出推理过程然后再给分数。这样虽然 token 消耗多一些但分数的稳定性会明显提升。5.3 人工评估标准漂移怎么控制人工评估最大的敌人是疲劳和标准漂移。我的经验是每评 5 条休息 10 分钟不要连续评超过 30 条把评分标准打印出来每评一条对照一遍找第二个人独立评一遍不一致的地方讨论达成共识如果条件允许把评估顺序随机打乱避免同一类 JD 连续评导致的锚定效应5.4 样本量太小Spearman 结果不可靠怎么办28 条确实偏少。如果条件允许建议至少 50 条。但如果只能做小样本可以用 Bootstrap 方法重采样计算 rho 的置信区间不要只看 rho 的绝对值要看 p 值和置信区间把排序一致性作为辅助指标比如“Top 5 匹配的 JD 中Agent 和人工重合了几个”5.5 常见问题速查表问题现象可能原因排查方法解决方向rho 接近 0 或为负数据错位、分数区分度低、判断逻辑不一致检查数据对齐、看分数分布、分析极端案例重构 Prompt、校准权重、改用对比排序Agent 分数集中Prompt 引导中庸打分、维度权重不合理看标准差、看各维度分数分布引入门槛机制、调整权重、增加区分度人工评分不一致标准漂移、评估疲劳、标准模糊双人独立评估、计算评分者间信度明确评分标准、控制评估节奏、定期校准Prompt 效果不稳定temperature 过高、Prompt 有歧义重跑三次看方差降低 temperature、增加推理步骤、明确输出格式极端误判多字面匹配陷阱、关键经历被忽略逐条分析误判案例增加深度评估、引入关键经历加分项6. 几个我踩过的坑和最后的小建议第一个坑是“用 Agent 分数直接做排序”。我一开始觉得 Agent 给了 0 到 100 的分数直接按分数排序就行了。但实际上 LLM 给的绝对分数校准很差同样水平的候选人在不同 JD 下拿到的分数可能差 20 分。后来我改成“同一 JD 下做相对排序”问题才解决。第二个坑是“忽略 JD 本身的质量”。有些 JD 写得非常模糊比如“要求有较强的沟通能力”这种描述人工评估的时候都很难判断更别说 Agent 了。后来我在评测前先做了一轮 JD 质量筛选把过于模糊的 JD 剔除掉剩下的 JD 要求都比较具体Agent 和人工的一致性也提高了。第三个坑是“过度依赖 Spearman”。Spearman 只衡量排序相关性不衡量绝对分数的一致性。有时候 rho 不高但 Agent 在关键决策上比如“是否进入面试”和人工是一致的。所以后来我加了一个辅助指标Top N 匹配的一致性。比如 Agent 排前 5 的 JD 里人工也排前 5 的有几个。这个指标比单纯的 rho 更贴近实际使用场景。最后分享一个小技巧如果你也在做 Agent 匹配评测建议把“人工评估”和“Agent 评估”的原始数据都保留下来包括每条 JD 的文本、候选人的信息、Agent 的完整输出、人工的评分和评语。这些数据在后续优化的时候非常有用尤其是当你需要做错误分析的时候没有原始数据就只能凭记忆猜效率很低。这个项目后续还可以往几个方向扩展一是把对比排序和绝对打分结合起来用对比排序做粗排用绝对打分做精排二是引入更多维度的评估比如候选人的成长潜力、文化匹配度三是把评测流程自动化减少人工评估的工作量。不过这些都是后话了先把当前这套流程跑稳再说。