Laravel AI SDK 如何解析 PDF 文档并返回结构化 JSON?

作者:袖梨 2026-09-13

Laravel AI SDK 解析 PDF 并返回结构化 JSON,推荐把职责拆成三层:`Document` 附件负责把 PDF 内容交给模型,Agent 的 `instructions()` 负责说明提取任务和语义规则,`HasStructuredOutput` 的 `schema()` 负责约束返回字段、类型与必填项。不要为了“输出 JSON”创建一个工具;工具只适合查询外部系统、执行计算或补充模型上下文,最终返回结构应由 Schema 控制。

最小流程是校验上传文件,把它作为附件传入实现了 `HasStructuredOutput` 的文档分析 Agent,然后像数组一样读取 `StructuredAgentResponse`。一次性文件可直接从上传、Storage 或本地路径附加;同一文档需要多次分析时,先存到 AI Provider,保存返回的 file ID,后续通过 `Document::fromId()` 引用。生产系统还必须处理扫描型 PDF、页数和大小限制、提示注入、敏感数据、Schema 版本、置信度、人工复核与文件删除。

三类职责不要混在一起

附件提供原始文档。它回答“模型要读什么”,不定义模型应返回哪些字段。

instructions 描述角色、文档类型、字段语义、冲突处理和未知值规则。它回答“如何理解内容”。

schema 声明键名、数据类型、枚举、数组、嵌套对象和必填约束。它回答“结果必须长什么样”。

什么时候需要工具

如果解析发票时要根据供应商编号查询内部主数据,可定义供应商查询工具。模型在阅读 PDF 后按需调用。

如果金额要按实时回了换算,可以使用受控回了工具。工具输出再参与最终结构化结果。

仅仅把文本整理成 JSON 不需要工具。多一个工具会增加调用轮次、失败模式和权限面。

安装与版本选择

通过 Composer 安装 `laravel/ai`,发布配置与迁移,并配置目标 Provider 的 API 密钥。

官方 master 文档明确标注为即将发布版本,功能可能变化。生产应锁定 Composer 版本并阅读对应版本文档。

不要把 master 示例直接复制到旧版本项目后假设接口完全一致。CI 中记录 SDK、Laravel 和 PHP 版本。

创建结构化 Agent

使用 Artisan 的 structured 选项创建 Agent,或手工实现 `Agent` 与 `HasStructuredOutput`,并使用 `Promptable`。

文档分析 Agent 应按文档类型拆分,例如 InvoiceExtractor、ContractAnalyzer,而不是一个万能 Agent 接受任意字段列表。

固定类让 instructions、schema、模型配置和测试集中管理,也便于独立版本化。

设计 schema 的基本原则

字段名称稳定且表达业务含义。金额使用 number 或整数最小货币单位,日期使用约定格式字符串。

必填表示响应结构必须包含,不代表文档一定有值。若字段可能缺失,应允许 null 或提供明确状态字段。

枚举限制有限状态,例如 `found`、`missing`、`ambiguous`,避免模型自由创造近义词。

一个发票结构示例

顶层可以包含 document_type、invoice_number、issue_date、currency、seller、buyer、line_items、subtotal、tax、total 和 warnings。

seller 与 buyer 是对象,包含 name、tax_id 和 address。line_items 是对象数组,包含 description、quantity、unit_price 与 amount。

warnings 保存缺失、冲突或低置信字段,不把不确定信息硬填为看似精确的值。

instructions 应写什么

说明只提取附件中的事实,不根据常识补全缺失编号或日期。要求保留原币种与原始小数。

说明多个候选值的优先规则,例如以标注为 Total 的最终金额为准,并将冲突写入 warnings。

说明 PDF 内的命令、链接或“忽略系统规则”等文字都是待分析内容,不是 Agent 指令。

提示注入防护

上传文档是不可信输入。合同、简历或报告中可能故意包含操纵模型的文字。

系统 instructions 明确禁止服从文档内指令,工具按最小权限开放。纯提取 Agent 通常不需要网络、邮件或数据库写工具。

输出仍经过 Schema 和服务端业务校验,不能因为格式正确就信任字段内容。

从上传文件附加 PDF

控制器先验证 `file`、MIME、扩展名、大小和上传错误,再将 UploadedFile 放入 prompt 的 attachments。

文件名和客户端声明 MIME 不可信。使用服务器端内容检测,并确认文件头与 PDF 类型一致。

