vinuthna08/redrob_ai
GitHub: vinuthna08/redrob_ai
一个基于多阶段规则过滤与语义相似度的候选人智能筛选排名系统,专为在大规模简历池中快速定位匹配人选而设计。
Stars: 0 | Forks: 0
# redrob_hackathon — 智能候选人发现与排名
在 Redrob INDIA RUNS 黑客松(智能候选人发现与排名挑战)中,针对“高级 AI 工程师 — 创始团队”的职位描述 (JD),从 10 万名候选人中筛选并排名前 100 名候选人。
## 架构
三个独立、可解释的阶段,每个阶段的设计逻辑均记录在其模块 docstring 中:
- **阶段 A — `src/consistency_gate.py`**:检测诱饵类/不合理的档案(例如 11 年的工作经验空窗期,使用时间为零个月的“专家”技能)。包含六项检查,分为硬性/软性层级:单个“硬性”标记(确定的、没有合理借口的证据)足以将其归类为诱饵档案;“软性”标记(视情况而定的、个别可原谅的)则需要累积超过评分阈值。
- **阶段 B — `src/jd_disqualifiers.py`**:七条规则直接取自 JD 中“我们明确不想要的事物” / “我们实际适用的取消资格条件”部分。采用乘法惩罚,每一项均可独立解释。
- **阶段 C — `src/fit_scoring.py`**:将 sentence-transformers 的 embedding 相似度(候选人职业经历与 JD 实质内容)与结构化的 `relevant_career_fraction` 信号(来自可信的职位/行业字段,在真正的 ML/AI/检索相关职位上的职业月份数占比)相结合。这两种信号都是必需的 —— 经过测试发现,仅靠 embedding 相似度会将那些泛泛而谈“我对 ChatGPT 很感兴趣”的候选人,打出与真正的 ML 工程师非常接近的尴尬高分;而结构化信号解决了这个问题。完整推理见模块 docstring。
贯穿所有三个阶段的一项关键设计决策:**`career_history[].description` 在本代码库中的任何地方均不用于评分或 embedding。** `check_description_shuffle.py` 发现超过 50% 候选人的描述文本与其自身的职位/公司不符 —— 这些文本来自一个独立于实际职位的共享池。由于没有任何字段标记哪些描述是“真实的”,因此使用该字段都会给评分引入如同掷硬币般的噪声。`profile.summary`、`profile.headline` 以及 career_history 的 `title`/`company`/`industry`/`duration_months` 未被混淆,且是唯一被使用的文本字段。
## 计算资源限制(运行前必读)
根据 `submission_spec.docx` 第 3 节,排名步骤有严格的资源预算限制:**<=5 分钟实际运行时间,仅限 CPU,无 GPU,无网络调用。** 这就是为什么 pipeline 被拆分为两个阶段的原因:
1. **`precompute.py`** —— 运行缓慢,只需运行一次,不受 5 分钟预算限制。运行阶段 A+B(约 10-20 秒)以及阶段 C 的 embedding 计算(在纯 CPU 机器上处理真实的 10 万数据集实测耗时 **73-127 分钟**)。将结果写入 `data/processed/`。
2. **`rank.py`** —— 运行快速,这才是需要在第 3 阶段复现的内容。加载预计算的缓存,合并分数,排序,并输出提交的 CSV 文件。端到端实测耗时 **约 5 秒**,完全在预算范围之内。
这种拆分是规范明确允许的:*“如果您的系统需要预计算……预计算可以超过 5 分钟的时间窗口,但生成 CSV 的排名步骤必须在该时间窗口内完成。”*
## 如何复现提交结果
```
pip install -r requirements.txt
# 步骤 1:precompute(较慢 —— 在 CPU 上预计需要 1.5-2+ 小时)
python precompute.py --candidates data/raw/candidates.jsonl
# 步骤 2:rank(快速 —— 几秒钟内完成)
python rank.py --candidates data/raw/candidates.jsonl --out submission.csv
# 步骤 3:validate
python validate_submission.py submission.csv
```
如果您在 `data/processed/` 中已有当前缓存(来自之前的运行),并且仅修改了 `rank.py` 本身,则可跳过缓慢的步骤:
```
python precompute.py --candidates data/raw/candidates.jsonl --skip-stage-ab --skip-stage-c
python rank.py --candidates data/raw/candidates.jsonl --out submission.csv
```
## 代码库布局
```
redrob_hackathon/
├── README.md
├── requirements.txt
├── submission_metadata.yaml
├── precompute.py # Stage A+B+C precomputation (slow, run once)
├── rank.py # Final ranking + CSV writer (fast, Stage-3-reproduced)
├── validate_submission.py # Organizer-provided validator
│
├── data/
│ ├── raw/ # Hackathon bundle, untouched (gitignored: candidates.jsonl)
│ ├── processed/ # Precompute cache (gitignored, regenerable)
│ └── manual_labels/ # Hand-labeled ground truth for calibration
│
├── src/
│ ├── consistency_gate.py # Stage A
│ ├── jd_disqualifiers.py # Stage B
│ ├── fit_scoring.py # Stage C
│ └── load_candidates.py # Standalone Stage A/B runner (used by precompute.py logic)
│
├── tests/
│ ├── test_stage_a_b.py
│ └── test_fit_scoring_sanity.py
│
└── check_*.py, score_fit.py # Diagnostic scripts used during development
# (not part of the reproduction path, kept
# for methodology transparency -- see git
# history for the findings each one produced)
```
## 方法学说明 / 已知局限
本着诚实记录而非刻意隐瞒的态度,因为第 4/5 阶段的审查会对此进行考量:
- **阶段 A:** `title_history_mismatch` 和 `closed_source_no_validation` 在真实数据集上的触发率为 0% 或接近 0% —— 通过 `check_dead_rules_vocab.py` 确认它们处于正确的休眠状态(触发它们的词汇在此数据集中并不存在),而非逻辑错误。
- **阶段 B:** `senior_no_recent_code` 触发率为 0% —— 确认该数据集中 44 个不同的职位永远不包含“architect”/“tech lead”/“principal”。`pure_research_no_production` 按照设计极为罕见(研究类标记的基础概率仅占候选人的 0.14%)。
- **阶段 C:** `RELEVANT_TITLE_MARKERS` 在检查了真实数据后排除了“Data Engineer”和“Data Scientist” —— 起初将这两者作为听起来合理的猜测包含在内,但在针对完整的 10 万数据集运行后发现,尽管 JD 从未将数据工程列为相关职能,仅“Data Engineer”就占据了所有相关度匹配命中的 73%。验证后已将其移除;查看 git 历史记录可了解修改前后的数据对比。
- 权重(`rank.py` 中的 `CONSISTENCY_WEIGHT`/`FIT_WEIGHT`,`fit_scoring.py` 中的 `COSINE_WEIGHT`/`STRUCTURED_WEIGHT`)是经过逻辑推演的选择,并未针对 ground truth 进行经验调参 —— 我们没有带标签的相关性层级数据可供调参。`data/manual_labels/` 目录在填充数据后即用于此目的。
## AI 工具使用
本项目在架构设计、规则实现和调试方面大量借助了 Claude (Anthropic) 的协助。本代码库中的每一个 bug 修复和设计决策,在被采纳之前都针对真实的 10 万候选人数据集进行了验证 —— 查看 git 历史记录,可以看到迭代式的“发现-测试-修复”模式(例如 `endorsement_inflation` 的阈值、`cv_speech_robotics_no_nlp` 经过三次迭代的修复、`rank.py` 中的平局处理和舍入精度 bug,这些都是通过运行真实的诊断工具或实际的 validator 发现的,而非基于理论的假设)。
标签:Python, 人工智能, 候选人筛选, 招聘自动化, 文本相似度计算, 无后门, 时序数据库, 用户模式Hook绕过, 逆向工具