返回使用场景
数据处理

AI 数据提取——从 PDF、发票和非结构化文本中提取结构化输出

这是一个乏味但有价值的用例。发票、收据、合同、潜在客户、简历——过去需要构建解析器的任何场景,如今都可以让遵循 JSON 模式的 LLM 用 30 行代码完成,准确率更高,并且一天即可上线,而不是耗时一个季度。

最后审核于 。

乏味但有价值的用例

二十年来,从非结构化文档中提取结构化数据一直是一个持续数月的项目:OCR 流水线、正则表达式规则、边界情况处理,以及按供应商制作布局模板。使用受 JSON Schema 约束的 LLM 后,只需 30 行代码,首次处理就能达到较高准确率,并可在一天内上线。下面的示例运行在 Kunavo 上——一个独立的 OpenAI 兼容网关;但这种模式属于模型本身,对任何模型的调用方式都相同。

只处理发票吗?本页面是跨文档概览。专门的发票数据提取指南会深入介绍这一种文档:旧式模板与模型方法如何与视觉 LLM 调用进行比较、完整的受 Schema 约束的 Python 教程、算术护栏、双层模型路由,以及每张发票的成本。

特别适合这种方法的类别:

  • 发票、收据、采购订单
  • 合同、法律协议(提取当事方、日期、义务)
  • 简历 / CV(解析为适合 ATS 的结构)
  • 从电子邮件签名或网页中补充潜在客户信息
  • 医疗记录、化验报告(需处理 PII)
  • 房地产房源、产品目录
  • 电子邮件分拣和结构化导入

30 行代码的核心模式

extract.py
import json
from openai import OpenAI
client = OpenAI(api_key="sk-kn-...", base_url="https://api.kunavo.com/v1")

# The schema is the output contract. Claude enforces a json_schema
# response_format (json_object it does not), so the reply has this shape
# unless max_tokens cuts it off (finish_reason == "length").
STR = {"type": ["string", "null"]}
NUM = {"type": ["number", "null"]}
INVOICE = {
    "type": "object",
    "properties": {
        "vendor": {"type": "string"},
        "invoice_number": STR, "date_iso": STR, "due_date_iso": STR,
        "currency": STR, "subtotal": NUM, "tax": NUM, "total": NUM,
        "line_items": {"type": "array", "items": {
            "type": "object",
            "properties": {"description": {"type": "string"},
                           "qty": NUM, "unit_price": NUM, "amount": NUM},
            "required": ["description", "qty", "unit_price", "amount"],
            "additionalProperties": False,
        }},
    },
    "required": ["vendor", "invoice_number", "date_iso", "due_date_iso",
                 "currency", "subtotal", "tax", "total", "line_items"],
    "additionalProperties": False,
}
RESPONSE_FORMAT = {"type": "json_schema",
                   "json_schema": {"name": "invoice", "schema": INVOICE}}
RULES = "Extract the invoice. Use null for missing fields. Dates in ISO 8601."

# Extract structured fields from an invoice PDF (after OCR)
def extract_invoice(ocr_text: str) -> dict:
    resp = client.chat.completions.create(
        model="claude-haiku-4-5",
        messages=[
            {"role": "system", "content": RULES},
            {"role": "user", "content": ocr_text},
        ],
        response_format=RESPONSE_FORMAT,
        max_tokens=1200,
    )
    return json.loads(resp.choices[0].message.content)

# Extract from an image directly (no OCR step needed)
def extract_invoice_from_image(image_url: str) -> dict:
    resp = client.chat.completions.create(
        model="claude-haiku-4-5",   # vision + an enforced schema
        messages=[
            {"role": "system", "content": RULES},
            {"role": "user", "content": [
                {"type": "text", "text": "Extract this invoice:"},
                {"type": "image_url", "image_url": {"url": image_url}},
            ]},
        ],
        response_format=RESPONSE_FORMAT,
        max_tokens=1200,
    )
    return json.loads(resp.choices[0].message.content)

有两种流程:纯文本流程(先单独执行 OCR)和直接视觉流程(视觉模型读取图像并在一次调用中输出 JSON)。视觉流程构建更快,但每次调用成本略高;OCR 后接 LLM 的流程在大规模场景下更便宜,因为 OCR 对每页只需付费一次。

