Initial commit
This commit is contained in:
133
skills/resume-builder/SKILL.md
Executable file
133
skills/resume-builder/SKILL.md
Executable file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
name: resume-builder
|
||||
description: 从零生成或全面优化一份中文简历,并导出 docx / pdf / markdown 多种格式。用 STAR 法则改写经历、做 ATS 关键词覆盖率检查、根据行业(互联网产品 / 技术 / 金融 / 通用)选模板。当用户说"帮我写简历 / 优化简历 / 简历不会写 / 我的简历太弱了 / 简历看起来不专业 / 简历改一改 / 给我做个简历模板 / 简历导出 / 简历加点关键词",或者上传 .pdf/.docx 简历后说"看看怎么改"时,必须触发本 skill。即使用户只问"我的简历有什么问题"也要触发。
|
||||
---
|
||||
|
||||
# Resume Builder(简历生成与优化)
|
||||
|
||||
这个 skill 干三件事:
|
||||
|
||||
1. **结构化生成**:从用户经历产出一份符合中文求职市场审美的简历
|
||||
2. **STAR 法则改写**:把"参与了 X"这种弱句子,改写成"通过 X 实现 Y,结果 Z"
|
||||
3. **ATS 关键词优化 + 多模板导出**:保证简历能过自动筛选,并支持 docx/pdf/md
|
||||
|
||||
不做:JD 定向改写(那是 jd-resume-tailor 的事,请在那里做"针对某 JD 改简历")
|
||||
|
||||
---
|
||||
|
||||
## 何时触发
|
||||
|
||||
- "帮我写一份简历"
|
||||
- "我的简历太弱了 / 没有亮点 / 看起来不专业"
|
||||
- "把这段经历用 STAR 改一下"
|
||||
- "简历里关键词够不够"
|
||||
- "导出 PDF / docx 简历"
|
||||
- 用户上传简历但没明确说"针对某 JD 改" → 触发本 skill;如果说了"针对 X 公司 / X 岗位改" → 调用 jd-resume-tailor
|
||||
|
||||
---
|
||||
|
||||
## 工作流
|
||||
|
||||
### Step 1: 摸清简历当前状态
|
||||
|
||||
如果用户**有简历文件**(.pdf / .docx / .md / .txt):
|
||||
- pdf 走 pdf skill 解析
|
||||
- docx 走 docx skill 解析
|
||||
- 提取出:基本信息、教育、工作经历、项目经历、技能、其他
|
||||
|
||||
如果用户**没有简历**:
|
||||
- 用 AskUserQuestion 收集信息(参考 `references/intake_questions.md` 里的问题清单)
|
||||
- 一次问 3~4 个问题,分轮收集,避免劝退
|
||||
|
||||
### Step 2: 选模板
|
||||
|
||||
读取 `references/templates/` 决定结构:
|
||||
|
||||
- 互联网产品 / 运营 / PM → `templates/internet.md`
|
||||
- 技术 / 研发 / 数据 → `templates/tech.md`
|
||||
- 金融 / 咨询 / 商科 → `templates/finance.md`
|
||||
- 通用 / 跨行业 → `templates/general.md`
|
||||
|
||||
如果用户没指定方向,用通用模板,但**询问一句**:"你下一步主要往什么方向投?我可以用更适合那个方向的版式。"
|
||||
|
||||
### Step 3: 用 STAR 改写每段经历
|
||||
|
||||
读取 `references/star_rewrite_guide.md`,对每条工作 / 项目经历做 STAR 改写。
|
||||
|
||||
**STAR 不是死板的四段式**,而是确保每条 bullet 都有:
|
||||
- **背景信号**(一句话点出问题大小或情境)
|
||||
- **动作**(你具体做了什么,要有动词)
|
||||
- **结果**(数字 / 百分比 / 排名 / 规模)
|
||||
|
||||
如果用户提供的信息里**没有数字**,要主动追问:"这个项目用户量大概是多少?""这个优化大概提了多少?记不准的话给个量级也行。"
|
||||
|
||||
### Step 4: ATS 关键词检查
|
||||
|
||||
调用脚本:
|
||||
|
||||
```bash
|
||||
python scripts/ats_check.py --resume <resume.md> \
|
||||
--industry internet \
|
||||
[--jd <jd.txt>]
|
||||
```
|
||||
|
||||
脚本会:
|
||||
1. 抽取简历里的关键词
|
||||
2. 对照行业关键词库(来自 job-intent-tracker 或本 skill 的 `references/keywords/`)
|
||||
3. 输出"已覆盖 / 建议补充"两个清单
|
||||
4. 给出 ATS 友好度评分(字体单一性、表格使用、特殊符号、图片等)
|
||||
|
||||
**ATS 友好的硬规则**:
|
||||
- 不要用 word 表格放经历(很多 ATS 解析不了)
|
||||
- 不要把日期放在装饰性图片里
|
||||
- 不要写两栏布局(有些 ATS 会按列读,导致顺序混乱)
|
||||
- 不要插图标 / emoji 在标题里
|
||||
- 字体用宋体 / 思源宋体 / Arial / Helvetica 之一
|
||||
|
||||
### Step 5: 多格式导出
|
||||
|
||||
读取 `references/export_guide.md`,按用户需求选择:
|
||||
|
||||
**docx 导出**(最通用,国内 HR 优先要 docx):
|
||||
- 调用 docx skill
|
||||
- 用 `assets/resume_template.docx` 作为模板(如果存在)
|
||||
|
||||
**pdf 导出**(最终投递版):
|
||||
- 推荐流程:先 docx → 再用 word/libreoffice 转 pdf
|
||||
- 直接生成 pdf 用 reportlab 比较丑,不推荐
|
||||
- 调用 pdf skill 做后处理(加密 / 元数据清理)
|
||||
|
||||
**markdown 导出**(备份 + GitHub):
|
||||
- 直接写 .md 文件即可
|
||||
|
||||
**默认行为**:除非用户指定,同时输出 docx + md 两个版本。
|
||||
|
||||
### Step 6: 自检 & 反馈
|
||||
|
||||
输出后做一次自检(写到聊天里给用户看,不用单独存文件):
|
||||
|
||||
```
|
||||
✓ 长度:< 1 页(应届)/ ≤ 2 页(社招)
|
||||
✓ 联系方式齐全(手机 + 邮箱,可选 GitHub/作品集)
|
||||
✓ 每段经历都有量化结果
|
||||
✓ 关键词覆盖率(vs <industry> 行业库):__%
|
||||
✓ ATS 友好度:__/10
|
||||
⚠ 待用户确认:<还需要补的信息>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 反模式(不要做)
|
||||
|
||||
- ❌ 帮用户编数字(说"提升 30%"但用户根本没说过)—— 必须基于用户提供的信息,不知道就标 `[待补充:具体数字]`
|
||||
- ❌ 用形容词堆砌("具有出色的沟通能力" "认真负责" "有上进心")—— 删掉
|
||||
- ❌ 一段经历写超过 5 条 bullet —— 太密会被 HR 跳过
|
||||
- ❌ 写"自我评价"长篇 —— 国内现在不流行,1~2 行 summary 即可
|
||||
- ❌ 把所有公司都写一样的 bullet 数 —— 重要的多写,次要的少写
|
||||
- ❌ 把"熟悉 / 了解 / 会用"当能力描述 —— 改成"用 X 做了 Y"
|
||||
|
||||
## 与其他 skill 的协作
|
||||
|
||||
- 用户接着说"针对这家公司改一下" → 转 `jd-resume-tailor`
|
||||
- 用户接着说"准备面试" → 转 `interview-prep`
|
||||
- 用户没确定方向就来改简历 → 先反问"你打算投什么方向?",必要时转 `job-intent-tracker`
|
||||
55
skills/resume-builder/references/export_guide.md
Executable file
55
skills/resume-builder/references/export_guide.md
Executable file
@@ -0,0 +1,55 @@
|
||||
# 简历导出指南
|
||||
|
||||
## 推荐组合
|
||||
|
||||
- **投递主用**:docx(HR 直接收的格式)+ pdf(最终版本,防排版错乱)
|
||||
- **备份**:md(自己迭代用、放 GitHub)
|
||||
|
||||
## docx 导出(默认)
|
||||
|
||||
调用 docx skill。模板优先级:
|
||||
1. 用户提供模板 → 用用户的
|
||||
2. `assets/resume_template.docx` 存在 → 用本 skill 的
|
||||
3. 都没有 → 用 docx skill 的默认样式(注意控制字体、行距、margin)
|
||||
|
||||
样式参数(推荐默认):
|
||||
- 中文字体:思源宋体 / 宋体 / 微软雅黑(HR 电脑大概率有)
|
||||
- 英文字体:Arial / Helvetica / Calibri
|
||||
- 字号:正文 10.5~11pt,标题 12~14pt,姓名 16~18pt
|
||||
- 行距:1.15~1.3
|
||||
- 页边距:上下 1.5cm,左右 1.8cm
|
||||
- 颜色:通体黑色 + 一个低饱和度强调色(深蓝 / 深灰)
|
||||
|
||||
## pdf 导出
|
||||
|
||||
**推荐**:docx → libreoffice headless 转 pdf
|
||||
|
||||
```bash
|
||||
libreoffice --headless --convert-to pdf <input.docx> --outdir <out_dir>
|
||||
```
|
||||
|
||||
**不推荐**:直接用 reportlab / weasyprint 从头画,效果丑且容易踩字体坑。
|
||||
|
||||
## markdown 导出
|
||||
|
||||
最简单直接:文件名建议 `resume_<姓名拼音>_<YYYYMM>.md`,例如 `resume_zhangsan_202605.md`。
|
||||
|
||||
## 文件命名建议
|
||||
|
||||
投递时的文件名极其重要(很多 HR 直接按文件名搜):
|
||||
|
||||
`<姓名>_<目标岗位>_<X 年经验>.<ext>`
|
||||
|
||||
例:`张三_高级产品经理_5年.pdf`
|
||||
|
||||
不要叫 `final.pdf` `final_v2.pdf` `修改版.docx`,HR 会觉得你不专业。
|
||||
|
||||
## 元数据清理(pdf)
|
||||
|
||||
调用 pdf skill 清理 metadata(作者、创建工具),避免泄露原始 word 模板的来源(比如某些模板会留下"WPS 简历模板 v3.2"字样)。
|
||||
|
||||
## 隐私 & 安全
|
||||
|
||||
- 简历**默认不写身份证号、家庭住址、紧急联系人**
|
||||
- 投行 / 公务员 / 国企等特殊岗位另外要求时再补
|
||||
- 如果用户上传的简历里有这些,导出新版本时**主动删除并提示用户**
|
||||
44
skills/resume-builder/references/intake_questions.md
Executable file
44
skills/resume-builder/references/intake_questions.md
Executable file
@@ -0,0 +1,44 @@
|
||||
# 简历信息收集问题清单
|
||||
|
||||
分 3 轮问,不要一次性塞给用户。
|
||||
|
||||
## 第 1 轮:基本信息(必问)
|
||||
|
||||
1. 你的姓名 + 联系方式(手机、邮箱,可选 GitHub / 作品集)
|
||||
2. 学历(学校 + 专业 + 学历层次 + 毕业年份;多段教育依次列)
|
||||
3. 你目前 / 最近一份工作的:公司、岗位、起止时间
|
||||
|
||||
## 第 2 轮:经历主体(必问)
|
||||
|
||||
针对每段工作 / 实习 / 项目,按这个套路问:
|
||||
|
||||
- 这段经历你**主要负责什么**?
|
||||
- 有哪些**具体的事情**是你独立或主导做的?(关键词:你"做了什么",不是"参与了什么")
|
||||
- **结果如何**?有没有可以量化的数字(用户量、转化率、收入、效率提升、排名等)
|
||||
- 这段经历你最得意的**一件事**是什么?
|
||||
|
||||
如果用户记不清数字,可以这样追问:
|
||||
- "大致量级也可以,比如 10 万 / 百万 / 千万"
|
||||
- "百分比记不清的话,给一个 range,比如『大约 20-30%』"
|
||||
- "如果完全没办法估,我会标成『[需补具体数字]』,你后面填"
|
||||
|
||||
## 第 3 轮:补充信息(可选)
|
||||
|
||||
- 技能 / 工具:编程语言、框架、设计 / 数据 / 办公工具
|
||||
- 语言能力:英语 / 其他语种 + 等级
|
||||
- 证书 / 获奖:仅写有含金量的(CFA Level 2、ACM 区域赛、PMP 等)
|
||||
- 兴趣 / 其他:除非真的有亮点(比如马拉松、独立游戏作品),否则不写
|
||||
|
||||
## 应届生补充问
|
||||
|
||||
- 校园经历(学生会、社团、志愿者)—— 但只挑能体现"领导 / 组织 / 推动力"的写
|
||||
- 课程项目 —— 挑跟目标岗位相关的 1~2 个
|
||||
- GPA / 排名 / 奖学金 —— 高于 3.5/4.0 或专业前 20% 才写
|
||||
|
||||
## 转行候选人补充问
|
||||
|
||||
- 你为什么想转到这个方向?
|
||||
- 你已经为转行做了哪些准备(自学、项目、副业、证书)?
|
||||
- 原岗位有哪些**可迁移技能**?(举具体例子)
|
||||
|
||||
把这些信息会用到一段简短的"个人简介 / Career Summary"里,化解 HR 看到转行简历时的困惑。
|
||||
50
skills/resume-builder/references/keywords/finance.txt
Executable file
50
skills/resume-builder/references/keywords/finance.txt
Executable file
@@ -0,0 +1,50 @@
|
||||
DCF
|
||||
LBO
|
||||
Comps
|
||||
M&A
|
||||
IPO
|
||||
Pitchbook
|
||||
Bloomberg
|
||||
Capital IQ
|
||||
Wind
|
||||
Choice
|
||||
财务建模
|
||||
估值
|
||||
敏感性分析
|
||||
行业研究
|
||||
deal
|
||||
路演
|
||||
招股书
|
||||
投资逻辑
|
||||
catalyst
|
||||
催化剂
|
||||
风险点
|
||||
ROE
|
||||
ROIC
|
||||
EBITDA
|
||||
PE
|
||||
PB
|
||||
EV
|
||||
sizing
|
||||
case interview
|
||||
hypothesis
|
||||
MECE
|
||||
issue tree
|
||||
PowerPoint
|
||||
Excel 高阶
|
||||
VBA
|
||||
SQL
|
||||
Python
|
||||
CFA
|
||||
CPA
|
||||
FRM
|
||||
ACCA
|
||||
PMP
|
||||
量化
|
||||
策略
|
||||
回测
|
||||
因子
|
||||
基本面
|
||||
技术面
|
||||
夏普
|
||||
最大回撤
|
||||
25
skills/resume-builder/references/keywords/general.txt
Executable file
25
skills/resume-builder/references/keywords/general.txt
Executable file
@@ -0,0 +1,25 @@
|
||||
SQL
|
||||
Excel
|
||||
PowerPoint
|
||||
Word
|
||||
Notion
|
||||
飞书
|
||||
Jira
|
||||
Asana
|
||||
英语
|
||||
项目管理
|
||||
跨部门协作
|
||||
推动落地
|
||||
ownership
|
||||
数据驱动
|
||||
用户同理心
|
||||
快速学习
|
||||
影响力
|
||||
说服力
|
||||
量化
|
||||
可迁移
|
||||
0-1
|
||||
1-N
|
||||
ROI
|
||||
KPI
|
||||
OKR
|
||||
45
skills/resume-builder/references/keywords/internet.txt
Executable file
45
skills/resume-builder/references/keywords/internet.txt
Executable file
@@ -0,0 +1,45 @@
|
||||
产品规划
|
||||
产品迭代
|
||||
PRD
|
||||
需求评审
|
||||
用户访谈
|
||||
用户画像
|
||||
用户增长
|
||||
留存
|
||||
转化率
|
||||
A/B 测试
|
||||
漏斗分析
|
||||
数据驱动
|
||||
跨部门协作
|
||||
推动落地
|
||||
0-1
|
||||
1-N
|
||||
商业化
|
||||
PMF
|
||||
增长黑客
|
||||
AARRR
|
||||
私域
|
||||
GMV
|
||||
ROI
|
||||
CAC
|
||||
LTV
|
||||
SOP
|
||||
SaaS
|
||||
B 端
|
||||
C 端
|
||||
内容运营
|
||||
社群运营
|
||||
活动运营
|
||||
PMP
|
||||
Scrum
|
||||
看板
|
||||
Sprint
|
||||
Jira
|
||||
Confluence
|
||||
Notion
|
||||
飞书
|
||||
SQL
|
||||
Tableau
|
||||
Figma
|
||||
Axure
|
||||
墨刀
|
||||
69
skills/resume-builder/references/keywords/tech.txt
Executable file
69
skills/resume-builder/references/keywords/tech.txt
Executable file
@@ -0,0 +1,69 @@
|
||||
Java
|
||||
Go
|
||||
Python
|
||||
TypeScript
|
||||
Spring Boot
|
||||
Spring Cloud
|
||||
gRPC
|
||||
微服务
|
||||
Kafka
|
||||
RabbitMQ
|
||||
Redis
|
||||
ZooKeeper
|
||||
MySQL
|
||||
PostgreSQL
|
||||
MongoDB
|
||||
ClickHouse
|
||||
HBase
|
||||
TiDB
|
||||
Docker
|
||||
Kubernetes
|
||||
Helm
|
||||
AWS
|
||||
GCP
|
||||
阿里云
|
||||
高并发
|
||||
高可用
|
||||
分布式
|
||||
一致性
|
||||
限流
|
||||
降级
|
||||
熔断
|
||||
分库分表
|
||||
读写分离
|
||||
React
|
||||
Vue
|
||||
Next.js
|
||||
Vite
|
||||
Webpack
|
||||
PyTorch
|
||||
TensorFlow
|
||||
sklearn
|
||||
XGBoost
|
||||
LightGBM
|
||||
特征工程
|
||||
RAG
|
||||
向量检索
|
||||
Embedding
|
||||
LLM
|
||||
SFT
|
||||
RLHF
|
||||
Agent
|
||||
MCP
|
||||
vLLM
|
||||
量化
|
||||
SQL
|
||||
Spark
|
||||
Flink
|
||||
Hive
|
||||
Presto
|
||||
Airflow
|
||||
A/B 测试
|
||||
模型评估
|
||||
Prometheus
|
||||
Grafana
|
||||
ELK
|
||||
CI/CD
|
||||
Jenkins
|
||||
GitLab CI
|
||||
Terraform
|
||||
83
skills/resume-builder/references/star_rewrite_guide.md
Executable file
83
skills/resume-builder/references/star_rewrite_guide.md
Executable file
@@ -0,0 +1,83 @@
|
||||
# STAR 改写指南
|
||||
|
||||
## 核心心法
|
||||
|
||||
STAR = Situation(情境)+ Task(任务)+ Action(动作)+ Result(结果)
|
||||
|
||||
但**写在简历里的 bullet,不是把 STAR 四段都堆进去**,而是浓缩成一句话,里面隐含 STAR 信号:
|
||||
|
||||
```
|
||||
[动作动词] + [对象 / 范围] + [方法 / 工具] + [量化结果]
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
❌ 弱:参与了 XX 系统的开发
|
||||
✅ 强:主导设计并落地 XX 订单系统的库存模块,引入 Redis 分布式锁解决超卖,支撑日均 80 万订单,P99 延迟从 320ms 降至 95ms
|
||||
|
||||
❌ 弱:负责活动运营
|
||||
✅ 强:策划"618 老客回流"活动,覆盖 30 万沉默用户,通过分层 push + 优惠券组合,回流率 11.4%(基线 4.2%),ROI 3.8
|
||||
|
||||
## 改写流程
|
||||
|
||||
1. **找到原 bullet 的 STAR 短板**
|
||||
- 没有动作动词?补
|
||||
- 没有量化结果?追问用户
|
||||
- 动作太空泛("参与/协助/配合/支持")?换成实做动词
|
||||
- 没有方法 / 工具?补
|
||||
|
||||
2. **应用动词库**(见下文)
|
||||
|
||||
3. **加量化**(数字 / 百分比 / 排名 / 时间 / 规模 任选)
|
||||
|
||||
4. **控制长度**:单条 bullet ≤ 2 行
|
||||
|
||||
## 强动作动词库(按职能分)
|
||||
|
||||
### 通用
|
||||
主导、负责、推动、发起、设计、搭建、优化、复盘、孵化、闭环
|
||||
|
||||
### 产品 / 运营
|
||||
规划、迭代、调研、定义(功能)、灰度、A/B 测试、数据归因、上线、回滚
|
||||
|
||||
### 技术
|
||||
重构、架构设计、调优、解耦、抽象、模块化、自动化、监控、容灾、降级
|
||||
|
||||
### 数据
|
||||
建模、清洗、归因、可视化、回归、聚类、特征工程、训练、上线
|
||||
|
||||
### 销售 / BD
|
||||
开拓、签约、续约、回款、谈判、漏斗管理、客户分层
|
||||
|
||||
### 管理
|
||||
组建(团队)、培养、绩效管理、目标拆解、跨部门协调
|
||||
|
||||
## 弱词替换表
|
||||
|
||||
| 弱词 | 推荐替换 |
|
||||
|------|---------|
|
||||
| 参与了 | 主导 / 负责模块 ___(写明边界) |
|
||||
| 协助 | 与 ___ 协作完成 ___(写明合作方和成果) |
|
||||
| 配合 | 同上 |
|
||||
| 跟进 | 推动 / 督办 / drive |
|
||||
| 帮助 | 通过 ___ 帮 ___ 实现 ___ |
|
||||
| 学习了 | 掌握并应用 ___ 完成 ___ |
|
||||
| 接触过 | 删掉,要么改成具体项目 |
|
||||
| 熟悉 / 了解 | 删掉抽象词,写具体项目 |
|
||||
|
||||
## 量化暗示库
|
||||
|
||||
如果用户实在给不出数字,可以用以下"软量化"先占位,标注 `[待补]`:
|
||||
|
||||
- 用户 / 客户规模:万级 / 百万级 / 千万级
|
||||
- 团队规模:3 人 / 10 人 / 跨部门
|
||||
- 项目周期:2 周 / 1 个季度 / 半年
|
||||
- 业务影响:核心 / 关键 / 试点
|
||||
- 同行对比:行业首个 / 公司第一个 / Tier 1 客户
|
||||
|
||||
## 自检:每条 bullet 问自己
|
||||
|
||||
- 用动词开头了吗?
|
||||
- 有 1 个以上的数字 / 量级吗?
|
||||
- 删掉这条,简历会损失什么?如果答案是"不会",就删
|
||||
- 这条让 HR 联想到什么具体能力?
|
||||
63
skills/resume-builder/references/templates/finance.md
Executable file
63
skills/resume-builder/references/templates/finance.md
Executable file
@@ -0,0 +1,63 @@
|
||||
# 金融 / 咨询 / 商科 简历模板
|
||||
|
||||
## 结构(投行 / 咨询风格,强调 deal / case 列表)
|
||||
|
||||
```
|
||||
姓名 | 电话 | 邮箱 | LinkedIn | 城市
|
||||
|
||||
【教育背景】(金融 / 咨询岗放最前面,因为学校 + GPA 是硬筛)
|
||||
学校 | 专业 | 学位 | 起止时间
|
||||
- GPA: X.XX/4.00 (Major: X.XX/4.00)
|
||||
- 排名 / 奖学金 / 荣誉
|
||||
- 相关核心课程:Corporate Finance, Financial Modeling, ...
|
||||
- 交换 / 海外经历
|
||||
|
||||
【工作经历】(按倒序)
|
||||
公司 | 部门 / 组 | 岗位 | 起止时间,地点
|
||||
- Deal / Case 1:项目名称 + 你的角色 + 关键贡献 + 成交规模 / 成果
|
||||
- Deal / Case 2:同上
|
||||
- Deal / Case 3:同上
|
||||
(投行/PE 一般 3~5 个 deal;咨询 3~5 个 case;研究员可写 coverage 行业 + 主要观点)
|
||||
|
||||
【实习经历】(应届 / 早期必备,按倒序)
|
||||
(同上结构)
|
||||
|
||||
【技能 & 证书】
|
||||
- 财务建模:DCF / LBO / Comps / M&A model 熟练
|
||||
- Excel / PowerPoint 高阶
|
||||
- Bloomberg / Capital IQ / Wind / Choice
|
||||
- CFA Level X / CPA / FRM / ACCA
|
||||
- 编程(量化加分):Python / SQL / VBA
|
||||
- 语言:英语(雅思 7.5 / GMAT 750)、其他
|
||||
|
||||
【领导力 / 课外活动】(仅写有含金量的)
|
||||
- 学生会 / 社团:领导职务 + 量化结果
|
||||
- 公益项目:组织规模 + 影响
|
||||
- 国际比赛:CFA Research Challenge 区域第 X 等
|
||||
```
|
||||
|
||||
## 风格要点
|
||||
|
||||
- **每个 deal / case 必须有**:项目类型、客户行业、自己的具体动作(建模 / 路演 / 调研)、成果(融资额 / 估值 / 报告页数 / 客户决策)
|
||||
- 投行强调 deal flow 数量 + 规模;咨询强调 case 类型多样 + 客户层级
|
||||
- 量化模板:
|
||||
- 投行:"参与 X 亿美金 ___ 行业 IPO/M&A,搭建 LBO / DCF 模型,输出 ___ 页投资人 deck"
|
||||
- 咨询:"为 X 行业 Top 3 客户开展 ___ 项目,定量分析 X 个细分市场,最终建议被客户采纳并执行 ___"
|
||||
- **学历分层敏感**:投行咨询 PE 一般只看 Tier 1 学校(清北复交浙、HKU、新加坡国立、藤校 / Top 30 美校等)。如果学校非 Tier 1,要更突出实习 / 比赛 / 自学
|
||||
|
||||
## 中英文版本
|
||||
|
||||
金融 / 咨询岗位**很多公司只接受英文简历**(外资行、MBB、IBD)。本 skill 默认产出中文版,但要主动问:"你需要英文版本吗?我可以同时生成。"
|
||||
|
||||
英文版本注意:
|
||||
- 用 American English(金融业以美式为主)
|
||||
- Action verb 用过去式:Led、Built、Drove、Analyzed、Advised
|
||||
- 不要用 we / our team,要用 I / my team;强调 individual contribution
|
||||
- 一页为限(除非 senior 候选人)
|
||||
|
||||
## 雷区
|
||||
|
||||
- 投行 / 咨询简历**没有 deal / case 列表** → 致命,重写
|
||||
- 把"在 ___ 实习"当工作经历写 → 必须改成 deal / case
|
||||
- GPA / 学校 / 标化分数缺失 → 即使低也要写(除非真的拉低很多)
|
||||
- 写"对金融感兴趣" / "希望进入投行" → 删,简历不是个人陈述
|
||||
55
skills/resume-builder/references/templates/general.md
Executable file
55
skills/resume-builder/references/templates/general.md
Executable file
@@ -0,0 +1,55 @@
|
||||
# 通用简历模板(不绑定行业)
|
||||
|
||||
适用场景:
|
||||
- 用户暂时没有明确目标方向
|
||||
- 跨行业求职(同一份简历投不同方向)
|
||||
- 早期 / 应届候选人
|
||||
- 行业不在前三类(教育 / 医疗 / 政府 / 实业 / 文娱 etc.)
|
||||
|
||||
## 结构
|
||||
|
||||
```
|
||||
姓名 | 电话 | 邮箱 | 城市 | 目标岗位 / 期望方向
|
||||
|
||||
【个人简介 / Career Summary】(2~3 行)
|
||||
关键定位 + 核心能力 + 一个最有说服力的成就
|
||||
|
||||
【工作经历 / 实习经历】(社招倒序;应届实习放教育下方)
|
||||
公司 | 岗位 | 起止时间
|
||||
- 主要职责(一行)
|
||||
- 关键成果 1(量化)
|
||||
- 关键成果 2(量化)
|
||||
- 横向 / 软技能体现(一句)
|
||||
|
||||
【教育背景】
|
||||
学校 | 专业 | 学历 | 时间
|
||||
- GPA / 排名 / 奖学金(≥ 平均水平才写)
|
||||
- 相关课程 / 论文 / 项目(仅写与岗位相关的)
|
||||
|
||||
【技能与证书】
|
||||
- 工具:Excel / Word / PPT 高阶;Notion / Trello;其他行业工具
|
||||
- 语言:英语等级;其他语种
|
||||
- 证书:仅写有公信力的
|
||||
|
||||
【其他亮点】(可选,强力 case 才写)
|
||||
- 创业 / 副业经历
|
||||
- 公开演讲 / 自媒体(粉丝 / 阅读量到一定规模)
|
||||
- 公益 / 志愿者(持续 ≥ 1 年)
|
||||
- 体育 / 艺术成就(省级以上 / 商业认可)
|
||||
```
|
||||
|
||||
## 风格
|
||||
|
||||
- 中性、克制,避免过度行业化术语
|
||||
- 每段经历强调"可迁移技能":沟通 / 推动 / 数据 / 学习速度 / 客户 / 领导力
|
||||
- 跨行业候选人需要在 Summary 里点明"为什么这个方向适合我"
|
||||
|
||||
## 长度
|
||||
|
||||
- 应届 / 实习生:1 页
|
||||
- 1~5 年:1 页(顶多 1.2 页)
|
||||
- 5+ 年:1~2 页
|
||||
|
||||
通用模板的最大风险是**显得"啥都行但啥都不精"**。如果发现写出来就是这种感觉,要主动建议用户:
|
||||
- 选一个最强方向,切到对应的行业模板
|
||||
- 或者准备 2 份版本(互联网版 + 通用版),分场景投
|
||||
50
skills/resume-builder/references/templates/internet.md
Executable file
50
skills/resume-builder/references/templates/internet.md
Executable file
@@ -0,0 +1,50 @@
|
||||
# 互联网产品 / 运营 / PM 简历模板
|
||||
|
||||
## 结构(顺序很重要)
|
||||
|
||||
```
|
||||
姓名|电话|邮箱|城市|目标岗位
|
||||
(应届可加:在读学校 + 期望毕业时间)
|
||||
|
||||
【个人简介 / Summary】(2~3 行,可选)
|
||||
一句话定位:X 年 ___ 经验,专注 ___,擅长 ___,曾在 ___ 主导 ___
|
||||
|
||||
【工作经历】(社招放最前;应届放教育下面)
|
||||
公司 A | 岗位 | 起止时间
|
||||
- bullet 1(核心成绩,量化)
|
||||
- bullet 2(次重要成绩)
|
||||
- bullet 3(横向能力 / 影响力)
|
||||
|
||||
【项目经历】(与岗位强相关的 2~4 个)
|
||||
项目名 | 角色 | 时间
|
||||
- 背景:___(一句话)
|
||||
- 动作:___(你做了什么)
|
||||
- 结果:___(量化)
|
||||
|
||||
【教育背景】
|
||||
学校 | 专业 | 学历 | 起止时间
|
||||
(GPA 高于 3.5/4.0 才写)
|
||||
|
||||
【技能 / 工具】
|
||||
- 数据:SQL(熟练)、Python(pandas/numpy)、Tableau
|
||||
- 产品工具:Figma / Axure / 墨刀
|
||||
- 协作:Notion / 飞书 / Jira
|
||||
- 语言:英语 CET-6 / 雅思 7.0
|
||||
|
||||
【其他】(可选)
|
||||
证书 / 自媒体 / 开源项目 / 演讲 / 获奖
|
||||
```
|
||||
|
||||
## 风格要点
|
||||
|
||||
- bullet 句式:"动词 + 对象 + 方法 + 结果(数字)"
|
||||
- 突出 ownership:用"主导/负责/推动",不要用"参与/协助"
|
||||
- 数字密度:每段经历 ≥ 60% 的 bullet 含数字
|
||||
- 长度:1 页(≤ 3 年经验);最多 2 页(5+ 年)
|
||||
|
||||
## 常见加分项
|
||||
|
||||
- 0-1 项目经历(哪怕规模小)
|
||||
- 跨部门 / 跨业务线协作
|
||||
- 业务复盘文章 / 公开演讲
|
||||
- 数据驱动 case(写清楚假设→实验→结论)
|
||||
53
skills/resume-builder/references/templates/tech.md
Executable file
53
skills/resume-builder/references/templates/tech.md
Executable file
@@ -0,0 +1,53 @@
|
||||
# 技术 / 研发 / 数据 简历模板
|
||||
|
||||
## 结构
|
||||
|
||||
```
|
||||
姓名|电话|邮箱|GitHub|城市|目标岗位
|
||||
|
||||
【个人简介 / Summary】(可选,1~2 行)
|
||||
X 年 ___ 经验,专注 ___(高并发后端 / 推荐系统 / LLM 应用 / ...),熟悉 ___ 技术栈
|
||||
|
||||
【技能】(技术岗放前面,让 HR 一眼看到栈是否对口)
|
||||
- 语言:Java(精通)、Python(熟练)、Go(了解)
|
||||
- 后端:Spring Boot、Spring Cloud、gRPC、Kafka、Redis、MySQL、ClickHouse
|
||||
- 大数据 / 算法:Spark、Flink、Hive、PyTorch(如果是算法岗)
|
||||
- 工程:Docker、Kubernetes、Linux、Git、CI/CD
|
||||
- 其他:TypeScript、AWS
|
||||
|
||||
【工作经历】
|
||||
公司 A | 职级(高级工程师 / 资深工程师 / Tech Lead)| 起止
|
||||
- 系统级成绩(含 QPS、延迟、可用性、规模等数字)
|
||||
- 架构 / 设计贡献(你设计了什么、为什么这么选)
|
||||
- 业务影响(推动了什么业务结果)
|
||||
|
||||
【项目经历】
|
||||
项目名 | 角色 | 技术栈 | 时间
|
||||
- 背景:业务规模 / 痛点(一句话)
|
||||
- 方案:你的核心设计 + 关键技术决策(讲为什么)
|
||||
- 结果:性能 / 稳定性 / 成本 数字
|
||||
|
||||
【教育背景】
|
||||
|
||||
【开源 / 论文 / 比赛】(强加分)
|
||||
- GitHub 项目(star 数 / 主要 contributor)
|
||||
- 论文(标注会议 / 期刊)
|
||||
- 比赛(Kaggle / ACM / 天池 / 黑客松,含名次)
|
||||
```
|
||||
|
||||
## 风格要点
|
||||
|
||||
- **少形容词,多数字 + 技术细节**
|
||||
- 弱:"优化了系统性能"
|
||||
- 强:"通过引入二级缓存 + SQL 改写,将商品详情接口 P99 从 480ms 降至 110ms"
|
||||
- **讲清楚『你做了什么』vs『团队做了什么』**:用"主导"/"负责"明确 ownership 边界
|
||||
- 算法岗:技能列表里**强调具体模型 / 框架版本**(避免堆砌 buzzword)
|
||||
- LLM / Agent 岗:明确写"训练 / 微调 / 推理 / 应用"中你做的部分,避免被以为是 prompt-only
|
||||
- 长度:1~2 页
|
||||
|
||||
## 常见雷区
|
||||
|
||||
- 简历里写"精通",面试问到一脸懵 → 不熟就写"熟练 / 了解"
|
||||
- 列出 20+ 技能,问哪个都不深 → 删到 8~12 个真正会的
|
||||
- 把课程内容当项目经历 → 标注"课程项目 (Course Project)",不要假装是工业项目
|
||||
- 项目描述只有"什么是 ___",没有"我做了什么" → 重写
|
||||
269
skills/resume-builder/scripts/ats_check.py
Executable file
269
skills/resume-builder/scripts/ats_check.py
Executable file
@@ -0,0 +1,269 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
ats_check.py — 简历 ATS(Applicant Tracking System)友好度检查 + 关键词覆盖率
|
||||
|
||||
用法:
|
||||
python ats_check.py --resume resume.md --industry internet
|
||||
python ats_check.py --resume resume.md --industry tech --jd jd.txt
|
||||
python ats_check.py --resume resume.docx --industry finance --out report.md
|
||||
|
||||
支持输入:.md / .txt / .docx(docx 走 python-docx,需要 pip install python-docx)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
INDUSTRIES = {"internet", "tech", "finance", "general"}
|
||||
|
||||
|
||||
def load_resume_text(path: Path) -> str:
|
||||
suffix = path.suffix.lower()
|
||||
if suffix in {".md", ".txt"}:
|
||||
return path.read_text(encoding="utf-8")
|
||||
if suffix == ".docx":
|
||||
try:
|
||||
from docx import Document
|
||||
except ImportError:
|
||||
print(
|
||||
"✗ 缺少 python-docx,请先安装:pip install python-docx --break-system-packages",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
doc = Document(str(path))
|
||||
return "\n".join(p.text for p in doc.paragraphs)
|
||||
print(f"✗ 暂不支持的格式:{suffix}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def load_keywords(industry: str, references_dir: Path) -> list[str]:
|
||||
path = references_dir / "keywords" / f"{industry}.txt"
|
||||
if not path.exists():
|
||||
print(f"✗ 关键词库不存在:{path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return [
|
||||
line.strip()
|
||||
for line in path.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
]
|
||||
|
||||
|
||||
def coverage(resume_text: str, keywords: list[str]) -> dict:
|
||||
text_lower = resume_text.lower()
|
||||
hits, missing = [], []
|
||||
for kw in keywords:
|
||||
# 兼容大小写、中英混排
|
||||
if kw.lower() in text_lower:
|
||||
hits.append(kw)
|
||||
else:
|
||||
missing.append(kw)
|
||||
return {
|
||||
"hits": hits,
|
||||
"missing": missing,
|
||||
"rate": len(hits) / len(keywords) if keywords else 0,
|
||||
}
|
||||
|
||||
|
||||
def jd_extract_keywords(jd_text: str) -> list[str]:
|
||||
"""从 JD 文本里抽取候选关键词。简易版:取常见技能/工具/动词。"""
|
||||
# 抓中文 2~10 字、英文 2~30 字的"实词"
|
||||
candidates = re.findall(
|
||||
r"[A-Za-z][A-Za-z0-9+/.\-_]{1,29}|[一-龥]{2,10}",
|
||||
jd_text,
|
||||
)
|
||||
# 简单去停用词
|
||||
stop = {
|
||||
"公司", "工作", "我们", "你将", "团队", "需要", "能够", "具备", "熟悉",
|
||||
"了解", "良好", "优秀", "经验", "能力", "岗位", "职责", "要求", "以上",
|
||||
"相关", "及其", "或者", "进行", "完成", "负责", "推动", "实现", "提升",
|
||||
"并且", "包括", "以下", "根据",
|
||||
}
|
||||
seen = set()
|
||||
out = []
|
||||
for c in candidates:
|
||||
key = c.lower()
|
||||
if key in seen or c in stop:
|
||||
continue
|
||||
seen.add(key)
|
||||
out.append(c)
|
||||
return out[:80] # 取前 80 个候选
|
||||
|
||||
|
||||
def ats_friendliness(text: str, source_path: Path) -> tuple[int, list[str]]:
|
||||
"""评估 ATS 友好度,返回 (分数 / 10, 警告列表)。"""
|
||||
score = 10
|
||||
warnings = []
|
||||
|
||||
# 长度
|
||||
if len(text) < 200:
|
||||
score -= 3
|
||||
warnings.append("⚠ 简历文本过短(< 200 字符),可能解析失败或内容不足")
|
||||
elif len(text) > 6000:
|
||||
score -= 1
|
||||
warnings.append("⚠ 简历偏长(> 6000 字符),建议精简到 1~2 页")
|
||||
|
||||
# 联系方式
|
||||
has_email = bool(re.search(r"[\w.\-+]+@[\w.\-]+\.\w+", text))
|
||||
has_phone = bool(re.search(r"(\+?86[-\s]?)?1[3-9]\d{9}|\d{3}[-\s]?\d{4}[-\s]?\d{4}", text))
|
||||
if not has_email:
|
||||
score -= 1
|
||||
warnings.append("⚠ 没找到邮箱")
|
||||
if not has_phone:
|
||||
score -= 1
|
||||
warnings.append("⚠ 没找到手机号")
|
||||
|
||||
# 装饰符号
|
||||
decorative = re.findall(r"[★☆●○◆◇▶▷■□▪▫♦]", text)
|
||||
if len(decorative) > 5:
|
||||
score -= 1
|
||||
warnings.append(f"⚠ 用了 {len(decorative)} 个装饰符号(★●◆等),ATS 可能识别异常,建议精简")
|
||||
|
||||
# emoji
|
||||
emojis = re.findall(r"[\U0001F300-\U0001FAFF\U0001F600-\U0001F64F]", text)
|
||||
if emojis:
|
||||
score -= 1
|
||||
warnings.append(f"⚠ 检测到 {len(emojis)} 个 emoji,部分 ATS 会乱码,建议删掉")
|
||||
|
||||
# 数字密度(量化结果是否充分)
|
||||
numbers = re.findall(r"\d+(?:\.\d+)?%?", text)
|
||||
bullet_count = len(re.findall(r"^\s*[-*•]\s+", text, flags=re.MULTILINE))
|
||||
if bullet_count > 0:
|
||||
density = len(numbers) / bullet_count
|
||||
if density < 0.4:
|
||||
score -= 1
|
||||
warnings.append(
|
||||
f"⚠ 量化密度低(每条 bullet 平均 {density:.2f} 个数字),"
|
||||
f"建议在工作 / 项目经历里多加数字"
|
||||
)
|
||||
|
||||
# docx 特定
|
||||
if source_path.suffix.lower() == ".docx":
|
||||
try:
|
||||
from docx import Document
|
||||
doc = Document(str(source_path))
|
||||
tables = len(doc.tables)
|
||||
images = sum(1 for s in doc.inline_shapes)
|
||||
if tables > 1:
|
||||
score -= 1
|
||||
warnings.append(
|
||||
f"⚠ docx 里有 {tables} 个表格,部分 ATS 解析表格会丢字段,"
|
||||
f"建议改成正文段落"
|
||||
)
|
||||
if images > 0:
|
||||
score -= 1
|
||||
warnings.append(
|
||||
f"⚠ docx 里有 {images} 张图片(含证件照),ATS 不读图,"
|
||||
f"重要信息别只放在图里;证件照可保留"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return max(0, score), warnings
|
||||
|
||||
|
||||
def render_report(
|
||||
industry_cov: dict,
|
||||
industry: str,
|
||||
jd_cov: dict | None,
|
||||
ats_score: int,
|
||||
ats_warnings: list[str],
|
||||
) -> str:
|
||||
lines = [
|
||||
"# 简历 ATS 检查报告",
|
||||
"",
|
||||
f"## 行业关键词覆盖({industry})",
|
||||
f"- 命中率:**{industry_cov['rate'] * 100:.1f}%** "
|
||||
f"({len(industry_cov['hits'])} / {len(industry_cov['hits']) + len(industry_cov['missing'])})",
|
||||
"",
|
||||
"**已命中**:" + (", ".join(industry_cov["hits"]) or "(无)"),
|
||||
"",
|
||||
"**建议补充**(前 15 个):" + (", ".join(industry_cov["missing"][:15]) or "(无)"),
|
||||
"",
|
||||
]
|
||||
|
||||
if jd_cov is not None:
|
||||
lines += [
|
||||
"## JD 关键词覆盖",
|
||||
f"- 命中率:**{jd_cov['rate'] * 100:.1f}%**",
|
||||
"",
|
||||
"**已命中**:" + (", ".join(jd_cov["hits"][:30]) or "(无)"),
|
||||
"",
|
||||
"**JD 出现但简历没有**(重点补这些):" + (", ".join(jd_cov["missing"][:20]) or "(无)"),
|
||||
"",
|
||||
]
|
||||
|
||||
lines += [
|
||||
f"## ATS 友好度评分:**{ats_score}/10**",
|
||||
"",
|
||||
]
|
||||
if ats_warnings:
|
||||
lines += ats_warnings
|
||||
else:
|
||||
lines.append("✅ 没有明显问题")
|
||||
|
||||
lines += [
|
||||
"",
|
||||
"---",
|
||||
"## 改进建议优先级",
|
||||
"",
|
||||
"1. 先补 JD 命中率 → 这是 ATS 通过率的最直接信号",
|
||||
"2. 再补行业关键词 → 让简历能在更宽的搜索里被捞到",
|
||||
"3. 最后调 ATS 友好度 → 移除装饰符号、emoji、表格、图片",
|
||||
"",
|
||||
"注意:覆盖率不是越高越好,**关键词必须出现在真实的成就 bullet 里**,",
|
||||
"不要把关键词单独列一长串当 skills,会被 HR 一眼识破。",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--resume", required=True, help="简历文件路径 (.md/.txt/.docx)")
|
||||
parser.add_argument(
|
||||
"--industry", choices=list(INDUSTRIES), required=True, help="行业方向"
|
||||
)
|
||||
parser.add_argument("--jd", help="可选:JD 文本文件,做精准对比")
|
||||
parser.add_argument("--out", help="输出报告路径,缺省直接打印")
|
||||
parser.add_argument(
|
||||
"--references-dir",
|
||||
default=str(Path(__file__).resolve().parent.parent / "references"),
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
resume_path = Path(args.resume).expanduser()
|
||||
if not resume_path.exists():
|
||||
print(f"✗ 简历文件不存在:{resume_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
text = load_resume_text(resume_path)
|
||||
references_dir = Path(args.references_dir)
|
||||
|
||||
industry_keywords = load_keywords(args.industry, references_dir)
|
||||
industry_cov = coverage(text, industry_keywords)
|
||||
|
||||
jd_cov = None
|
||||
if args.jd:
|
||||
jd_path = Path(args.jd).expanduser()
|
||||
if not jd_path.exists():
|
||||
print(f"✗ JD 文件不存在:{jd_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
jd_keywords = jd_extract_keywords(jd_path.read_text(encoding="utf-8"))
|
||||
jd_cov = coverage(text, jd_keywords)
|
||||
|
||||
ats_score, ats_warnings = ats_friendliness(text, resume_path)
|
||||
report = render_report(industry_cov, args.industry, jd_cov, ats_score, ats_warnings)
|
||||
|
||||
if args.out:
|
||||
out_path = Path(args.out).expanduser()
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
out_path.write_text(report, encoding="utf-8")
|
||||
print(f"✓ 报告已生成:{out_path}")
|
||||
else:
|
||||
print(report)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user