结构化抽取(Structured Extraction)

一句话定义:从非结构化文本里恢复出结构化字段。 这一范式的关键不是让模型”写出”一个值,而是让程序先用规则(正则表达式)把可能的候选都找出来,再让 Jev 从候选里”选一个”,最后由代码逐字拷贝。

1. 核心要点

1.1 三步走:find / pick / copy

官方预解析取值(Pre-parsed Value Extraction)模板把这个分工固定成三步:

  1. 正则超量召回:用一条调成”宁可多找”的正则,把候选值全部抓出来并去重(官方原话 “Tune it to over-find.”)。
  2. Jev 挑一个:把候选直接当成选择题的选项,问”哪个候选是问题要的那个”,顺带读出下游要的属性(货币、国家、金额是 credit 还是 charge)。
  3. 代码逐字拷贝并归一化:代码复制被选中的那个 span,再自己做格式化(转小写、转 E.164、转 Decimal)。

“Because TypeSafe only ever chooses among the spans the regex found, the value you get back is one of those spans, copied unchanged. It cannot invent a value or transpose a digit.” 译:因为 TypeSafe 只能在正则找到的那些 span 里选,你拿回来的值一定是这些 span 之一、原样拷贝。它不可能编出一个值,也不可能把数字抄错位。

代码注释把这件事说得更直白:选项本身就是候选 span,所以 choice 是其中一个的原样拷贝(或 none 逃生口)——模型负责选,代码负责持有字符串。

1.2 三个官方实例

  • 邮箱:文档里有 4 个地址,正文要求小票发到私人地址。Jev 选出 dana.personal@gmail.com(conf 0.98),“发件人”选出 From 行那个(conf 1.00);两个都是正则命中的原样拷贝,只在代码里转小写。
  • 电话:三个号码都没有国别码。Jev 选出手机 (415) 555-0177(conf 1.00),再分类国家 US(conf 0.90),phonenumbers 合成 E.164 → +14155550177。
  • 金额:发票 4 个金额。选出总额 $1,315.50 与抵扣 $50.00;一道 Noul 判定”这是退给客户的 credit 而不是 charge 吗”——总额 P(credit)=0.01、抵扣 P(credit)=0.99,代码据此决定 Decimal 的正负号。

1.3 日期抽取:拆成小块分别选,代码组装

日期被拆成 7 个选择题(Choice)一次问完:mode(absolute / relative / none)、month、day、year、day_anchor、weekday、week_offset。其中 year 列出 1900–2050 每一年,外加 none 与 out_of_range 两个逃生口。

“The model reads what the text says and never does the calendar math.” 译:模型只读文本说了什么,从不算日历数学。

代码负责剩余一切:

  • 文本没写年份 → 代码用当前年份补,只有当日期已经比今天早一个月以上才顺延到下一年;
  • out_of_range(写了但不在列表里)→ 标记,不猜;
  • 拼出来是 2 月 30 日这类不可能日期 → 报 impossible date;
  • 一个日期的置信度取所用各部件里的最低值,低于 REVIEW_BELOW = 0.60 就转人工。

4 个短文档、6 个日期:5 个自动接收(conf 0.91–0.97),1 个转人工——问了一个文档根本没提的日期,模式被读成 absolute 却拿不到月份,conf 0.46,标注 absolute date incomplete。

1.4 两条限制

  • 选择题最多 255 个选项。候选超过这个数,就要分两阶段:先选章节,再选章节里的 span。
  • 困难的部分是”找候选”,不是”选候选”。邮箱、电话、金额有现成正则;人名没有通用正则,候选只能来自一份已有的名册、命名实体识别(NER)或 LLM 提议。

1.5 为什么这样能防幻觉

生成模型可以写出任意字符串;而在这里,输出空间等于程序给出的候选集合,模型不可能返回候选之外的值。

“when the answer space is bounded, turn extraction into a Choice over the options rather than asking for the value itself.” 译:当答案空间是有界的时候,把抽取变成一道”从选项里选”的选择题,而不是直接向模型索要那个值。

官方 jaggedness 页给出同样建议:

“For data extraction, it is better to extract possible options using regex or a generative model and let jev-1.13 pick the correct extraction.” 译:做数据抽取时,更好的做法是用正则或生成模型先把可能的选项找出来,再让 jev-1.13 挑出正确的那一个。

2. 与 Jev 的关系

  • 抽取被重新定义为”判断”而非”生成”:选一个是判断,写一个值是生成;Jev 只做前者——见 模型与框架分责。
  • 日期是官方承认的弱项(日期当文字读、不做大小比较),“抽取给模型、比较给代码”正是官方开出的处方。参见 幻觉。
  • 抽取出来的结果还能被 Jev 自己复核:官方 SDE 级联模板里有一道 Noul——“抽出来的这个字段是否为源文本不支持、或根本不存在?“——用来直接抓幻觉。
  • 把自由文本先压成有界候选,也减少了材料被 指令遵循 之外的力量劫持的空间。

3. 相关来源

  • 官方文档 cookbooks__pre_parsed_value_extraction_cookbook.md —— find/pick/copy 三步、邮箱/电话/金额三例与 255 选项限制
  • 官方文档 cookbooks__date_extraction_cookbook.md —— 7 个日期选择题、代码组装、0.60 转人工阈值与运行结果
  • 官方文档 model-jaggedness__jev-1.13.md(Date and time comparison / Generation)—— 官方”抽取给模型、算术给代码”的建议
  • 官方文档 cookbooks__sde_cascade.md —— 用 hallucinated Noul 复核抽取结果