简历 AI 帮你写
面向学员端完成简历内容优化。只使用用户提供的简历,以及 gaodun-job MCP 下发的静态 Prompt、模块配置和 HTML 模板;不读取后端源码,不调用简历业务接口,不落库。
核心契约
每一步都必须满足进入条件后才能执行,并产生明确产物后才能进入下一步。岗位确认是硬门禁,岗位值不是绝对必填:缺少意向岗位时询问一次;用户给出岗位则定向优化,用户明确不填或要求通用优化则记录跳过并继续。不得把岗位问题混入字段追问。
路由与分支
| 用户请求 | 进入条件 | 路径 | 产物 |
|---|---|---|---|
| 只优化一段或一个字段 | 已提供待优化原文 | 单字段优化 | 优化后的字段文本 |
| 优化已上传的整份简历 | 已提供完整附件或全文 | 整份优化 | 本地 HTML + PDF;失败时降级为已完成内容 |
| 只排版,不改内容 | 已提供整份简历 | 仅排版 | 本地 HTML |
| 诊断、评分、问题报告 | 请求重点是评价而非改写 | 改用 resume-diagnosis |
由对应 skill 决定 |
| 面试练习 | 请求重点是模拟面试或刷题 | 改用 interview-brush |
由对应 skill 决定 |
用户已提供整份简历并泛化要求“优化简历”时,直接走整份优化;不再询问范围、模板或输出格式。只有用户明确限定字段时才缩小范围。
意向岗位确认门禁
何时进入
- 单字段或整份内容优化:必须执行岗位确认。
- 仅排版:不执行岗位确认,直接解析和渲染。
- 简历已有明确
position:视为已确认,不重复询问。
决策分支与产物
| 情况 | 动作 | 产物 / 状态 | 下一步 |
|---|---|---|---|
| 有一个明确岗位 | 直接采用 | position=<岗位>、positionConfirmed=true |
准备优化资源 |
| 没有岗位 | 单独询问一次目标岗位并停止 | 等待用户输入 | 收到答复后重新判定 |
| 用户明确不填或要求通用优化 | 接受跳过,不再追问 | position=""、positionConfirmed=true;Prompt 中岗位变量由脚本填“无” |
准备优化资源 |
| 只有岗位名称、没有 JD | 按岗位名称定向,不索要 JD | position=<岗位> |
准备优化资源 |
| 用户要求按具体 JD 匹配但未提供 JD | 询问 JD 并停止 | 等待 JD | 收到后继续;不得臆测 JD 要求 |
| 多个意向岗位且未指定主岗位 | 请用户选一个主岗位,或明确选择通用优化 | 等待选择 | 不得把冲突岗位要求混入同一版本 |
整份流程的机器门禁:init 返回 positionMissing=true 时,必须先完成上表分支;有岗位执行 set-position --position '<目标岗位>',明确跳过执行 set-position --skip。在此之前 next 必须拒绝推进。
单字段流程没有 runner 状态文件,但门禁语义相同:确认结果写入 fields.json.position;用户明确跳过时写空值,由脚本统一填“无”。
不可违背的执行断言
- 用户上传整份简历并泛化要求优化时,默认且立即执行整份优化并生成 HTML + PDF;整份简历优化的最终交付物固定为 HTML 和 PDF,并自动进入 Phase 5(即本文“汇总/渲染”步骤)。禁止询问“希望怎么优化”,不得提供“整份重写 / 诊断 / 重点字段”选项,也不得推荐或切换到
resume-diagnosis。 - 禁止询问或提供 Word / PDF / HTML 输出格式选择;默认模板固定为
default。 --resume-type只使用 CLI 枚举键,例如havingInternshipExperience;禁止数字别名,也不得让用户选择resumeType。- 每个优化字段无条件走两阶段,第一个动作恒为追问 Prompt;问题产生后用户可全部跳过,但展示追问后必须结束当前回复。不得把“用户尚未回答”解释为“全部跳过”。
- 整份简历必须使用
scripts/full_resume_runner.py,禁止由模型自行维护循环下标。优化结果逐条累计到overrides.json;仍有未处理项目,runner 会禁止提前生成 HTML。没有需要优化的字段时直接进入渲染。 - 用户明确跳过追问时执行
skip-questions --state runner-state.json --confirmed-by-user。优化响应通过complete --state runner-state.json --response-file optimization-response.json传递 LLM 原始 JSON;禁止用complete --resume。
全局约束
- Prompt、模板和模块配置默认只通过一次
resume_resource_bundle_get获取;旧的resume_prompt_get、resume_module_config_get、resume_template_get仅用于整任务兜底,不得读取后端工程作为运行依赖。 - MCP 只接收资源查询参数。简历正文、追问答案、优化结果和个人信息不得传给 MCP。
- MCP 返回值原样保存为 UTF-8 JSON,再交给
scripts/materialize_resources.py;不得手工拆 JSON、复制 Prompt 或改写 HTML。 - 简历解析只用
scripts/resume_parse.py;整份编排只用scripts/full_resume_runner.py;HTML 只用scripts/render_resume_html.py;HTML 转 PDF 只用scripts/html_to_pdf.py。 - 多行 JSON、简历正文和问答通过文件传递,不放进 shell 参数。模型原始响应只用
scripts/save_response.py从 stdin 落盘,禁止 shell>重定向或临时脚本转写。 - 每个进入优化的字段必须先执行追问 Prompt。返回 3 个问题时,展示后停止;只有用户回答或明确跳过才能继续。返回
questions: []时不打扰用户,直接优化。 - 空变量和跳过答案由脚本填“无”,不得编造用户信息。
- 追问结果必须是 3 个非空问题或零问题,不允许残缺;优化结果必须含非空
resume。解析失败只允许修复一次并再校验一次。
流程总览
| 步骤 | 进入条件 | 动作 | 必须产物 | 分支 / 退出条件 |
|---|---|---|---|---|
| 1. 路由 | 收到用户请求 | 按“路由与分支”分类 | single / full / layout-only / 转交目标 |
转交即结束本 skill |
| 2. 岗位确认 | 路径包含内容优化 | 执行岗位确认门禁 | 已确认的岗位值或明确跳过记录 | 未确认则停止等待;仅排版跳过此步 |
| 3. 资源准备 | 路由和岗位状态已确定 | 一次获取并物化对应模式的 MCP 资源包 | 完整资源目录 | 失败则按资源失败语义停止;仅“不支持新工具”可整任务兜底 |
| 4. 输入准备 | 模块配置已物化 | 保存用户内容;整份简历再解析 | fields.json 或 finalized.json |
解析失败则报告并停止 |
| 5. 字段追问 | 字段原文和追问 Prompt 就绪 | 调模型、保存并解析响应 | 3 个问题或 questions: [] |
3 问则等待;零问直接优化 |
| 6. 字段优化 | 用户已回答/明确跳过,或追问为零问 | 渲染优化 Prompt、调模型并校验 | 非空 resume |
失败可重试、跳过当前字段或停止 |
| 7. 汇总/渲染 | 单字段完成,或整份队列全部结束 | 单字段直接交付;整份累计 overrides 后渲染 HTML 并导出 PDF | 字段文本或 HTML + PDF | HTML 失败则降级交付已完成内容;PDF 失败只降级 PDF |
准备 MCP 资源
默认执行“一次 MCP 业务调用 + 一次 Python 执行”。宿主只把完整 tool result 保存为一个 UTF-8 JSON 文件,禁止逐字段复制、拆分或重复启动 Python。详细协议见 references/pipeline.md。
单字段
进入条件:已确定
dataFieldCode,并完成岗位确认。从
references/field-config.json取得该字段的promptOneId/promptTwoId,调用一次resume_resource_bundle_get {"prompt_ids":["<promptOneId>","<promptTwoId>"]}。将完整响应保存到资源目录之外的临时 JSON 文件,然后只启动一次 Python:
python scripts/materialize_resources.py ingest-bundle --mode single \ --input <bundle-response.json> --out-dir <资源目录> \ --prompt-ids <promptOneId,promptTwoId>
整份简历
- 进入条件:用户已提供整份简历;必须在
resume_parse.py emit-template/finalize之前准备资源。 - 调用一次
resume_resource_bundle_get {"include_all_prompts":true,"include_module_config":true,"theme":"default"}。 - 将完整响应保存到资源目录之外的临时 JSON 文件,然后只启动一次
ingest-bundle --mode full。脚本同时校验、转换模板、写 manifest 并事务替换资源目录;成功后不得再单独运行verify。 - 使用已物化的
resume-module-config.json执行解析,再执行 runnerinit。 - 若输出
positionMissing=true:立即执行岗位确认门禁;未完成前不得调用next。
仅排版调用一次 resume_resource_bundle_get {"include_module_config":true,"theme":"default"},随后执行一次 ingest-bundle --mode layout。旧路径诊断可用 verify;--layout-only 与 --prompt-ids/--field-config 互斥。
单字段执行
- 进入条件:岗位已确认,字段类型和原文已确定。输出
fields.json,其中包含position。 - 执行
aihelp.py render --stage ask。输出渲染后的追问systemPrompt/userContent。 - 调当前模型,用
save_response.py保存ask-response.json,再执行parse-ask。 - 分支:
- 3 个问题:展示问题并停止;用户回答后输出
qa.json。 questions: []:无需用户输入,直接进入优化。- 非法响应:只修复一次;仍非法则停止。
- 3 个问题:展示问题并停止;用户回答后输出
- 执行
aihelp.py render --stage opt,保存optimization-response.json,再执行parse-opt。 - 完成条件:解析得到非空
resume;只交付该字段内容。
整份简历编排(本地扩展)
处理前必须阅读 references/analysis-resume-rules.md 和 references/pipeline.md;结构不清楚时再读 references/resume-schema.md。
- 进入条件:已提供整份简历。提取文本、填充解析模板,并用
resume_parse.py finalize输出finalized.json。 - 进入条件:解析完成且基础资源已物化。执行
full_resume_runner.py init,输出runner-state.json、requiredPromptIds和岗位状态。 - 进入条件:岗位门禁已解除、所需 Prompt 已物化。重复执行
next,只按其返回动作推进:ask:调用追问模型;3 问则展示后停止,零问则执行no-questions。- 用户回答:保存
qa.json,执行answers --qa-file qa.json。 - 用户明确跳过追问:执行
skip-questions --confirmed-by-user;仍进入优化。 optimize:调用模型,用complete --response-file保存结果。- 字段失败:由用户选择重试、
skip-item --confirmed-by-user或停止。
- 输出:所有结果按
(moduleCode, dataSort, dataFieldCode)逐条累计到overrides.json;不得自行维护循环下标。 - 只有
next返回render_html后才能生成 HTML;仍有未处理字段时禁止提前导出。
模型调用或会话中断后,从 runner-state.json 继续,不得重新初始化覆盖进度。
交付与降级
单字段:只返回优化后的字段内容。
整份简历:默认同时交付 HTML 和 PDF。HTML 渲染成功后,立即执行一次:
python scripts/html_to_pdf.py --html <简历.html>输出到 HTML 同目录同名
.pdf;脚本返回非零或 PDF 校验失败时,只降级 PDF,仍交付 HTML 并明确说明。编辑事实源:HTML 是唯一可编辑事实源,PDF 是从 HTML 重新生成的只读产物。用户后续要求修改内容或样式时,一律先改 HTML(或改
finalized.json/overrides.json后重新渲染),再用html_to_pdf.py重新导出 PDF,保证两份产物同步。禁止直接编辑 PDF。模板缺失或转换失败:仍交付已完成的优化内容,并明确 HTML/PDF 未生成。
某字段失败:保留已完成结果;等待用户选择重试、跳过该字段或停止。
不在日志或 manifest 中保存完整电话、邮箱、简历正文、问答或模型响应。
交付结束语
整份优化交付 HTML + PDF 后,固定以以下话术收尾(路径替换为实际产物路径):
优化版简历已生成:
- HTML:
.../张三的简历.html(浏览器打开可预览、打印)- PDF:
.../张三的简历.pdf(可直接投递)如果想调整内容,直接在对话里告诉我要改哪里,我会改完同步更新 HTML 和 PDF;也可以下载 PDF 自行使用,或在浏览器打开 HTML 后另存/打印。
常见错误
| 错误 | 正确处理 |
|---|---|
| 把意向岗位混入某字段的 3 个追问 | 岗位是前置门禁,必须单独询问一次 |
| 把岗位值当成绝对必填 | 用户明确要求通用优化时记录跳过并继续 |
| 没有 JD 就阻塞所有优化 | 只有用户明确要求“按 JD 匹配”时 JD 才是必需输入 |
| 同一版本同时迎合多个冲突岗位 | 先确定主岗位,或选择通用优化 |
| 追问后自动替用户作答 | 展示并停止,等用户回答或明确跳过 |
runner 尚未返回 render_html 就导出 |
继续队列,直到 runner 明确放行 |
只有用户明确要求按具体 JD 匹配时,JD 缺失才构成卡点;其他优化不得因没有 JD 而停住。
内部映射边界
后端实现、接口、配置与 PromptId 的来源和影响分析不属于本 Skill,由服务端团队维护;不要把它们加入学员执行流程。