投了二三十份简历,一个面试电话都没有,这时候先别急着怀疑能力,很可能只是简历在机器筛选那一关就被过滤掉了。现在不少公司用ATS系统先筛一轮,它看的是关键词、技能匹配度和经历描述的清晰度。AI在这个环节能帮上忙,但前提是你得把流程设计对:先让模型读懂JD,再把你的经历用STAR法则改写成招聘方想看的表达。下面这套方法不依赖特定工具,会Python的话可以自己跑通,不会的话也可以用ChatGPT、Kimi等对话框按同样提示词操作。

一、JD分析:让AI拆出硬条件、软技能和ATS关键词
很多岗位描述写得很长,但招聘系统真正用来匹配的关键词往往只有十几个。人工读JD容易凭感觉抓重点,AI的优势是能把JD里出现的技能词、经验要求、加分项分类整理出来。比如一段JD里写“熟悉Java,有分布式系统开发经验,具备良好的沟通能力”,人工看可能只记住Java,但AI可以拆成硬技能、经验年限、软素质三个维度。
设计提示词时,不要让模型输出自然语言段落,那样后续解析很麻烦。更实用的做法是要求它直接返回JSON,字段固定为hard_skills、soft_skills、must_have、nice_to_have和keywords。keywords这个字段专门用来收集JD里适合写进简历的高频名词短语,比如Kubernetes、高并发、数据分析。温度参数建议调到0.2以下,减少随机发挥。
下面是一段Python调用代码,接OpenAI兼容接口就能跑,换成国内模型只需要改base_url和模型名。
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key", base_url="https://api.openai.com/v1")
def extract_jd_keywords(jd_text):
prompt = f"""你是一名资深招聘顾问。请从以下职位描述中提取结构化信息,只返回JSON,不要包含其他文字。
JSON字段包括:
- hard_skills:硬性技能列表,保留JD中的原始写法
- soft_skills:软性素质列表
- must_have:必须满足的条件
- nice_to_have:加分项
- keywords:用于ATS筛选的关键词列表,尽量覆盖JD中的名词短语
职位描述:
{jd_text}
"""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
)
content = resp.choices[0].message.content.strip()
if content.startswith("```"):
content = content.split("\n", 1)[1]
if content.endswith("```"):
content = content[:-3]
return json.loads(content)
if __name__ == "__main__":
jd = "负责分布式系统的设计与开发,熟悉Java、Kubernetes,有3年以上后端经验,具备良好的沟通能力"
print(extract_jd_keywords(jd))
跑这段代码前,建议先准备好几份你目标岗位的JD,把提取结果放到一起对比。你会发现很多JD里反复出现的词,就是简历里必须覆盖的ATS关键词。如果AI提取的词和你自己的技能确实匹配,可以直接在简历摘要或技能列表里使用原词,不要自己改成同义词,因为系统匹配是按字面比对的。
二、STAR改写:从职责罗列到可量化的结果表达
简历里最常出现的问题是写“负责XX系统的开发”“参与需求讨论”这类职责描述。这样的句子没有动作主体、没有结果、没有数据,招聘方看不出你做了什么、做得怎么样。STAR法则要求把一段经历拆成情境、任务、行动和结果,最后浓缩成一句可以用在简历项目栏里的强动词表达。
AI改写时的提示词要明确三件事:一是必须使用强动词开头,比如“搭建”“重构”“推动”;二是尽量补出可量化数据,但只能从原始经历里合理推断,不能凭空生成;三是输出JSON,方便后续拼装。如果原始经历里没有明确数字,可以让模型把metrics字段设为null,不要硬编一个“提升50%”出来。
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key", base_url="https://api.openai.com/v1")
def rewrite_experience_with_star(original):
prompt = f"""请用STAR法则改写以下工作经历。要求:
1. 输出JSON,字段:situation、task、action、result、star_sentence、metrics
2. star_sentence不超过80字,使用强动词开头
3. metrics中只保留能从原文合理推断的量化数据,如果没有则填null
4. 不要编造数据
原始经历:
{original}
"""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.3,
)
content = resp.choices[0].message.content.strip()
if content.startswith("```"):
content = content.split("\n", 1)[1]
if content.endswith("```"):
content = content[:-3]
return json.loads(content)
if __name__ == "__main__":
raw = "负责公司内部管理系统开发,参与需求讨论,编写接口文档,修复线上问题。"
result = rewrite_experience_with_star(raw)
print(json.dumps(result, ensure_ascii=False, indent=2))
实际跑下来,模型常常会把“负责开发”改写成“搭建内部管理系统,对接三个业务部门,修复线上故障并输出接口文档”。这个方向是对的,但你需要逐条核对:岗位JD里要求高并发,而你的经历里没有,就不能硬加。AI的作用是把已有事实表达得更清晰,而不是替你虚构经历。
如果一段经历实在没有数字,可以从规模、频率、影响范围三个角度补述。比如“负责系统开发”可以改成“负责日均处理5000条工单的内部系统开发”,前提是5000条来自你的真实场景。把这个原则写进提示词里,模型会稳定很多。
三、全流程实操:把JD分析和STAR改写串起来,避开常见坑
单次调用只能解决一个环节,真正提升效率的是把JD分析、关键词映射、经历改写串成一条流水线。先让模型解析JD,拿到keywords列表,再把每段原始经历和关键词一起送进STAR改写函数。这样改写出来的句子会更贴合目标岗位,而不是泛泛地优化表达。
下面的代码把两个步骤合并,输入JD和几条原始经历,输出结构化结果。你可以把raw_experiences换成自己简历里的项目描述,跑完后挑出满意的star_sentence拼进最终简历。
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key", base_url="https://api.openai.com/v1")
def extract_jd(jd_text):
prompt = f"""请从以下JD中提取JSON,字段为hard_skills、soft_skills、must_have、nice_to_have、keywords。只返回JSON。JD:{jd_text}"""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
)
return json.loads(resp.choices[0].message.content)
def rewrite_star(original, jd_keywords):
prompt = f"""请用STAR法则改写以下经历。参考JD关键词:{jd_keywords}。只返回JSON,字段包括star_sentence、action_verbs、metrics。不要编造数据。原始经历:{original}"""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.3,
)
return json.loads(resp.choices[0].message.content)
def optimize_resume(jd_text, raw_experiences):
jd_data = extract_jd(jd_text)
rewritten = []
for exp in raw_experiences:
star = rewrite_star(exp, jd_data.get("keywords", []))
rewritten.append({"original": exp, "star": star})
return {"jd": jd_data, "rewritten": rewritten}
if __name__ == "__main__":
jd = "负责后端服务开发,熟悉Python、Docker,3年以上经验,有高并发项目背景优先。"
experiences = [
"负责公司订单系统的开发和维护,参与需求评审,修复线上问题。",
"参与了一个数据统计平台的建设,写了一些接口。"
]
result = optimize_resume(jd, experiences)
print(json.dumps(result, ensure_ascii=False, indent=2))
流程跑通后,有几个坑需要重点留意。第一是JSON解析失败,有些模型会在JSON外面包一层围栏或者返回文字说明,所以要在解析前做strip和去围栏处理。第二是AI幻觉,提取JD关键词时可能把你根本没掌握的技能列进去,改写经历时也可能顺手编一个数字,这些都必须人工过一遍。第三是不要优化过度,如果简历写得太满,面试官追问细节时很容易露馅,所有star_sentence都要保证你自己能展开讲三分钟。
总体上,这套方法的价值不在于让AI替你写简历,而是把简历优化变成一个半标准化的流程。JD分析保证方向对,STAR改写保证表达密度够,人工校验保证真实性。按这个顺序多跑几个岗位,你会越来越清楚目标岗位到底需要什么,写出来的简历也会比之前更有针对性。

