从文件到数字资产:一次 AI 文件解析工程实践

前言

时至今日,很多传统公司的大部分的数据依然使用office文件去管理,,把excel和图片当做数据库去管控是一个很常见的现象。

Excel、CSV、PDF、Word、邮件正文、聊天记录、扫描件、截图、各种系统导出的半结构化表。它们每天在业务人员之间流转,被下载、转发、改名、复制,再上传到另一个系统。文件很多,数据以一种极低效率的方式在企业中运转。而且这些数据往往有时效性,所以自然会有“过期”无用的数据。

从文件到数字资产:一次 AI 文件解析工程实践

可以说文件只是信息的载体。它还不是数据。

文件只是信息的载体,还不是数据。真正的数据,至少要能被查询、关联、复用,也要能解释它从哪里来。否则它只是一个看起来很完整的 JSON,出了错却没人敢用。

我最开始做这类文件解析时,也很自然地想过:能不能直接把文件扔给大模型,让大模型直接输出业务需要的JSON?

后来发现这个想法太轻了。

难点不在于模型能不能识别几个字段。难点在于系统敢不敢相信这些字段。企业文件有一个很现实的特点:他们最初是给人看的,不是给机器看的。

人看得懂标题、备注、合并单元格、上下文、颜色、空行、缩写、附件说明。机器不懂。机器看到的是行、列、段落、文本块、坐标、页码,还有一堆不稳定的表格:

同一个字段,在不同文件里可能叫不同名字。

同一个表格,今天从第 3 行开始,明天从第 7 行开始。

同一个业务对象,可能被拆在多个 sheet、多个段落、多个附件里。

有些数字是金额,有些数字是数量,有些数字只是备注里的编号。

所以想要引入AI去解决文件导入的问题,一开始如果就想着怎么引入大模型,然后使用大模型去把数据“转成JSON”,那这个问题开始就已经偏了。

从文件到数字资产:一次 AI 文件解析工程实践

所以一上来就问“怎么让大模型把文件转成 JSON”,问题已经偏了。更应该先问的是:哪些内容可以稳定识别?哪些内容必须结合上下文?哪些字段即使识别出来,也不能直接入库?哪些地方必须保留来源,方便后面复查?

企业更想要的是一条能解释、能复查、能修正的数据生产线。

先看整体流程

从文件到数字资产:一次 AI 文件解析工程实践

这张图看着长,其实核心就几件事:先认识文件,再拆开处理,再保留来源,再检查有没有漏,最后再决定能不能入库。

Excel 文件解析技术分析

从文件到数字资产:一次 AI 文件解析工程实践

从文件到数字资产:一次 AI 文件解析工程实践

阶段一 试图使用大模型去解析Excel/CSV数据

我们最开始试过一条很直接的路:把 Excel / CSV 转成 Markdown,再交给大模型理解,让模型输出符合业务 schema 的结果。

这个方案上手很快,非标准文本也能覆盖一些。但大表一来,问题就很明显:等待时间长、输出太大、容易触发 context window 或 max tokens,金额事实也不可控。

更麻烦的是,一旦字段错位,很难追溯到底是哪个单元格导致的。

阶段二 使用大模型去做layout处理

我们尝试过让 LLM 做 Layout detector,也尝试过轻量 Layout hint。

这个方向比“LLM 直接输出金额”更安全,因为模型只判断结构,不给事实金额。并且在这个过程中也尝试过引入MarkItDown。MarkItDown 可以把 Excel 转成更容易阅读的 Markdown。它适合:人工快速理解文件内容,离线分析某些文件的文本表达,给模型提供较友好的文本上下文。

但是它不适合作为正式解析主链路的原因主要在于:

Markdown 可能丢失合并单元格语义。

横向块和空表头列的坐标语义会变弱。

模型读 Markdown 后仍可能生成事实。

解析结果不容易回到 workbook row/column。

所以这个阶段我们都是考虑如何处理数据才能让大模型得以解析,但是慢慢发现一个问题,那就是如果后端已经能稳定识别结构,调用 LLM 只会增加等待。并且如果 LLM 输出完整 LayoutPlan,仍然有 schema 重和超时问题。如果只输出 hint,后端还需要负责 section 展开、坐标校验和 executor。

