AI 如何自動填寫 PDF 表格
How to Autofill PDF Forms with AI
文章提出一套 AI 自動填寫 PDF 表格的流程,由程式讀取欄位、LLM 按語義配對內容,再經程式驗證和用戶覆核後寫入 PDF。作者建議為欄位加入可讀標籤,要求模型逐項提供答案理由和信心程度,並容許以 null 表示不填;座標由程式處理。用戶確認或修改後才下載 PDF,文中附有程式碼,並稱這套方法適用於任何技術堆疊和 LLM。
I've spent the last few months building an AI tool that fills PDF forms from a user's own documents (a passport, a W-2, a spreadsheet, or just a few typed sentences). The first version was the obvious one: send the PDF to an LLM and ask it to fill the form.
It didn't work. This post covers what did work, with code, so you can build your own.
Full disclosure: the tool is Simplifier. Everything below works with any stack and any LLM.
The core idea: split "understanding" from "doing"
LLMs are great at understanding meaning: "this passport says the date of birth is 03/14/1990, and this form field asks for DOB." They're bad at precise, mechanical work: exact field names, coordinates, checkbox export values.
So the pipeline looks like this:
- Code reads the form's fields.
- The LLM decides what goes in each field and explains why.
- Code validates the answers.
- A human reviews them.
- Code writes the values into the PDF.
The AI never touches the file.
Step 1: Read the fields (no AI)
Fillable PDFs (most IRS and USCIS forms, for example) contain AcroForm fields. With 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(), // e.g. "topmostSubform[0].Page1[0].f1_01[0]"
type: f.constructor.name, // PDFTextField, PDFCheckBox, ...
}));
First surprise: field names are often useless. f1_01[0] tells the model nothing. To fix it, I attach the text printed next to each field on the page ("Line 1 – Name"), using each field's widget rectangle and the page's text positions. For forms that come up again and again, a hand-made map from field name to human-readable label beats everything else.
Step 2: Let the LLM map meaning, not coordinates
Send the model the field list (with labels), the user's documents, and a strict output format:
[
{ "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" }
]
Three things made a big difference:
-
nullis a valid answer. Tell the model explicitly that leaving a field empty is better than guessing. Most bad fills I saw were confident guesses. - A reason for every field. It improves accuracy, and it's gold for the review screen.
- Field IDs only, never positions. The model refers to fields by name. Code handles the geometry.
Step 3: Validate in code
Don't trust the output blindly. Cheap checks catch a lot:
const checks = {
ssn: (v) => /^\d{3}-?\d{2}-?\d{4}$/.test(v),
date: (v) => !Number.isNaN(Date.parse(v)),
zip: (v) => /^\d{5}(-\d{4})?$/.test(v),
};
Also check that every required field has a value, that checkbox values are valid for that checkbox, and that text fits the field's max length.
Step 4: A review screen (not optional)
Show each field with its value and the model's reason, and highlight low-confidence and empty fields. The user confirms or edits before anything is downloaded.
This is the most important feature. Forms like immigration and tax forms have real consequences, and "the AI filled it" is not an excuse anyone accepts.
Step 5: Fill and (carefully) flatten
js
for (const { field, value } of approved) {
const f = form.getField(field);
if (f.constructor.name === 'PDFTextField')
來源:DEV Community · dev.to