前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9264
  • Vercel AI SDK 新增 ACP 协议兼容 Harness 层
  • GLM 5.2 Eve模型:百万上下文免费用
  • Gemini 3.7 Flash登陆AI Gateway,折扣50%
  • Exa神经网络搜索引擎登陆Vercel Agent市场
  • OpenAI被黑背后:AI Agent失控的三个技术根源
  • Cursor Agent 环境预构建:启动速度提升 3 倍
  • Simon Willison测评:DeepSeek V4 Pro推理能力差异化显著
  • 四步法区分Flaky Test与真实回归
  • AI工具调用测试夹具设计的四大原则
  • EXL2量化:分数位宽如何实现精确显存匹配
  • ExecuTorch移动端推理:三阶段导出流程详解
  • LLM输出快照测试失败不等于回归
  • 事件流处理架构核心:分区与状态的成本推导
  • OpenCode 评测:终端原生 AI 编程 Agent 体验
  • AWS ECS自动扩缩容:正确用队列深度替代CPU利用率
  • AI Agent 内容工厂实战:19 个 Agent 日产 53 篇内容
  • LLM 测试去 flaky:按根因分组而非按测试名
  • AI 编程双车道工作流:量大任务用便宜模型,重大判断需人工审核
  • AI 输出日期格式暗坑:DD/MM 与 MM/DD 歧义为何难发现
  • Claude Chrome扩展升级:侧边栏对话与全平台历史同步
  • LLM 从简历提取工作经历的结构化schema设计
  • LLM 从简历提取学历的结构化schema设计
  • 模型别名指向的模型下线后会发生什么
  • Cursor 推出专用 AI Agent Git 托管服务 Origin
  • LLM 多轮对话截断策略的迁移实践
  • Context Caching 迁移的真实要求
  • Prompt 变更 Code Review 审查清单:六个关键维度
  • Cloudflare Vectorize 定价与维度计费陷阱详解
  • Anthropic引入AI输出水印,部分用户不满
  • Claude各模型知识截止日期详解:训练数据与可靠 cutoff 的差异
  • Claude Message Batches API:24小时窗口内50%折扣的异步批处理
  • Claude API强制输出JSON的规范做法:不用JSON Mode
  • Claude交错思考模式:工具调用后如何继续推理
  • Claude Extended Thinking原理:budget_tokens与max_tokens共享配额
  • Claude API 并行工具调用机制与禁用选项详解
  • ShieldFont:用字体特征对抗AI爬取
  • KEDA 按队列长度扩缩容 Celery 工人
  • CodeRabbit 推变更管理:PR 成 SDLC 瓶颈
  • Celery + Redis 队列化 K8s 推理架构实战
  • 用合同测试拦截第三方 API 破坏性变更
  • AI 能否生成真正的粤语而非书面中文
  • MCP 协议让 AI 操控 Minecraft:61 个工具覆盖移动/建造/战斗
  • Eval 分数骗人:AI 模型金丝雀指标应看 token 消耗/截断率/工具调用
  • 引用文献解析的正确姿势:分段策略比单次全量提取更可靠
  • 本地跑 BGE 向量模型:normalize_embeddings 是关键参数
  • 供应链攻击泄露数千亿字节凭证:2500 名 AI 包用户中招
  • AWS Bedrock 按token计费常见陷阱:单位换算与实时查询方法
  • Bedrock 知识库+S3 文档实战:分块策略与同步链路详解
  • Anthropic Chrome插件升级为Cowork模式
  • 分类模型准确率骤降诊断:指向数据输入问题
  • 跨API迁移异步轮询循环的六个假设
  • 已加载 51 / 9264
8.0
热点
AI SCORE
技术实践2026-08-13 07:02

LLM 从简历提取工作经历的结构化schema设计

dev.to · AI#LLM#数据提取#Schema设计
Editor brief · 编辑速览

文章指出「每公司一行」schema 会丢失内部晋升记录,建议用「每角色一行」+共享雇主字段设计,可保留完整信息且避免歧义。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