方案结论:
LLM layout 能力可以作为低置信复杂结构的辅助。
生产主链路仍应优先后端 resolver 和 executor。
当前 Local Fee 主链路不依赖 Layout Detector,LLM 只保留为后端解析结果校验器。

阶段三 后端规则 + 通用布局层 + LLM 校验器(当前方案)

对于Excel文件而言,不同的企业里面有着截然不同的使用方式,Excel不再是纯数据文件,同时承载着数据、布局、视觉表达和人工填写习惯。在真实的业务文件里,关键信息不是常来自某个固定字段,它可能来自sheet名,可能来自文件名,或者它可能来自标题行、表头甚至子表头。并且出现很多场景会合并单元格,有的列有的行又可能是空。所以Excel解析的目标不是“把所有文本读出来”,而是:把带布局语义的表格,转成业务可消费/可追溯/可复核的结构化事实。

从文件到数字资产:一次 AI 文件解析工程实践

这句话里有三个关键要求:

可消费:输出必须符合业务schema

可追溯:重要字段最好能回到sheet、row、column或原文片段

可复核:不确定的地方要进入missing / warning / confidence,不能静默编造

实际业务结合

这是一个真实的需求,在海运报价的场景中,我们需要把报价文件的数据转变成运价的一个routes,关键的信息可能包含:船公司、币种,还要重要的数据比如起运港、目的港、中转港等,除此之外还要航线柜型对应的价格的信息,一条route对应包含有效期,除此之外还有其他数据就不在这里过多罗列。

而在另一个local费用的场景中,解析的目标不是routes,而是本地费用的模版,包含的信息则为船公司、起运港、费用项(各类的附加费和计费规则)、币种等。

消费方往往是上游查询的应用,解析结果最终会进入报价池,用于后续报价匹配。两个业务都在“解析excel”,但它们不是同一个解析任务,维度不同关注的数据也不一样。但是对于AI应用而言,数据又需要保持跟业务相关,且需要保证数据的准确性。

但是两者又有本质行为的相似之处,输入源都是Excel,底层文件读取模型调用或者是trace、token usage又可以复用。但是又需要将业务的schema、prompt、归一化、校验、失败策略拆开。

解决思路

做 Excel 解析时,我现在不会先问“用哪个 OCR / LLM / 库”。我会先问几个更业务的问题。

第一,先定义业务对象。

最重要的入库对象是什么?它的业务主键是什么?哪些字段必填?哪些字段可以后续补?哪些字段绝对不能推断?它会不会直接参与金额计算或业务决策?

报价解析里的港口和柜型金额不能乱猜。Local Fee 里的金额也不能被模型结合常识补齐。很多解析问题,都是因为一开始没有把这个边界说清楚,最后把“读到了文本”误认为“解析成功”。

第二,再定义消费方。

同一份解析结果,给后台入库、给业务人员预览、给上游报价匹配系统使用,设计都不一样。哪些字段入库,哪些字段展示,哪些字段只作为 trace 保留,需要提前想清楚。

第三,再判断 Excel 的结构类型。

不要按客户名或文件名堆判断。真实 Excel 更适合先归纳成结构原语:标准表、分段表、宽表、横向块、文本块、混合表。

这一步要回答:业务实体在行上还是列上?金额是单列还是拆列?信息来自显示列,还是来自标题、sheet 名、文件名?备注和条件是不是混在某个单元格里?

第四,区分结构判断和事实读取。

LayoutPlan 只告诉系统“去哪里读”,不能代替事实本身。关键金额、柜型、费用项,最终应该由 executor 回读 workbook 原始单元格。

第五,设计观测字段。

至少要有 parseTrace、timings、missing、warning、confidence、source。否则解析失败时,只能靠人肉看文件,很快就会变成玄学。

实现路径

我现在把链路拆成了几部分
文件预处理只保留信息

文件预处理不应该过早去做业务解释,它更重要的职责在于:识别文件类型、读取workbook bytes、sheet文本和对Excel做必要内容的提取

可以说,它不应该决定哪个是业务模版,哪一列是金额,然后哪一行对应什么数据,模板是否覆盖这样的业务问题。

