1. 为什么喂给 AI 的文档格式决定了回答质量的上限
很多人用 AI 处理文档时都有过类似的体验:把一份排版精美的 PDF 直接丢进去,问它"帮我总结第三季度的销售数据",结果 AI 要么答非所问,要么把表格里的数字张冠李戴,要么干脆说"我无法读取该文件内容"。换一份 Word 文档试试,情况好一点,但遇到多级标题、页眉页脚、文本框混排的时候,AI 依然会漏掉关键信息。至于 Excel 和图片,那更是重灾区——表格结构丢失、图片里的文字完全读不到,几乎等于白喂。
这个问题的根源不在于 AI 模型本身不够聪明,而在于文档格式与 AI 理解方式之间的错配。大语言模型处理信息的底层单位是 token,它天然擅长处理连续的、结构清晰的纯文本。而 PDF、Word、Excel 这些格式本质上是"给人看的排版容器",里面塞满了大量对 AI 毫无意义的排版指令:字体、字号、颜色、边距、分页符、浮动元素、嵌入对象。AI 在解析这些格式时,需要先做一层"格式还原",而这一步恰恰是最容易丢信息、最容易出错的环节。
Markdown 则完全不同。它是一种轻量级标记语言,用极少的符号就能表达标题层级、列表、表格、代码块、引用等结构。对 AI 来说,Markdown 几乎是"母语"级别的输入格式——结构显式、噪声极低、token 利用率高。同样一份内容,用 Markdown 喂给 AI,模型能更准确地抓住层级关系和重点,回答质量自然上一个台阶。
所以"先统一成 Markdown 再交给 AI"这个思路,本质上是在做一件事:把人类友好的排版格式,转换成机器友好的语义格式。这一步做得好不好,直接决定了后续 AI 处理的天花板。我在这件事上踩过的坑不算少,下面把整套流程拆开讲清楚,包括为什么这么选、每一步怎么做、以及哪些地方最容易翻车。
提示:本文讨论的是文档格式转换与 AI 输入优化的通用工程实践,所有工具和方法均为本地或通用场景下的常规操作,不涉及任何特殊网络环境。
2. 四种格式各自的"脾气":转换前必须搞清楚的底层差异
在动手写转换脚本之前,得先明白每种格式的"脾气"。不同格式的信息组织方式差异极大,用同一套逻辑去处理,必然会在某些格式上栽跟头。我按处理难度从低到高排一下,顺便说清楚每种格式的核心坑点。
2.1 Word 文档:结构最规整,但隐藏元素最多
Word 的底层是 OOXML,本质上是一个 zip 包,里面用 XML 描述段落、样式、表格。它的好处是结构相对规整,标题层级、列表、表格都有明确的样式标记,转换工具能比较容易地识别出"这是一个一级标题""这是一个无序列表"。
但 Word 的坑在于隐藏元素。页眉页脚、批注、修订记录、文本框、艺术字、嵌入的 OLE 对象,这些东西在视觉上可能不显眼,但在解析时会被当成正文内容混进来。我遇到过最离谱的一次,一份 Word 文档的页眉里写着"内部资料 请勿外传",转换后这行字被当成正文第一段,AI 总结时直接把它当成了文档主题。所以处理 Word 时,必须显式过滤页眉页脚和批注,这是硬性要求。
另一个坑是样式滥用。很多人写文档不用真正的标题样式,而是手动加粗放大来"假装"标题。这种情况下转换工具无法识别层级,出来的 Markdown 就是一堆没有结构的段落。遇到这种文档,要么手动修,要么用基于字体大小和加粗状态的启发式规则去猜层级,但准确率没法保证。
2.2 Excel 表格:结构信息全在"位置"里,最容易丢
Excel 是所有格式里最难处理的一种,没有之一。原因很简单:Excel 的语义不靠标记表达,而靠单元格的位置关系。合并单元格、跨行跨列、多级表头、公式引用,这些在视觉上一目了然,但转成纯文本后极易丢失。
举个典型场景:一张销售表,第一行是"2024年",跨了四个季度列;第二行是"Q1/Q2/Q3/Q4";第三行才是具体指标。人一眼就能看懂这是两级表头,但很多转换工具会把它拍平成三行普通数据,AI 拿到后就完全懵了——它不知道"2024年"和"Q1"是什么关系。
处理 Excel 的核心原则是:保留表格的二维结构,不要拍平。Markdown 的表格语法天然支持二维结构,所以转换时要尽量把每个 sheet 转成一个独立的 Markdown 表格。对于合并单元格,需要在转换时做"填充"处理——把合并单元格的值复制到它覆盖的每一个格子里,这样 AI 才能正确理解归属关系。多级表头则建议在转换后手动补一行说明,或者用"表头1_表头2"的拼接方式命名列。
2.3 PDF:视觉保真度高,语义保真度低
PDF 的设计目标是"在任何设备上看起来都一样",它描述的是每个字符画在页面上的精确坐标,而不是"这是一段话""这是一个标题"。这就导致 PDF 的语义信息几乎为零,转换工具只能靠版面分析去猜结构:字号大的可能是标题,居中的可能是标题,连续短行可能是列表。
PDF 的坑主要有三类。第一类是双栏排版,工具如果按从左到右的顺序读,会把左右两栏的内容交错混在一起,读起来完全不通。第二类是扫描件,本质是图片,必须走 OCR,而 OCR 的准确率受清晰度、字体、倾斜角度影响很大。第三类是表格跨页,一张表被分到两页,转换后变成两个断裂的表格,AI 无法关联。
我的经验是:能拿到原始 Word/Excel 就绝不用 PDF。如果只有 PDF,优先用带版面分析能力的工具,转换后一定要人工抽查双栏和表格部分。扫描件则必须走 OCR,且要预留人工校对的时间。
2.4 图片:信息密度最低,OCR 质量决定一切
图片处理最直接——就是 OCR。但 OCR 的质量差异极大,清晰的正楷印刷体准确率能到 99%,手写体、艺术字、低分辨率截图可能连 60% 都不到。而且图片里的表格、流程图、公式,OCR 基本无能为力,只能识别出文字,结构全丢。
处理图片的实用策略是:先判断图片类型再决定要不要转。纯文字截图,OCR 后转 Markdown 完全可行;带复杂表格的图片,OCR 后需要人工重建表格结构;流程图、架构图这类,OCR 出来的文字没有意义,不如直接用多模态模型看图,或者人工描述。
下面这张表把四种格式的核心差异和转换策略总结一下,方便对照:
| 格式 | 结构信息载体 | 主要坑点 | 推荐转换策略 | 人工校对优先级 |
|---|---|---|---|---|
| Word | 样式标记 | 页眉页脚、批注、假标题 | 解析 OOXML,过滤隐藏元素 | 中 |
| Excel | 单元格位置 | 合并单元格、多级表头 | 保留二维结构,填充合并格 | 高 |
| 字符坐标 | 双栏、扫描件、跨页表格 | 版面分析 + OCR,抽查双栏 | 高 | |
| 图片 | 像素 | OCR 准确率、结构丢失 | 先分类,纯文字才转 | 高 |
3. 转换工具怎么选:从命令行到脚本的完整选型逻辑
搞清楚格式差异后,下一步是选工具。市面上的转换工具大致分三类:在线转换服务、桌面软件、编程库。三类各有适用场景,我的建议是优先用编程库,因为可控性最强,能针对具体文档做定制处理,而且批量处理时效率最高。
3.1 编程库选型:按格式对号入座
不同格式对应不同的库,没有万能工具。下面是我实际用过、比较靠谱的组合:
- Word 转 Markdown:Python 生态里
python-docx负责读取内容,pandoc负责格式转换。pandoc 是文档转换领域的"瑞士军刀",支持 Word、Markdown、HTML、LaTeX 等几十种格式互转,命令行调用即可。它的优点是转换质量高、维护活跃;缺点是遇到复杂样式时仍需后处理。 - Excel 转 Markdown:
openpyxl读 xlsx,pandas做数据处理,然后手动拼 Markdown 表格。为什么不直接用 pandoc?因为 pandoc 对 Excel 的支持很弱,合并单元格和多 sheet 处理得一塌糊涂。自己用 pandas 读出来再拼表格,虽然多写几行代码,但可控性完全不一样。 - PDF 转 Markdown:
pdfplumber适合处理有文字层的 PDF,能提取文字和表格;PyMuPDF(fitz)速度更快,版面分析能力也不错。扫描件则要配合 OCR 引擎,比如pytesseract或PaddleOCR。PaddleOCR 对中文的支持明显好于 tesseract,这是实测结论。 - 图片 OCR:同样推荐 PaddleOCR,中文识别准确率高,而且支持表格识别模式,能把图片里的表格还原成结构化数据。
注意:pandoc 需要单独安装,不是 Python 包。在 Linux 上可以用包管理器装,Windows 上直接下安装包。装完后用
pandoc --version验证。
3.2 为什么不用在线转换服务
在线转换服务看起来最省事,上传文件、点一下、下载 Markdown,三步搞定。但我强烈不建议在正式流程里用它,原因有三个。
第一是隐私风险。文档里可能包含敏感的业务数据、个人信息,上传到第三方服务器等于把数据交出去了。第二是不可控。你不知道它用什么算法转换,出了问题也没法调。第三是批量效率低。几十上百个文件,一个个上传下载,时间成本太高,而且很多服务有文件大小和数量限制。
编程库虽然前期要写点代码,但一旦跑通,批量处理就是几行循环的事,而且全程本地,数据不出机器。这笔投入绝对值得。
3.3 一个容易被忽略的细节:编码问题
中文文档转换时,编码是最容易翻车的地方。Word 和 Excel 内部用 Unicode,一般没问题;但 PDF 和 OCR 结果经常出现乱码,尤其是 GBK 和 UTF-8 混用的时候。我的做法是:所有读写操作显式指定encoding='utf-8',并且在转换后加一步编码校验,发现乱码就回退到gbk重试。这个细节看起来小,但不处理的话,转换出来的 Markdown 里全是问号,AI 根本没法读。
4. 手把手搭建转换流水线:从单文件到批量处理
理论讲完,进入实操。这一节我把整套流水线拆成可复现的步骤,从环境准备到批量脚本,每一步都给出代码和说明。你可以直接照着搭,也可以按自己的需求裁剪。
4.1 环境准备与依赖安装
先建一个干净的虚拟环境,避免依赖冲突。Python 版本建议 3.9 以上,太低的话某些库不支持。
python -m venv doc2md source doc2md/bin/activate # Windows 用 doc2md\Scripts\activate pip install python-docx openpyxl pandas pdfplumber PyMuPDF paddleocr paddlepaddle pytesseractpandoc 单独装:
# Ubuntu/Debian sudo apt install pandoc # macOS brew install pandoc # Windows 去官网下安装包装完后验证一下关键库能不能正常导入:
import docx, openpyxl, pandas, pdfplumber, fitz from paddleocr import PaddleOCR print("all ok")如果 PaddleOCR 导入报错,多半是 paddlepaddle 版本不匹配,按官方文档装对应版本即可。这一步别偷懒,环境问题不解决,后面全是坑。
4.2 Word 转 Markdown:过滤隐藏元素是关键
Word 转换我分两步走:先用 pandoc 做基础转换,再用 python-docx 做后处理,清理页眉页脚和批注。
import subprocess import docx def word_to_markdown(docx_path, md_path): # 第一步:pandoc 基础转换 subprocess.run([ "pandoc", docx_path, "-t", "markdown", "-o", md_path, "--wrap=none" ], check=True) # 第二步:读取文档,收集页眉页脚文本用于过滤 doc = docx.Document(docx_path) hidden_texts = set() for section in doc.sections: for para in section.header.paragraphs: if para.text.strip(): hidden_texts.add(para.text.strip()) for para in section.footer.paragraphs: if para.text.strip(): hidden_texts.add(para.text.strip()) # 第三步:过滤 Markdown 中的隐藏文本 with open(md_path, "r", encoding="utf-8") as f: lines = f.readlines() cleaned = [l for l in lines if l.strip() not in hidden_texts] with open(md_path, "w", encoding="utf-8") as f: f.writelines(cleaned) return md_path这段代码的核心逻辑是:pandoc 负责把 Word 的结构转成 Markdown 标记,python-docx 负责把页眉页脚这些"混进来的杂质"找出来,然后在 Markdown 里删掉。为什么要分两步?因为 pandoc 本身不区分正文和页眉页脚,它会把所有文字都转出来,所以必须靠后处理清理。
--wrap=none这个参数很重要,它禁止 pandoc 自动换行。默认情况下 pandoc 会按 72 字符折行,导致一个段落被拆成多行,AI 读的时候会误以为是多个段落。加上这个参数,段落就保持完整了。
4.3 Excel 转 Markdown:合并单元格的填充处理
Excel 转换的核心是保留二维结构。我用 pandas 读数据,然后手动处理合并单元格和多级表头。
import pandas as pd from openpyxl import load_workbook def excel_to_markdown(xlsx_path, md_path): wb = load_workbook(xlsx_path, data_only=True) output = [] for sheet_name in wb.sheetnames: ws = wb[sheet_name] output.append(f"## Sheet: {sheet_name}\n") # 处理合并单元格:把合并区域的值填充到每个格子 merged_values = {} for merge_range in ws.merged_cells.ranges: top_left = ws.cell(merge_range.min_row, merge_range.min_col).value for row in range(merge_range.min_row, merge_range.max_row + 1): for col in range(merge_range.min_col, merge_range.max_col + 1): merged_values[(row, col)] = top_left # 读取所有数据,合并格用填充值 data = [] for row in ws.iter_rows(): row_data = [] for cell in row: if (cell.row, cell.column) in merged_values: row_data.append(merged_values[(cell.row, cell.column)]) else: row_data.append(cell.value) data.append(row_data) # 转成 DataFrame 再输出 Markdown 表格 df = pd.DataFrame(data) output.append(df.to_markdown(index=False, headers=df.iloc[0] if len(df) > 0 else None)) output.append("\n") with open(md_path, "w", encoding="utf-8") as f: f.write("\n".join(output)) return md_path这里最关键的是合并单元格填充那段。openpyxl 读取合并单元格时,只有左上角的格子有值,其他格子是 None。如果不填充,转出来的表格里合并区域就是一片空白,AI 完全看不懂归属关系。填充之后,每个格子都有值,二维结构就完整了。
多级表头的情况更复杂一些。如果第一行是"2024年"跨四列,第二行是"Q1/Q2/Q3/Q4",填充后第一行会变成"2024年/2024年/2024年/2024年",第二行是"Q1/Q2/Q3/Q4"。这时候可以在转换后手动加一行说明,或者用脚本把两行拼成"2024年_Q1"这样的列名。具体怎么处理取决于你的数据特点,没有一刀切的方案。
4.4 PDF 与图片:OCR 与版面分析的组合拳
PDF 分两种情况。有文字层的 PDF,直接用 pdfplumber 提取;扫描件走 OCR。
import pdfplumber import fitz # PyMuPDF def pdf_to_markdown(pdf_path, md_path): output = [] with pdfplumber.open(pdf_path) as pdf: for i, page in enumerate(pdf.pages): text = page.extract_text() if text and len(text.strip()) > 20: # 有文字层,直接提取 output.append(f"## Page {i+1}\n\n{text}\n") else: # 无文字层,走 OCR output.append(f"## Page {i+1} (OCR)\n\n{ocr_page(pdf_path, i)}\n") with open(md_path, "w", encoding="utf-8") as f: f.write("\n".join(output)) return md_path def ocr_page(pdf_path, page_num): doc = fitz.open(pdf_path) page = doc[page_num] pix = page.get_pixmap(dpi=300) # 300 DPI 是 OCR 的甜点值 img_path = f"/tmp/page_{page_num}.png" pix.save(img_path) ocr = PaddleOCR(use_angle_cls=True, lang="ch") result = ocr.ocr(img_path, cls=True) lines = [line[1][0] for line in result[0]] if result[0] else [] return "\n".join(lines)这里有两个经验值值得说。第一是DPI 设 300。太低(比如 150)OCR 识别率明显下降,太高(比如 600)文件巨大且速度慢,300 是实测下来准确率和速度的平衡点。第二是use_angle_cls=True,这个参数开启文字方向分类,能处理倾斜的扫描件,不开的话倾斜文字识别率会掉一大截。
图片 OCR 更简单,直接调 PaddleOCR 就行:
def image_to_markdown(img_path, md_path): ocr = PaddleOCR(use_angle_cls=True, lang="ch") result = ocr.ocr(img_path, cls=True) lines = [line[1][0] for line in result[0]] if result[0] else [] with open(md_path, "w", encoding="utf-8") as f: f.write("\n".join(lines)) return md_path4.5 批量处理脚本:一次搞定整个文件夹
单文件转换跑通后,批量处理就是加一层循环和格式分发。下面这个脚本扫描指定目录,按扩展名分发到对应的转换函数,输出到统一的输出目录。
import os from pathlib import Path def batch_convert(input_dir, output_dir): input_dir = Path(input_dir) output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) handlers = { ".docx": word_to_markdown, ".xlsx": excel_to_markdown, ".pdf": pdf_to_markdown, ".png": image_to_markdown, ".jpg": image_to_markdown, ".jpeg": image_to_markdown, } results = [] for file in input_dir.rglob("*"): if not file.is_file(): continue ext = file.suffix.lower() if ext not in handlers: continue out_path = output_dir / (file.stem + ".md") try: handlers[ext](str(file), str(out_path)) results.append((file.name, "成功", out_path.stat().st_size)) except Exception as e: results.append((file.name, f"失败: {e}", 0)) # 打印处理报告 print(f"{'文件':<40}{'状态':<20}{'大小(字节)'}") for name, status, size in results: print(f"{name:<40}{status:<20}{size}") return results batch_convert("./docs", "./markdown_output")跑完之后会打印一份处理报告,哪些成功、哪些失败、输出多大,一目了然。失败的文件单独拎出来排查,通常是格式特殊或文件损坏。
5. 转换质量校验:怎么判断 Markdown 能不能直接喂给 AI
转换完成不等于可以用了。我见过太多人转完直接丢给 AI,结果 AI 答得一塌糊涂,回头怪模型不行。其实问题出在转换质量上。这一节讲怎么校验,以及校验不过时怎么修。
5.1 三个必查项:结构、内容、编码
校验 Markdown 质量,我固定查三样东西。
第一是结构完整性。打开转换后的 Markdown,看标题层级对不对。原本 Word 里的一级标题,转出来应该是#,二级是##,不能全变成普通段落。表格是不是还是表格,有没有被拍平成一行行文字。列表有没有保留-或1.标记。结构一旦丢失,AI 就抓不住文档的骨架。
第二是内容完整性。对比原文和转换结果,看有没有整段丢失。PDF 双栏排版最容易出这个问题,左右栏内容交错或者某一栏直接没了。表格跨页也容易丢,第二页的表头和数据可能没接上。我的做法是随机抽 3 到 5 个段落,逐字对比,发现丢失就定位原因。
第三是编码正确性。中文乱码是高频问题,表现为一串问号或者奇怪的符号。用file -i output.md看编码,应该是utf-8。如果是别的编码,用iconv转一下。乱码不解决,AI 读到的就是垃圾。
5.2 用 AI 反向验证转换质量
有个很实用的技巧:把转换后的 Markdown 喂给 AI,让它复述文档结构。比如问它"这份文档有几个一级标题?分别是什么?""文档里有哪些表格?"如果 AI 能准确回答,说明结构保留得不错;如果答得含糊或者答错,说明转换有问题。
这个方法的好处是,它模拟了真实使用场景。你最终就是要让 AI 读这份 Markdown,那不如直接用 AI 来验收。我一般会问三个问题:文档主题是什么、有几个主要章节、某个具体数据在第几节。三个都能答对,基本就合格了。
5.3 常见转换问题的修复清单
下面这张表列了我遇到过的高频问题和对症修复方法,可以直接当排查手册用:
| 问题现象 | 根本原因 | 修复方法 |
|---|---|---|
| 页眉页脚混入正文 | 转换工具不区分正文和页眉 | 用 python-docx 提取页眉页脚文本后过滤 |
| 表格变成一堆文字 | 转换工具不支持表格结构 | 换用 pandas 手动拼 Markdown 表格 |
| 合并单元格内容丢失 | 只读左上角格子 | 遍历合并区域,填充每个格子 |
| PDF 双栏内容交错 | 按坐标顺序读取 | 用版面分析工具,或按栏切分后分别提取 |
| 中文乱码 | 编码不一致 | 显式指定 utf-8,乱码时回退 gbk |
| 段落被拆成多行 | pandoc 自动折行 | 加--wrap=none参数 |
| OCR 识别率低 | DPI 太低或文字倾斜 | DPI 提到 300,开启角度分类 |
这张表建议存下来,每次转换出问题先对照排查,能省不少时间。
6. 让 Markdown 更适合 AI 阅读的进阶处理
基础转换做完,如果想让 AI 读得更准,还可以做一层进阶优化。这些处理不是必须的,但在处理长文档、复杂表格时效果很明显。
6.1 给长文档加"导航层"
一份几十页的文档转成 Markdown 后,AI 读起来容易"迷路",尤其是问它"第 5 节讲了什么"的时候,它得从头扫一遍。解决办法是在文档开头加一个目录导航层,把所有标题按层级列出来,并标注大致位置。
import re def add_toc(md_path): with open(md_path, "r", encoding="utf-8") as f: content = f.read() # 提取所有标题 headings = re.findall(r"^(#{1,6})\s+(.+)$", content, re.MULTILINE) toc_lines = ["## 文档目录\n"] for level, title in headings: indent = " " * (len(level) - 1) toc_lines.append(f"{indent}- {title}") toc_lines.append("\n---\n") # 插到文档最前面 new_content = "\n".join(toc_lines) + content with open(md_path, "w", encoding="utf-8") as f: f.write(new_content)这个目录层对 AI 特别有用,相当于给了它一张地图。问它具体章节内容时,它能先定位再细读,准确率明显提升。
6.2 表格的语义增强
Markdown 表格虽然保留了二维结构,但表头如果太简略,AI 还是容易误解。比如一列叫"数量",到底是库存数量还是销售数量?这时候可以在表格上方加一行说明,或者把列名改得更明确。
我的做法是给每个表格加一个表标题和字段说明:
### 表 1:2024 年各季度销售数据 字段说明:季度为自然季度,销售额单位为万元,同比为与去年同期相比的增长率。 | 季度 | 销售额 | 同比 | |------|-------|------| | Q1 | 1200 | +15% | | Q2 | 1350 | +12% |多这一行说明,AI 理解表格的准确率会高很多。尤其是涉及单位、口径、时间范围的时候,这行说明几乎是必需的。
6.3 图片和公式的处理策略
图片转 Markdown 后,OCR 出来的文字是"裸文本",没有上下文。如果图片是流程图,OCR 出来的文字顺序可能是乱的。这种情况我建议保留图片引用 + 人工描述的方式:
 图 1 说明:该流程描述订单从创建到发货的五个步骤,依次为下单、支付、审核、拣货、发货,其中审核不通过会退回支付环节。这样 AI 既知道这里有张图,又能通过文字描述理解图的内容。纯靠 OCR 的文字,AI 很难还原出流程逻辑。
