☰
第10章:RAGFlow 表格、Markdown、图片与扫描件处理
2026/10/1 14:28:14 网站建设 项目流程

1 项目背景

业务场景

「云帆科技」的财务总监在月度总结会上提出了一个尖锐的问题:“你们的问答机器人,我问’P3 职级在北京出差的住宿标准是多少’,它给我来了一长段小作文,里面夹杂着 P1、P2、P3 的各种标准混在一起。我要的是一个数字,不是一个故事。能不能让它像 Excel 一样精准回答?”

与此同时,技术文档组的同事也在抱怨——他们用 Markdown 写的 API 文档上传到 RAGFlow 后,代码示例里的缩进全丢了,```python代码块被当成普通文字切得七零八落,问"怎么调用 createDataset 接口"永远搜不到正确的代码示例。

最要命的还是行政部——他们用手机拍的几张「会议室使用规则」贴在墙上那种,上传后解析出来全是乱码。行政大姐直接甩了一句:“看来这 AI 的拍照技术还不如我妈。”

痛点

表格、Markdown、图片是知识库中仅次于纯文本的高频格式。处理不好,直接影响三类核心场景:

  1. 表格处理失败:合并单元格信息丢失、跨页表格切成两半、数值列被当成普通文字——导致精确数据查询(金额、比例、职级)完全失效。
  2. Markdown 结构破坏:代码块被切散、标题层级丢失、列表缩进混乱——导致技术文档检索形同虚设。
  3. 图片/扫描件质量差:手机拍照的倾斜、阴影、低分辨率——导致 OCR 准确率从 95% 暴跌到 30%。
三种格式的处理难点对比: 表格 ── 难点:合并单元格、跨页、数值精确保留 后果:"住宿费500" 识别成 "住 宿 费 5 0 0" Markdown ── 难点:代码块边界、层级关系、符号转义 后果:```python```代码块被切成3个无关片段 图片/扫描件 ── 难点:倾斜、阴影、低分辨率、图文混排 后果:把"会议"认成"会义",把"流程"认成"流桂"

2 项目设计

小胖:(拿着手机对准桌上的打印表格拍照)“大师你看,我把这份’出差住宿标准表’拍下来上传到 RAGFlow,结果它把表格解读成这样——'城市级别住宿费北京一线 500 上海一线 500 广州一线 450’连个标点都没有,谁知道北京对应 500 还是上海对应 500?”

大师:(指着表格)“你这份表格有三个难点:第一,合并单元格——'一线城市’这个标签合并了 3 行,OCR 只认得出来一次;第二,数字和单位分离——'500元/晚’被分到了两个不同的识别行;第三,手机拍照有阴影倾斜,表格线都歪了。”

技术映射:表格 OCR = 对着碎纸机拼图——你不仅要认出每一片纸上的字,还要知道这些纸片在原始表格中的行列位置。

小胖:“那 RAGFlow 到底能不能处理表格?如果能,怎么配?”

大师:“能,但有前提。分两种情况:”

情况1:PDF 中的原生表格(Word 转 PDF 的那种)

  • DeepDoc 的版面分析能识别表格区域
  • 通过table_enhance: true开启表格增强
  • 能够较准确地提取行列对应关系
  • 输出为 Markdown 表格格式

情况2:扫描件中的表格(拍照、扫描)

  • 首先需要 OCR 识别文字
  • 然后需要检测表格线(横线和竖线)重建行列
  • 最后把识别出的文字填到对应格子里
  • 这项技术叫 Table Structure Recognition(表格结构识别)
# RAGFlow 表格处理的核心配置parser_config={"parser_id":"pdf","enable_ocr":True,"layout_recognize":True,"table_enhance":True,# 表格增强"table_output_format":"markdown",# 或 "html", "json""language":"chinese",}

小白:“那 Markdown 文档呢?技术文档组说他们的 API 文档解析后代码块全乱了。”

大师:“Markdown 解析的最大挑战不是文字本身,而是结构保留。一份典型的 API 文档 Markdown 是这样的:”

# createDataset 接口 ## 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | name | string | 是 | 数据集名称 | | description | string | 否 | 数据集描述 | ## 请求示例 ```python from ragflow import RAGFlow rag = RAGFlow(api_key="xxx") dataset = rag.create_dataset(name="测试数据集")
"RAGFlow 的 Markdown 解析器需要正确处理四件事:" 1. **标题层级保留**:`#` `##` `###` 不要丢失,切片时会根据标题做切分边界。 2. **代码块完整性**:` ```python ... ````整个代码块应该尽量在一个切片内(或至少不要从中间切断)。 3. **表格转译**:Markdown 表格 `| col1 | col2 |` 转成文档引擎可检索的格式。 4. **列表结构**:`-` `1.` 无序/有序列表的缩进层级保留。 "**核心坑点**:默认的 Naive 切片会在 token 数量达到阈值时硬切一刀——这一刀如果切在代码块中间,代码就废了。所以要优先使用 Title 切片方法(以标题为自然边界),代码块尽量保持完整。" **技术映射**:Markdown 解析 = 整理手写笔记——不仅要把字抄下来,还要保留大纲、重点标记、示意图的原始布局。 **小胖**:"那手机拍照的图片呢?行政部那几张'会议室规则'怎么办?" **大师**:"手机拍照在 OCR 领域是'地狱难度'。但可以通过预处理和配置优化来提升效果:" **拍照劣化因素 => 应对策略**: | 劣化因素 | 影响 | RAGFlow 应对策略 | |---------|------|-----------------| | 倾斜(未对齐) | 文字行检测失败,OCR 错行 | 自动倾斜校正(Image Deskew) | | 阴影/不均匀光照 | 部分文字太暗,对比度不足 | 自适应二值化、对比度增强 | | 低分辨率 | 笔画断裂,小字无法识别 | 超分辨率预处理(谨慎使用,耗资源) | | 透视变形(斜着拍) | 文字扭曲,表格变形 | 透视矫正(Perspective Correction) | | 噪点/污渍 | 干扰文字识别 | 高斯模糊、中值滤波去噪 | **小白**:"那如果图片完全无法 OCR 识别怎么办?比如一张产品架构图。" **大师**:"对于纯图像(架构图、流程图、UI 截图),OCR 本来就不是正确的工具。RAGFlow 支持通过多模态模型(如 GPT-4V、Gemini Vision)对图片生成文字描述,然后以'图片描述切片'的形式纳入知识库。这样用户搜索'模块 A 和模块 B 的关系'时,虽然搜不到这张图,但能搜到对这张图的描述文本。" ```python # 多模态图片处理(概念性代码) parser_config = { "parser_id": "image", "enable_ocr": True, # 对图中的文字做OCR "enable_vision_description": True, # 用多模态模型生成场景描述 "vision_model": "gpt-4-vision", # 多模态模型 "description_language": "chinese", # 描述语言 "max_tokens": 300, # 描述文本长度 } # 输出: # - OCR 文字内容(如有) # - 场景描述:"该图片展示了云帆科技的产品架构图,包含前端层、 # 服务层、数据层三层架构,通过 API Gateway 连接外部系统。"

技术映射:多模态图片处理 = 把一幅画用文字讲给盲人听——不是让他"看"画,而是让他"听"描述。

小胖:“那扫描件如果质量实在太差怎么办?我手上有几份 2010 年的老合同,纸都黄了,字都快看不清了。”

大师:“这种情况要做预期管理——告诉业务方 OCR 准确率大概只有 60-70%。处理策略分三步:”

  1. 能做多少做多少:用最强 OCR 配置(layout_recognize: true,table_enhance: true, 300 DPI 扫描),尽量还原。
  2. 标记低质量切片:对 OCR 置信度低于 80% 的切片加标记[低置信度],提示用户该信息可能不准确。
  3. 人工补救:对于关键合同条款,在切片可视化界面手动修正文本——这是最后一道防线。

小白:“最后一个系统性问题。不同类型的文档用不同的解析策略,但一个数据集里可能同时有 PDF、Markdown、图片,怎么做到自动选择合适的 Parser?”

大师:“RAGFlow 的 API Server 在接收上传文件时会根据文件扩展名自动匹配 Parser。mimetype → parser_id的映射在源码中硬编码。但需要注意的是——默认匹配不一定最佳。比如一个.pdf文件,你没法从扩展名判断它是文本型还是扫描型。所以建议按文件类型分数据集,或者在上传时显式指定parser_config。”

RAGFlow Parser 自动匹配逻辑(简化): .pdf → pdf_parser .docx → docx_parser .xlsx → excel_parser .pptx → pptx_parser .md → markdown_parser .html → html_parser .png/.jpg/.jpeg → image_parser .csv → csv_parser .txt → txt_parser

3 项目实战

环境准备

目标:准备一份包含表格、Markdown、图片的"全格式测试集",验证 RAGFlow 的综合解析能力。

测试文件清单:

  • 出差住宿标准表.pdf:含合并单元格的 PDF 表格
  • API接口文档.md:含代码块、表格、标题层级的 Markdown
  • 会议室使用规则.jpg:手机拍照的图片(倾斜、有阴影)
  • 项目架构图.png:纯图像的架构图(无文字或少文字)
  • 旧版合同_扫描件.pdf:2010 年扫描合同(发黄、低对比度)

分步实现

步骤1:PDF 表格解析与配置

目标:上传含表格的 PDF,配置表格增强解析,验证表格输出质量。

# table_parse.py - PDF 表格解析fromragflowimportRAGFlow rag=RAGFlow(api_key="xxx",base_url="http://localhost:8080/api/v1")ds=rag.create_dataset(name="测试-表格解析",chunk_method="table")doc=ds.upload_document("test_docs/出差住宿标准表.pdf",parser_config={"parser_id":"pdf","layout_recognize":True,"table_enhance":True,# 关键:启用表格增强"table_output_format":"markdown",# 输出Markdown表格"enable_ocr":False,# 此PDF为文本型"language":"chinese","chunk_method":"table",# 按表格切分})# 等待解析完成importtimefor_inrange(30):time.sleep(3)doc=ds.get_document(doc.id)ifdoc.status=="success":print(f"表格解析完成,共{doc.chunk_count}个切片(每个切片一个表格)")break# 查看表格切片内容chunks=ds.list_chunks(doc.id)fori,chunkinenumerate(chunks[:3]):print(f"\n--- 切片{i+1}(第{chunk.page_num}页) ---")print(chunk.content[:300])

预期切片输出示例:

## 出差住宿费标准 | 城市级别 | 城市 | 住宿费标准(元/晚) | 备注 | |---------|------|------------------|------| | 一线城市 | 北京、上海、广州、深圳 | 500 | 含早餐 | | 二线城市 | 杭州、成都、武汉、南京 | 350 | 含早餐 | | 三线城市 | 其他城市 | 250 | — |

坑点:如果表格横跨两页,合并后的表格可能丢失分页处的分隔线。可在控制台手动合并两个相邻的表格切片。

步骤2:Markdown 文档解析

目标:上传 Markdown 技术文档,验证代码块和层级结构保留效果。

# markdown_parse.py - Markdown 解析doc_md=ds.upload_document("test_docs/API接口文档.md",parser_config={"parser_id":"markdown","chunk_method":"title",# 按标题层级切分(重要!)"chunk_size":1000,"overlap_size":100,"preserve_code_blocks":True,# 保护代码块完整性})# 检查代码块是否完整forchunkinds.list_chunks(doc_md.id):if"```"inchunk.content:open_count=chunk.content.count("```")ifopen_count%2!=0:# 不成对 = 代码块被切断print(f"[WARN] 切片{chunk.id}: 代码块不完整,请手动调整")else:print(f"[OK] 切片{chunk.id}: 代码块完整")

手动验证 Markdown 层级:进入控制台 → 数据集 → 文档详情 → 查看切片列表,检查标题层级是否正确保留。如发现### 子标题被切到了和父标题不同的切片中,手动合并它们。

步骤3:手机拍照图片处理

目标:上传手机拍摄的图片,测试 OCR 效果和预处理选项。

# image_ocr.py - 图片OCR处理doc_photo=ds.upload_document("test_docs/会议室使用规则.jpg",parser_config={"parser_id":"image","enable_ocr":True,"language":"chinese","image_preprocess":{"deskew":True,# 自动倾斜矫正"contrast_enhance":True,# 对比度增强"denoise":True,# 去噪"grayscale":True,# 转灰度},"chunk_method":"naive","chunk_size":500,})

坑点:image_preprocess中的去噪参数如果开太大,会把笔画也当成噪声去掉,尤其是细字体(如仿宋、楷体)。建议先去噪后再 OCR,对比效果。

# 使用 OCR 引擎命令行测试预处理效果(以 PaddleOCR 为例)# 查看 PaddleOCR 的预处理参数:dockerexecragflow-task-executor python3-c" from paddleocr import PaddleOCR ocr = PaddleOCR(lang='ch') result = ocr.ocr('test_docs/会议室使用规则.jpg') for line in result[0]: print(line[1][0], '| 置信度:', line[1][1]) "
步骤4:纯图像的场景描述生成

目标:对架构图等无文字图片,启用多模态描述生成。

# vision_description.py - 多模态图片描述# 注意:此功能需要配置多模态模型(如 GPT-4V、Gemini Vision)# 在「系统设置」→「模型供应商」中先添加 Vision 模型doc_diagram=ds.upload_document("test_docs/项目架构图.png",parser_config={"parser_id":"image","enable_ocr":True,# 提取图中文字(如有)"enable_vision":True,# 启用多模态描述"vision_model":"gpt-4-vision",# 多模态模型"vision_prompt":"请用中文描述这张图中展示的架构。包括:1)主要模块 2)模块间的关系 3)数据流向。","vision_max_tokens":400,})
步骤5:综合验证——复杂文档问答测试

目标:用综合测试问题验证表格、Markdown、图片三类文档的检索与问答效果。

# comprehensive_test.py - 综合验证test_cases=[# 表格类问题("在上海出差,住宿费标准是多少?","table",["500","上海"]),("二线城市的住宿标准?","table",["350"]),# Markdown 技术文档类问题("怎么用SDK创建一个数据集?","markdown",["create_dataset","RAGFlow"]),("createDataset接口的必填参数有哪些?","markdown",["name","必填"]),# 图片 OCR 类问题("会议室使用时间是几点到几点?","image",["会议室","时间"]),("会议室预约需要提前多久?","image",["提前"]),]forquestion,doc_type,keywordsintest_cases:response=rag.chat(question=question,dataset_ids=[ds.id],stream=False)hits=[kwforkwinkeywordsifkwinresponse.answer]status="PASS"iflen(hits)>=len(keywords)*0.5else"FAIL"print(f"[{status}] [{doc_type}] Q:{question}")print(f" A:{response.answer[:120]}...")print(f" 命中关键词:{hits}/{keywords}")print()

测试验证

# test_format_quality.py - 多格式解析质量测试importpytestclassTestTableParsing:deftest_table_markdown_output(self):"""验证表格解析输出为 Markdown 格式"""chunks=ds.list_chunks(doc_table.id)table_chunks=[cforcinchunksif"|"inc.content]assertlen(table_chunks)>0,"未检测到表格格式切片"# 检查表格结构完整性(有表头分隔线)forchunkintable_chunks:assert"|---"inchunk.contentor"|--"inchunk.content,\"表格缺少表头分隔线"deftest_table_cell_not_empty(self):"""验证表格单元格非空"""chunks=ds.list_chunks(doc_table.id)forchunkinchunks:if"|"inchunk.content:# 拒绝完全空白的单元格行lines=chunk.content.split("\n")forlineinlines:ifline.startswith("|"):cells=[c.strip()forcinline.split("|")[1:-1]]assertlen(cells)>=2,f"表格行列异常:{line[:50]}"classTestMarkdownParsing:deftest_code_block_preserved(self):"""验证代码块被完整保留"""chunks=ds.list_chunks(doc_md.id)forchunkinchunks:backtick_count=chunk.content.count("```")assertbacktick_count%2==0,\f"代码块不完整:{chunk.content[:80]}..."deftest_heading_hierarchy(self):"""验证标题层级保留"""chunks=ds.list_chunks(doc_md.id)has_h1=any("# "inc.contentforcinchunks)has_h2=any("## "inc.contentforcinchunks)asserthas_h1orhas_h2,"未检测到 Markdown 标题"classTestImageOCR:deftest_chinese_text_detected(self):"""验证图片中检测到中文字符"""importre chunks=ds.list_chunks(doc_photo.id)all_text="".join(c.contentforcinchunks)chinese_chars=len(re.findall(r'[\u4e00-\u9fff]',all_text))assertchinese_chars>5,f"检测到的中文太少:{chinese_chars}个字符"deftest_confidence_threshold(self):"""验证 OCR 置信度可获取"""# 如果有置信度字段...metadata=ds.get_document(doc_photo.id).metadataif"ocr_confidence"inmetadata:assertmetadata["ocr_confidence"]>0.5,\f"OCR 置信度过低:{metadata['ocr_confidence']}"

完整代码清单

Git 仓库:https://github.com/infiniflow/ragflow

路径说明
deepdoc/parser/pdf_parser.pyPDF 解析:表格识别 + OCR
deepdoc/parser/markdown_parser.pyMarkdown 结构解析
deepdoc/parser/image_parser.py图片 OCR + 多模态描述
deepdoc/vision/table_structure.py表格结构识别算法
deepdoc/vision/ocr.pyOCR 引擎封装与预处理

4 项目总结

优点 & 缺点

维度RAGFlowTesseract OCRAzure Form RecognizerGoogle Document AI
表格识别★★★ 结构+合并单元格★☆☆ 无表格结构★★★ 预训练表格模型★★★ 企业级
Markdown 解析★★★ 层级保留+代码块★☆☆ 不支持★☆☆ 不支持★☆☆ 不支持
OCR 预处理★★☆ 基本预处理★★☆ 基本预处理★★★ 自动预处理★★★ 自动预处理
多模态图片★★☆ 需外接模型☆☆☆ 无★★☆ 有限支持★★☆ 有限支持
私有化部署★★★ 完全本地★★★ 完全本地★☆☆ 仅云端★☆☆ 仅云端
低质量图像★★☆ 有限增强★★☆ 有限增强★★★ 强★★★ 强

适用场景

  1. 财务报表知识库:包含大量表格的财务制度、薪资标准、预算表——需开启table_enhance。
  2. 技术文档门户:Markdown 格式的 API 文档、开发指南——需用 Title 切片保留层级。
  3. 纸质制度数字化:贴在墙上的通知、流程图——拍照上传 + OCR + 手动修正低质量切片。
  4. 合同条款查询:扫描合同 PDF——OCR + 表格识别,关键条款手动标注。
  5. 混合格式知识库:同时包含文字、表格、代码、图片的综合文档库——按文件类型分数据集,各自配置。

不适用场景:

  1. 手写笔记识别:潦草手写 OCR 准确率太低(< 30%),不可用于知识库。
  2. 极低质量扫描件:纸张严重破损、文字大部分缺失的文档——OCR 产出无意义碎片。

注意事项

  1. 表格切片大小限制:超大表格(如 50 行 × 20 列的年度预算表)转为 Markdown 后可能超过模型 token 上限。需要按行列拆分为多个子表格。
  2. 代码块和敏感信息:Markdown 文档中的代码示例可能包含 API Key、内网地址——上传前需要做脱敏检查。
  3. 图片预处理性能损耗:deskew+contrast_enhance+denoise三重处理,每张图片增加 2-5 秒处理时间。简单文档可关闭。
  4. 多模态模型的成本:使用 GPT-4V 为每张图生成描述,按图片尺寸计费。1000 张图可能花费几十美元。
  5. 图片格式兼容性:WebP、HEIC、TIFF 等高压缩或专业格式可能需要先转换为 JPEG/PNG 再上传。

常见踩坑经验

故障现象根因解决方法
表格解析后数字和单位分离OCR 将 “500元” 识别为 “500” + “元” 两个框增加 OCR 文本框合并阈值,或在 Prompt 中提示模型关联数字和单位
Markdown 代码块被切成两半Naive 切片在 token 上限处硬切,不识别代码块边界改用 Title 切片方法,或手动合并
手机拍照图片 OCR 全是乱码图片未经预处理,倾斜 30 度还带阴影开启deskew: true+contrast_enhance: true+denoise: true
多模态描述生成失败未在系统设置中配置 Vision 模型,或 API Key 错误检查「系统设置→模型供应商」中的 Vision 模型状态
超大表格解析耗时巨长(> 5 分钟)每个单元格单独做 OCR,50×20=1000 次调用降低表格复杂度(只保留关键行列),或事后手动编辑

思考题

  1. 一份 Markdown 技术文档中包含 20 个代码示例(Python/JavaScript/Shell)。如果某代码示例中恰好包含了一个 API Key 字符串(api_key = "sk-xxxx"),目前 RAGFlow 不会自动检测并脱敏。请设计一个上传前的文档安全扫描机制,自动发现并脱敏敏感信息后再上传。

  2. 公司的财务部每个月会导出一份新的 Excel 薪资标准表(文件名不变,内容更新)。如果直接重新上传并解析,新旧两份记录会并存,导致检索出两个版本的薪资数据(可能不同)。请设计一个"版本化文档管理"方案,确保检索始终返回最新版本,同时保留历史版本可追溯。

(答案提示见第11章末尾或附录 D。)

延伸阅读与资源

10倍开发者的 Dify 魔法书:从零构建全栈 AI 应用
后端工程师转型AI第一课-Ollama 与私有化大模型实战
大型语言模型(LLM) vLLM 高性能推理落地实战
Agent开发之LlamaIndex 实战修炼与源码进阶
大语言模型Transformers 实战修炼与源码剖析

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询