一份简历没有固定的模式、没有权威依据、也没有校验位。它有的只是一组一致的结构,这些结构会破坏那种简单的"雇主—职位—开始—结束"式记录,而所有这些问题都可以在写 prompt 之前就设计掉,而不是事后打补丁。

职位才是最小单位,而非雇主

最容易想到的记录方式是一条记录对应一家公司——但在"每公司一条"和"每职位一条"之间的选择,其实是"多实体文档模式设计"中的通用问题。这种选择在一个最常见的简历模式上必败:内部晋升,写成一个区块,雇主名只出现一次,下面嵌套两三个职位,各自带有独立的时间段:

Borealis Logistics                                  Apr 2022 - Present
  Senior Platform Engineer                          Feb 2024 - Present
  Platform Engineer                                 Apr 2022 - Feb 2024

如果用公司级模式,你必须选一个职位名和一个时间段,无论选哪个都丢弃了真实信息。如果用职位级模式,这就是两条记录共享一个雇主值,不需要丢弃任何东西。外层的时间范围由此变成可推导的——它就是各职位的并集——而不是模型需要调和的第四个东西。

同样的选择还能免费处理其他三种情况。一个承包商通过一家中介在四个客户那里工作,就是四条职位记录,中介放在单独字段里。一个人在从事日常工作的同时兼任顾问,就是时间段重叠的两条职位记录,这是合法的,不是错误。复聘——相隔多年在同一公司的两段任职——是两条职位记录,而不是一个吞掉中间时间空白的单一时间段。

最后这种情况的意义比看起来更大。复聘的公司级记录会覆盖整个时间段,包括当事人在别处的那些年份,任何基于此计算在职时长或空档期的下游逻辑都会出错,而且这种错误不会被任何人发现。具体可参见从简历日期范围提取就业空档期,看看这种计算究竟需要什么。

日期:精度、开结尾和歧义

三个独立的问题被混为一谈成了"解析日期",每个都需要在模式设计时单独做决定。

精度在同一份文档内就有差异。2019 年 3 月、03/2019、2019、2019 年春都会出现,有时就在同一份简历的相邻行上。把它们全部存成完整的 ISO 日期,迫使模型编造一个具体日期,而一旦进入数据库,这个编造的日期就和一个真实的日期无法区分。要以原始精度存储数值,同时存储精度本身,这样任何使用方都知道 2019-03-01 是代表 3 月 1 日,还是只表示 3 月。

结束日期往往是开放的。Present、Current、Now、to date,以及破折号后什么都没有,都表示同一件事。不要让模型用今天的日期来替代:那样的话这条记录的语义会根据提取时间悄然变化,两年前写的简历提取后会显示当事人仍然在职。把它建模为一个显式的空结束,加一个布尔标志,如果确实需要闭区间来做计算,就在提取日期处关闭,并记录那个日期。

数字日期按地区有歧义。04/07/2021 在美式格式的简历里是 4 月,在世界大多数地方是 7 月,token 本身无法告诉你答案。唯一可靠的消歧手段是同一份文档内的上下文:如果简历上任何日期的第一个组成部分大于 12,那么整个文档就是"日在前",其余日期都可以依此处理。如果没有任何日期能消歧,就记录这个歧义而不是猜测——起始日期三个月的小错误,恰好是会悄悄破坏在职时长计算的那种错误量级。

const ROLE_SCHEMA = {
  type: "object",
  additionalProperties: false,
  required: ["employer", "title", "start", "end", "raw"],
  properties: {
    employer: { type: "string" },
    employer_via: { type: ["string", "null"] },   // agency or umbrella company
    title: { type: "string" },
    employment_type: {
      enum: ["full_time", "part_time", "contract", "internship",
             "freelance", "volunteer", "unknown"],
    },
    location: { type: ["string", "null"] },
    start: {
      type: "object",
      additionalProperties: false,
      required: ["value", "precision"],
      properties: {
        value: { type: "string" },                 // "2022-04" or "2022"
        precision: { enum: ["day", "month", "year"] },
      },
    },
    end: {
      type: ["object", "null"],                    // null means still in role
      additionalProperties: false,
      required: ["value", "precision"],
      properties: {
        value: { type: "string" },
        precision: { enum: ["day", "month", "year"] },
      },
    },
    is_current: { type: "boolean" },
    date_order_ambiguous: { type: "boolean" },
    raw: { type: "string" },                       // the block as it appeared
  },
};

