工作随笔

Agent 第一章:文件识别、LLM 抽数与 Zod 校验

  • 2026年 7月 17日
aiSummaryIcon

展开

这篇博客总结了一个聊天型AI Agent的文件分析模块从上传到生成结构化数据的完整链路。核心结论是:文件分析不是一步到位的OCR,而是一个分层加工的过程,每一层解决不同的问题。      作者从实际项目出发,新建了一个干净的TypeScript项目,只复刻文件分析链路,不涉及聊天和入库,便于观察每一层的输出。      整体流程为:文件上传 -> 文件解析/OCR -> 页面文字拼接 -> LLM结构化抽数 -> JSON格式校验 -> 业务数据清洗 -> 提供给Agent继续对话。      第一层:文件解析决定如何获取文字   并非所有文件都需要OCR。TXT、CSV、Word、Excel以及有文字层的PDF可以直接提取文字;图片和扫描版PDF才调用PaddleOCR。PDF提取文字时如果内嵌文字少于30个字符,会退回到OCR。本地解析优先,速度快且减少OCR识别错误。      第二层:PaddleOCR将图片变成文字   只负责读取页面上的字符,返回分页结果,包括每页的识别文本和置信度。置信度表示OCR对页面文字的把握,不表示业务字段的准确性。      第三层:拼接文字并截断   将非空页面按顺序拼接成一段纯文本,为避免模型上下文溢出,只发送前12000个字符。这一步决定了LLM看到的内容质量——OCR的错误会直接传递到LLM。      第四层:通过Prompt要求LLM返回结构化JSON   Prompt中明确字段、枚举、对象结构,并要求只输出JSON,不解释,不猜测。返回结果包含candidate数组(人物、公司、小区等)和extractedFields(姓名、身份证等)。candidate通过slots将多个字段绑定到同一实体,防止后续拼接错误。      第五层:LLM返回JSON后不能直接使用   即使开启response_format: { type: "json_object" },模型返回的JSON结构仍可能不符合业务要求。例如字段位置错误、类型不对等。需要服务端进一步校验。      第六层:使用Zod约束数据结构   定义Zod Schema对LLM的原始输出进行safeParse。首次接入严格校验立刻发现了模型将archiveDocument放在顶层而非extractedFields内的问题。Zod只检查结构正确性,不检查内容真实性。      第七层:业务清洗弥补Zod的不足   Zod通过后还需要服务端处理:去重、转大写、移除空白/连字符、检查关系两端是否存在、防止孤立字段自动关联、避免重复候选等。最终生成normalizedInsight。      第八层:通过接口观察每一层中间结果   提供一个POST /files/analyze接口,返回pages/parsedText、llmRawText、llmRawOutput、normalizedInsight、wouldPersist等字段。调试时可以直接对照OCR文字、LLM原始输出和服务端清洗结果,快速定位问题。      总结:文件分析的每一层职能清晰   【文件解析器】决定如何拿到文字   【PaddleOCR】负责扫描件转文字   【LLM】从文字中抽取结构   【Zod】拦截错误数据结构   【业务清洗】决定数据能否真正使用      最容易产生的误解是认为LLM输出JSON就等于已经结构化。实际上它只是“模型认为的结构化数据”,必须经过服务端校验才能进入Agent。      后续章节计划:文件结果如何进入聊天上下文、用户追问时关联最近文件、以及从文件中生成安全候选池。

推荐