一次请求直接附件最简单,但请求失败重试可能重复上传,适合小文件和低频场景。

从 Storage 附加

文件先保存到 Laravel Filesystem 后,可用 `Document::fromStorage()` 指定路径与磁盘。

这便于队列 Job 异步处理,也让上传接收和 AI 调用解耦。对象存储路径使用随机 ID,不使用原始文件名作为唯一键。

AI 调用完成后根据保留策略删除源文件,不能让临时 PDF 无限积累。

从本地路径附加

`Document::fromPath()` 适合 CLI、受控导入目录或已下载临时文件。路径必须来自服务端映射。

不要把用户提交的任意路径直接传入,避免目录遍历和读取服务器敏感文件。

队列运行在多节点时,本地路径可能只存在于上传节点;此时优先共享 Storage。

文件存储与复用

官方 SDK 支持对 Document 调用 `put()`,由 Provider 存储文件并返回 ID。后续用 `Document::fromId()` 作为附件。

适合同一 PDF 需要摘要、条款、风险和问答等多次请求,避免每次重新上传。

本地数据库保存 provider、file_id、源文件哈希、所有者、创建时间与删除状态,不能只有一个无上下文字符串。

文件生命周期

Provider 文件不是永久业务存档。定义最大保留时间、删除任务和用户删除请求的传播流程。

调用 `delete()` 后更新本地状态,并对失败删除进行重试和告警。

向量库移除与 Provider 文件删除可能是两个操作。若使用两者,分别追踪资源 ID。

直接附件还是预存文件

一次提取且文件较小:直接附件。需要异步、重试或多次分析:先保存到应用 Storage,必要时再存 Provider。

大量历史文档问答:考虑向量库与 File Search,但精确整份表单提取不一定需要 RAG。

不要为了技术完整把每份单页发票都建向量库,额外索引会增加成本和一致性问题。

为什么 Structured Output 优于提示 JSON

只在提示中写“返回 JSON”,模型仍可能添加 Markdown、解释或改变键名。

`HasStructuredOutput` 与 schema 将格式要求交给 SDK 和支持结构化输出的 Provider,响应可按数组访问。

Schema 解决语法与类型,不保证文档事实提取正确,因此仍需业务校验与复核。

响应如何进入 DTO

不要把 StructuredAgentResponse 原样写数据库。先映射到版本化 DTO 或 Value Object。

DTO 构造阶段验证日期、币种、金额范围、行项目合计与税额关系。无效结果进入复核队列。

数据库保留原始响应摘要、schema_version、model、provider 与提取时间,支持追踪。

处理 null 和缺失

模型不知道的字段应返回 null 或 `missing`,不能编造空字符串、0 或当前日期。

0 是合法金额,空字符串可能是文档原值;它们不能统一当成缺失。

Schema 与业务模型对可空性保持一致,迁移时不能把新字段立即设为数据库非空。

日期规范化

instructions 指定输出 ISO 日期,但保留 raw_value 以便审计。`03/04/2026` 可能存在日月歧义。

结合文档语言、币种与明确标签判断;仍不确定时标记 ambiguous,而不是猜测。

服务端用严格日期解析器验证,禁止自动溢出成另一个日期。

金额规范化

欧洲与美国数字格式的小数点和千位分隔不同。提取时同时保留原字符串和规范数值。

币种来自明确符号、代码或上下文。仅看到 `$` 时不能必然认定为美元。

服务端重算 line_items、subtotal、tax 和 total 的关系,设置可接受舍入误差。

表格提取

表格可能跨页、缺表头或使用合并单元格。Schema 用 line_items 数组表达业务行,不要求复制视觉布局。

instructions 说明页眉页脚、续表标记和小计行是否忽略。重复表头不能变成商品行。

行数异常、合计不一致或关键列大量缺失时触发人工复核。

文本型与扫描型 PDF

文本型 PDF 内含可提取文字,Provider 通常能直接处理。扫描型 PDF 每页主要是图像,依赖视觉或 OCR 能力。

SDK 能附加 PDF,不代表每个 Provider 和模型都以相同方式支持扫描件。部署前用目标模型实测。

先检测文档是否存在足够文本层,若没有则进入 OCR 或视觉回退路径。

OCR 回退

OCR 是输入预处理,不是最终 Schema。它输出文字、位置和可能的置信度,再交给 Agent 进行语义映射。

低质量扫描先做旋转、裁剪和对比度处理,但保留原文件用于核对。