employer_via 这个字段之所以必要,是因为没有它就无法代表性用工场景:简历上写的是"Ravensworth Consulting(客户:Northgate Bank)",而单一雇主字段必然要丢失其中之一。raw 这个字段在所有这类场景中都有必要——原因是一样的——它是当 prompt 或模型发生变化时用来做 diff 的依据,而这就是提取模型版本审计追踪的意义所在;也是审核人员不需要重新打开 PDF 就能阅读的内容。

两条指令就能完成大部分工作,而且两条都是关于"禁止主动帮忙"而不是"请求帮忙"。

提取每一条独立的职位。一条职位是指在同一个雇主下、
同一个连续时间段内的唯一一个职位名称。

- 如果一个雇主区块下列出了多个各有时间段的头衔,
  每条头衔输出一条职位。不要为雇主区块本身输出一条职位。
- 按原文复制日期。不要把月份转换成具体某一天,
  不要推断缺失的月份,也不要把 "Present" 替换成日期。
  如果结束日期缺失或开放,将 end 设为 null,
  并将 is_current 设为 true。
- 如果一个数字日期既可能是日在前也可能是月在前,
  且文档中没有其他日期可以消歧,
  将 date_order_ambiguous 设为 true。
- raw 必须是原文区块的完整文本,包括换行符。

不转换精度的指令是最容易被遗漏的一条,也是对输出影响最大的一条。没有这条指令,模型每次遇到"2019 年 3 月"都会返回 2019-03-01,而这个编造的日期就变成了系统中的一个既定事实。这是提取类 prompt 的一般特性,而非简历特有的问题——提取类 prompt 中有详细讨论。

简历在大多数隐私法规下属于个人数据,发送给第三方模型的简历等于数据离开了你的基础设施。这是否合法取决于你的处理依据以及你与提供商的合同,而非提取过程本身;相关义务见 GDPR 分处理商清单。本文不构成法律建议。

无需人工的校验

简历没有外部权威可以验证,但提取结果可以通过五种方式做内部校验,而且五种都很廉价:

每条职位的 start 必然早于 end。时间范围颠倒几乎总是模型把右对齐日期布局中的两列互换了一下,这是最常见的结构性错误。

没有任何日期在未来,除了标记为当前职位的 end(本来也应该是 null)。未来的 start 日期通常意味着两位年份被扩展到了错误的世纪。

每个雇主最多只有一条标记为 current 的职位,除非简历中确实显示了同时任职。同时存在于同一雇主的两个 current 职位,意味着一个晋升区块被错误地拆分开了。

每条 raw 值都是源文本经空白符规范化后的子串。这是对非结构化文档可用的最强校验:如果找不到 raw 区块在输入中的位置,说明是模型自己编造的,那么从中解析出的所有内容都值得怀疑。

各职位时间范围的并集不超过从最早教育日期起的合理工作年限。这能捕捉到世纪错误,虽然只能抓到这一种,但它只花费一次比较。

子串校验值得优先实现。它把"模型在编造内容"从人工审核时才发现的问题,变成了管道在每条记录上都能检测到的异常,而且不需要 ground truth、不需要标签、不需要第二次模型调用。

简历解析是一种按文档选择模型而非按任务选择模型的工作负载:纯文本简历需要一个小型廉价模型,两栏设计的 PDF 需要视觉能力强的模型,而且不同提供商之间的每页价格差异很大。按文档通过单一 API 路由,意味着批处理驱动选择的是层级而非供应商,而按请求的成本归因可以在事后告诉你 корпус 中实际花费最多的那十分之一是哪些文档。


从简历日期范围提取就业空档期

从 CV 逐个提取教育经历

从简历提取技能与资质

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
Claude Chrome扩展升级:侧边栏对话与全平台历史同步
下一篇
LLM 从简历提取学历的结构化schema设计