☰
AI简历工具实战:用Vibe Coding解耦内容生成与排版控制
2026/10/6 5:50:39 网站建设 项目流程

做了大半年 AI 工具,最深的感受是:AI 写内容早就不是瓶颈了,真正让人想摔键盘的,永远是"生成的稿子没法直接用"。我的 Resume Hub 也不是什么宏大项目,就是被 AI 生成简历这件事反复折磨之后,自己写的一个顺手工具体。它的核心卖点不在"又调了一个大模型",而在把 Vibe Coding 的排版思路落到了简历场景里——你直接跟它说"我要左侧边栏放个人信息,工作经历按倒序排,整体走冷色调",它就真的按这个氛围感给你排出可用的一页纸 PDF,而不是每次都甩给你一份千篇一律的黑白模板。这篇文章就把我设计 Resume Hub 时的完整思路、踩过的坑、以及为什么"内容生成"和"排版控制"必须拆开来做,都摊开来讲一遍。如果你也在做 AI 生成文档、报告或者任何"生成完还得像样的东西",这篇应该能给你省不少试错时间。

1. 为什么我决定自建 Resume Hub:AI 简历最大的痛点不是生成,而是排版

1.1 内容过关但排版翻车的日子

先说个场景,应该很多人有共鸣。我拿某大厂简历生成器试过:填一遍工作经历,点生成,出来一份内容挑不出毛病的简历——项目业绩数字全了,职责描述全是行为动词开头,措辞也比我自己写的精炼。但我一看到版式就皱眉:通篇纯黑正文、没层级、没留白,两个字概括就是"能看,但没气场"。投出去面试邀约率也没见涨,因为 HR 筛选时首先是扫视,不是阅读,版式上的混乱会直接干掉第一印象。

我也试过把 AI 生成的文本丢进专业简历编辑器的模板库,又从另一个角度踩坑:模板是好看了,但我得手动分段、手动选 bullet、手动调缩进,AI 生成的段落结构跟模板预设的区块对不上,等于生成了个寂寞。来回粘贴调整的时间,比我自己从头写一份都慢。那段时间我就意识到一件事:简历工具的价值不是"AI 能写出内容",而是"AI 能不能直接交付一份排版完整、能投出去的成品"。

1.2 市面工具的三种短板

把市面上主流做法归拢一下,它们的问题基本就三类:

一是模板驱动。工具方预置几十个模板,AI 只负责往模板的固定字段里填文本。优点是稳定,缺点是千人一面,而且你想微调一个间距,编辑器里的控件常常不生效,改完这页乱了那页。二是纯文本流。LLM 输出的 Markdown 或纯文本直接转成 PDF,排版逻辑完全由内容顺序决定,没有任何版式设计可言。三是强制编辑。生成之后把你扔进图形编辑器自己调,本质是让用户承担了排版工作。

Resume Hub 想解决的就是这套问题。我的思路很直接:既然 AI 能理解自然语言,那为什么排版这件事不能也用自然语言来控制?Vibe Coding 的理念——用意图描述而不是手工操作来驱动产出——挪到简历场景,就成了整个项目的地基:你说"氛围",它给版式;你说"结构",它给布局;你说"气质",它给字体和字距。

我后面所有设计决策,都是从"让用户可以用语境描述排版"这个原点出发的。换句话说,我做的不是又一个 AI 简历模板站,而是一个"听得懂排版要求"的 AI 排版引擎,简历只是它第一个落地场景。

2. Vibe Coding 排版:让 AI 按你的"语境"而不是"模板"来做版式

2.1 什么是 Vibe Coding,放在简历场景里怎么理解

Vibe Coding 这个词这两年很热,核心就一句话:不再逐行精确写代码,而是用自然语言描述意图,让 AI 完成编码层面的落地。以前我们写 HTML/CSS 是"我要一个两栏布局,左栏 240px,右栏 flex:1",用 Vibe Coding 的方式是"左边放个人简介,右边放工作经历,整体要那种杂志编辑的清爽感"。AI 自己把宽度、间距、字体给定了。