准确率基准

在公开发票数据集上(来自 50 家供应商的 1,000 张发票),使用 JSON 模式和 200 词系统提示词:

  • Claude Haiku 4.5:字段级准确率 96%
  • Claude Sonnet 4.6:字段级准确率 98%
  • 传统模板:对已知供应商为 80-90%,对新供应商为 0%

LLM 可以零样本处理新供应商的布局。在系统提示词中加入 2-3 组示例对(few-shot)后,Haiku 可以用很低的成本接近 Sonnet 的准确率。

每份文档的成本

  • 发票(约 2K 输入 token、约 500 输出 token):Haiku 约 $0.003,Sonnet 约 $0.02
  • 一页合同(约 5K 输入 token):Haiku 约 $0.005,Sonnet 约 $0.04
  • 10 页合同(约 50K 输入 token,输出结构化摘要):Sonnet 约 $0.30
  • 简历(约 3K 输入 token):Haiku 约 $0.003
  • 带视觉输入的收据图像:Haiku,成本约等于一张发票——图像约计为 1.5K 输入 token

每月处理 10,000 张发票:使用 Haiku 约 $30。最接近的商业替代方案(Rossum、AWS Textract + 后处理)处理相同数量时每月约需 $2,000-5,000。

保持高准确率的 5 个模式

  • 明确处理 null:告诉模型缺失字段使用 null,不要使用“N/A”或空字符串。下游代码可以区分“缺失”和“有意留空”。
  • 使用 ISO 8601 日期:明确说明这一点。否则模型会选择地区格式,导致下游解析失败。
  • 货币使用 ISO 代码:“USD”而不是“$”;“EUR”而不是“€”。避免歧义($ 可能表示 USD、CAD 或 AUD)。
  • 验证 JSON:使用 Pydantic / Zod 强制执行 Schema。如果无效,则携带错误重新提示模型。
  • 连续一周手动抽查 1%,之后持续抽查 0.1%。跟踪字段级准确率,而不仅是记录级准确率。

如何选择模型

文档类型推荐模型
简单结构化文档(发票、收据)Claude Haiku 4.5
长合同 / 协议Claude Sonnet 5(支持长上下文)
直接视觉处理(未经 OCR 的 PDF)Claude Haiku 4.5;对于大页面使用 Claude Sonnet 5
高风险场景(法律、医疗)Claude Sonnet 5 + 人工核验
批量导入(100K+/天)Haiku 4.5 + few-shot 示例 + 缓存

合规注意事项

对于包含 PII 的文档(发票包含姓名、地址;医疗记录包含所有信息),请在提取前进行假名化,或在上游使用 Zero Data Retention。有关地区特定模式,请参阅合规指南;有关德国实践,请参阅DSGVO 深入指南。

开始使用:/app/signup——按需付费,充值 $10 可覆盖约 3,000 次发票提取,余额永不过期。阅读 /docs/chat 中的聊天文档,了解 response_format 对每个模型系列执行的约束,以及工具调用模式。

常见问题

使用 LLM 从文档中提取数据需要多少费用?

使用 Claude Haiku 4.5 每份文档约需 $0.003–$0.005,使用 Claude Sonnet 4.6 则约需 $0.02–$0.04。每月处理 10,000 张发票的成本约为 $30,而商业数据提取服务的费用为 $2,000–$5,000。

零样本 LLM 数据提取的准确率有多高?

零样本字段级准确率可达 95–98%,约需 30 行代码——准确率足以替代 OCR 加正则表达式的处理流程。

文档提取应该使用哪个模型?

发票、收据等简单的结构化文档使用 Claude Haiku 4.5。长篇合同使用 Claude Sonnet 4.6。直接以图像形式读取的文档使用 Claude Haiku 4.5;大页面则使用 Sonnet 4.6。

如何确保生产环境中的数据提取准确?

五种做法:明确处理 null、使用 ISO 8601 日期、使用 ISO 货币代码、进行架构验证并在输出无效时重新提示,以及人工抽查——第一周检查 1% 的输出,此后持续检查 0.1%。跟踪字段级准确率,而非记录级准确率。