公式同理。PDF 里的公式转成 Markdown 后经常变成乱码,这时候要么用 LaTeX 重写,要么用文字描述公式的含义。对于 AI 来说,一段准确的文字描述比一堆乱码符号有用得多。
7. 实测中的几个坑与我的应对经验
前面讲的都是"应该怎么做",这一节讲"实际做的时候会出什么意外"。这些坑都是我一个个踩过来的,写出来希望能帮你少走弯路。
7.1 pandoc 版本差异导致的转换结果不一致
pandoc 不同版本对 Word 的解析行为有差异。我在两台机器上跑同一个脚本,一台转出来的表格是标准 Markdown 表格,另一台转出来是 HTML 表格混在 Markdown 里。排查半天才发现是 pandoc 版本不同,一个 2.x 一个 3.x。
应对方法很简单:在脚本里锁定 pandoc 版本,或者在转换后加一步格式规范化,把 HTML 表格统一转成 Markdown 表格。我现在的做法是在 CI 环境里固定 pandoc 版本,本地开发也尽量对齐,避免"在我机器上是好的"这种问题。
7.2 大文件转换的内存爆炸
处理几百页的 PDF 或者几万行的 Excel 时,一次性读入内存很容易爆。我遇到过一次,一个 200MB 的 PDF 直接把内存吃满,进程被系统杀掉。
解决办法是分块处理。PDF 按页处理,每处理完一页就释放;Excel 按 sheet 或按行分块读。pandas 的read_excel支持chunksize参数,openpyxl 也支持read_only模式逐行读。改成流式处理后,内存占用能降一个数量级。
# openpyxl 只读模式,适合大文件 wb = load_workbook(xlsx_path, read_only=True, data_only=True) for ws in wb.worksheets: for row in ws.iter_rows(): # 逐行处理,不一次性加载 process_row(row)7.3 OCR 的"幻觉"问题
OCR 不是万能的,它在识别不清的时候会"猜",猜出来的字可能是错的。我遇到过把"销售额"识别成"销售颤"的,把"2024"识别成"202A"的。这种错误很隐蔽,不仔细看根本发现不了。
应对方法是关键数据二次校验。对于数字、金额、日期这类关键信息,OCR 后要人工抽查,或者用规则校验(比如金额应该是数字,日期应该符合日期格式)。发现异常就回退到原图人工确认。这一步虽然费时间,但比 AI 基于错误数据给出错误结论要好得多。
7.4 转换后的 Markdown 体积控制
Markdown 虽然比原格式小,但长文档转出来依然可能很大。一份 100 页的 PDF 转成 Markdown 可能有几十万字符,直接喂给 AI 会超出上下文窗口。
这时候需要分段投喂。按章节切分,每次只喂相关章节。或者先做一层摘要,把每节的核心内容提炼出来,再喂给 AI 做全局分析。我的做法是保留完整的 Markdown 作为"知识库",实际问答时按需检索相关段落,而不是一股脑全塞进去。
8. 把这套流程用起来:从个人文档到团队知识库
这套转换流程最初是我自己处理文档时攒出来的,后来发现它在团队场景下价值更大。一个团队积累的 Word 报告、Excel 数据、PDF 资料,如果都统一转成 Markdown 存起来,就形成了一个结构化的知识库,AI 可以直接在上面做问答、总结、检索。
具体落地时,我建议分三步走。第一步是建立转换规范,明确哪些格式必须转、转换后怎么命名、存到哪里。第二步是搭自动化流水线,用脚本或定时任务批量处理新增文档,避免手动操作。第三步是加质量校验环节,转换后自动跑一遍结构和编码检查,不合格的文档打回重转。
这套流程跑顺之后,你会发现 AI 处理文档的体验完全不一样了。以前是"喂进去一堆乱码,得到一堆废话",现在是"喂进去结构清晰的内容,得到准确有用的回答"。差别就在转换这一步。
最后分享一个我常用的小技巧:转换脚本里加一个--dry-run模式,只扫描文件、打印将要执行的操作,不实际转换。批量处理前先跑一遍 dry-run,确认文件列表和分发逻辑没问题,再正式跑。这个习惯帮我避免过好几次"误转了整个目录"的事故。