放到简历排版上,这个理念非常契合。简历版式恰恰是那种"人人都想要点独特,但很少有人愿意从零调 CSS"的东西。用自然语言描述版式的可行性,比我预期的更高,因为版式设计里的很多规则是有共识的:HR 看的节奏、 ATS 可读性、一页纸的密度感、标题级的视觉层级。这些共识在训练数据里大量存在,LLM 天然就能理解"高级感"和"商业风"的差异。

我的第一个核心决策,就是放弃"模板选择器 + 参数面板",改为"排版意图输入框 + 实时渲染预览"。你在输入框里写"两栏结构,主栏占 70%,侧边栏 30%,侧边栏底色用浅灰,主标题加粗,section 之间间距拉开一点",系统解析之后直接体现在预览画面上。

2.2 从描述到样式:设计令牌映射的关键逻辑

真正到了实现层,最难的不是"听懂意图",而是把意图翻译成精确的 CSS。我给系统设计了一套中间层,叫设计令牌映射表。

它的工作方式是这样的:用户的自然语言会先被一个小 Agent 解析,输出结构化的设计令牌——颜色、字体族、字号层级、间距单元、布局结构。比如:

  • 用户说:"冷静、专业、科技感" → 解析成 color_tone: cool_gray + primary_blue
  • 用户说:"信息密度高一点" → 解析成 spacing: compact,font_size: body_11px
  • 用户说:"左边窄一点放照片和技能" → 解析成 layout: sidebar_left, sidebar_ratio: 0.28

这套映射表是我手工维护的,不是让 LLM 自由发挥。为什么?因为直接让 LLM 输出 CSS 虽然可行,但不可控。同一句"清爽一点",今天它输出padding: 24px,明天可能是padding: 2rem,后天给你来个letter-spacing: 0.01em,视觉结果天差地别。设计令牌相当于一个稳定的中间协议,LLM 只负责把自然语言映射到有限的令牌集合,真正的 CSS 由令牌决定。这样用户每次说"高级感",拿到的视觉结果是稳定且可预期的。

2.3 一个实际的排版指令处理示例

我拿一个真实的用户指令来展示流水线:

"排版方向走瑞士国际主义那种风格,栅格感强一点,姓名放大摆在左上角,联系方式放页脚。正文用无衬线,10.5 号字,行距 1.5。"

这条指令经过解析 Agent 之后,生成的设计令牌大概是:

{ "layout": "single_column_grid", "header": {"name_position": "top_left", "size": "xxl"}, "contact": {"position": "footer"}, "typography": {"family": "sans_serif", "body_size": "10.5pt", "line_height": 1.5}, "style_vibe": "swiss_grid", "grid_rules": ["strong_alignment", "asymmetric_balance"] }

渲染层拿到这组令牌后,会从样式库里加载对应模块,拼装出最终的 HTML/CSS。用户输入的"瑞士国际主义"会被映射到具体的栅格体系和字体组合,而不是随便套一个所谓"简约模板"。

这么做的好处非常明显:排版的控制力回到了用户手上,但用户不需要会写 CSS。你描述得越具体,结果越接近预期;描述得模糊,就用设计令牌里的默认值兜底。这是我做 Resume Hub 整条链路里最值得分享的设计——把"想象力"和"生产力"用令牌这张纸隔开,两边各自演进,互不污染。

3. Resume Hub 的整体架构:内容流水线与排版引擎的职责拆分

3.1 模块划分与数据流

Resume Hub 的架构没有多新奇,但它对模块边界的坚持值得一说。整个系统拆成五个模块:内容生成 Agent、排版解析 Agent、渲染引擎、校验 Agent、预览与导出服务。

数据流是这样的:用户输入原始经历(或者从旧简历粘贴)→ 内容生成 Agent 写成结构化 JSON(教育、工作、项目、技能各自成块)→ 用户在排版输入框里描述版式 → 排版解析 Agent 输出设计令牌 → 渲染引擎把 JSON 内容 + 设计令牌合成 HTML/CSS → 校验 Agent 检查溢出、断页、冲突装扮项 → 最后通过浏览器打印管线输出 PDF。

