---
name: resume-screener
version: 1.0.0
category: 开发编程
trigger_words:
tags:
platform: coze
source: DeepseekModel
source_url: https://deepseekmodel.com/skill?id=1xiaoyueryuer-boss-hr-agent-toolkit-resume-screener-skill-md
---

name resume-screener description 简历筛选与评分系统的**实现参考**。LLM 评 4 维度最终分（exp/skill/proj/major）+ 脚本查 school_tier 校准 edu + 公式重算 total。 **本 Skill 不是工作流入口**。通用智能体应只通过 [boss-hr-auto](../boss-hr-auto/SKILL.md) → 统一 CLI `boss-hr score` 调用。 本文档保留作为：评分规则参考 / LLM 提示词片段来源 / 算法实现文档。 **唯一方案**：5 维度 weighted 求和（edu 25% / exp 25% / skill 25% / proj 15% / major 10%），Tier 阈值 ≥70 推荐 / 60-69 待定 / <60 不推荐。 Resume Screener 🔁 跨 run 评分去重（脚本自动执行） score_resumes.py 自带去重， 智能体不需要手工过滤已评分候选人 ： 入口 ：按 job_id:geek_id 查 state/scored_state.json ，历史评过的自动跳过 出口 ：本轮评分结果自动回写 scored_state.json 逃生门 ： --rescore 强制重评（换 JD、改评分口径时用） # 正常评分（自动跳过历史已评人员） python score_resumes.py --input _llm_scores.json --output screening_results.json \ --job-name "<岗位名>" --encrypt-job-id "<id>" --run-id " $RUN_ID " # → ⏭ 跳过 12 位历史已评分候选人：张三、李四... # 缺 _llm_scores.json → SystemExit(26) + JSON 错误提示 # 换了 JD 要全部重评 python score_resumes.py --input _llm_scores.json --output screening_results.json \ --job-name "<岗位名>" --encrypt-job-id "<id>" --run-id " $RUN_ID " --rescore 去重按 geek_id 而非姓名。BOSS 上「杨先生」「吕女士」这类匿名昵称会重名， 脚本对同一姓名维护 ID 列表： 只要还有任一同名候选人未评分就放行 （宁可偶尔重复评分，也不把没评过的人误杀）。 姓名 → geek_id 的映射从 state/resumes_master.json 反查，所以 _llm_scores.json 里的 name 必须与简历原始姓名一致 ，改写姓名会导致匹配失败（脚本会告警）。 评分架构 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 "<岗位名>" \ --encrypt-job-id "<BOSS 的 encryptJobId>" \ --job-info <JD JSON 字符串> \ --run-id <run_id> 🚨 新接口必传 --encrypt-job-id ：工作区目录名 = encryptJobId ，与 Step 1/2/4 保持一致。也可以设 env BOSS_HR_ENCRYPT_JOB_ID 作为 fallback。缺则直接 ValueError 退出（严格模式，不静默回退）。 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} 支持精确匹配 + 模糊匹配（输入校名是表内校的子串或父串时也能命中）。 完整工作流（2026-07-31 v3：LLM 每评一份立即落盘） # 公共参数（5 步全流程同一个 encryptJobId） export ENCRYPT_ID="9a7759badfd95d350nFz3d-_F1NX" export JOB_NAME="线控底盘制动、转向工程师" export RUN_ID="2026-07-29_150915" # 假设已有 runs/<run_id>/process/new_resumes.json（来自 boss-recommend-downloader） # 0. 简历净化层 —— 把 new_resumes.json 拆成每人一份（2026-07-31 v2） # 输入：new_resumes.json（动辄几 MB，含 _meta/active_status/空字段等噪声） # 输出：runs/<run_id>/process/scoring/ # ├── manifest.json # 候选人清单 + status（pending/scored/missing） # ├── inputs/candidate_<geek_id>.json # 净化输入（LLM 读这里） # ├── outputs/candidate_<geek_id>.json # LLM 评分落盘点（每评一个立即写一份） # └── _skipped.json # 被跳过的简历 # 关键：不改变评分标准，只是把「一坨 JSON」拆成「每人一文件」 python scripts/prepare_scoring_inputs.py \ --job-name "$JOB_NAME" --encrypt-job-id "$ENCRYPT_ID" --run-id "$RUN_ID" # 1. LLM agent 读 scoring/manifest.json（拿到候选人清单 + status） # 2. 对 status="pending" 的候选人循环： # a) 读 scoring/inputs/candidate_<geek_id>.json（一份精简简历） # b) 调 LLM API 评 4 维度（exp / skill / proj / major），产出评分 object # c) **立即落盘**到 scoring/outputs/candidate_<geek_id>.json（单个评分 object） # d) 中途崩了下次只需重跑循环里 status="pending" 的那批 # 3. 跑 collect_llm_scores.py：把 outputs/ 合并成 _llm_scores.json（幂等可重跑） # - 回写 manifest.status 为 scored / missing / invalid # - 不读简历、不做评分，只做文件收集 + 数组拼接 python scripts/collect_llm_scores.py \ --job-name "$JOB_NAME" --encrypt-job-id "$ENCRYPT_ID" --run-id "$RUN_ID" # 4. 跑 score_resumes.py 收尾（不读 outputs/，只接 _llm_scores.json） # - 用 school_tier 查 edu # - 加权 + total + tier 判定 # - 跨 run 去重（state/scored_state.json） python score_resumes.py \ --job-name "$JOB_NAME" --encrypt-job-id "$ENCRYPT_ID" --run-id "$RUN_ID" # Step 4: 生成 HTML 报告 python html-report/scripts/generate_html_report.py \ --job-name "$JOB_NAME" \ --encrypt-job-id "$ENCRYPT_ID" \ --run-id <run_id> 关键设计点 断点续评 ：LLM agent 任何时候崩了，下次只需读 manifest.json 挑 status="pending" 的继续评，已评的 scored 直接跳过。 不污染评分标准 ： score_resumes.py 的入参 schema 完全不变（仍是 _llm_scores.json 数组）；collect_llm_scores.py 只做文件收集 + 拼接，不做任何评分/打分/校准。 校验兜底 ： collect_llm_scores.py 校验每个 outputs 文件的 schema（必含 name / dims.{exp,skill,proj,major} 且 0-100），不合法的标 status="invalid" 不入数组，错误信息打印在 stdout。 geek_id / job_id 兜底 ：如果 LLM 在 outputs 文件里漏写 geek_id ，collect_llm_scores.py 从 manifest 自动补（避免 score_resumes.py 拒绝评分）。 净化层字段规则（白名单 + 必保留） prepare_scoring_inputs.py 从 new_resumes.json[i] 净化出 <index>_<name>.json ，规则： 只删 ： ok / age / expectation / active_status （接口包装 / 平台状态 / 与评分无关） _meta 整层（包装字段； encrypt_geek_id / encrypt_job_id 抽到顶层） work_experience[].performance / work_experience[].keywords / work_experience[].department （历年空 / BOSS 内部字段） project_experience[] 中的全空字段（保留 name 作为骨架） 空字段（ null / "" ）在 work_experience / project_experience 内做最小保留（让 LLM 看到"无技能"是证据，不是字段缺失） 必保留 （评分主体证据）： name / degree / work_years （脚本硬门槛过滤依据） work_experience[].company / position / start / end / duration / responsibility project_experience[].name / role / start / end / duration / description / achievement education[] （school_tier 查表 + 专业匹配） certifications[] （英语 / 计算机证书是辅助证据） skills （JD 关键词命中证据；空串也保留） 顶层 geek_id / job_id （从 _meta 抽出，供 score_resumes.py 去重） 额外 ： 顶层加 __meta__ 块标 source / source_index / generated_at，方便反查 写 _manifest.json （文件清单 + 字节数 + geek_id）和 _skipped.json （被跳过的 ok=false / 缺 name 的简历） 工作区路径约定（新设计 · 2026-07-29+） 所有数据统一存放在 ~/Desktop/boss-hr-output/<encryptJobId>/ 下 ， 目录名直接用 BOSS 的 encryptJobId （不再用中文岗位名）。 job_name 仅作为 jobs.json 里的可读元数据。 ~/Desktop/boss-hr-output/ ├── jobs.json # JobRegistry：encryptJobId → {name, company} └── <encryptJobId>/ # 目录名 = BOSS 的 encryptJobId ├── state/ # 跨 run 保留（不覆盖） │ ├── candidate_pool.json │ ├── download_state.json │ ├── resumes_master.json # 累计成功简历（含 _meta） │ ├── collection_state.json │ ├── scored_state.json └── runs/ └── <run_id>/ # 一次筛选任务 ├── <run_id>_screening_report.html └── process/ ├── job_detail.json ← Step 1: boss_jd.py 输出 ├── recommend_geek_ids.json ← Step 2a: list 输出 ├── new_resumes.json ← Step 2b: download 输出 ├── scoring/ ← Step 3: prepare_scoring_inputs.py 输出 │ ├── manifest.json # 候选人清单 + status（pending/scored/missing） │ ├── _skipped.json # 被跳过的简历 │ ├── inputs/candidate_<geek_id>.json # LLM 读这里 │ └── outputs/candidate_<geek_id>.json # LLM 落盘点（每评一个立即写一份） ├── _llm_scores.json ← Step 3: collect_llm_scores.py 合并产物 ├── screening_results.json ← Step 3: score_resumes.py 输出 ├── failed_resumes.json └── greet_log.json ← Step 5: auto_greet.py 输出 上游 boss-job-detail / boss-recommend-downloader 已自动写入此目录，下游脚本（ score_resumes.py / generate_html_report.py / auto_greet.py ）通过 --input/--output 读取此目录。 JobOutputManager 提供的标准路径属性： jd_path / recommend_geek_ids_path / new_resumes_path / screening_results_path / report_path / run_summary_path 。 同一 run 必须传同一个 --run-id 给所有脚本（list / download / score / HTML / greet），产物才落在同一个 runs/<run_id>/ 。 同一 job 必须传同一个 --encrypt-job-id 给所有脚本，工作区目录才一致。 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 查表（校名→档次分）；可选本/硕/博层次加成 脚本 （强制）