1116 lines
74 KiB
Python
1116 lines
74 KiB
Python
"""自备数据集生成器(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算法", ["Transformers", "Transformer"], "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应用开发", "大模型应用", "大语言模型应用", "LLM", "大语言模型", "大模型", "LLM推理", "LLM评测", "大模型推理", "大语言模型应用开发"],
|
||
"L3", ["Python", "NLP"]),
|
||
("RAG", "AI算法", ["检索增强生成"], "L3", ["大模型应用开发", "向量数据库"]),
|
||
("提示词工程", "AI算法", ["Prompt工程", "Prompt Engineering", "提示词设计"], "L2", ["大模型应用开发"]),
|
||
("智能体开发", "AI算法", ["Agent开发", "多智能体", "Multi-Agent", "智能体", "Agent", "AI Agent"], "L3", ["大模型应用开发"]),
|
||
("向量数据库", "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 = ["科技", "网络", "信息", "数据", "智能", "软件", "互联", "数字"]
|
||
|
||
# ---------------------------------------------------------------- 近期演化信号(2024–2026Q3)
|
||
# 评审反馈修复:此前仅 6 个岗位有深度演化剧本,其余岗位 2023Q1 后事件空档、
|
||
# 且 2026Q4 属未来窗口。这里为每个既有岗位补 3-6 个轻量近期信号(贴合"AI 渗透"
|
||
# 真实趋势:2024+ 多数岗位出现 AI 辅助/大模型加分项,2025+ 部分技能减弱/退出):
|
||
# add_pref: [(起始年, 技能)] 该年起作为加分项写入 JD(触发"新增"事件)
|
||
# fade: (起始年, 技能) 该年起从 JD 技能清单消失(触发"退出"事件)
|
||
# weaken: (起始年, 技能, 保留概率) 高量级岗位该年起提及率下降(触发"减弱"事件)
|
||
RECENT_SIGNALS = {
|
||
# —— 2024 年时间轴已换代的岗位:只补 2025/2026 信号 ——
|
||
"Java开发工程师": {"add_pref": [(2025, "RAG")], "weaken": (2026, "MySQL", 0.4)},
|
||
"Python开发工程师": {"add_pref": [(2025, "向量数据库")], "weaken": (2026, "Redis", 0.4)},
|
||
"前端工程师": {"add_pref": [(2025, "大模型应用开发")], "fade": (2026, "微前端")},
|
||
"算法工程师": {"add_pref": [(2025, "RAG")], "fade": (2026, "强化学习")},
|
||
"数据分析师": {"add_pref": [(2025, "提示词工程")], "weaken": (2026, "Excel", 0.4)},
|
||
"运维工程师(SRE)": {"add_pref": [(2025, "AI辅助编程")], "weaken": (2026, "Docker", 0.4)},
|
||
"NLP工程师": {"add_pref": [(2025, "AI辅助编程")], "fade": (2026, "LangChain")},
|
||
"CV工程师": {"add_pref": [(2025, "AI辅助编程")], "fade": (2026, "模型微调")},
|
||
# —— 其余岗位:2024 起补 AI 加分项 + 2026 技能退出 ——
|
||
"数据工程师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"weaken": (2026, "Spark", 0.4)},
|
||
"测试开发工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "大模型应用开发")],
|
||
"weaken": (2026, "性能测试", 0.4)},
|
||
"嵌入式工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "边缘推理")],
|
||
"fade": (2026, "STM32")},
|
||
"物联网工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "大模型应用开发")],
|
||
"fade": (2026, "LoRa")},
|
||
"云原生工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "大模型应用开发")],
|
||
"fade": (2026, "Service Mesh")},
|
||
"AI产品经理": {"add_pref": [(2024, "AI辅助编程"), (2025, "RAG")],
|
||
"fade": (2026, "用户增长")},
|
||
"Go开发工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "大模型应用开发")],
|
||
"fade": (2026, "Kafka")},
|
||
"大数据开发工程师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"fade": (2026, "Hive")},
|
||
"机器学习工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "RAG")],
|
||
"fade": (2026, "XGBoost")},
|
||
"智能机器人算法工程师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"fade": (2026, "OpenCV")},
|
||
"数据治理工程师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"fade": (2026, "Hive")},
|
||
"边缘计算工程师": {"add_pref": [(2024, "AI辅助编程"), (2025, "大模型应用开发")],
|
||
"fade": (2026, "KubeEdge")},
|
||
"物联网安全工程师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"fade": (2026, "嵌入式开发")},
|
||
"智能系统架构师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"fade": (2026, "Service Mesh")},
|
||
"隐私计算工程师": {"add_pref": [(2024, "大模型应用开发"), (2025, "AI辅助编程")],
|
||
"fade": (2026, "Spark")},
|
||
}
|
||
|
||
# 数据收敛到当前季度:今天是 2026-08(2026Q3),2026 年 JD 只落在 1-9 月,
|
||
# 不生成 2026Q4 等未来窗口(含近重复副本与噪声记录的日期上限)。
|
||
CURRENT_YEAR_MAX_MONTH = 9
|
||
|
||
|
||
def apply_recent_signals(a: dict, year: int, req: list[str], pref: list[str],
|
||
) -> tuple[list[str], list[str]]:
|
||
"""按 RECENT_SIGNALS 对当年技能清单施加近期演化信号(先定结构再渲染,gold 自动一致)。"""
|
||
sig = RECENT_SIGNALS.get(a["title"])
|
||
if not sig:
|
||
return req, pref
|
||
for y0, s in sig.get("add_pref", ()):
|
||
if year >= y0 and s not in req and s not in pref:
|
||
pref.append(s)
|
||
fade = sig.get("fade")
|
||
if fade and year >= fade[0]:
|
||
req = [x for x in req if x != fade[1]]
|
||
pref = [x for x in pref if x != fade[1]]
|
||
wk = sig.get("weaken")
|
||
if wk and year >= wk[0] and rng.random() > wk[2]:
|
||
req = [x for x in req if x != wk[1]]
|
||
pref = [x for x in pref if x != wk[1]]
|
||
return req, pref
|
||
|
||
# 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])]
|
||
req, pref = apply_recent_signals(a, year, req, pref)
|
||
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)
|
||
# 2026 年只取 1-9 月:数据收敛到当前季度 2026Q3,不出现未来窗口
|
||
month = month or rng.randint(1, CURRENT_YEAR_MAX_MONTH if year >= 2026 else 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, CURRENT_YEAR_MAX_MONTH, 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", resp: list[str] | None = None) -> dict:
|
||
"""构造一条待审核候选的快照(审核留痕种子用)。"""
|
||
return {"job_id": f"cand_{title}", "title": title, "category": "新岗位候选",
|
||
"required_skills": req, "preferred_skills": pref,
|
||
"responsibilities": list(resp or []),
|
||
"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,
|
||
resp=["负责智能助手/企业知识库等大模型应用的开发与落地",
|
||
"设计提示词与流程编排,建设应用评测体系",
|
||
"优化推理成本与延迟,跟进生态工具"]),
|
||
"after": _cand("大模型应用工程师",
|
||
["提示词工程", "Python", "LangChain", "大模型应用开发", "NLP"],
|
||
["模型微调", "向量数据库", "RAG"], ["教育", "医疗", "金融"], 42, 38, "active",
|
||
resp=["负责智能助手/企业知识库等大模型应用的开发与落地",
|
||
"设计提示词与流程编排,建设应用评测体系",
|
||
"优化推理成本与延迟,跟进生态工具"]),
|
||
"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,
|
||
resp=["负责检索链路搭建与召回重排优化",
|
||
"建设知识库加工流水线,评估问答质量"]),
|
||
"after": _cand("RAG工程师",
|
||
["Python", "RAG", "向量数据库", "大模型应用开发", "LangChain", "Elasticsearch"],
|
||
["模型微调", "知识图谱"], ["金融", "政务", "教育"], 28, 22, "active",
|
||
resp=["负责检索链路搭建与召回重排优化",
|
||
"建设知识库加工流水线,评估问答质量"]),
|
||
"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,
|
||
resp=["负责提示词设计与模板库沉淀",
|
||
"评估输出质量,编写最佳实践文档"]),
|
||
"after": _cand("提示词工程师",
|
||
["提示词工程", "大模型应用开发", "Python", "数据分析"],
|
||
["LangChain", "RAG", "AI产品"], ["教育", "电商", "广告"], 18, 14, "active",
|
||
resp=["负责提示词设计与模板库沉淀",
|
||
"评估输出质量,编写最佳实践文档"]),
|
||
"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
|
||
# 月份年内均匀铺开:季度窗口计数只随剧本(时间轴/量级)变化;
|
||
# 2026 年收敛到 1-9 月(当前季度 2026Q3,不生成未来窗口)
|
||
span = CURRENT_YEAR_MAX_MONTH if year >= 2026 else 12
|
||
rec, _ = make_jd(a, year, f"J{seq:05d}", month=i * span // 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)
|
||
max_month = CURRENT_YEAR_MAX_MONTH if year >= 2026 else 12
|
||
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, max_month), 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()
|