Resume screener
BOSS 直聘 HR 智能体工具箱,基于 boss-agent-cli 的简历筛选全流程自动化
npx -y skills add 1xiaoyueryuer/boss-hr-agent-toolkit --skill resume-screenerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 16 stars16 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
简历筛选与评分系统(boss-hr-auto 工作流的 Step 3)。LLM 评 4 维度最终分(exp/skill/proj/major)+ 脚本查 school_tier 校准 edu + 公式重算 total。 **本 Skill 是 boss-hr-auto 编排流程的子步骤,通常由 boss-hr-auto 在 Step 3 阶段调用,不应作为入口 Skill 直接加载。** **唯一方案**:5 维度 weighted 求和(edu 25% / exp 25% / skill 25% / proj 15% / major 10%),Tier 阈值 ≥70 推荐 / 60-69 待定 / <60 不推荐。
SKILL.md
16.2 KB, as published. Nobody here has run it
Resume Screener
评分架构
- LLM 评 4 维度最终分:
exp / skill / proj / major全部由 LLM 真实分析完整简历后给出 0–100 的最终分(已综合考虑年限、对口度、实操深度、复杂度等) - 脚本只覆盖 1 维度:用
scripts/school_tier.py查表覆盖edu - 公式重算:5 维度 × 权重 = total(按 25/25/25/15/10)
- Tier 判定:≥70 推荐 / 60-69 待定 / <60 不推荐
- 通用:不限岗位(任一 JD 都能用)
LLM 不输出
industry_fit之类的系数标签。exp分本身已综合考虑对口度,脚本不会再乘任何系数。
核心不变量
| 项 | 值 |
|---|---|
| 5 维度权重 | edu 25% / exp 25% / skill 25% / proj 15% / major 10% |
| Tier 阈值 | 推荐 ≥70 / 待定 60-69 / 不推荐 <60 |
| 公式 | total = Σ (raw × weight) |
| Tier 名称 | 推荐 / 待定 / 不推荐 |
| 学校分档 | 7 档(C9 / 985 / 211 / 双一流 / 一本公办 / 二本公办 / 民办) |
| 评分主体 | LLM 评 4 维度最终分 + 脚本查 edu(仅此一套) |
工具脚本
scripts/score_resumes.py
工具函数(agent 直接 import 调用):
| 函数 | 作用 |
|---|---|
_extract_school_name(score) | 智能拆纯校名(优先 school_name,兜底从 school 按 /·(( 拆分) |
validate_score(score) | LLM 评分收尾:用 school_tier 覆盖 edu + 重算 weighted + total + 判定 tier |
calc_tier(total) | ≥70 推荐 / 60-69 待定 / <60 不推荐 |
calc_weighted(dims) | 5 维度 × 权重 |
calc_total(weighted) | 求和 |
candidate_to_report(c, rank) | list 元素 → candidates[] 格式 |
build_actions(candidates) | 生成 actions 三段式(recommend/pending/reject) |
build_meta(job_name, job_info) | 构造报告 meta |
CLI:
python score_resumes.py --input <llm_scores.json> \
--output <screening_results.json> \
--job-name "车架工程师" \
--job-info <JD JSON 字符串>
scripts/school_tier.py
from school_tier import lookup
info = lookup("辽宁工业大学")
# → {"tier": "二本公办", "score": 62, "matched": "辽宁工业大学", "fuzzy": False}
info = lookup("江南大学")
# → {"tier": "211", "score": 85, "matched": "江南大学", "fuzzy": False}
支持精确匹配 + 模糊匹配(输入校名是表内校的子串或父串时也能命中)。
分批策略
按 boss-recommend-downloader 的下载批次逐批评分,每批独立写文件、最后合并。
- 批次大小:默认每批 25 份(下载侧默认
--batch-size 25) - 单批内部小批:若 25 份简历偏长或 JD 复杂,LLM 内部可按 10 份/次再分小批循环处理,结果合并到同一个
_llm_scores_batch_N.json - 中途容错:单批评分失败不影响其他批;可重跑该批
完整工作流
# === Step 3a: 逐批评分(与下载批次对齐)===
# 假设已有 batch_1_resumes.json / batch_2_resumes.json / ...(来自 boss-recommend-downloader)
# 对每批简历:
for batch_n in 1 2 3 ...:
# 1. LLM 读 batch_n_resumes.json + JD
# 2. LLM 真实分析每份简历,评 4 维度最终分(exp / skill / proj / major)
# — 单批 25 份时,可内部按 10 份/次循环
# 3. 对每份评分,agent 调 validate_score(score) 收尾:
# - 自动从 score 拆出纯校名
# - 自动用 school_tier 查 edu(强制覆盖 LLM 凭印象打的分数)
# - 自动重算 weighted + total(按公式)
# - 自动判定 tier
# 4. 写出 _llm_scores_batch_${batch_n}.json
# === Step 3b: 合并所有批次 ===
# 方式 1(推荐):LLM agent 在内存里把所有 batch 的 _llm_scores_batch_*.json
# 拼成一个 list,写 _llm_scores.json
# 方式 2:跑 python -c "import json,glob; json.dump(sum([json.load(open(f,encoding='utf-8')) for f in sorted(glob.glob('_llm_scores_batch_*.json'))], []), open('_llm_scores.json','w',encoding='utf-8'), ensure_ascii=False, indent=2)"
# === Step 3c: 跑评分脚本 ===
python score_resumes.py --input _llm_scores.json \
--output screening_results.json \
--job-name "车架工程师" \
--job-info <JD JSON 字符串>
# === Step 4: 生成 HTML 报告 ===
python generate_html_report.py --input screening_results.json --output <job_name>_统一方案.html
preview_url 在 IDE 内置浏览器打开
工作区路径约定
所有数据统一存放在 ~/Desktop/boss-hr-output/<job_name>/ 下,由 shared/output_manager.JobOutputManager 管理。
~/Desktop/boss-hr-output/<job_name>/
├── process/
│ ├── job_detail.json ← Step 1: boss_jd.py 输出
│ ├── recommend_geek_ids.json ← Step 2: recommend_list.py 输出
│ ├── batch_N_resumes.json ← Step 2: recommend_download.py 输出(每批)
│ ├── test_resumes.json ← Step 2: 累计所有已下载简历
│ ├── _llm_scores_batch_N.json ← Step 3: LLM agent 评分(每批,可选)
│ ├── _llm_scores.json ← Step 3: 合并后的全量评分(喂给 score_resumes.py)
│ └── screening_results.json ← Step 3: score_resumes.py 输出
└── <job_name>_统一方案.html ← Step 4: generate_html_report.py 输出
上游
boss-job-detail/boss-recommend-downloader已自动写入此目录,下游脚本(score_resumes.py/generate_html_report.py)通过--input/--output读取此目录。
JobOutputManager提供的标准路径属性:jd_path/recommend_geek_ids_path/resumes_path/screening_results_path/report_path。
LLM 评分输入 schema
[
{
"name": "陈瀚",
"school": "辽宁工业大学/车辆工程/本科",
"work_years": "3 年",
"match_type": "山东浩信 · 汽车零部件三维设计",
"dims": {
"exp": 80,
"skill": 65,
"proj": 60,
"major": 100
},
"highlights": ["3 年 CATIA", "2 项发明专利"],
"concerns": ["做的是轮端非车架"],
"advice": "强烈建议电话沟通..."
}
]
字段说明:
| 字段 | 必填 | 说明 |
|---|---|---|
name | 是 | 候选人姓名 |
school | 是 | 校名(脚本自动拆出纯校名) |
work_years | 否 | 工作年限 |
match_type | 否 | 当前岗位 / 业务方向 |
dims.exp | 是 | LLM 评 0-100 最终分(工作经验:综合年限 + 对口度 + 实操深度) |
dims.skill | 是 | LLM 评 0-100 最终分(专业技能) |
dims.proj | 是 | LLM 评 0-100 最终分(项目经历) |
dims.major | 是 | LLM 评 0-100 最终分(专业匹配) |
dims.edu | 否 | 会被 validate_score 强制覆盖 |
school_name | 否 | 备选字段,优先级高于 school 拆分 |
highlights | 否 | 候选人亮点(推荐动作背景) |
concerns | 否 | 候选人顾虑(不推荐原因 / 待确认问题) |
advice | 否 | 个性化建议(推荐/待定动作方向) |
注意:
- 4 个 LLM 评分维度全部是最终分(0-100),脚本不会再做任何乘法 / 折扣
school字段允许任意格式,脚本智能拆出纯校名(支持/ · ( (等分隔符)- LLM 不要评
edu,会强制被school_tier覆盖
5 维度评分方法(理工类通用)
适用于一切工程/技术岗(机械、车辆、电子、材料、自动化、化工、土木、软件等)。LLM 评分时结合具体 JD 的核心技能清单与方向,按本表锚点给 0–100。所有维度给的都直接是最终分。
| 维度 | 权重 | 评分方 | 评分主体 |
|---|---|---|---|
| 学历 | 25% | school_tier 查表(校名→档次分);可选本/硕/博层次加成 | 脚本(强制) |
| 工作经验 | 25% | 综合考虑工作年限 + 与 JD 对口度 + 实操深度,给最终分 | LLM |
| 专业技能 | 25% | JD 核心技能覆盖度 × 实操深度 | LLM |
| 项目经历 | 15% | 项目与岗位的相关度 × 复杂度 × 角色 | LLM |
| 专业匹配 | 10% | 专业与 JD 的对口度(优先/相关/弱相关/无关) | LLM |
维度评分锚点
① 学历 edu(脚本查表,LLM 不评)
- 分数取
school_tier:C9=100 / 985=92 / 211=85 / 双一流=77 / 一本公办=71 / 二本公办=62 / 民办=53 - 表外学校:edu 显示"缺失",建议人工复核(可给默认 60 并标"需复核")
- (可选扩展)层次加成:硕士 +8、博士 +12,封顶 100——由脚本读
degree字段实现
② 工作经验 exp(LLM 评最终分 0–100)
LLM 在评 exp 时综合以下 3 个因素,给一个最终分:
- 工作年限(参考锚点):
- ≥8 年 = 95 / 5–7 年 = 85 / 3–4 年 = 75 / 1–2 年 = 60 / <1 年 = 45
- 与 JD 对口度(参考锚点,已并入最终分):
- 精准对口(与 JD 核心方向完全一致)= 不折扣
- 行业相关但非精准(测试/工艺/验证/零部件/相近子领域)= 视情况打 0.7×基础分附近
- 完全跨行业(纯销售/行政/文科背景)= 视情况打 0.4×基础分附近
- 实操深度(参考锚点):
- 能独立负责核心模块 + 有可验证产出 = 锚点 +5
- 仅参与执行 / 无量化成果 = 锚点 −5
以上三因素LLM 在打分时一次性综合考虑,直接给出最终分。脚本不参与任何乘法。
③ 专业技能 skill(LLM 评最终分 0–100)
- 按 JD 列出的核心技能清单评估"覆盖度 × 熟练度":
- 全覆盖且能独立负责核心模块 = 85–100
- 核心技能 70%+ 且较熟 = 70–84
- 覆盖 40–70% 或仅部分了解 = 55–69
- 覆盖 <40% 或仅字面提及 = 40–54
- 有 JD 硬性要求但不会的"硬伤":该档下限再 −10
④ 项目经历 proj(LLM 评最终分 0–100)
- 按"与 JD 岗位的相关度 + 复杂度 + 担任角色":
- 主导本岗核心项目(0–1 设计/量产落地)= 85–100
- 重要角色参与核心项目 = 70–84
- 边缘/支持角色、或项目仅部分相关 = 55–69
- 非相关但体现工程能力 = 40–54
- 无可验证项目 / 完全无关 = <40
⑤ 专业匹配 major(LLM 评最终分 0–100)
- 以 JD 要求的对口专业为"优先"基准,按专业大类映射(理工类通用):
- 优先=100:JD 直接点名的对口专业(随岗而定,如机械设计/车辆工程/材料成型/自动化/电子/化工等)
- 相关=80:同大类工科(机械类、车辆类、材料类、自动化/机电、土木、化工、计算机偏硬等相近领域)
- 弱相关=60:基础/交叉学科(力学、数学、物理、计算机偏软、工业工程等)
- 无关=40:文科、经管、艺术、生化医药等非工程背景
- 跨专业但有扎实对口课程 + 项目经历的,按"相关"档处理
评分公式
单维度加权分 = 原始分 (0-100) × 该维度权重
总分 = Σ(所有维度加权分)
示例 A(精准对口,3 年结构设计):
edu=62, exp=80, skill=65, proj=60, major=100
→ 62×0.25 + 80×0.25 + 65×0.25 + 60×0.15 + 100×0.10
→ 15.5 + 20.0 + 16.25 + 9.0 + 10.0 = 70.75 → "推荐"(≥70)
示例 B(行业相关非精准对口,3 年结构测试):
LLM 综合评估后直接给 exp 最终分 = 56(已包含"年限 75 × 对口度 0.7 ≈ 53" 的折扣判断)。
edu=62, exp=56, skill=65, proj=60, major=100
→ 62×0.25 + 56×0.25 + 65×0.25 + 60×0.15 + 100×0.10
→ 15.5 + 14.0 + 16.25 + 9.0 + 10.0 = 64.75 → "待定"(≥60)
Tier 判定
def calc_tier(total):
if total >= 70: return "推荐"
if total >= 60: return "待定"
return "不推荐"
学校分档表(脚本内置,500+ 学校)
| 档次 | 分数 | 示例学校 |
|---|---|---|
| C9 | 100 | 清华、北大、复旦、交大、浙大、中科大、南大、哈工大、西交 |
| 985 | 92 | 其他 30 所 985 高校 |
| 211 | 85 | 非 985 的 211 高校(如江南大学、苏州大学、华东理工) |
| 双一流 | 77 | 南方科技大学、上海科技大学、中国科学院大学 |
| 一本公办 | 71 | 深圳大学、广东工业大学、西安理工大学、杭州电子科技大学 |
| 二本公办 | 62 | 辽宁工业大学、信阳农林学院、太原工业学院、滁州学院、长江师范学院 |
| 民办/独立学院 | 53 | 燕京理工学院、黄河科技学院、郑州工商学院、四川工业科技学院 |
完整 500+ 学校列表见
scripts/school_tier.py。 不在表内的学校:返回score=None,edu 维度显示"缺失(XX 不在学校表)"。
LLM 评分调用示例
from score_resumes import validate_score
score = {
"name": "陈瀚",
"school": "辽宁工业大学/车辆工程/本科",
"work_years": "3 年",
"match_type": "山东浩信 · 汽车零部件三维设计",
"dims": {
"exp": 80, # LLM 评最终分
"skill": 65, # LLM 评最终分
"proj": 60, # LLM 评最终分
"major": 100 # LLM 评最终分
# edu 不需要填
},
"highlights": ["3 年 CATIA 三维设计", "2 项发明专利"],
"concerns": ["做的是轮端非车架本体", "无 CAE 仿真经验", "无焊接/工艺经验"],
"advice": "专业对口 + 设计经验真实,建议电话沟通是否有车架/底盘结构项目经验"
}
score = validate_score(score)
# → score["dims"]["edu"] = 62(二本公办,school_tier 查表)
# → score["total"] = 69.8
# → score["tier"] = "待定"
# → score["dims_edu_reason"] = "二本公办(school_tier 查询:辽宁工业大学)"
输出 schema(screening_results.json)
{
"job_name": "车架工程师",
"meta": {
"title": "车架工程师 · 简历筛选报告",
"subtitle": "LLM 主导评分 + school_tier 学历分档校准",
"job": {
"name": "...",
"company": "...",
"location": "...",
"salary": "...",
"experience_required": "...",
"degree_required": "..."
},
"type_judgment": {"type": "技术岗", "reason": "..."},
"core_requirements": ["..."]
},
"summary": {"total": 32, "recommend": 0, "pending": 2, "reject": 30},
"dimension_labels": ["学历", "工作经验", "专业技能", "项目经历", "专业匹配"],
"candidates": [
{
"rank": 1,
"name": "陈瀚",
"tier": "待定",
"total": 69.8,
"school": "辽宁工业大学/车辆工程/本科",
"work_years": "3年",
"current_role": "汽车零部件三维设计(轮端)",
"dimensions": [
{
"pct": 62,
"weighted": 15.5,
"weight": 25,
"reason": "二本公办(school_tier 查询:辽宁工业大学)"
}
],
"highlights": ["..."],
"concerns": ["..."]
}
],
"actions": {
"recommend": [{"name", "score", "background", "action"}],
"pending": [{"name", "score", "strengths", "action"}],
"reject": [{"name", "score", "concerns"}]
}
}
注意事项
- LLM 评 4 维度时务必读完完整简历再打分,避免"看一半就判断"
- 测试 / 设计 / 验证 / 仿真等职能差异要识别(如底盘电控功能测试 ≠ 车架结构设计)
- 学校档次 / tier 阈值 / 公式权重都由脚本控制,LLM 不要尝试覆盖
- exp 维度给的分数就是最终分,不要再额外标 industry_fit / 对口度系数,这些已经综合在 exp 分里了
- highlights / concerns / advice 是个性化建议的核心,必须基于候选人实际经历