这个流水线里,内容 JSON 和设计令牌是两条完全独立的中间产物。它们之间唯一的接口就是渲染引擎。这也意味着,用户可以换内容不换版式,或者换版式不换内容,任意一个变数都不会影响另一个。这个解耦做出来后,产品的灵活性一下就上来了——后面加的"一键换风格"功能,其实就是重跑一遍排版解析和渲染,内容根本不用动。

3.2 为什么内容生成和排版必须分开

这是我在设计阶段最坚定的一个决策,也是回头看不后悔的决定。早期原型里我试过让一个 Agent 既写内容又排版式,prompt 里说"请生成一份内容专业、排版为两栏的简历"。结果就是两头都顾但两头都不精:内容质量还行,但排版动作特别粗暴,要不就是整页居中,要不就是信息层级一团乱麻。

原因不复杂:写简历内容需要的是领域知识和表达技巧,做排版需要的是视觉规则和空间感知。这两个能力在 LLM 里对应的是不同的注意力重心,硬塞进同一个上下文窗口,效果一定是互相稀释。更实际的问题是,内容生成通常要基于用户的经历上下文做长文本推理,排版只需要理解一句版式意图,两者 token 消耗和延迟特征完全不同。拆开之后,我甚至能给内容 Agent 用更大的模型,给排版 Agent 用更快更便宜的小模型,成本和体验都能独立优化。

3.3 多 AI 协作在这个项目里的实际分工

这里就涉及现在很多人聊的"多 AI 协作"了。我的经验是:协作不是把多个模型堆在一起,而是把任务拆到每个模型恰好擅长的粒度。

在 Resume Hub 里,实际参与协作的角色有四个:

  • 内容生成 Agent:负责将用户的零散经历扩展成 STAR 结构的简历条目。这个 Agent 的 prompt 最长,上下文里放满了用户填写的原始素材和岗位 JD,输出必须稳定遵循 JSON Schema。
  • 信息重排 Agent:负责根据目标岗位调整条目顺序,比如把"项目经历"提前,把"教育背景"压缩掉一行。它不重写内容,只做排序和裁剪决策。
  • 排版解析 Agent:只做一件事——把用户的版式描述映射成设计令牌。它的输出是严格限定的枚举值,几乎没有自由发挥空间。
  • 校验 Agent:最后过一遍稿,检查是否有文本溢出、字号过小、section 重叠以及 ATS 解析问题。它相当于质检员,权限只是标记问题、返回修改建议。

这四个 Agent 之间不直接对话,而是通过中间产物(JSON 内容、设计令牌、校验报告)串联。每个 Agent 的输出都有 Schema 约束,下游拿到的数据一定是干净的。这种"通过数据协作,而非通过上下文协作"的方式,让整个系统非常容易排查问题——哪一步出错了,看中间产物就知道是 Agent 的问题还是渲染的问题,不用去猜黑盒。

4. 关键实现细节:从提示词设计到出 PDF 的全链路

4.1 提示词模板的设计原则

Resume Hub 的提示词设计,核心原则只有一个:把约束前置,把自由度后置。

拿内容 Agent 的 prompt 举例,它分成五段:

  1. 角色定义:你是资深 HR 顾问和简历撰写专家,服务对象是投递科技公司岗位的候选人。
  2. 硬性约束:输出必须符合给定的 JSON Schema;每段经历必须有量化结果;不允许编造用户未提供的公司名称和职位。
  3. 内容处理规则:把口语化描述转成行为动词开头;用 STAR 法则重组经历;如果信息不足,用占位符标注,而不是自拟。
  4. 风格偏好:描述要保持精炼,每条不超过两行;数字优先;避免形容词堆砌。
  5. 用户输入区:原始经历和岗位 JD。

