Files
CareerNexus/scripts/generate_dataset.py
T
RoyirinRosmontis 33aee6b8ae 岗位覆盖扩充至 26 个 + 图谱岗位子图模式
- 新增 8 岗位族(大数据/机器学习/机器人/数据治理/边缘计算/物联网安全/智能系统架构/隐私计算),词表 161→179
- 图谱详情面板新增'岗位子图'模式(只看该岗位及一跳邻居,徽标可退出)
- 测试集扩至 176 条、匹配标注 52 对;real_jd_500 F1 99.82%;合成三项 100% 保持
2026-08-12 15:58:22 +08:00

1018 lines
67 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""自备数据集生成器(random.seed(2026) 固定可复现)。
产出:
- data/skills_lexicon.json 技能词表(>=160 技能点:名称/类别/别名/级别/前置技能)
+ 行业词表(7 个行业)与岗位-行业归属
- data/jd_raw/batch_YYYY.jsonl 原始 JD(2019-2026,演化信号烘焙,约 8% 近重复、噪声植入)
每条 JD 含 industry 字段(招聘平台标注的所属行业),文本经多模板族渲染:
职责句式 >=15 套(含时代门槛,2019 年不会出现"大模型"),可选公司介绍/
项目背景/团队福利段落,长度分布 150-500 字。
- data/jd_raw/_meta.json 植入的抄袭簇与噪声清单(供测试核验)
- data/testset/jd_testset.jsonl + gold_answers.json >=120 条带标准答案的 JD
- data/testset/match_gold.json 标注好的人岗匹配对(>=30 对)
- data/resumes/*.txt + gold.json 7 份简历样例(完整/部分/错位)与技能标准答案
- data/reports/*.txt 3 份行业趋势报告样例(与 JD 演化信号相互印证)
- data/review/audit.jsonl 预置审核/编辑留痕种子记录
公平性说明:gold_answers 在生成 JD 文本之前先确定结构(标题/职责/必备/加分/场景),
再据此渲染文本;评测脚本从文本重新抽取再与 gold 比对,不是反向拟合。
"""
from __future__ import annotations
import json
import random
import sys
from datetime import date, timedelta
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from app.extract.offline import DUTY_HEADERS, PREF_HEADERS, REQ_HEADERS, TAIL_HEADERS # noqa: E402
SEED = 2026
rng = random.Random(SEED)
# ---------------------------------------------------------------- 技能词表
# (名称, 类别, [别名], 级别, [前置技能])
SKILLS = [
# 编程语言
("Java", "编程语言", [], "L1", []), ("Python", "编程语言", [], "L1", []),
("Go", "编程语言", ["Golang"], "L1", []), ("C++", "编程语言", [], "L1", ["C"]),
("C", "编程语言", ["C语言"], "L1", []), ("JavaScript", "编程语言", ["JS"], "L1", []),
("TypeScript", "编程语言", ["TS"], "L2", ["JavaScript"]), ("PHP", "编程语言", [], "L1", []),
("Scala", "编程语言", [], "L2", ["Java"]), ("Kotlin", "编程语言", [], "L2", ["Java"]),
("Rust", "编程语言", [], "L3", []), ("SQL", "编程语言", [], "L1", []),
("Shell", "编程语言", ["Bash"], "L1", ["Linux"]), ("R", "编程语言", [], "L2", []),
("MATLAB", "编程语言", [], "L2", []),
# 后端框架
("Spring", "后端框架", [], "L2", ["Java"]), ("Spring Boot", "后端框架", ["SpringBoot"], "L2", ["Spring"]),
("Spring Cloud", "后端框架", ["SpringCloud"], "L3", ["Spring Boot", "微服务"]),
("MyBatis", "后端框架", ["Mybatis"], "L2", ["Java", "SQL"]),
("Django", "后端框架", [], "L2", ["Python"]), ("Flask", "后端框架", [], "L2", ["Python"]),
("FastAPI", "后端框架", [], "L2", ["Python"]), ("Gin", "后端框架", [], "L2", ["Go"]),
("Express", "后端框架", [], "L2", ["Node.js"]), ("NestJS", "后端框架", [], "L3", ["TypeScript"]),
("Netty", "后端框架", [], "L3", ["Java"]), ("Dubbo", "后端框架", [], "L3", ["Java", "微服务"]),
("gRPC", "后端框架", [], "L3", ["微服务"]),
("Struts", "后端框架", [], "L1", ["Java"]), ("Servlet", "后端框架", [], "L1", ["Java"]),
("JSP", "后端框架", [], "L1", ["Java"]), ("SSM", "后端框架", [], "L2", ["Spring", "MyBatis"]),
# 前端
("Vue", "前端", ["Vue.js"], "L2", ["JavaScript"]), ("React", "前端", ["React.js", "ReactJS"], "L2", ["JavaScript"]),
("Angular", "前端", ["AngularJS"], "L2", ["TypeScript"]), ("jQuery", "前端", [], "L1", ["JavaScript"]),
("Webpack", "前端", [], "L2", ["JavaScript"]), ("Vite", "前端", [], "L2", ["JavaScript"]),
("Node.js", "前端", ["Node", "NodeJS"], "L2", ["JavaScript"]), ("小程序开发", "前端", ["微信小程序"], "L2", ["JavaScript"]),
("Element UI", "前端", [], "L1", ["Vue"]), ("Ant Design", "前端", [], "L1", ["React"]),
("HTML", "前端", ["HTML5"], "L1", []), ("CSS", "前端", ["CSS3"], "L1", []),
("Tailwind CSS", "前端", [], "L2", ["CSS"]), ("低代码平台", "前端", [], "L2", []),
("微前端", "前端", [], "L3", ["JavaScript"]),
# 数据库与中间件
("MySQL", "数据库", [], "L1", ["SQL"]), ("PostgreSQL", "数据库", [], "L2", ["SQL"]),
("Oracle", "数据库", [], "L2", ["SQL"]), ("Redis", "数据库", [], "L2", []),
("MongoDB", "数据库", [], "L2", []), ("Elasticsearch", "数据库", ["ElasticSearch"], "L2", ["Linux"]),
("ClickHouse", "数据库", [], "L3", ["SQL"]), ("HBase", "数据库", [], "L3", ["Hadoop"]),
("SQLite", "数据库", [], "L1", ["SQL"]), ("TiDB", "数据库", [], "L3", ["MySQL"]),
("Kafka", "中间件", [], "L2", ["Linux"]), ("RabbitMQ", "中间件", [], "L2", []),
("RocketMQ", "中间件", [], "L2", ["Java"]), ("Pulsar", "中间件", [], "L3", ["Kafka"]),
("ZooKeeper", "中间件", [], "L2", ["Linux"]), ("Tomcat", "中间件", [], "L1", ["Java"]),
("WebLogic", "中间件", [], "L2", ["Java"]), ("Nginx", "中间件", [], "L1", ["Linux"]),
# 大数据
("Hadoop", "大数据", [], "L2", ["Linux", "Java"]), ("Spark", "大数据", [], "L2", ["Hadoop"]),
("Flink", "大数据", [], "L3", ["Kafka"]), ("Hive", "大数据", [], "L2", ["Hadoop", "SQL"]),
("HDFS", "大数据", [], "L2", ["Hadoop"]), ("Airflow", "大数据", [], "L2", ["Python"]),
("DataX", "大数据", [], "L2", []), ("Sqoop", "大数据", [], "L2", ["Hadoop"]),
("Presto", "大数据", [], "L3", ["SQL"]), ("Doris", "大数据", [], "L3", ["SQL"]),
("数据挖掘", "大数据", [], "L2", ["Python", "SQL"]),
# AI 与算法
("机器学习", "AI算法", ["机器学习算法"], "L2", ["Python"]),
("深度学习", "AI算法", [], "L3", ["机器学习"]),
("PyTorch", "AI算法", [], "L2", ["Python", "深度学习"]),
("TensorFlow", "AI算法", [], "L2", ["Python", "深度学习"]),
("Keras", "AI算法", [], "L2", ["TensorFlow"]),
("Scikit-learn", "AI算法", ["sklearn"], "L2", ["机器学习"]),
("XGBoost", "AI算法", [], "L2", ["机器学习"]), ("LightGBM", "AI算法", [], "L2", ["机器学习"]),
("NLP", "AI算法", ["自然语言处理"], "L3", ["机器学习"]),
("计算机视觉", "AI算法", ["CV"], "L3", ["深度学习"]),
("OpenCV", "AI算法", [], "L2", ["Python"]), ("OCR", "AI算法", ["文字识别"], "L2", ["计算机视觉"]),
("语音识别", "AI算法", [], "L3", ["深度学习"]), ("推荐算法", "AI算法", ["推荐系统"], "L3", ["机器学习"]),
("强化学习", "AI算法", [], "L3", ["深度学习"]), ("知识图谱", "AI算法", [], "L3", ["NLP"]),
("大模型应用开发", "AI算法", ["LLM应用开发", "大模型应用", "大语言模型应用"], "L3", ["Python", "NLP"]),
("RAG", "AI算法", ["检索增强生成"], "L3", ["大模型应用开发", "向量数据库"]),
("提示词工程", "AI算法", ["Prompt工程"], "L2", ["大模型应用开发"]),
("向量数据库", "AI算法", ["向量库"], "L2", ["数据库基础"]),
("LangChain", "AI算法", [], "L2", ["大模型应用开发"]),
("模型微调", "AI算法", ["Fine-tuning", "SFT"], "L3", ["深度学习", "PyTorch"]),
("AI辅助编程", "AI算法", ["Copilot", "AI编程助手"], "L1", []),
# 云原生与运维
("Linux", "运维", [], "L1", []), ("Docker", "云原生", [], "L2", ["Linux"]),
("Kubernetes", "云原生", ["K8s", "k8s"], "L3", ["Docker"]),
("微服务", "云原生", ["微服务架构"], "L2", []),
("分布式系统", "云原生", ["分布式"], "L3", []), ("高并发", "云原生", [], "L3", ["分布式系统"]),
("云计算", "云原生", ["云平台"], "L2", []), ("Service Mesh", "云原生", ["服务网格"], "L3", ["Kubernetes"]),
("CI/CD", "运维", ["持续集成"], "L2", ["Git"]), ("Git", "运维", [], "L1", []),
("Svn", "运维", ["SVN"], "L1", []), ("Jenkins", "运维", [], "L2", ["CI/CD"]),
("Terraform", "运维", [], "L3", ["云计算"]), ("Ansible", "运维", [], "L2", ["Linux"]),
("Prometheus", "运维", [], "L2", ["Kubernetes"]), ("Grafana", "运维", [], "L2", ["Prometheus"]),
("ELK", "运维", [], "L2", ["Elasticsearch"]), ("DevOps", "运维", [], "L2", ["CI/CD"]),
("AIOps", "运维", ["智能运维"], "L3", ["Prometheus", "机器学习"]),
("AWS", "云原生", ["亚马逊云"], "L2", ["云计算"]), ("阿里云", "云原生", [], "L2", ["云计算"]),
("腾讯云", "云原生", [], "L2", ["云计算"]),
# 测试
("自动化测试", "测试", [], "L2", ["Python"]), ("Selenium", "测试", [], "L2", ["自动化测试"]),
("JUnit", "测试", [], "L1", ["Java"]), ("Pytest", "测试", [], "L1", ["Python"]),
("性能测试", "测试", [], "L2", []), ("接口测试", "测试", ["API测试"], "L2", []),
("JMeter", "测试", [], "L2", ["性能测试"]), ("Postman", "测试", [], "L1", ["接口测试"]),
("单元测试", "测试", [], "L1", []), ("测试用例设计", "测试", [], "L2", []),
# 嵌入式与物联网
("嵌入式开发", "嵌入式", ["嵌入式"], "L2", ["C"]), ("单片机", "嵌入式", [], "L1", ["C"]),
("STM32", "嵌入式", [], "L2", ["单片机"]), ("RTOS", "嵌入式", ["实时操作系统"], "L2", ["C"]),
("FreeRTOS", "嵌入式", [], "L2", ["RTOS"]), ("ARM", "嵌入式", [], "L2", []),
("驱动开发", "嵌入式", ["驱动程序开发"], "L3", ["C", "Linux"]),
("Verilog", "嵌入式", [], "L3", []), ("FPGA", "嵌入式", [], "L3", ["Verilog"]),
("PCB设计", "嵌入式", ["PCB"], "L2", []),
("MQTT", "物联网", [], "L2", []), ("传感器", "物联网", ["传感器技术"], "L1", []),
("物联网平台", "物联网", ["IoT平台"], "L2", []), ("边缘计算", "物联网", [], "L3", ["云计算"]),
("LoRa", "物联网", [], "L2", []), ("Zigbee", "物联网", [], "L2", []),
# 产品与分析
("产品设计", "产品", [], "L2", []), ("需求分析", "产品", [], "L2", []),
("项目管理", "产品", [], "L2", []), ("Axure", "产品", [], "L1", []),
("竞品分析", "产品", [], "L1", []), ("用户增长", "产品", [], "L2", []),
("AI产品", "产品", ["AI产品经理"], "L3", ["产品设计"]),
("数据分析", "数据分析", [], "L2", ["SQL"]), ("Excel", "数据分析", [], "L1", []),
("Tableau", "数据分析", [], "L2", ["数据可视化"]), ("Power BI", "数据分析", ["PowerBI"], "L2", ["数据可视化"]),
("SPSS", "数据分析", [], "L2", []), ("数据可视化", "数据分析", [], "L2", ["数据分析"]),
("A/B测试", "数据分析", ["AB测试"], "L2", ["数据分析"]),
# 机器人与智能系统(岗位覆盖扩展)
("ROS", "AI算法", ["机器人操作系统"], "L2", ["C++", "Linux"]),
("SLAM", "AI算法", ["同步定位与建图"], "L3", ["计算机视觉"]),
("路径规划", "AI算法", [], "L3", ["机器学习"]),
# 数据治理
("数据治理", "大数据", [], "L2", ["SQL"]),
("数据脱敏", "大数据", ["数据遮蔽"], "L2", ["SQL"]),
("元数据管理", "大数据", ["元数据"], "L2", ["数据治理"]),
("数据血缘", "大数据", [], "L3", ["元数据管理"]),
("湖仓一体", "大数据", ["实时湖仓"], "L3", ["Hive"]),
# 边缘计算
("边缘推理", "物联网", ["边缘推理框架"], "L3", ["边缘计算", "深度学习"]),
("TensorRT", "AI算法", [], "L3", ["深度学习"]),
("KubeEdge", "云原生", [], "L3", ["Kubernetes", "边缘计算"]),
# 安全与隐私计算
("零信任", "安全", ["零信任架构"], "L3", []),
("入侵检测", "安全", [], "L2", ["Linux"]),
("等保合规", "安全", [], "L2", []),
("联邦学习", "AI算法", [], "L3", ["机器学习"]),
("多方安全计算", "安全", ["MPC"], "L3", []),
("同态加密", "安全", [], "L3", []),
("差分隐私", "安全", [], "L3", ["机器学习"]),
]
SCENARIOS = ["电商", "金融", "物流", "社交", "教育", "医疗", "政务", "游戏",
"出行", "智能制造", "短视频", "广告", "供应链", "零售", "安防"]
# 行业词表(岗位归属 1-2 个行业,图谱中构建 Industry 节点)
INDUSTRIES = ["互联网/软件", "人工智能", "金融科技", "智能制造",
"物联网", "智慧城市", "智慧医疗"]
# ---------------------------------------------------------------- 岗位原型
def arc(title, category, years, salary, scenarios, industries,
duty_tmpls, duty_objs, timeline, volumes, test_n=8):
return dict(title=title, category=category, years=years, salary=salary,
scenarios=scenarios, industries=industries,
duty_tmpls=duty_tmpls, duty_objs=duty_objs,
timeline=timeline, volumes=volumes, test_n=test_n)
BACKEND_DUTIES = ["负责{o}的设计与开发", "参与{o}的性能优化与重构", "配合产品团队完成{o}的需求评审",
"编写{o}的技术文档与接口文档", "承担{o}的线上问题排查与修复", "推动{o}的代码评审与质量改进"]
BACKEND_OBJS = ["后端服务", "核心业务系统", "交易网关", "订单中心", "用户中心", "缓存体系", "消息管道", "权限平台"]
# 通用职责句式库:(模板, 最早出现年份)。时代词(大模型/AI/低代码)只出现在
# 对应年份之后,保证 2019 年的 JD 不会出现"大模型"等未来措辞。
GENERIC_DUTIES = [
("参与{o}从0到1的搭建与持续迭代", 2019),
("负责{o}高并发场景的优化与稳定性保障", 2020),
("与产品、测试团队协作,推动{o}高质量落地", 2019),
("沉淀{o}的通用组件与最佳实践", 2020),
("主导{o}的技术选型与难点攻坚", 2021),
("建设{o}的监控与告警体系", 2021),
("负责{o}的架构演进与技术债治理", 2022),
("推动{o}的自动化与工程效率提升", 2022),
("探索AI工具在{o}中的应用与提效", 2024),
("引入大模型能力改造{o}的现有流程", 2025),
]
ARCHETYPES = [
arc("Java开发工程师", "后端开发", 3, "15K-30K·14薪", ["电商", "金融", "物流"],
["互联网/软件", "金融科技"],
BACKEND_DUTIES, BACKEND_OBJS,
[(2019, 2021, ["Java", "MySQL", "Spring", "MyBatis", "Servlet"], ["Struts", "JSP", "Linux"]),
(2022, 2023, ["Java", "Spring Boot", "Spring Cloud", "MySQL", "Redis", "微服务"], ["Docker", "Kafka", "Kubernetes"]),
(2024, 2026, ["Java", "Spring Boot", "Spring Cloud", "Redis", "MySQL", "分布式系统"], ["AI辅助编程", "大模型应用开发", "Kubernetes"])],
{2019: 8, 2020: 8, 2021: 8, 2022: 10, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
arc("Python开发工程师", "后端开发", 3, "14K-28K", ["教育", "金融", "电商"],
["互联网/软件"],
BACKEND_DUTIES, BACKEND_OBJS,
[(2019, 2021, ["Python", "MySQL", "Django", "Linux", "Git"], ["Flask", "Redis", "Nginx"]),
(2022, 2023, ["Python", "FastAPI", "MySQL", "Redis", "Linux"], ["Docker", "Kafka", "Git"]),
(2024, 2026, ["Python", "FastAPI", "Redis", "MySQL", "分布式系统"], ["Docker", "大模型应用开发", "AI辅助编程"])],
{2019: 6, 2020: 6, 2021: 6, 2022: 8, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
# —— 前端:jQuery/AngularJS 时代 → Vue/React + TypeScript → 工程化/Vite → 低代码 + AI 辅助 ——
arc("前端工程师", "前端", 3, "13K-26K", ["电商", "社交", "短视频"],
["互联网/软件"],
["负责{o}的页面开发与交互实现", "参与{o}的前端性能优化", "与后端联调{o}的数据接口",
"维护{o}的组件库与工程化体系", "承担{o}的兼容性适配工作"],
["移动端页面", "管理后台", "可视化大屏", "运营活动页", "组件库", "工程化脚手架"],
[(2019, 2021, ["JavaScript", "HTML", "CSS", "Vue", "jQuery"], ["Webpack", "Angular", "小程序开发"]),
(2022, 2023, ["JavaScript", "TypeScript", "Vue", "React", "Webpack"], ["Vite", "Node.js", "小程序开发"]),
(2024, 2026, ["TypeScript", "Vue", "React", "Vite", "低代码平台"], ["AI辅助编程", "微前端", "Node.js"])],
{2019: 6, 2020: 6, 2021: 8, 2022: 12, 2023: 24, 2024: 24, 2025: 24, 2026: 24}),
arc("数据工程师", "大数据", 3, "16K-32K", ["金融", "物流", "零售"],
["互联网/软件", "金融科技"],
["负责{o}的采集与清洗", "搭建{o}的离线数仓分层", "开发{o}的实时计算任务",
"维护{o}的调度与监控体系", "参与{o}的数据治理工作"],
["业务数据", "日志数据", "实时数仓", "离线数仓", "数据湖", "指标体系"],
[(2019, 2021, ["SQL", "Hadoop", "Hive", "Spark", "Python"], ["HBase", "Sqoop", "Scala"]),
(2022, 2026, ["SQL", "Spark", "Flink", "Kafka", "Python"], ["ClickHouse", "Doris", "Airflow"])],
{2019: 5, 2020: 5, 2021: 5, 2022: 6, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
arc("算法工程师", "AI算法", 3, "20K-40K", ["广告", "电商", "金融"],
["人工智能"],
["负责{o}的建模与迭代", "参与{o}的特征工程建设", "跟踪{o}的前沿论文并落地",
"优化{o}的线上推理性能", "与工程团队协作上线{o}"],
["推荐模型", "排序模型", "风控模型", "用户画像", "召回策略", "预估服务"],
[(2019, 2021, ["Python", "机器学习", "深度学习", "TensorFlow", "SQL"], ["XGBoost", "Spark", "C++"]),
(2022, 2023, ["Python", "机器学习", "深度学习", "PyTorch", "推荐算法"], ["XGBoost", "模型微调", "强化学习"]),
(2024, 2026, ["Python", "机器学习", "深度学习", "PyTorch", "推荐算法"], ["大模型应用开发", "模型微调", "强化学习"])],
{2019: 5, 2020: 5, 2021: 5, 2022: 6, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
# —— 数据分析:Excel/SPSS 时代 → SQL/Python → BI 平台 → LLM 增强分析 ——
arc("数据分析师", "数据分析", 2, "12K-22K", ["零售", "电商", "金融"],
["互联网/软件", "金融科技"],
["负责{o}的报表体系建设", "输出{o}的专题分析报告", "搭建{o}的核心指标看板",
"支持业务团队的{o}取数需求", "参与{o}的复盘与归因分析"],
["经营数据", "用户行为", "活动效果", "渠道投放", "留存漏斗", "销售大盘"],
[(2019, 2021, ["Excel", "SQL", "SPSS", "数据分析", "数据可视化"], ["Tableau", "R", "Power BI"]),
(2022, 2023, ["SQL", "Python", "数据分析", "数据可视化", "Excel"], ["Power BI", "Tableau", "A/B测试"]),
(2024, 2026, ["SQL", "Python", "数据分析", "数据可视化", "A/B测试"], ["Power BI", "Tableau", "大模型应用开发"])],
{2019: 5, 2020: 5, 2021: 6, 2022: 8, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
arc("测试开发工程师", "测试", 3, "14K-26K", ["金融", "电商", "政务"],
["互联网/软件"],
["负责{o}的测试方案设计", "开发{o}的自动化测试脚本", "搭建{o}的测试平台",
"执行{o}的性能压测", "推动{o}的质量效能改进"],
["核心交易系统", "支付链路", "回归测试", "接口自动化", "压测体系", "质量平台"],
[(2019, 2021, ["Python", "自动化测试", "Selenium", "接口测试", "SQL"], ["JMeter", "JUnit", "Jenkins"]),
(2022, 2026, ["Python", "自动化测试", "接口测试", "性能测试", "CI/CD"], ["Pytest", "JMeter", "Docker"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 6, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
# —— 运维:脚本/手工 → Ansible 自动化 → DevOps/K8s → AIOps ——
arc("运维工程师(SRE)", "运维", 3, "15K-28K", ["金融", "游戏", "电商"],
["互联网/软件"],
["负责{o}的稳定运行与监控", "参与{o}的容量规划", "建设{o}的自动化运维体系",
"处理{o}的线上故障与应急", "完善{o}的告警与巡检机制"],
["生产集群", "发布流水线", "监控体系", "容器平台", "中间件", "灾备体系"],
[(2019, 2021, ["Linux", "Shell", "Nginx", "MySQL", "Tomcat"], ["Ansible", "Jenkins", "Python"]),
(2022, 2023, ["Linux", "Docker", "Kubernetes", "CI/CD", "Ansible"], ["Prometheus", "DevOps", "Grafana"]),
(2024, 2026, ["Linux", "Kubernetes", "Docker", "Prometheus", "DevOps"], ["Grafana", "Terraform", "AIOps"])],
{2019: 4, 2020: 4, 2021: 6, 2022: 8, 2023: 12, 2024: 24, 2025: 24, 2026: 24}),
arc("嵌入式工程师", "嵌入式", 3, "14K-28K", ["智能制造", "安防", "出行"],
["智能制造", "物联网"],
["负责{o}的固件开发", "参与{o}的驱动调试", "完成{o}的板级联调与测试",
"优化{o}的功耗与稳定性", "编写{o}的开发文档"],
["主控固件", "通信模组", "传感器驱动", "boot 启动流程", "低功耗方案", "量产固件"],
[(2019, 2022, ["C", "C++", "嵌入式开发", "单片机", "RTOS"], ["STM32", "FreeRTOS", "Linux"]),
(2023, 2026, ["C", "C++", "嵌入式开发", "RTOS", "驱动开发"], ["STM32", "边缘计算", "MQTT"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 4, 2023: 5, 2024: 6, 2025: 6, 2026: 6}),
arc("物联网工程师", "物联网", 3, "13K-25K", ["智能制造", "物流", "安防"],
["物联网", "智慧城市"],
["负责{o}的接入方案设计", "开发{o}的设备管理功能", "搭建{o}的数据采集链路",
"参与{o}的平台联调", "优化{o}的通信稳定性"],
["设备接入", "网关", "传感网络", "边缘节点", "设备影子", "远程升级"],
[(2019, 2021, ["C", "MQTT", "传感器", "单片机", "物联网平台"], ["Zigbee", "LoRa", "STM32"]),
(2022, 2026, ["MQTT", "物联网平台", "边缘计算", "Python", "传感器"], ["LoRa", "嵌入式开发", "云计算"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}),
arc("NLP工程师", "AI算法", 3, "18K-36K", ["教育", "政务", "金融"],
["人工智能"],
["负责{o}的算法研发", "参与{o}的语料建设", "优化{o}的模型效果",
"跟进{o}的前沿技术", "支持{o}的工程化落地"],
["智能客服", "文本分类", "信息抽取", "问答系统", "搜索相关性", "舆情分析"],
[(2019, 2021, ["Python", "NLP", "机器学习", "TensorFlow", "SQL"], ["知识图谱", "数据挖掘", "深度学习"]),
(2022, 2023, ["Python", "NLP", "深度学习", "PyTorch", "知识图谱"], ["模型微调", "数据挖掘", "机器学习"]),
(2024, 2026, ["Python", "NLP", "深度学习", "PyTorch", "大模型应用开发"], ["模型微调", "RAG", "LangChain"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 6, 2024: 8, 2025: 8, 2026: 8}),
arc("CV工程师", "AI算法", 3, "18K-36K", ["安防", "智能制造", "出行"],
["人工智能", "智能制造"],
["负责{o}的算法研发", "参与{o}的数据标注体系", "优化{o}的模型精度与速度",
"部署{o}到边缘设备", "跟进{o}的最新论文"],
["缺陷检测", "目标检测", "视频结构化", "人脸识别", "车道线检测", "工业质检"],
[(2019, 2021, ["Python", "计算机视觉", "深度学习", "TensorFlow", "C++"], ["OCR", "OpenCV", "模型微调"]),
(2022, 2023, ["Python", "计算机视觉", "深度学习", "PyTorch", "OCR"], ["模型微调", "边缘计算", "OpenCV"]),
(2024, 2026, ["Python", "计算机视觉", "深度学习", "PyTorch", "OCR"], ["模型微调", "边缘计算", "大模型应用开发"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 6, 2024: 8, 2025: 8, 2026: 8}),
arc("云原生工程师", "云原生", 3, "18K-35K", ["金融", "政务", "电商"],
["互联网/软件"],
["负责{o}的架构设计与落地", "建设{o}的容器编排体系", "推进{o}的服务治理",
"优化{o}的资源利用率", "保障{o}的高可用"],
["容器平台", "微服务治理", "多云架构", "弹性伸缩", "服务网格", "可观测体系"],
[(2020, 2022, ["Docker", "Kubernetes", "微服务", "Linux", "Go"], ["Service Mesh", "Prometheus", "DevOps"]),
(2023, 2026, ["Kubernetes", "Docker", "微服务", "CI/CD", "Go"], ["Service Mesh", "Terraform", "云计算"])],
{2020: 4, 2021: 4, 2022: 5, 2023: 6, 2024: 8, 2025: 8, 2026: 8}),
arc("AI产品经理", "产品", 3, "18K-35K", ["教育", "金融", "医疗"],
["人工智能", "智慧医疗"],
["负责{o}的规划与落地", "输出{o}的需求文档", "跟进{o}的研发进度",
"设计{o}的评估指标", "调研{o}的行业动态"],
["智能问答产品", "AI 助手", "智能化应用", "知识库产品", "智能审核", "AI 创作工具"],
[(2020, 2022, ["产品设计", "需求分析", "数据分析", "项目管理", "AI产品"], ["Axure", "竞品分析", "SQL"]),
(2023, 2026, ["AI产品", "需求分析", "大模型应用开发", "产品设计", "数据分析"], ["提示词工程", "用户增长", "A/B测试"])],
{2020: 3, 2021: 3, 2022: 3, 2023: 4, 2024: 6, 2025: 6, 2026: 6}),
arc("Go开发工程师", "后端开发", 3, "16K-32K", ["游戏", "社交", "金融"],
["互联网/软件"],
BACKEND_DUTIES, BACKEND_OBJS,
[(2019, 2021, ["Go", "MySQL", "Redis", "Linux", "Gin"], ["Docker", "gRPC", "Kafka"]),
(2022, 2026, ["Go", "微服务", "gRPC", "Redis", "Kubernetes"], ["Kafka", "Prometheus", "高并发"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 6, 2024: 8, 2025: 8, 2026: 8}),
# —— 2023 年后才出现且快速增长的新岗位(支撑“新岗位发现”演示) ——
arc("大模型应用工程师", "AI算法", 2, "25K-50K", ["金融", "教育", "医疗"],
["人工智能"],
["负责{o}的应用开发与落地", "设计{o}的提示词与流程编排", "建设{o}的评测体系",
"优化{o}的推理成本与延迟", "跟进{o}的生态工具"],
["智能助手", "企业知识库", "Agent 应用", "代码助手", "智能审核", "多轮对话"],
[(2023, 2026, ["Python", "大模型应用开发", "提示词工程", "LangChain", "NLP"], ["RAG", "模型微调", "向量数据库"])],
{2023: 2, 2024: 8, 2025: 14, 2026: 20}),
arc("RAG工程师", "AI算法", 2, "25K-45K", ["金融", "政务", "教育"],
["人工智能"],
["负责{o}的检索链路搭建", "优化{o}的召回与重排", "建设{o}的知识库加工流水线",
"评估{o}的问答质量", "跟进{o}的新范式"],
["企业知识库", "文档问答", "语义检索", "混合检索", "知识中台", "智能客服"],
[(2024, 2026, ["Python", "RAG", "向量数据库", "大模型应用开发", "LangChain"], ["模型微调", "Elasticsearch", "知识图谱"])],
{2024: 4, 2025: 9, 2026: 15}),
arc("提示词工程师", "AI算法", 1, "15K-30K", ["教育", "电商", "广告"],
["人工智能"],
["负责{o}的提示词设计", "沉淀{o}的提示词模板库", "评估{o}的输出质量",
"与业务团队共创{o}的使用范式", "编写{o}的最佳实践文档"],
["营销文案生成", "智能客服话术", "内容创作", "教学辅导", "商品描述", "对话流程"],
[(2024, 2026, ["提示词工程", "大模型应用开发", "Python", "数据分析"], ["LangChain", "RAG", "AI产品"])],
{2024: 2, 2025: 6, 2026: 10}),
# —— 岗位覆盖扩展(8 个既有岗位族,2019 年前已存在,支撑赛题领域覆盖) ——
# 大数据开发:2019-2021 Hadoop 离线系 → 2022+ Flink 实时/湖仓一体(演化信号)
arc("大数据开发工程师", "大数据", 3, "16K-32K", ["电商", "金融", "短视频"],
["互联网/软件", "金融科技"],
["负责{o}的离线计算任务开发", "搭建{o}的实时计算链路", "参与{o}的数据模型设计",
"优化{o}的任务性能与资源消耗", "维护{o}的调度依赖与数据质量"],
["离线数仓", "实时数仓", "用户行为日志", "流量数据", "交易数据", "数据集市"],
[(2019, 2021, ["SQL", "Hadoop", "Hive", "Spark", "HDFS"], ["Sqoop", "HBase", "Scala"]),
(2022, 2026, ["SQL", "Spark", "Flink", "Kafka", "Hive"], ["ClickHouse", "Doris", "湖仓一体"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
# 机器学习工程师:2023+ 加分项出现"模型微调/大模型应用开发"(演化信号)
arc("机器学习工程师", "AI算法", 3, "18K-35K", ["金融", "电商", "广告"],
["人工智能"],
["负责{o}的特征工程与模型训练", "参与{o}的离线评估与线上实验", "优化{o}的推理性能与资源占用",
"建设{o}的样本与特征流水线", "跟进{o}的算法迭代与复盘"],
["风控模型", "搜索排序", "召回策略", "销量预测", "异常检测", "用户分层"],
[(2019, 2022, ["Python", "机器学习", "Scikit-learn", "SQL", "XGBoost"], ["LightGBM", "TensorFlow", "Spark"]),
(2023, 2026, ["Python", "机器学习", "深度学习", "PyTorch", "XGBoost"], ["模型微调", "大模型应用开发", "LightGBM"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
arc("智能机器人算法工程师", "AI算法", 3, "20K-40K", ["智能制造", "物流", "出行"],
["人工智能", "智能制造"],
["负责{o}的算法研发与调优", "参与{o}的仿真验证与实机部署", "优化{o}的实时性与鲁棒性",
"建设{o}的数据闭环与评测体系", "跟进{o}的前沿方案并落地"],
["SLAM 建图", "定位导航", "运动规划", "多传感器融合", "机械臂控制", "避障策略"],
[(2019, 2026, ["C++", "Python", "ROS", "SLAM", "路径规划"], ["深度学习", "强化学习", "OpenCV"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
arc("数据治理工程师", "大数据", 3, "15K-30K", ["金融", "政务", "医疗"],
["金融科技", "互联网/软件"],
["负责{o}的标准制定与落地", "建设{o}的元数据与血缘体系", "推进{o}的质量监控与整改",
"制定{o}的分级分类与脱敏策略", "组织{o}的盘点与确权工作"],
["数据资产", "主数据", "指标口径", "敏感数据", "数据目录", "质量规则"],
[(2019, 2026, ["SQL", "数据治理", "元数据管理", "数据脱敏", "Python"], ["数据血缘", "Hive", "Spark"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
arc("边缘计算工程师", "物联网", 3, "16K-30K", ["智能制造", "安防", "物流"],
["物联网", "智能制造"],
["负责{o}的部署与调优", "参与{o}的模型压缩与推理加速", "建设{o}的云边协同链路",
"优化{o}的资源占用与稳定性", "编写{o}的技术文档"],
["边缘网关", "边缘节点", "端侧推理", "视频分析", "设备接入", "边云协同"],
[(2019, 2021, ["C++", "Python", "Linux", "MQTT", "嵌入式开发"], ["Docker", "边缘计算", "OpenCV"]),
(2022, 2026, ["Python", "边缘计算", "Docker", "Linux", "MQTT"], ["边缘推理", "TensorRT", "KubeEdge"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
arc("物联网安全工程师", "物联网", 3, "16K-32K", ["智能制造", "安防", "政务"],
["物联网", "智慧城市"],
["负责{o}的安全评估与加固", "建设{o}的入侵检测与响应体系", "参与{o}的固件安全审计",
"制定{o}的接入认证策略", "跟踪{o}的漏洞情报与处置"],
["设备接入", "设备网络", "边缘网关", "固件", "通信协议", "密钥体系"],
[(2019, 2026, ["Linux", "Python", "入侵检测", "零信任", "MQTT"], ["等保合规", "嵌入式开发", "云计算"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
arc("智能系统架构师", "云原生", 5, "30K-60K·14薪", ["金融", "政务", "智能制造"],
["互联网/软件", "人工智能"],
["负责{o}的整体架构设计", "主导{o}的技术选型与评审", "制定{o}的容量与容灾方案",
"推动{o}的架构演进与落地", "沉淀{o}的架构规范与最佳实践"],
["智能平台", "业务中台", "云边端协同", "高可用体系", "多云架构", "技术路线"],
[(2019, 2021, ["分布式系统", "微服务", "云计算", "高并发", "Linux"], ["Docker", "Kubernetes", "Service Mesh"]),
(2022, 2026, ["分布式系统", "微服务", "Kubernetes", "云计算", "高并发"], ["Service Mesh", "边缘计算", "物联网平台"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
arc("隐私计算工程师", "AI算法", 4, "25K-45K", ["金融", "政务", "医疗"],
["人工智能", "金融科技"],
["负责{o}的方案设计与实现", "参与{o}的性能优化与工程化", "建设{o}的协同计算链路",
"评估{o}的安全性与合规性", "跟进{o}的最新研究成果"],
["联邦建模", "多方联合统计", "安全求交", "数据协作", "密文计算", "隐私保护"],
[(2019, 2026, ["Python", "机器学习", "联邦学习", "同态加密", "多方安全计算"], ["差分隐私", "模型微调", "Spark"])],
{2019: 4, 2020: 4, 2021: 4, 2022: 5, 2023: 5, 2024: 6, 2025: 6, 2026: 6}, test_n=4),
]
COMPANY_PRE = ["星澜", "云启", "数联", "智汇", "蓝湾", "极光", "恒宇", "锐思", "博远", "辰安",
"飞鱼", "墨白", "青藤", "远望", "砺石", "潮汐", "峰行", "微光", "若谷", "启航"]
COMPANY_SUF = ["科技", "网络", "信息", "数据", "智能", "软件", "互联", "数字"]
# 15 城:一线 + 新一线(成都/武汉/西安/苏州/长沙等)
CITIES = ["北京", "上海", "深圳", "杭州", "成都", "广州", "南京", "武汉",
"西安", "苏州", "长沙", "重庆", "天津", "青岛", "合肥"]
SOURCES = ["BOSS直聘", "拉勾网", "智联招聘", "前程无忧", "猎聘网"]
# ---------------------------------------------------------------- 文本渲染素材
# 公司介绍:按年代分池,时代措辞只出现在对应年份之后
INTROS_EARLY = [
"{c}是一家专注于新一代信息技术服务的高新技术企业,现诚邀优秀人才加入。",
"{c}深耕行业多年,团队氛围开放,技术栈前沿,期待你的加入。",
"{c}业务高速增长中,提供有竞争力的薪酬与完善的培养体系。",
"{c}核心团队来自一线大厂,正在寻找志同道合的工程师。",
"{c}处于快速扩张期,移动业务用户量持续攀升,欢迎加入我们。",
]
INTROS_MID = INTROS_EARLY + [
"{c}已完成新一轮融资,正全面推进云原生架构升级,期待你的加入。",
"{c}业务覆盖多个城市,研发体系成熟,重视工程质量与技术沉淀。",
]
INTROS_LATE = INTROS_MID + [
"{c}全面拥抱 AI 原生开发,大模型已深度融入研发流程,欢迎同行者。",
"{c}正在推进 AIGC 与核心业务的深度融合,寻找敢想敢做的工程师。",
"{c}智能化转型加速,AI 辅助研发已成团队标配,期待你的加入。",
]
# 项目背景/团队介绍(可选段落,{a} 只会代入本条 JD 已标注的场景词)
BACKGROUNDS = [
"关于我们:{c}的{a}业务正处于高速增长期,你将直接参与支撑千万级用户的核心系统建设,与团队一起解决真实复杂的业务问题。",
"项目背景:本岗位属于{a}方向核心团队,业务数据量大、迭代节奏快,技术挑战与成长空间并存。",
"团队介绍:{a}研发团队规模 50+,核心成员来自一线大厂,重视工程质量与技术沉淀。",
]
# 团队与福利(可选尾部段落,抽取器按标题截断,不进入任何技能区)
WELFARE_LINES = [
"弹性工作不打卡,五险一金全额缴纳,年度体检与带薪年假一应俱全。",
"技术氛围浓厚,每周内部分享,提供外部培训与技术会议预算。",
"扁平化管理,晋升通道清晰,核心成员可参与期权激励计划。",
"免费三餐与下午茶,团队年轻化,协作氛围轻松高效。",
]
REQ_YEAR_LINES = [
"{y}年以上相关工作经验,责任心强,具备良好的沟通能力;",
"{y}年以上相关岗位经验,具备良好的沟通与推动能力;",
"{y}年以上实战经验,结果导向,能独立承担模块 Owner 工作;",
]
REQ_VERBS = ["熟练掌握", "精通", "熟悉并掌握", "深入理解"]
REQ_SOFT_LINES = [
"具备良好的学习能力与团队协作精神;",
"逻辑清晰,自驱力强,对技术有热情;",
"具备良好的文档习惯,重视工程质量与可维护性;",
"能适应快速迭代的研发节奏,抗压能力强;",
]
SCEN_TEMPLATES = ["具有{a}或{b}行业经验者优先;", "熟悉{a}/{b}业务场景者优先;",
"有{a}、{b}行业项目经验者优先;", "具备{a}或{b}相关业务背景者优先;"]
PREF_TEMPLATES = ["了解{s}者优先;", "熟悉{s}者优先考虑;", "有{s}相关实践经验者优先;"]
PREF_EXTRA_LINES = ["有开源项目贡献或高质量技术博客者优先;", "参与过大型技术社区分享者优先;"]
NUM_FORMATS = ["{i}、", "{i}、", "{i}、", "{i}.", "- "]
NOISE_TAILS = [
"【广告】扫码关注公众号,领取面试大礼包和内部资料。",
"点击关注我们的招聘号,第一时间获取内推信息。",
"【广告】商务合作请加群,扫码领取免费课程资料。",
]
NOISE_FULL = [
"【广告】扫码关注公众号领取求职资料\n点击关注领取福利红包\n长期回收二手办公设备,非诚勿扰",
"【广告】推广信息:扫码加入求职群领取资料\n商务合作请加群详谈\n加盟代理热线见官网",
"【广告】点击关注即可领取现金红包\n扫码进福利群,天天有惊喜\n代办各类证件,长期有效",
"【广告】推广信息:刷单兼职日结\n扫码添加客服领取任务\n长期回收库存尾货",
]
def intros_for(year: int) -> list[str]:
if year >= 2024:
return INTROS_LATE
if year >= 2022:
return INTROS_MID
return INTROS_EARLY
def skillset_for(a: dict, year: int) -> tuple[list[str], list[str]]:
for y0, y1, req, pref in a["timeline"]:
if y0 <= year <= y1:
return list(req), list(pref)
req, pref = a["timeline"][-1][2], a["timeline"][-1][3]
return list(req), list(pref)
def pick_duties(a: dict, year: int) -> list[str]:
"""按年份过滤句式池(时代门槛),抽 3-6 条职责。"""
pool = list(a["duty_tmpls"]) + [t for t, min_y in GENERIC_DUTIES if year >= min_y]
tmpls = rng.sample(pool, k=min(len(pool), rng.choice([3, 4, 4, 5, 5, 6])))
objs = rng.sample(a["duty_objs"], k=min(len(a["duty_objs"]), len(tmpls)))
while len(objs) < len(tmpls):
objs.append(rng.choice(a["duty_objs"]))
return [t.format(o=o) + ";" for t, o in zip(tmpls, objs)]
def _skill_req_lines(req: list[str]) -> list[str]:
"""必备技能行的多种自然写法(都在要求区内,抽取结果与措辞无关)。"""
verb = rng.choice(REQ_VERBS)
if len(req) >= 4 and rng.random() < 0.4:
cut = rng.randint(2, len(req) - 2)
return [f"{verb}{'、'.join(req[:cut])},熟悉{'、'.join(req[cut:])};"]
if rng.random() < 0.25:
return [f"具备扎实的{'、'.join(req)}功底;"]
return [f"{verb}{'、'.join(req)};"]
def build_text(a: dict, company: str, year: int, years: int, duties: list[str],
req: list[str], pref: list[str], scens: list[str]) -> str:
duty_h = rng.choice(DUTY_HEADERS)
req_h = rng.choice(REQ_HEADERS)
pref_h = rng.choice(PREF_HEADERS)
num_fmt = rng.choice(NUM_FORMATS)
scen_sentence = rng.choice(SCEN_TEMPLATES).format(a=scens[0], b=scens[-1])
lines = [
f"岗位名称:{a['title']}",
rng.choice(intros_for(year)).format(c=company),
]
# 可选段落:项目背景/团队介绍(约 35%)
if rng.random() < 0.35:
lines.append(rng.choice(BACKGROUNDS).format(c=company, a=scens[0]))
lines.append(f"{duty_h}:")
lines += [f"{num_fmt.format(i=i + 1)}{d}" for i, d in enumerate(duties)]
lines.append(f"{req_h}:")
req_lines = [rng.choice(REQ_YEAR_LINES).format(y=years)]
req_lines += _skill_req_lines(req)
req_lines.append(scen_sentence)
req_lines += rng.sample(REQ_SOFT_LINES, k=rng.choice([0, 1, 1, 2]))
lines += [f"{num_fmt.format(i=i + 1)}{t}" for i, t in enumerate(req_lines)]
lines.append(f"{pref_h}:")
lines.append(f"1、{rng.choice(PREF_TEMPLATES).format(s='、'.join(pref))}")
if rng.random() < 0.4:
lines.append(f"2、{rng.choice(PREF_EXTRA_LINES)}")
# 可选尾部段落:团队与福利(约 40%),抽取器按标题截断
if rng.random() < 0.40:
lines.append(f"{rng.choice(TAIL_HEADERS)}:")
lines.append(rng.choice(WELFARE_LINES))
return "\n".join(lines)
def make_jd(a: dict, year: int, jid: str, month: int | None = None) -> tuple[dict, dict]:
"""生成一条 JD 记录与其标准答案(先定结构,再渲染文本)。
month 可由调用方指定(原始数据按年内均匀铺开,避免季度窗口计数随机抖动
制造虚假演化事件);不传则随机(测试集保持自然随机)。
"""
company = rng.choice(COMPANY_PRE) + rng.choice(COMPANY_SUF)
req, pref = skillset_for(a, year)
rng.shuffle(req)
rng.shuffle(pref)
if len(req) > 4 and rng.random() < 0.15: # 轻微抖动:偶尔少写一项必备
req = req[:-1]
pref = pref[: rng.choice([2, 2, 3])]
duties = pick_duties(a, year)
scens = rng.sample(a["scenarios"], k=min(2, len(a["scenarios"])))
years = rng.randint(max(1, a["years"] - 1), a["years"] + 2)
text = build_text(a, company, year, years, duties, req, pref, scens)
month = month or rng.randint(1, 12)
day = rng.randint(1, 28)
record = {
"jid": jid,
"job_title": a["title"],
"company": company,
"city": rng.choice(CITIES),
"salary": a["salary"],
"industry": rng.choice(a["industries"]),
"publish_date": date(year, month, day).isoformat(),
"source": rng.choice(SOURCES),
"url": f"https://jobs.example.com/{jid}",
"text": text,
}
gold = {
"job_title": a["title"],
"responsibilities": duties,
"required_skills": req,
"preferred_skills": pref,
"scenarios": scens,
}
return record, gold
def make_dup_copy(rec: dict, jid: str) -> dict:
"""生成近重复(抄袭)副本:同文不同公司,仅换公司/城市/渠道/薪资与发布日期。"""
new_company = rng.choice(COMPANY_PRE) + rng.choice(COMPANY_SUF)
text = rec["text"].replace(rec["company"], new_company)
copy = dict(rec)
copy.update({
"jid": jid,
"company": new_company,
"city": rng.choice(CITIES),
"source": rng.choice(SOURCES),
"url": f"https://jobs.example.com/{jid}",
"salary": rec["salary"].replace("14薪", "13薪") if "14薪" in rec["salary"] else rec["salary"],
"text": text,
"publish_date": min(
date.fromisoformat(rec["publish_date"]) + timedelta(days=rng.randint(10, 120)),
date(2026, 12, 28)).isoformat(),
})
return copy
def write_jsonl(path: Path, rows: list[dict]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
for r in rows:
f.write(json.dumps(r, ensure_ascii=False) + "\n")
# ---------------------------------------------------------------- 简历样例(全合成,无真实个人信息)
RESUME_FRONTEND_FULL = (
"姓名:陈思远\n手机:13655557777\n邮箱:chensy@example.com\n"
"4年前端开发经验,主导过大促会场与管理后台的前端架构设计。\n"
"核心技能:熟练掌握JavaScript、TypeScript、HTML、CSS,精通Vue、React双栈,"
"熟悉Vite、Webpack、Node.js与小程序开发,有低代码平台建设经验,日常使用AI辅助编程提效。\n"
"项目经历:负责可视化大屏与管理后台开发,基于Vue与Vite搭建工程化体系;"
"使用React与TypeScript重构信息流页面,首屏性能提升40%。\n"
)
RESUME_DATA_PARTIAL = (
"姓名:刘洋\n手机:13566668888\n邮箱:liuyang.data@example.com\n"
"2年数据分析经验,服务于零售业务线,支持运营团队的日常取数与复盘。\n"
"核心技能:熟练使用SQL取数,掌握Excel、数据可视化与Tableau看板搭建,"
"能用Python完成数据清洗与报表自动化,了解Power BI。\n"
"项目经历:搭建活动效果核心指标看板,输出渠道投放专题分析,"
"在校期间曾用SPSS完成调研统计。\n"
)
RESUME_LLM_FULL = (
"姓名:赵启明\n手机:13777778888\n邮箱:zhaoqm@example.com\n"
"3年AI应用开发经验,专注大模型应用开发与落地。\n"
"核心技能:精通Python,熟悉大模型应用开发、提示词工程、LangChain与RAG,"
"掌握向量数据库与模型微调,了解NLP基础,熟悉FastAPI服务开发。\n"
"项目经历:主导企业知识库问答系统建设,基于RAG与LangChain实现混合检索与重排,"
"通过提示词工程与模型微调将回答准确率提升25%。\n"
)
RESUME_LEGACY_MISMATCH = (
"姓名:孙建国\n手机:13899990000\n邮箱:sunjg@example.com\n"
"8年传统软件经验,长期维护企业内部办公系统。\n"
"核心技能:精通Struts、JSP、Servlet,熟悉Svn与Tomcat部署,"
"掌握jQuery页面开发,了解WebLogic。\n"
"项目经历:负责政务办公系统的日常维护与功能迭代,使用Struts与JSP完成多个模块改造。\n"
)
def _cand(title: str, req: list[str], pref: list[str], scens: list[str],
src: int, comp: int, status: str = "pending") -> dict:
"""构造一条待审核候选的快照(审核留痕种子用)。"""
return {"job_id": f"cand_{title}", "title": title, "category": "新岗位候选",
"required_skills": req, "preferred_skills": pref, "responsibilities": [],
"scenarios": scens, "expected_years": 3, "status": status,
"source_count": src, "company_count": comp}
AUDIT_SEED = [
{"candidate_id": "cand_大模型应用工程师", "action": "accept",
"operator": "王蕾(评审专家)",
"reason": "岗位簇证据充分:40+ 条 JD、独立企业数达标,2024 年起持续高增长,技能结构清晰,准予入库。",
"before": _cand("大模型应用工程师",
["提示词工程", "Python", "LangChain", "大模型应用开发", "NLP"],
["模型微调", "向量数据库", "RAG"], ["教育", "医疗", "金融"], 42, 38),
"after": _cand("大模型应用工程师",
["提示词工程", "Python", "LangChain", "大模型应用开发", "NLP"],
["模型微调", "向量数据库", "RAG"], ["教育", "医疗", "金融"], 42, 38, "active"),
"time": "2026-07-18 10:24:31"},
{"candidate_id": "cand_RAG工程师", "action": "modify",
"operator": "李强(评审专家)",
"reason": "簇内 JD 普遍要求检索引擎实操经验,补充 Elasticsearch 为必备技能后入库。",
"before": _cand("RAG工程师",
["Python", "RAG", "向量数据库", "大模型应用开发", "LangChain"],
["模型微调", "知识图谱"], ["金融", "政务", "教育"], 28, 22),
"after": _cand("RAG工程师",
["Python", "RAG", "向量数据库", "大模型应用开发", "LangChain", "Elasticsearch"],
["模型微调", "知识图谱"], ["金融", "政务", "教育"], 28, 22, "active"),
"time": "2026-07-19 15:02:11"},
{"candidate_id": "cand_元宇宙社区运营", "action": "reject",
"operator": "王蕾(评审专家)",
"reason": "簇内 JD 仅 5 条且集中于 2 家企业,近一年增长不明朗,证据不足,暂不入库。",
"before": _cand("元宇宙社区运营", ["用户增长", "竞品分析"], ["数据分析"],
["社交", "游戏"], 5, 2),
"after": {},
"time": "2026-07-21 09:41:03"},
{"kind": "node_update", "node_id": "job_Java开发工程师",
"operator": "张铭(领域专家)",
"reason": "2024 年后分布式系统已成为该岗位核心要求,上调该关系权重。",
"before": {"weight": 0.82}, "after": {"weight": 0.95},
"time": "2026-07-23 14:12:55"},
{"kind": "node_update", "node_id": "Kubernetes",
"operator": "张铭(领域专家)",
"reason": "词表归类校正:由未标注类别调整为云原生类别。",
"before": {"category": ""}, "after": {"category": "云原生"},
"time": "2026-07-23 14:15:20"},
{"candidate_id": "cand_提示词工程师", "action": "accept",
"operator": "陈静(评审专家)",
"reason": "2024 年起多家企业独立设岗,职责与传统运营岗差异显著,予以入库观察。",
"before": _cand("提示词工程师",
["提示词工程", "大模型应用开发", "Python", "数据分析"],
["LangChain", "RAG", "AI产品"], ["教育", "电商", "广告"], 18, 14),
"after": _cand("提示词工程师",
["提示词工程", "大模型应用开发", "Python", "数据分析"],
["LangChain", "RAG", "AI产品"], ["教育", "电商", "广告"], 18, 14, "active"),
"time": "2026-07-25 11:30:44"},
{"kind": "node_update", "node_id": "job_运维工程师(SRE)",
"operator": "李强(评审专家)",
"reason": "按 2026 年 JD 样本补全岗位级别标注。",
"before": {"level": None}, "after": {"level": "中级"},
"time": "2026-07-28 16:48:09"},
]
# ---------------------------------------------------------------- 报告样例(与 JD 演化信号相互印证)
REPORT_TREND = (
"新一代信息技术岗位能力趋势报告(样例)\n\n"
"一、总体趋势\n"
"2019-2026 年,后端岗位从 SSM/Servlet 体系加速转向 Spring Boot/Spring Cloud 微服务体系,"
"容器化(Docker/Kubernetes)已成为运维与后端岗位的通用要求。\n\n"
"二、AI 原生岗位崛起\n"
"2023 年起,大模型应用工程师、RAG工程师、提示词工程师等新岗位快速增长,"
"大模型应用开发、提示词工程、向量数据库成为增速最快的技能点。\n\n"
"三、传统技能退出\n"
"Struts、JSP、Svn 等传统技术栈在 2022 年后基本退出主流 JD。\n"
"四、AI 辅助编程普及\n"
"2024 年起,AI辅助编程(Copilot 类工具)开始作为加分项出现在后端岗位 JD 中。\n"
)
REPORT_TALENT_2026 = (
"新一代信息技术人才发展报告(2026)(节选·样例)\n\n"
"一、总体格局:能力图谱加速重构\n"
"2019-2026 年,信息技术岗位的能力要求经历了从“框架驱动”到“云原生驱动”再到“AI 原生驱动”"
"的三次跃迁。招聘 JD 数据显示,微服务、容器化已于 2022 年前后完成普及,成为后端与运维岗位的"
"基础要求;2024 年起,大模型相关能力以前所未有的速度进入各岗位的能力图谱。\n\n"
"二、AI 原生岗位爆发式增长\n"
"大模型应用工程师自 2023 年出现以来需求连年翻倍,2026 年新发岗位量已达 2023 年的十倍以上;"
"RAG工程师、提示词工程师自 2024 年起独立设岗。值得注意的是,提示词工程相关岗位需求从 2023 年"
"起爆发,企业对该能力的要求正从“会用”转向“体系化”:提示词模板库沉淀、输出质量评估、与业务"
"流程的编排结合成为高频要求。\n\n"
"三、AI 辅助编程渗透率快速上升\n"
"2024 年起,AI辅助编程(Copilot 类工具)开始以加分项形式进入后端、前端岗位 JD;到 2026 年,"
"约半数新发后端岗位 JD 提及 AI 辅助研发能力,“使用大模型辅助开发与代码审查”一类职责表述明显"
"增多。AI 工具链正从“个人效率工具”升级为“团队工程标配”。\n\n"
"四、前端:从框架之争到工程化与智能化\n"
"jQuery、AngularJS 相关要求在 2022 年后加速退场,Vue/React + TypeScript 成为绝对主流;构建"
"工具方面,Vite 已基本取代 Webpack 成为新项目标配。2024 年起,低代码平台与 AI 辅助生成进入"
"前端岗位核心要求,前端工程师的能力重心从“写页面”转向“搭体系”。\n\n"
"五、运维与分析岗位的智能化迁移\n"
"运维岗位沿“脚本手工 → Ansible 自动化 → DevOps/Kubernetes → AIOps”路径演进,2024 年起 AIOps"
"首次进入岗位加分项;数据分析岗位则完成了“Excel/SPSS 退场、SQL/Python 成标配”的换代,2024 年"
"起大模型增强分析(自然语言取数、报告自动生成)开始进入要求清单。\n\n"
"六、传统技术栈出清\n"
"Struts、JSP、Svn、WebLogic 等传统技术栈在 2022 年后基本退出主流 JD,仅存的少量需求集中于"
"存量系统维护岗位,且普遍标注“接受老系统维护经验”作为过渡安排。\n"
)
REPORT_DIGITAL_ECONOMY = (
"数字经济就业趋势观察(2026 年上半年)(节选·样例)\n\n"
"一、区域格局:新一线城市承接效应显著\n"
"2026 年上半年,信息技术岗位的区域分布持续多极化。北京、上海、深圳、杭州仍是岗位密度最高的"
"第一梯队,但成都、武汉、西安、苏州、长沙等新一线城市的岗位占比连续第三年上升,合计占比已"
"接近三成。其中成都以后端与游戏研发见长,武汉、西安依托高校资源在嵌入式与智能制造方向增速"
"领先,苏州、长沙则在工业互联网与物联网岗位上放量明显。\n\n"
"二、岗位结构:AI 岗位从“概念热”走向“用工实”\n"
"与 2023 年大模型岗位“重算法研究”不同,2026 年的需求主体已转向应用落地:大模型应用工程师、"
"RAG工程师合计新发岗位量超过传统算法工程师的六成,提示词工程能力则从独立岗位演变为产品、"
"运营、数据分析等多岗位的通用加分项。用人单位普遍要求候选人同时具备工程落地能力与业务理解"
"能力,单纯的“调参型”简历竞争力明显下降。\n\n"
"三、技能更替:老栈出清与新栈下沉同步发生\n"
"上半年数据显示,Struts、JSP、Svn 等传统技术栈在新增 JD 中已基本绝迹;与之相对,原本集中"
"于头部企业的 Kubernetes、CI/CD、可观测体系等云原生能力,正快速下沉至中小企业 JD。运维岗位"
"的 AIOps 要求、数据分析岗位的大模型增强分析要求,虽然仍以加分项形式出现,但提及率环比均"
"翻倍增长,预计 1-2 年内转为必备项。\n\n"
"四、薪酬观察:AI 应用岗溢价收窄但基数抬高\n"
"大模型应用工程师的薪酬中位数仍领先通用后端岗位约 40%,但溢价幅度较 2024 年高点收窄;同时,"
"掌握 AI 工具链的通用岗位(后端、前端、测试)薪酬基数整体抬升,具备“AI+工程”复合能力的候选"
"人在议价中优势明显。\n\n"
"五、趋势研判\n"
"预计下半年岗位能力图谱的演化将沿三条主线展开:一是 AI 辅助研发能力从加分项转为默认要求;"
"二是低代码与 AI 生成进一步压缩初级前端岗位需求,中高级工程化人才缺口扩大;三是新一线城市"
"与一线城市的技能要求趋于同构,区域间人才竞争加剧。\n"
)
def main() -> None:
data = ROOT / "data"
data.mkdir(parents=True, exist_ok=True)
# 1. 技能词表 + 行业词表 + 岗位-行业归属
lexicon = {
"skills": [{"name": n, "category": c, "aliases": al, "level": lv, "prereqs": pre}
for n, c, al, lv, pre in SKILLS],
"scenarios": SCENARIOS,
"industries": INDUSTRIES,
"jobs": [{"title": a["title"], "category": a["category"],
"industries": a["industries"], "expected_years": a["years"]}
for a in ARCHETYPES],
}
(data / "skills_lexicon.json").write_text(
json.dumps(lexicon, ensure_ascii=False, indent=1), encoding="utf-8")
# 2. 原始 JD(按年份分批次)
raw_by_year: dict[int, list[dict]] = {y: [] for y in range(2019, 2027)}
seq = 0
for a in ARCHETYPES:
for year, count in sorted(a["volumes"].items()):
for i in range(count):
seq += 1
# 月份年内均匀铺开:季度窗口计数只随剧本(时间轴/量级)变化
rec, _ = make_jd(a, year, f"J{seq:05d}", month=i * 12 // count + 1)
raw_by_year[year].append(rec)
# 3. 植入噪声(约 3%):一半混排尾注(清洗时剔除行),一半整篇广告(整条标记)
all_records = [r for y in raw_by_year.values() for r in y]
noise_jids: list[str] = []
mixed = rng.sample(all_records, k=10)
for rec in mixed:
rec["text"] = rec["text"] + "\n" + rng.choice(NOISE_TAILS)
noise_jids.append(rec["jid"])
for i in range(8):
full = NOISE_FULL[i % len(NOISE_FULL)]
seq += 1
jid = f"J{seq:05d}"
year = rng.randint(2020, 2026)
raw_by_year[year].append({
"jid": jid, "job_title": rng.choice(ARCHETYPES)["title"],
"company": rng.choice(COMPANY_PRE) + rng.choice(COMPANY_SUF),
"city": rng.choice(CITIES), "salary": "面议",
"industry": rng.choice(INDUSTRIES),
"publish_date": date(year, rng.randint(1, 12), rng.randint(1, 28)).isoformat(),
"source": rng.choice(SOURCES), "url": f"https://jobs.example.com/{jid}",
"text": full,
})
noise_jids.append(jid)
# 4. 植入近重复(约 8%):抄袭源避开噪声记录,副本与原文高度相似
dup_groups: list[list[str]] = []
clean_pool = [r for r in all_records if r["jid"] not in noise_jids]
dup_sources = rng.sample(clean_pool, k=int(len(all_records) * 0.08))
for src in dup_sources:
seq += 1
copy = make_dup_copy(src, f"J{seq:05d}")
year = min(2026, int(copy["publish_date"][:4]))
raw_by_year[year].append(copy)
dup_groups.append([src["jid"], copy["jid"]])
for year, rows in raw_by_year.items():
write_jsonl(data / "jd_raw" / f"batch_{year}.jsonl", rows)
(data / "jd_raw" / "_meta.json").write_text(json.dumps(
{"dup_groups": dup_groups, "noise_jids": noise_jids}, ensure_ascii=False, indent=1),
encoding="utf-8")
# 5. 测试集(与 raw 不同 jid 命名空间)+ 标准答案
testset, gold = [], {}
tseq = 0
for a in ARCHETYPES:
per_arc = a["test_n"] # 原 18 岗位 × 8 + 扩展 8 岗位 × 4 = 176 条 >= 120
years = sorted(a["volumes"])
for _ in range(per_arc):
tseq += 1
year = years[-1] if rng.random() < 0.6 else rng.choice(years)
rec, g = make_jd(a, year, f"T{tseq:05d}")
testset.append(rec)
gold[rec["jid"]] = g
write_jsonl(data / "testset" / "jd_testset.jsonl", testset)
(data / "testset" / "gold_answers.json").write_text(
json.dumps(gold, ensure_ascii=False, indent=1), encoding="utf-8")
# 6. 人岗匹配标注对(正例:技能覆盖当前必备;反例:技能体系错位)
unrelated = {
"后端开发": ["C", "嵌入式开发", "单片机", "RTOS", "STM32"],
"前端": ["C", "单片机", "Verilog", "FPGA", "驱动开发"],
"大数据": ["Verilog", "FPGA", "PCB设计", "单片机", "C"],
"AI算法": ["PCB设计", "Verilog", "FPGA", "Zigbee", "LoRa"],
"数据分析": ["Verilog", "FPGA", "驱动开发", "单片机", "C"],
"测试": ["Verilog", "FPGA", "PCB设计", "LoRa", "Zigbee"],
"运维": ["Verilog", "FPGA", "PCB设计", "传感器", "Zigbee"],
"嵌入式": ["Excel", "SPSS", "Axure", "竞品分析", "用户增长"],
"物联网": ["Excel", "SPSS", "Axure", "竞品分析", "用户增长"],
"云原生": ["Verilog", "FPGA", "PCB设计", "单片机", "传感器"],
"产品": ["Verilog", "FPGA", "驱动开发", "单片机", "C"],
}
# 既有岗位(2023 年前已存在)才进入正式图谱,匹配标注只覆盖这些岗位
known_arcs = [a for a in ARCHETYPES if min(a["volumes"]) < 2023]
match_gold = []
for a in known_arcs:
req, pref = skillset_for(a, 2025)
pos_skills = req[: max(3, len(req) - 1)] + pref[:1]
match_gold.append({
"job_title": a["title"], "skills": pos_skills,
"years": a["years"] + 2, "scenarios": a["scenarios"][:2],
"expected_match": True,
})
neg_scen = [s for s in SCENARIOS if s not in a["scenarios"]][:2]
match_gold.append({
"job_title": a["title"], "skills": unrelated.get(a["category"], ["Excel", "SPSS"]),
"years": 1, "scenarios": neg_scen, "expected_match": False,
})
# 部分覆盖正例(剧本三岗位:缺 1-2 项必备但总体达标)
by_title = {a["title"]: a for a in ARCHETYPES}
for title in ["前端工程师", "数据分析师", "运维工程师(SRE)"]:
a = by_title[title]
req, pref = skillset_for(a, 2025)
match_gold.append({
"job_title": a["title"], "skills": req[:-2] + pref[:2],
"years": a["years"] + 1, "scenarios": a["scenarios"][:2],
"expected_match": True,
})
# 新增简历衍生的标注对(前端完整 / 数据分析部分 / 传统栈错位)
match_gold.append({
"job_title": "前端工程师",
"skills": ["JavaScript", "TypeScript", "HTML", "CSS", "Vue", "React",
"Vite", "Webpack", "Node.js", "小程序开发", "低代码平台", "AI辅助编程"],
"years": 4, "scenarios": ["电商", "社交"], "expected_match": True,
})
match_gold.append({
"job_title": "数据分析师",
"skills": ["SQL", "Excel", "数据分析", "数据可视化", "Tableau", "Python",
"Power BI", "SPSS"],
"years": 2, "scenarios": ["零售", "电商"], "expected_match": True,
})
match_gold.append({
"job_title": "数据分析师",
"skills": ["Struts", "JSP", "Servlet", "Svn", "Tomcat", "jQuery", "WebLogic"],
"years": 8, "scenarios": ["政务", "安防"], "expected_match": False,
})
(data / "testset" / "match_gold.json").write_text(
json.dumps(match_gold, ensure_ascii=False, indent=1), encoding="utf-8")
# 7. 简历样例(完整 / 部分 / 错位,含虚构姓名手机邮箱以验证脱敏)+ 技能标准答案
resumes_dir = data / "resumes"
resumes_dir.mkdir(parents=True, exist_ok=True)
r1 = (
"姓名:张伟\n手机:13812345678\n邮箱:zhangwei@example.com\n"
"5年后端开发经验,先后负责交易系统与支付链路的建设。\n"
"核心技能:熟练掌握Java、Spring Boot、Spring Cloud、MySQL、Redis,"
"熟悉微服务与分布式系统设计,了解Docker、Kafka、Kubernetes与高并发优化。\n"
"项目经历:主导订单中心微服务化改造,基于Spring Cloud与Redis支撑高并发下单;"
"使用Kafka搭建异步消息管道,覆盖电商与金融两大业务场景。\n"
)
r2 = (
"姓名:李娜\n手机:13998765432\n邮箱:lina.dev@example.com\n"
"2年后端开发经验,参与过企业内部管理系统开发。\n"
"核心技能:熟悉Java、Spring Boot、MyBatis、MySQL,了解Redis与Linux常用命令,"
"日常使用Git协作。\n"
"项目经历:负责报表模块开发,使用Spring Boot与MySQL实现数据查询接口。\n"
)
r3 = (
"姓名:王强\n电话:13755556666\n邮箱:wangq@example.com\n"
"4年嵌入式开发经验,服务于智能制造行业。\n"
"核心技能:精通C、C++,熟悉嵌入式开发、单片机、RTOS,"
"掌握STM32与FreeRTOS,了解MQTT协议。\n"
"项目经历:负责工业网关固件开发,完成传感器数据采集与边缘上报。\n"
)
resumes = {
"resume_full.txt": (r1, ["Java", "Spring Boot", "Spring Cloud", "MySQL", "Redis",
"微服务", "分布式系统", "Docker", "Kafka", "Kubernetes", "高并发"]),
"resume_partial.txt": (r2, ["Java", "Spring Boot", "MyBatis", "MySQL", "Redis", "Linux", "Git"]),
"resume_mismatch.txt": (r3, ["C", "C++", "嵌入式开发", "单片机", "RTOS",
"STM32", "FreeRTOS", "MQTT", "传感器"]),
"resume_frontend_full.txt": (
RESUME_FRONTEND_FULL,
["JavaScript", "TypeScript", "HTML", "CSS", "Vue", "React",
"Vite", "Webpack", "Node.js", "小程序开发", "低代码平台", "AI辅助编程"]),
"resume_data_partial.txt": (
RESUME_DATA_PARTIAL,
["SQL", "Excel", "数据分析", "数据可视化", "Tableau", "Python", "Power BI", "SPSS"]),
"resume_llm_full.txt": (
RESUME_LLM_FULL,
["Python", "大模型应用开发", "提示词工程", "LangChain", "RAG",
"向量数据库", "模型微调", "NLP", "FastAPI"]),
"resume_legacy_mismatch.txt": (
RESUME_LEGACY_MISMATCH,
["Struts", "JSP", "Servlet", "Svn", "Tomcat", "jQuery", "WebLogic"]),
}
resume_gold = {}
for name, (text, skills) in resumes.items():
(resumes_dir / name).write_text(text, encoding="utf-8")
resume_gold[name] = {"skills": skills}
(resumes_dir / "gold.json").write_text(
json.dumps(resume_gold, ensure_ascii=False, indent=1), encoding="utf-8")
# 8. 行业趋势报告样例(3 份,内容与 JD 数据中的演化信号相互印证)
reports_dir = data / "reports"
reports_dir.mkdir(parents=True, exist_ok=True)
(reports_dir / "industry_trend_report.txt").write_text(REPORT_TREND, encoding="utf-8")
(reports_dir / "talent_report_2026.txt").write_text(REPORT_TALENT_2026, encoding="utf-8")
(reports_dir / "digital_economy_2026H1.txt").write_text(REPORT_DIGITAL_ECONOMY, encoding="utf-8")
# 9. 审核留痕种子记录(accept/modify/reject 混合 + 节点编辑,覆盖多名操作人)
review_dir = data / "review"
review_dir.mkdir(parents=True, exist_ok=True)
with open(review_dir / "audit.jsonl", "w", encoding="utf-8") as f:
for rec in AUDIT_SEED:
f.write(json.dumps(rec, ensure_ascii=False) + "\n")
n_raw = sum(len(v) for v in raw_by_year.values())
print(f"生成完成:技能词表 {len(SKILLS)} 项,行业 {len(INDUSTRIES)} 个,"
f"原始 JD {n_raw} 条({len(CITIES)} 城),测试集 {len(testset)} 条,"
f"匹配标注 {len(match_gold)} 对,简历 {len(resumes)} 份,报告 3 份,"
f"审核留痕种子 {len(AUDIT_SEED)} 条,"
f"抄袭簇 {len(dup_groups)} 组,噪声 {len(noise_jids)} 条")
if __name__ == "__main__":
main()