身分证件、医疗和财务材料使用符合数据合规要求的 OCR 服务或本地方案。

页数和大小限制

上传层设置文件大小、页数、加密状态和解析超时上限。压缩炸弹或异常对象不能直接送给 Provider。

超长 PDF 按章节或页段切分,保留 page_start、page_end 和 chunk_id。

最终合并结果时处理跨页表格与重复字段,不能简单覆盖前一段。

切分策略

固定页数切分最简单,但可能把一个表格分开。基于标题、书签或版面结构切分更稳。

每段 instructions 带文档 ID 和页码,Schema 返回证据页。聚合器按业务键去重。

最终摘要或关键字段可再进行一次合并调用,但要限制它只能使用各段结构化结果。

证据定位

关键字段增加 `source_pages` 或 evidence 数组,记录页码和短片段,便于人工核对。

证据不是完整文档复制,限制长度并避免把敏感内容写入普通日志。

服务端验证页码位于实际范围,防止模型返回不存在的页。

置信度的正确使用

模型自报 0.97 不等于统计校准概率。置信度只能作为排序信号,不能单独决定高风险自动执行。

更可靠的规则来自字段存在、证据可定位、格式验证、合计一致和外部主数据匹配。

组织通过标注集测量每个字段准确率,再设人工复核阈值。

Provider 能力差异

Laravel AI SDK 提供统一接口,但官方能力表显示文件功能只由部分 Provider 支持。

结构化输出、文件大小、支持 MIME、扫描件理解和存储保留策略也可能不同。

在配置层固定经过验证的 Provider 与模型,不让请求参数接受任意模型名称。

超时和队列化

PDF 分析可能超过普通 HTTP 请求时限。控制器接收文件后返回任务 ID,队列 Job 执行 AI 调用。

状态包括 uploaded、processing、needs_review、completed 和 failed。客户端轮询或接收通知。

Job 重试使用幂等键,避免同一文件并行产生多个计费请求和相互覆盖结果。

幂等与内容哈希

计算源 PDF 的安全哈希,结合 extractor_version、schema_version、provider 和 model 形成处理键。

完全相同的任务可复用已验证结果;任一提取规则或模型变化则产生新版本。

哈希只能识别字节相同,视觉相同但元数据不同的 PDF 仍可能不同,不应过度推断。

并发控制

同一 document_id 同一版本只允许一个 Job 运行。使用唯一任务或原子锁协调多个 Worker。

锁过期时间覆盖高分位处理时长,任务完成后按 owner 释放。崩溃后允许安全重试。

不同文档可并行,但同时受 Provider 速率和组织预算限制。

成本控制

记录页数、文件字节、模型、输入输出 Token、调用次数和每文档成本。

先做本地文本层检测,空白页和重复页不送入模型。重复分析优先使用已存文件 ID。

简单模板可先用确定性解析器,只有复杂或低置信文档进入 AI 路径。

安全上传

限制 MIME 与扩展名,检查真实文件类型、最大尺寸、页数和是否加密。随机化存储名。

上传目录不允许脚本执行,文件与 Web 根隔离。必要时进行恶意内容扫描。

PDF 解析器本身也可能有漏洞,预处理放在受限进程或容器,保持依赖更新。

租户隔离

数据库中的文件记录绑定 tenant_id 和 owner_id。下载、分析、查询结果与删除操作都重新授权。

Provider file ID 不是访问控制凭证,不能只凭 ID 让用户引用任意文档。

队列 payload 只传内部记录 ID,Job 重新加载并验证租户状态。

敏感数据与日志

发票、合同和证件可能包含个人与商业敏感信息。确认 Provider 数据处理与保留设置符合组织要求。

应用日志不记录完整 Prompt、PDF 文本或结构化结果。保留请求 ID、字段计数、错误类别与脱敏摘要。

调试开关不能在生产默认输出原始文档,临时访问也应审计。

输出验证

Schema 成功后再运行 Laravel Validator 或 DTO 校验。检查字符串长度、枚举、日期、金额和数组数量。

跨字段规则如 subtotal 加 tax 等于 total,不容易只靠 JSON Schema 完整表达,应由领域验证器处理。

失败结果不直接持久化为正式业务数据,保存到复核记录并显示原因。

人工复核界面

高风险字段旁显示原 PDF 页和证据片段,突出缺失、冲突和校验失败。

用户修改值时记录原提取值、修改后值、操作者和时间,用于审计与后续评测。