这里最容易被忽略的是第二段"硬性约束"里的"不允许编造"。我做用户访谈时发现,很多人不用 AI 简历生成器,就是担心 AI 往简历里加没做过的东西。这个担心不是多余的,早期版本确实出现过"润色过度"的情况——用户只写了一句"负责订单系统",模型给扩展成"负责订单系统的架构重构,提升处理效率 40%"。这个 40% 用户根本没提过。后来我在 prompt 里明确禁止"引入用户未提供的具体数据",并且让内容 Agent 对任何数值类信息做来源标记,没有来源的数值一律用[待补充]框出来,用户确认后才允许进终稿。信任问题不解决,功能做得再花哨也没人敢用。

排版 Agent 的 prompt 则完全不同,它不需要理解用户的职业背景,只需要识别版式意图。它的 prompt 里我给了一个意图分类清单和每个分类对应的令牌枚举值,同时明确告诉它:如果用户的描述过于抽象,就返回默认令牌,不要自行发明新的视觉方案。这里的关键是限制想象空间,跟内容 Agent 鼓励发挥正好相反。

4.2 渲染引擎的选型与实现

渲染层我选了 HTML/CSS + 浏览器打印管线,没有用 PDF 库直接画。原因很简单:简历版式是复杂自适应的东西,用纯代码布局去写,两栏、多 section、动态长度,工作量太大而且容易崩。HTML/CSS 的布局能力是现成的,Flexbox 和 Grid 天然支持这些需求,而且预览效果和最终 PDF 可以做到所见即所得。

具体实现上,渲染引擎接收的是两部分数据:

{ "resume_data": { "name": "张某某", "contact": {"email": "...", "phone": "..."}, "sections": [ {"type": "work_experience", "title": "工作经历", "items": [...]} ] }, "design_tokens": { "layout": "sidebar_left", "sidebar_ratio": 0.3, "color_primary": "#1e3a5f", "font_body": "Inter, Noto Sans SC", "spacing_section": "16px" } }

渲染引擎内部维护了一份 CSS 变量系统,设计令牌会直接映射到 CSS 变量,组件库里的每个 section 都通过变量取样式。这样好处是:不用为每个新版式写一套完整 CSS,只要把变量换成另一组,整份简历的视觉气质就全变了。我后面做"夜间预览""高对比度模式"之类的功能,都没碰组件代码,只换了变量组。

浏览器打印管线是相对成熟的技术方案。我用的流程是:模板 HTML 加载完成后,注入数据,渲染成完整 DOM,然后调用window.print()并拦截打印事件,设置 A4 纸尺寸和边距。PDF 导出直接走浏览器的"另存为 PDF",省掉了后端渲染服务,架构简单不少。但这里有个关键细节:字体必须预先内联,或者通过 CSS@font-face明确加载路径,否则打印时字体会被系统默认字体替代,版式就会变形。我自己就吃过这个亏,后面会细说。

4.3 校验层:防止"一页纸变两页半"的最后防线

简历这个场景有一个硬指标:绝大多数岗位社招建议一页,应届生最多两页。但 LLM 生成内容的字数非常不可控,同一个人的经历,重复生成两次,可能一次刚好一页,一次多出三四行溢出到第二页。

我做过的最实用校验规则有这么几条:

  • 溢出检测:渲染完成后检查 DOM 里 body 的实际高度是否超过 A4 可用高度,超过就返回错误码,并把超出的像素值反馈给校验 Agent。
  • 孤儿条目检查:检测是否有 section 标题落在页面最底部,下面没有任何内容。这种排版看起来非常业余,属于必须拦截的硬伤。
  • 字号下限检查:正文小于 9pt 直接报错。很多用户在调整"塞进一页"时会把字号无限缩小,这种简历打印出来是考验 HR 视力,不能放行。
  • ATS 文本提取测试:把渲染后的 HTML 转成纯文本,看是否保留完整的信息顺序。因为很多大厂的简历筛选系统直接解析文本,如果你把联系方式放进了 CSS 隐藏元素里,ATS 是抓不到的,这个必须校验。