对于业务解释,应该交还给后面的parser、LayoutPlan、normalizer和人工确认
高确定性规则先走规则parser

规则parser适合处理稳定、明确、可重复的格式,它不是大模型解析器,更多时候它是用工具进行解析的函数。这类规则特别适合处理:显示表头完整、列角色明确、section标题清晰、列表达固定 等场景。

好处是,规则parser提供快路径:解析速度快、可测试、不消耗token、不依赖模型稳定性、出错时容易定位。但坏处是没法覆盖全部情况。
复杂Excel引入布局中间层

真实的文件越来越以后,你会发现企业的数据是多样的,不可能每个文件都要写一个parser。企图处理所以场景,然后用枚举的方式去兼容是不现实的。更可维护的方式是引入布局中间层,我把这个层成为LayoutPlan。这个中间层主要描述sheet范围、行列范围、header行、数据起止行,还有meta数据的映射。

这样做的好处是新的Excel先归类为结构原语,不安客户名和文件名堆判断,并且executor 可以统一回读 workbook,validator 可以统一校验越界和缺轴。
Executor必须回读workbook

布局中间层只告诉后端“去哪里读”,但是不能代替后端读取事实,最终模版还是应该由executor从workbook原始单元格读取

这样做边界可以避免很多风险,比如模型看错数、模型补齐不存在的数据、markdown转换丢失坐标无法追溯。
LLM应该怎么用

大模型不是不能用,而是应该放在正确的位置:我更推荐使用LLM去做低置信解析结果的风险校验,或者去校验疑似错位字段,还有在 schema 很小的情况下输出 layout hint。最不推荐做的就是使用LLM 直接输出完整 workbook 解析结果并作为事实。
输出必须经过schema和normalizer

无论结果来自规则还是 LLM,都应该经过统一输出层。输出层负责: 缺失字段进入missing。 不确定内容进入warnings。风险费用标记needsReview或displayOnly。这样可以避免每个 parser 都各自输出一套字段习惯。

最终我们的方案职责拆分如下:

从文件到数字资产:一次 AI 文件解析工程实践

这个组合的好处是:

标准文件快。

非标准文件可以扩展结构原语。

关键金额来自原始单元格。

LLM 有价值,但不控制事实。

trace 能解释每一步为什么这样解析。

工程化保障

schema隔离

不同业务必须有不同 schema。报价解析和 Local Fee 解析如果共用一套 schema,短期看起来省事,长期一定会互相污染。

正确的做法是:底层能力复用,业务 schema、normalizer、测试样本分开。这样出问题时,才能知道是哪个业务、哪个模板、哪个规则出了问题。

Trace和Timings

我需要知道每一次解析到底发生了什么:走的是规则还是模型?命中了哪个 sheet?有没有进入 LayoutPlan?模型有没有被调用?慢点是在文件读取、Prompt、模型、schema 校验,还是 normalizer?所以 parseTrace 和 timings 不是锦上添花,而是排查问题的入口。

真实样本回归

Excel 解析不能只靠合成样本。合成样本通常太干净,真实业务文件才会暴露合并单元格、空行、横向块、多 sheet、样式撑大的百万行范围。每新增一种结构,都应该沉淀一个真实或脱敏样本,并记录预期对象数量、关键字段覆盖、关键费用或价格覆盖、预期 warning 和预期耗时。这套闭环看起来不如“一个模型解决一切”性感,但它更像企业系统真正需要的东西。文件格式一定会变,靠一次 Prompt 不可能兜住所有变化。最后能让系统稳定下来的,是样本、规则、观测和回归。

图片解析技术分析

图片解析这件事,我一开始也纠结过:到底是 OCR 先,还是直接让视觉模型读?后来我的看法变得没那么绝对。在清晰截图、复杂版面、业务语义强的场景里,视觉模型确实能读出一些 OCR 不好处理的关系。但 OCR 仍然有价值。它便宜、快,也适合先把可用文本抽出来。所以我现在更倾向于把 OCR 和视觉模型看成两种工具:先用便宜稳定的方式拿到材料,再把难判断的部分交给模型。这比简单说“LLM 比 OCR 强”要准确得多。很多团队写 Prompt 时,都会加一句:“请按照下面 JSON 格式输出”。这句话有用,但不够。模型可能返回半截 JSON,字段名可能漂移,价格可能从数字变成 "USD 3050",枚举值也可能从 success 变成“解析完成”。这时候就需要结构化输出工具,比如 Instructor。