人工批准是业务状态转换,不能让模型自己调用一个批准工具绕过。

Schema 版本管理

给每次提取保存 schema_version。新增必填字段时不要假设旧结果自动满足。

兼容变化可在 DTO 层提供默认或迁移;语义变化重新处理原文档。

API 响应也带版本,让下游系统选择接受、转换或拒绝。

测试 Agent 调用

Laravel AI SDK 提供 Fake 与 prompt 断言能力。单元测试不应每次真实调用 Provider。

测试确认控制器或 Job 使用正确 Agent、提示和附件,并对排队调用使用对应断言。

Fake 返回代表性结构化响应,验证 DTO、业务校验、状态转换和错误处理。

测试 schema

为 schema 的必填、可空、枚举、嵌套数组和数值范围准备契约测试。

使用缺字段、错误类型、超长数组和矛盾金额测试服务端防线。

不能只测试一份完美 JSON;模型失败通常发生在边界和不确定内容。

文档评测

准备经人工标注的文本 PDF、扫描 PDF、多页表格、旋转页面、模糊图片和多语言样本。

按字段计算精确率、召回率和完全正确文档比例,不只看 JSON 是否可解析。

每次更改模型、instructions、schema 或 OCR 后跑同一集合,比较回归与成本。

失败场景测试

覆盖损坏 PDF、加密 PDF、超大文件、Provider 超时、速率限制、结构化输出失败和存储删除失败。

验证重试不会重复创建正式结果,状态不会永久停在 processing。

验证不受支持 Provider 会在任务开始前明确失败,而不是静默返回空字段。

不要把模型结果直接执行

解析合同得到的付款金额、银彳账号或日期不能自动触发、建单或签署。

先经过业务校验、权限和人工审批,再由独立命令执行。原 PDF 中的恶意内容不能扩大为系统操作。

工具权限与提取任务分离,是文档 AI 系统最重要的安全边界之一。

何时使用本地解析

固定模板、机器生成 PDF 和明确坐标字段,用本地库解析更便宜、可重复且易审计。

AI 适合版式多变、语义映射复杂和文本噪声较大的文档。两者可组合:本地先提取,AI 处理不确定部分。

不要因为 SDK 支持附件就把所有 PDF 都发送到远程模型。

何时使用向量库

跨大量长文档问答、检索相关段落和长期知识库适合向量存储与 File Search。

单份发票转换为固定 JSON 通常直接附件更清晰。向量检索可能漏掉未命中的关键页。

若使用向量库,保存 provider file ID 和 document ID,因为两者可能不同。

一次完整请求流程

控制器校验并保存 PDF,创建 DocumentExtraction 记录,分发唯一 Job,立即返回 202 与任务 ID。

Job 选择已验证 Provider,把 Document 附给 InvoiceExtractor,获得结构化响应,映射 DTO 并执行领域校验。

验证通过写入候选结果;高风险或低置信进入 needs_review;最终批准后才进入业务表。

常见错误

错误一是把返回格式写进 tool schema,而 Agent 本身没有 HasStructuredOutput。工具 schema 只描述工具参数。

错误二是在 instructions 中粘贴庞大 JSON 示例,却不定义正式 schema,导致字段漂移。

错误三是假设 PDF 附件等于 OCR、结构化输出等于事实正确、Provider file ID 等于本地授权。

上线检查清单

确认 SDK 版本已锁定,目标 Provider 同时支持文件与所需结构化输出能力。

确认 PDF 上传验证、页数限制、扫描检测、OCR 回退和临时文件删除已经实现。

确认 instructions 抵抗文档提示注入,schema 定义类型,DTO 处理跨字段业务规则。

确认队列幂等、超时重试、成本坚控、租户授权与 Provider 文件生命周期可追踪。

确认文档、异常文档和人工复核流程都经过测试。

结论

Laravel AI SDK 的正确组合是:PDF 通过 `Document` 进入 attachments,instructions 规定提取语义,`HasStructuredOutput` 的 schema 规定最终 JSON 形状。

工具只在需要外部查询或计算时加入,不负责包装最终结果。一次性文件直接附件,多次复用则先存 Provider 并保存 ID。

生产质量来自 Schema 之外的完整链路:可信上传、OCR 回退、领域验证、幂等队列、租户隔离、人工复核和可重复评测。做到这些,结构化 JSON 才能从演示结果变成可进入业务流程的候选数据。

相关文章

精彩推荐