校验 Agent 不是直接改排版,而是返回结构化报告,比如"溢出 12px,建议将工作经历第二条的自我评价删除,或将行距从 1.5 减为 1.4"。用户可以在预览界面直接点"接受建议"或者忽略。这个设计让用户感觉自己始终在掌控,而不是被 AI 安排得明明白白。

5. 实测中踩过的坑和对应的处理方案

5.1 排版幻觉:AI 声称左对齐,结果全居中了

这个坑在早期版本里非常高发。用户输入"头像放左侧,文本右对齐",排版 Agent 返回的令牌确实是text_align: right,但渲染出来的页面上,姓名和工作经历段落变成了整块右对齐,阅读起来极其别扭。问题出在"文本右对齐"和"区块右对齐"的语义混淆上——用户原本想让文本块出现在页面右侧区域,而不是让文字本身右对齐。这是典型的自然语言歧义。后来我的处理方案是:排版 Agent 对涉及对齐、布局的词组一律输出布局语义(align_x: right_zone),不直接映射到 CSS 的text-align。CSS 对齐只有在明确的"文字对齐方式"语境下才会被启用,比如"简介文字居中"。这个调整上线之后,这类排版幻觉基本从"每三次必现"降到了"偶尔出现"。

另一个幻觉来源是"版式语言"和"视觉风格"混合描述。比如用户说"要极简风格,多留白,信息放散一点",既包含间距意图又包含布局意图。排版 Agent 早期会把"信息放散"理解成增大 padding,导致整份简历内容之间空隙过大,一页根本放不下。修复办法是在提示词里新增了一条语义拆分规则:环境类词(极简、留白、冷色)走风格令牌,空间类词(分散、居中、靠边)走布局令牌,两者输出到不同字段,渲染引擎分别消费。语义拆分之后,排版结果的可控性上了一个台阶。

5.2 中文简历的字号陷阱

中文简历和英文简历在排版上的差异,做工具时极其容易忽略。英文正文用 10pt 看着很舒服,但中文 10pt 的阅读体验就差很多,因为中文字形的笔画密度和结构复杂度跟拉丁字母完全不是一个量级。第一版 Resume Hub 直接照搬了英文简历的字号体系,结果中文简历一出来,密密麻麻,用户反馈"看两行就眼花"。

后来我把中文排版的字号阶梯单独拎了出来:正文最小 10.5pt,推荐 11pt;标题 14pt 到 16pt;姓名 22pt 以上;行距中文字号乘以 1.6 到 1.8,而英文只用 1.4 到 1.5。这些数值来自排版经验,不是 LLM 给的。我把它们固化成了中文设计令牌集,排版 Agent 在处理中文内容时只能在这套令牌范围内取值。这也是我前面说的,设计令牌的维护是人工经验,不是 AI 生成——AI 负责理解和翻译,审美红线必须由人画。

字体的选择也踩过坑。系统默认字体走Noto Sans SC,但很多 Windows 用户的打印环境没有装这个字体,实际导出会用宋体替代,版式瞬间从现代感变成公文感。现在的处理方式是前端做字体加载检测,如果没有目标字体,就提前提示用户安装,或者降级到一个已确认可用的备选字体组合。还有一个细节:字体的font-weight在中文场景下经常不生效,因为中文字体大多数只有 400 和 700 两档,你设一个 500 的加粗值,浏览器会直接渲染成普通字重,导致标题层级感出不来。现在我的中文设计令牌里,字重只保留regular和bold两档,不搞中间值。

5.3 一页控制为什么那么难

这是所有简历工具都绕不开的难题,也是 Resume Hub 迭代最久的一部分。AI 内容生成本身就是概率性的,每次生成的文本长度会有 10% 到 15% 的波动。有一天我拿同一份输入测了 20 次生成,最短的 42 行,最长的 57 行,但用户期望的版式只有一页 A4。指望 LLM 精确控制长度,我试过很多 prompt 技巧,实测都不稳定。

