krzznh/CHAOS-Redrob-TalentRank-AI

GitHub: krzznh/CHAOS-Redrob-TalentRank-AI

一个面向大规模招聘场景的AI候选人排名系统,通过多信号评分与语义相似度从十万级候选人中智能筛选Top候选人。

Stars: 0 | Forks: 0

# Redrob 黑客松 — 高级 AI 工程师候选人排名系统 ## 快速开始 ``` # 1. 安装 dependencies pip install -r requirements.txt # 2. 放置 dataset cp /path/to/candidates.jsonl data/ # 3. 运行 ranker python rank.py --candidates data/candidates.jsonl --out submission/submission.csv # 4. 验证 python validate_submission.py submission/submission.csv # 5. 启动 demo streamlit run demo/app.py ``` ## 仓库结构 ``` hackathon/ ├── rank.py # Main entry point ├── precompute_embeddings.py # Optional: pre-compute embeddings offline ├── requirements.txt ├── .gitignore │ ├── src/ │ ├── jd_config.py # JD taxonomy: skill lists, weights, thresholds │ ├── features.py # 7 scoring dimensions (rule-based) │ ├── honeypot_detector.py # Impossible profile detection │ ├── semantic.py # MiniLM-L6-v2 embedding similarity │ ├── ranker.py # Main orchestration pipeline │ ├── reasoning.py # Factual reasoning string generation │ └── writer.py # Submission CSV writer (tie-break aware) │ ├── demo/ │ └── app.py # Streamlit demo application │ ├── tests/ │ ├── test_features.py # 28 unit tests for feature scoring │ ├── test_honeypot.py # 8 unit tests for honeypot detection │ └── test_writer.py # 9 unit tests for CSV writer │ ├── submission/ │ ├── submission.csv # ✅ Validated, 100 candidates │ └── submission_metadata.yaml # Team + methodology declaration │ ├── data/ │ └── sample_candidates.json # 500-candidate sample for demo/tests │ └── docs/ ├── architecture.md # System design └── methodology.md # Ranking approach & JD analysis ``` ## 架构 ![Pipeline 架构](https://static.pigsec.cn/wp-content/uploads/repos/cas/2d/2d50eb6b9a895d79e7d9213eb25f0dacbe6cfea4dd1fa72c2ae2516a01474e39.svg) ## 工作原理 ### 挑战的隐藏难点 JD(职位描述)中包含一个明确的陷阱(直接引用): 天真的关键词匹配在两个方向上都会失败。我们的排名系统能同时处理这两种情况。 ### 评分流水线(4 个阶段,总计约 15 秒) ``` Phase 1 — Rule-based scoring of ALL 100K candidates (~14s) Phase 2 — Semantic embedding of TOP 2,000 only (~90s with MiniLM) Phase 3 — Final score combination + select Top-100 (~1s) Phase 4 — Reasoning generation (~1s) ``` **未预计算 embeddings**:约 15 秒(仅基于规则,semantic=0) **预计算 embeddings**:总计约 15 秒(从缓存加载) **实时生成 embeddings (top-2000)**:约 2.5 分钟 均完全符合 5 分钟的预算限制。 ### 评分维度 | 维度 | 权重 | 衡量标准 | |---|---|---| | **技能匹配** | 30% | 技能与 JD 分类法的精确匹配(必备技能权重 ×2,按熟练度 × 持续时间 × 认可数进行质量加权) | | **职位 + 职业** | 25% | 职位层级(理想/强相关/邻近/不合格)× 职业履历的 ML 相关性。不合格职位(Marketing Manager、HR Manager 等)将直接把该部分得分归零 | | **语义相似度** | 15% | 候选人文本与 JD 文本之间的 MiniLM-L6-v2 余弦相似度 | | **经验契合度** | 10% | 以 JD 的最佳区间(6-8 年)为中心的曲线 YoE(工作年限)评分 | | **行为信号** | 10% | 作为基础得分的**软乘数**(×0.60-1.0),而不仅仅是累加。不活跃的“纸面完美”候选人 < 活跃但不完美的候选人 | | **地域契合度** | 5% | Pune/Noida = 1.0 · 印度二线城市 = 0.80-0.95 · 印度以外 = 0.18-0.45 | | **教育背景** | 3% | IIT/IISc 等顶尖(tier-1)院校小幅加分;tier-4 保持中性 | | **GitHub 活跃度** | 2% | 开源信号(0-100 分) | #### 行为信号作为软乘数 JD 指出: 我们通过将 `behavioral_score` 作为基础得分的乘数来实现这一点: ``` behavior_multiplier = 0.60 + behavioral_score × 0.40 # range [0.60, 1.00] final = base × behavior_multiplier + behavioral × weight_behavioral ``` ### 技能匹配:精确名称 `src/jd_config.py` 中的所有技能名称都与数据集中的技能名称**完全匹配**(已针对所有 10 万个个人资料进行验证)。这避免了 `"embedding"` 永远无法匹配 `"Embeddings"` 的关键词重叠 Bug。 **必备技能**(占分数的 30%,每项权重 ×2): `FAISS, Pinecone, Qdrant, Milvus, Weaviate, OpenSearch, Elasticsearch, pgvector, Vector Search, Sentence Transformers, Embeddings, Semantic Search, Dense Retrieval, Hybrid Search, Learning to Rank, Information Retrieval, BM25, NDCG, MRR, Python, MLOps` 每个匹配的技能都会根据以下因素进行加权: ``` quality = proficiency_mult × duration_mult × endorsement_mult + assessment_bonus ``` ### 蜜罐检测 该数据集包含约 80 个伪造的个人资料。Top-100 列表中的蜜罐率 > 10% 即意味着**不合格**。 我们的检测器会标记具有以下特征的个人资料: 1. **不可能的时间线** — 职业履历总时长 > 标明的 YoE + 4 年 2. **专家 + 零持续时间** — `proficiency=expert` 且 `duration_months=0` 3. **认可度矛盾** — 所有技能都有 50+ 个认可,但 `endorsements_received=0` 4. **GitHub 不可能存在** — `github_activity_score=100` 且 `connection_count=0` 5. **完美完整度 + 零互动率** — `completeness=100`,`response_rate=0`,`interview_rate=0` 检测结果:在 10 万名候选人中标记了 **38 个蜜罐**。前 100 名中均未出现蜜罐。 ### 语义相似度 使用 **`all-MiniLM-L6-v2`**(22M 参数,384 维 embeddings): - CPU 上运行速度快:每秒约处理 500 名候选人 - 在基于规则的预过滤后,应用于排名前 2,000 的候选人(而非全部 10 万人) - 候选人文本 = headline + summary + 前 15 项技能(按熟练度排序)+ 前 4 段职业描述 - 得分为经过 L2 归一化的余弦相似度,范围偏移至 [0, 1] 预计算所有 embeddings(可选): ``` python precompute_embeddings.py \ --candidates data/candidates.jsonl \ --output outputs/embeddings.pkl ``` 然后使用缓存运行排名系统: ``` python rank.py \ --candidates data/candidates.jsonl \ --embeddings-cache outputs/embeddings.pkl \ --out submission/submission.csv ``` ## 运行测试 ``` python3 -m unittest tests/test_features.py tests/test_honeypot.py tests/test_writer.py -v ``` 输出: ``` Ran 45 tests in 0.019s OK ``` ## 演示应用 ``` streamlit run demo/app.py ``` 页面: - **概览** — 前 10 名候选人,评分权重图表 - **排行榜** — 可排序/过滤的排名表 - **候选人审查器** — 每位候选人得分组成的多维度雷达图 - **蜜罐检测器** — 可疑个人资料浏览器 - **评分分析** — 特征分布,YoE 直方图,职位细分 演示默认使用 `data/sample_candidates.json`。通过侧边栏上传任何 `.jsonl` 文件即可对自定义数据集进行排名。 ## 提交格式 ``` candidate_id,rank,score,reasoning CAND_0077337,1,0.698273,"Staff Machine Learning Engineer, 7.0 yrs — vector DB + embeddings..." CAND_0071974,2,0.697377,"Senior AI Engineer, 7.8 yrs — vector DB + embeddings..." ... ``` - 100 行(排名 1-100) - 得分非递增;同分情况下按 `candidate_id` 升序排序 - 推理依据:基于事实、具体且与排名一致(无幻觉) ## 设计决策与权衡 | 决策 | 依据 | |---|---| | 选择 MiniLM 而非 BERT-large | 在 CPU 上运行速度快 15 倍,符合 5 分钟预算限制,且对于此任务质量已足够 | | 精确技能名称匹配 | 避免因关键词列表导致的子串重叠误报 | | 行为信号作为乘数而非累加 | 保留了 JD 中的核心洞察:不活跃的候选人实际上并不具备可雇佣性 | | 对 top-2000 进行预过滤后再进行语义分析 | 10 万人 embeddings = 200 秒;top-2000 = 4 秒;对排名的影响微乎其微 | | 得分输出保留 6 位小数 | 防止因保留 4 位小数导致的虚假同分,避免破坏同分情况下的校验逻辑 | | 不合格职位得分直接归零 | 根据 JD 的明确指导,拥有 ML 技能的 Marketing Manager = 不符合要求 | ## 环境要求 ``` pandas>=2.0.0 numpy>=1.24.0 sentence-transformers>=2.7.0 # for semantic layer (optional) scikit-learn>=1.3.0 streamlit>=1.32.0 plotly>=5.18.0 tqdm>=4.66.0 pyyaml>=6.0.0 ``` 该流水线在**未**安装 sentence-transformers 的情况下也能运行(语义得分 = 0,其他 7 个维度依然有效)。安装它以获得完整性能: ``` pip install sentence-transformers ```
标签:Kubernetes, Python, Streamlit, 人工智能, 候选人排名, 数据筛选, 无后门, 用户模式Hook绕过, 访问控制, 语义相似度, 逆向工具