让代码管文件,让模型理解表单
文章给出带代码的 PDF 自动填表方案:代码提取字段,模型匹配资料并解释答案,再经程序校验、人工审核后写回文件。通过划分语义理解与机械操作,规避模型处理字段名、坐标和复选框值时的错误。
AI 深度解读
把 PDF 交给 LLM,让它直接填好表格,听起来很自然。作者为 Simplifier 做了几个月开发,最初也走这条路,结果没能奏效。最终采用的方案是:模型理解资料与字段的关系,代码负责读取、校验和写入,用户负责确认。
这篇值得读的地方,在于它把 AI 填表拆成了一条可检查的流程。对于要处理 PDF 的前端和全栈开发者,真正可复用的是职责划分,以及如何让模型在资料不足时停下来。
先把字段读对,模型才知道该填什么
作者把流程拆成五步:代码读取字段,LLM 给出填写建议,代码校验,用户审核,代码写回 PDF。所谓「AI 不碰文件」,指的是模型不直接修改 PDF,文件操作由程序执行。
可填写 PDF 通常包含 AcroForm 字段。作者以 IRS、USCIS 表单为例,用 pdf-lib 提取字段名称和类型:
import { PDFDocument } from 'pdf-lib';
const pdf = await PDFDocument.load(bytes);
const form = pdf.getForm();
const fields = form.getFields().map((f) => ({
name: f.getName(), // 例如 "topmostSubform[0].Page1[0].f1_01[0]"
type: f.constructor.name, // PDFTextField、PDFCheckBox 等
}));
要留意 f.getName():它拿到的是程序标识,不一定是人能理解的名称。像 f1_01[0],模型很难凭它判断应填姓名还是地址。
作者的做法是结合字段控件矩形与页面文字位置,把旁边印着的标签附上去。对于反复处理的固定表单,作者更认可手工维护「字段名到可读标签」的映射。这是开发经验,原文没有给出自动识别与人工映射的对照数据。
让模型提交建议,并允许它回答不知道
传给模型的材料包括带标签的字段列表、用户资料和严格的输出格式。作者用下面的结构,把填写结果变成可校验、可审核的数据:
[
{ "field": "f1_01[0]", "value": "Dana Cohen", "reason": "Full name from passport", "confidence": "high" },
{ "field": "c1_1[0]", "value": true, "reason": "Individual / sole proprietor", "confidence": "medium" },
{ "field": "f1_11[0]", "value": null, "reason": "No SSN found in the documents", "confidence": "none" }
]
这里最该关注第三条的 value: null。资料里没有 SSN,就留空,并解释原因。
缺失值是合法结果,不能靠猜测补齐。
作者称,自己遇到的很多错误填写都来自模型自信地猜答案。因此,每个字段都要附上 reason,既用于解释建议,也方便用户审核。模型只引用字段 ID,不输出坐标;位置处理继续交给代码。
confidence 里的 high、medium、none 是模型给出的标签。原文没有说明它们如何校准,不能把 high 当作经过验证的正确概率。
校验、审核和写回,各自解决不同问题
代码校验先拦住便宜且明确的错误。原文给了三个例子:
- SSN 使用
/^\d{3}-?\d{2}-?\d{4}$/,检查是否符合九位数字及可选连字符的格式。 - 日期使用
!Number.isNaN(Date.parse(v)),检查字符串能否被解析。 - ZIP 使用
/^\d{5}(-\d{4})?$/,检查美国邮编格式。
此外,还要检查必填项是否有值、复选框值是否有效,以及文本是否超过字段最大长度。格式通过,只说明数据形状合适,不能证明内容属于当前用户。
审核界面则把每个字段的值和原因一起展示,突出低置信度与空值,让用户修改或确认后再下载。作者把它视为最重要的功能,理由是税务、移民等表单填写错误会产生实际后果。
最后一步才是写回。遗憾的是,提供的原文在遍历 approved、调用 form.getField(field)、判断 PDFTextField 时截断了。虽然小节提到 flatten,也就是将字段内容固定到页面上,但没有提供完整实现,更没有解释该在什么情况下执行。
我的判断
我认可这套职责划分:让模型处理语义关系,让代码承担能够明确检查的操作,再把决定权交给用户。相比「直接让模型填 PDF」,它更容易定位错误,也更方便重试与修正。
但它还不能算完整教程。原文没有交代护照、W-2、电子表格如何被读取并传给模型,也没有说明扫描件、无 AcroForm 字段的 PDF 怎么处理。「适用于任何技术栈和任何 LLM」更适合作为架构主张,不能理解成兼容性已经验证。
日期校验也偏宽松。Date.parse(v) 能解析,不代表日期符合表单要求,更不能解决 03/14/1990 这类输入的格式转换问题。字段原因同样需要核对,流畅的解释不等于可靠的来源证据。
作者报告了失败尝试和改进经验,却没有提供准确率、成本、耗时或模型对照。因此,可以借用流程,效果仍要用自己的表单和资料验证。
能拿来做什么
- 用
pdf-lib先检查目标 PDF 的字段名和类型;如果主要处理固定模板,就维护字段标签映射,减少模型理解字段的难度。 - 在前端或 Node 服务中,把
field、value、reason、confidence作为填写建议的数据结构,并明确允许null,方便校验与审核共用。 - 按目标表单定义校验规则,同时检查格式、必填项、复选框取值和最大长度,不把正则通过当成内容正确。
- 做一个逐字段审核页,展示建议值与原因,标出空值和低置信度项;用户确认后,再由代码写回 PDF。