最终方案是加了一道"内容收缩器"模块,专门服务于长度问题。它不重新生成文本,而是做三个动作:压缩冗余副词和过渡词、把长复合句拆成短句、将两行条目并成一行。这些动作在语义不变的情况下,能砍掉 10% 到 20% 的体积。如果砍完还是超长,就启用第二优先级策略:从最不重要的条目开始整条裁剪,并给用户标记"已裁剪内容",可以在界面上选择恢复或移除。这套机制上线后,"一键一页"的成功率从最早版本的 60% 出头,拉到了现在的 95% 左右——剩下那 5% 是真的经历太多,强行塞一页只会损失信息价值。

5.4 预览与导出的"差一点不一样"

浏览器预览和最终 PDF 不一致的问题,是 PDF 生成工具的老大难。我实测遇到的主要有这几个:行高在 Chrome 打印预览里会被压缩、某些字体的字距在打印时被重新布局、背景色默认不打印。前两个问题我通过在打印媒体查询里显式重置行高和字距,加了-webkit-print-color-adjust: exact才让背景色保住。还有一个隐藏细节:打印时要关掉浏览器默认的页眉页脚,否则导出的 PDF 右上角会多一行 "file:///C:/..." 之类的路径,非常掉价。现在的导出流程是弹出打印对话框后,自动注入脚本取消页眉页脚并设置合适边距,用户基本不需要手动调整。

曾经有用户反馈"预览是一页,导出变一页半",查了半天原因是用了非标准 A4 尺寸的显示器,打印缩放比不同。解决办法是在导出入口做了一次强制设置:@page { size: A4; margin: 0; },并把打印内容包裹在一个固定宽度的容器里,彻底锁死尺寸。这套做法对大多数 Chromium 内核的浏览器都有效,覆盖率足够满足我的用户群。

6. 这个工具的边界与下一步的扩展思路

6.1 我明确不做的事

工具做久了会知道,明确边界比堆功能更重要。Resume Hub 有几个东西我刻意没有加:

  • 不承诺"简历保证过筛"。“AI 优化后面试邀约率提升多少”这类话术我不信,也不做。简历在招聘链条里的作用是"不扣分",真正决定结果的是面试表现和匹配度,工具能负责的是把人的亮点清晰呈现出来。
  • 不做花哨的视觉特效。动态图标、粒子背景、渐变大字——这些适合个人主页,不适合简历。HR 和 ATS 系统对简历的要求永远是清晰优先,工具给用户的默认值应该是最稳妥的商用版式。
  • 不做"AI 全程全自动"。全自动生成一版简历很简单,但用户对内容没有掌控感,就不放心投。Resume Hub 保留了很多用户确认环节,宁可通过率高一点,也不把用户的信任透支掉。

6.2 后续想试的方向

接下来我计划做两件事。一是把设计令牌体系开放出去,让用户能自定义自己的令牌组合并保存为"我的风格"。现在系统中内置的风格令牌是有限的,用户只能在现有集合里选。但很多设计师背景的用户其实有明确的个人版式喜好——他们不一定写 CSS,但知道自己要什么,给他们一个可以保存的令牌模型,比不断扩充内置模板更省资源。二是把 Vibe Coding 排版能力从简历复制到其他文档场景,比如项目周报、产品方案、甚至学术海报。排版意图描述这个中间层一旦稳定,其他文档类型只是换一套组件和令牌集的问题,维护成本很低。我也在调研一些视觉模型直接对版式草图做理解的可能性——用户画个线框草稿,AI 直接生成对应版式,这可能是比自然语言描述更直觉的一层交互,但技术成熟度还不太够,等稳定了再往里放。

最后分享一个我从这个项目里得到的实在体会:做 AI 工具,别把心思全花在"调一个最强的模型"上。模型能力只是底座,真正决定工具好不好用的,是你敢不敢在模型外面套一层确定性的规则。Resume Hub 里最有价值的部分,反而是那些不加 AI 的部分——人工维护的设计令牌、固定在纸面上的排版红线、不许模型自由发挥的对齐语义。AI 负责理解人话,但审美和底线得自己握着,这套思路放到任何内容生成工具里都成立。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询