Instructor 是什么

Instructor 不是一个大模型,也不是 Agent 框架。它是一个围绕大模型调用的结构化输出工具。

更准确地说:

它把“请模型输出 JSON”变成“请模型输出符合 Pydantic schema 的对象”。

它会把模型原始输出解析成 Python 类型对象。

它会用 Pydantic 校验字段是否存在、类型是否正确、枚举值是否合法。

它可以在校验失败时自动重试,但本项目报价解析默认不建议开启重试。

from pydantic import BaseModel, Fieldfrom langchainopenai import ChatOpenAIimport instructorclassBusiness(BaseModel):# 模型定义llm = ChatOpenAI(model="gpt-3.5-turbo",apikey="你的openai密钥")instructorllm = instructor.patch(llm)# invoke 直接返回校验后的结构化对象,无需手动解析JSONresult = instructorllm.invoke(input=prompt,response_model=Business)# 关键:强制模型输出匹配该模型结构

它解决什么问题

在当前涉及大模型解析的业务场景中,模型经常需要返回 JSON。只靠 Prompt 约束会遇到这些问题:

返回半截 JSON。

字段名漂移,例如routes写成route_list

类型错误,例如价格应该是数字却输出"USD 3050"

嵌套结构缺字段,例如某条 route 没有pod_raw

枚举值不受控,例如status输出成“解析完成”而不是success。

Instructor 可以把这些问题前置为 schema 校验问题。

它不能解决什么问题

Instructor 不能替代 OCR、不能替代业务规则,也不能自动理解业务逻辑。它就像一个输出约束,它不能替代业务解析的能力,更不知道每个字段代表了什么含义,它只知道哪些字段应该存在。

所以它应该放在“结构化输出校验层”,不能被误用成“报价解析能力本身”。

推荐接入方式

当前边界是:

单轮模型调用优先。成功就是返回完整 JSON。失败就是返回失败状态和错误信息。不开放同步人工复核中间态。默认不做“失败后二次模型修复”。

因此 Instructor 的默认策略应该是:

从文件到数字资产:一次 AI 文件解析工程实践

这能避免为了修复 JSON 格式而额外调用模型,导致成本和耗时不可控。

文本解析技术分析

文本解析反而不要想复杂 文本、邮件正文、聊天记录这类材料,有时候比图片和 Excel 简单。如果文本结构稳定,规则 parser 往往已经能解决大部分问题。比如固定的报价文本、明确的费用行、规则化的日期和金额表达,都不需要一上来就调用大模型。真正需要模型的,通常是上下文更强、表达更自由、字段边界不稳定的部分。这也是我现在反复强调的一点:不要先问“用哪个模型”,先问“事实从哪里来”。如果一份文件只是被模型读了一遍,然后生成一个没人敢查、没人敢改、没人敢追溯的 JSON,它仍然没有真正变成企业数据。真正有价值的数字资产,应该能回答这些问题:它来自哪个文件?它从哪一页、哪个 sheet、哪一行读出来?哪些字段是确定的,哪些字段有风险?解析过程有没有调用模型,花了多少时间和 token?出错以后,能不能沉淀成样本,下一次自动回归?AI 在这里当然有价值。它能处理过去很难规则化的内容,也能降低人工录入成本。但 AI 不应该成为事实黑盒。企业系统最终要管理的不是模型回答,而是可追溯、可验证、可回灌的业务事实。只有走到这一步,文件里的信息才算真正进入了企业的数据体系。

总结

最后附上我完整项目的时序图,这篇文章分享就到这里,感谢阅读。

从文件到数字资产:一次 AI 文件解析工程实践

企业落地新闻资讯智能化改造

卖咖啡的星巴克自研软件:AI对软件行业的第一记耳光

2026-7-11 8:07:01

AI知识库企业落地新闻资讯

Context Over Control:当 AI 开始旁听每场会议,公司会更聪明还是更紧张?

2026-7-11 13:09:03

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
购物车
优惠劵
搜索