基于您提供的 Python 脚本,该项目实现了一个从图片/文档识别到结构化数据输出的全自动化流水线。以下是该项目的工作流、技术栈及工程化经验总结:
一、 核心工作流
该项目采用 "预处理 -> OCR识别 -> LLM结构化 -> 多格式输出" 的分步处理模式:
-
环境与配置初始化
- 优先从环境变量 (
ZHIPU_API_KEY) 或命令行参数获取 API Key,若无则使用内置占位符。 - 对 API Key 进行清洗(去除空格、不可见字符),确保鉴权稳定性。
- 优先从环境变量 (
-
数据预处理
- 文件筛选 :自动过滤非目标文件(仅支持 jpg/jpeg/png/pdf),并通过文件名机制(
_reencoded后缀)避免重复处理。 - 图像优化:针对低 DPI(<150)图片进行自动插值放大(使用 LANCZOS 算法),并将图片统一重编码为 150 DPI 的高清图,显著提升 OCR 识别率。
- 文件筛选 :自动过滤非目标文件(仅支持 jpg/jpeg/png/pdf),并通过文件名机制(
-
批量 OCR 识别
- 将处理后的图片转为 Base64 编码(支持 Data URL 格式)。
- 调用 GLM-OCR 专用接口 (
layout_parsing) 进行版面分析与文字识别。 - 将原始 OCR 结果持久化存储为 JSON 文件,作为中间态数据。
-
LLM 智能后处理
- 文档分类:基于关键词(如"发票号码"、"<table")快速识别文档类型(发票、表格、普通文本)。
- 信息抽取与清洗 :
- 发票:引导 LLM 输出标准 JSON,提取发票号、金额、纳税人识别号等字段。
- 表格:将 OCR 文本转化为标准 Markdown 表格。
- 文本:生成摘要或整理格式。
- 并发加速 :使用线程池 (
ThreadPoolExecutor) 并行调用 LLM 接口,提升批量处理速度。
-
结果输出
- 生成包含所有文档汇总的 Markdown 报告。
- 针对发票类数据,自动生成结构化的 Excel 表格 (
.xlsx),方便财务归档。
二、 关键接口与技术栈
| 类别 | 技术组件/接口 | 用途说明 |
|---|---|---|
| OCR 核心 | zai SDK / zhipuai SDK |
优先使用 zai 库调用 layout_parsing 接口,支持版面分析与可视化。 |
| LLM 核心 | GLM-4.7-FlashX / GLM-4.7-FlashX |
用于文本理解、字段提取与格式化。Flash 系列模型具有高性价比与高响应速度。 |
| 图像处理 | Pillow (PIL) |
图片 DPI 读取、模式转换 (RGB)、尺寸缩放、质量压缩与重编码。 |
| 数据编码 | base64 |
将二进制图片文件转化为 API 传输所需的文本格式。 |
| 并发控制 | concurrent.futures.ThreadPoolExecutor |
实现多线程并发请求 LLM,解决网络 I/O 阻塞问题。 |
| 数据输出 | pandas, openpyxl |
将提取的结构化数据导出为 Excel 文件。 |
三、 工程化经验总结
这份代码体现了在 AI 落地项目中非常实用的工程思维,可作为后续项目的最佳实践参考:
1. "垃圾进,垃圾出" (GIGO) 的防御性编程
- 经验:直接将低分辨率原图送入 OCR 往往效果不佳。脚本内置了 DPI 检测与超分辨率重建逻辑(自动放大至 150 DPI),这是提升识别准确率最有效的前置手段,比事后用 LLM 纠错更可靠。
2. 异构 SDK 的兼容性设计
- 经验 :在导入库时采用了
try...except ImportError的回退机制。优先尝试专用 SDK (zai),失败后回退到通用 SDK (zhipuai)。这种设计增强了脚本在不同环境下的适应性,降低了部署门槛。
3. 模型分层策略
- 经验 :不同任务使用不同层级的模型。OCR 任务使用专用的
glm-ocr模型;后处理提取发票信息使用GLM-4.7-FlashX(结构化能力强),处理表格转换使用GLM-4.7-FlashX。通过模型分层,在保证效果的前提下优化了 Token 成本和响应速度。
4. 原始数据留痕
- 经验:将 OCR 原始结果先保存为 JSON 文件,再进行 LLM 处理。这样做的好处是如果 LLM 处理失败或 Prompt 需要调整,无需重新上传图片进行 OCR(OCR 通常按次收费且耗时),直接基于 JSON 数据重跑即可,节省成本与时间。
5. 提示词与数据清洗闭环
- 经验 :在调用 LLM 提取 JSON 时,代码中包含了去除 Markdown 代码块标记(
json ...)的逻辑。这是大模型开发中常见的"清洗"步骤,能够有效防止解析报错,确保输出数据可被程序直接使用。