犀牛鸟 2026 研究笔记 estelledc.github.io

RAGFlow 深度解读

“检索之前先把文档吃透”——深度文档理解驱动的 RAG 引擎


一句话定位

83K star 的 RAG 引擎,核心差异化在 DeepDoc 文档深度解析引擎——对 PDF 表格、扫描件 OCR、嵌套表格等 20+ 格式做专门处理,解决”垃圾进垃圾出”的文档质量根源问题。


调研元信息

项目
调研日期 2026-06-23
仓库 infiniflow/ragflow
Stars ~83K
主语言 Python(后端核心)/ React+TypeScript(前端)
代码量 ~2,000+ Python 文件(后端核心)+ 前端
许可证 Apache-2.0
犀牛鸟状态 D 线(RAG)研究项目,非直接贡献目标

设计哲学

核心洞察:文档理解决定 RAG 天花板

RAGFlow 的核心洞察是:RAG 系统的瓶颈往往不在检索算法,而在文档解析质量。再好的向量检索,如果把表格数据切碎了、把图片里的文字丢了,召回的就是残缺信息。

类比:其他 RAG 系统处理文档像”用吸管喝珍珠奶茶”——把所有内容当一股液体吸进来,珍珠(表格数据)、茶(正文)、奶泡(图片说明)全混在一起,检索时自然分不清。RAGFlow 的 DeepDoc 像”先用筛子把珍珠、茶、奶泡分开”,每种成分用不同方式处理——表格保留行列结构,正文按语义分段,图片先 OCR 再提取文字。

这个设计解决了企业场景中最痛的问题:一份年报 PDF 里的财务表格,如果被当成纯文本按 500 字切分,”营收”可能在一个 chunk,”23.5 亿”在另一个 chunk,检索时答案被撕裂。DeepDoc 先做版面分析识别出表格区域,保留行列关系后整体存入一个 chunk,检索质量从源头保证。

“向上游要质量”的思维

这是一种”向上游要质量”的思维——与其在检索和 Rerank 阶段做复杂补救,不如在解析阶段就把文档结构理清楚。这和 WeKnora “多路检索互补”的思路正好互补:

两种思路不矛盾。实际上,RAGFlow 的 DeepDoc + WeKnora 的三路检索是理想的组合——前端保证输入质量,后端保证检索质量。

设计取舍

RAGFlow 的设计是有意取舍的结果:


核心架构详解

全局架构图

                              ┌─────────────────────────────────────────────┐
                              │              RAGFlow 系统全景                 │
                              └──────────────────┬──────────────────────────┘
                                                 │
              ┌──────────────────────────────────┼──────────────────────────────────┐
              │                                  │                                  │
     ┌────────▼────────┐              ┌──────────▼──────────┐           ┌───────────▼──────────┐
     │   文档摄入管线    │              │    检索管线           │           │   对话/Agent 管线     │
     │  Ingest Pipeline │              │ Retrieval Pipeline  │           │  Conversation/Agent  │
     └────────┬────────┘              └──────────┬──────────┘           └───────────┬──────────┘
              │                                  │                                  │
     ┌────────┼────────────┐          ┌──────────┼──────────┐           ┌───────────┼──────────┐
     │        │            │          │          │          │           │           │          │
  格式适配  DeepDoc      模板分块    BM25      向量检索    Rerank     多轮对话   引用追踪   Agent 编排
  Parser   Engine     Template     关键词     Vector     精排        Multi-   Citation  Agent
  20+格式  深度解析     Chunker     检索       检索       可选        turn                Graph
     │        │            │          │          │          │           │           │          │
     └────────┼────────────┘          └──────────┼──────────┘           └───────────┼──────────┘
              │                                  │                                  │
              │                     ┌────────────▼────────────┐                      │
              │                     │   权重融合 (可配置)       │                      │
              └─────────────────────│  w_BM25 + w_Vector      │◄─────────────────────┘
                                    └────────────┬────────────┘
                                                 │
                                    ┌────────────▼────────────┐
                                    │   LLM 生成 + 引用溯源    │
                                    │  (chunk 来源标注)        │
                                    └─────────────────────────┘

四大子系统职责

子系统 职责 核心模块
文档摄入管线 把各种格式的”脏文档”变成结构化 chunk 格式适配器 + DeepDoc + 模板分块
检索管线 双路混合检索 + Rerank BM25 + 向量 + 权重融合 + Rerank
对话/Agent 管线 多轮对话 + 引用追踪 + Agent 编排 多轮上下文管理 + 引用溯源 + Graph Agent
基础设施 向量数据库 + 任务队列 + API/前端 Milvus/ES + Redis/Celery + Flask/React

DeepDoc 深度文档理解引擎

DeepDoc 是 RAGFlow 的核心差异化能力,也是整个项目最有技术深度的模块。理解了 DeepDoc,就理解了 RAGFlow 为什么能在文档解析赛道上领先。

为什么需要深度文档理解?

传统 RAG 系统对文档的处理流程是:读取文本 → 按固定长度切分 → 向量化。这个流程对结构简单的纯文本文档(如 Markdown 笔记)够用,但对企业场景中的复杂文档(年报 PDF、合同扫描件、技术手册)存在严重问题:

问题一:表格数据被撕裂。一份年报 PDF 里的财务报表,包含跨行跨列的复杂表格。按固定长度切分后,表头和数据行可能分属不同 chunk,向量检索召回的数据行缺少列名上下文,LLM 无法理解数字含义。

问题二:图片文字丢失。扫描件 PDF 中的文字以图片形式存在,纯文本提取完全拿不到内容。一份 50 页的扫描合同,传统方式只能提取到 OCR 失败的乱码或空白。

问题三:版面信息缺失。PDF 页面中标题、段落、表格、图片、页眉页脚混排。纯文本提取丢失了所有版面信息——无法区分标题和正文,无法识别表格边界,无法判断图片与哪段文字关联。

问题四:公式无法识别。学术论文中的数学公式在纯文本提取后变成一堆无意义的符号序列,丧失语义。

RAGFlow 的 DeepDoc 引擎就是为了系统性地解决这四个问题。

DeepDoc 引擎内部架构

文档输入(PDF / Word / Excel / PPT / Markdown / HTML / 图片...)
  │
  ├─ 格式适配层(Parser Router)
  │     └─ 根据文件后缀选择对应解析器
  │     └─ PDF → pdf_parser, Word → docx_parser, ...
  │
  └─ DeepDoc 核心处理管线
        │
        ├─ Step 1: 版面分析(Layout Analysis)
        │     └─ 输入:PDF 页面图像
        │     └─ 输出:每个区域的类型标注(文本/表格/图片/标题/页眉页脚)
        │     └─ 模型:基于深度学习的目标检测模型
        │
        ├─ Step 2: 文本提取(Text Extraction)
        │     ├─ 对文本区域:直接提取 PDF 内嵌文本
        │     └─ 对图片/扫描区域:调用 OCR 引擎
        │
        ├─ Step 3: 表格结构恢复(Table Structure Recognition)
        │     └─ 输入:表格区域图像
        │     └─ 输出:行列关系 + 跨行跨列信息
        │     └─ 输出格式:HTML table 或结构化 JSON
        │
        ├─ Step 4: 公式提取(Formula Extraction)
        │     └─ 识别数学公式区域
        │     └─ 输出:LaTeX 表示
        │
        └─ Step 5: 结构化内容组装
              └─ 按版面顺序组装各区域内容
              └─ 保留区域间的层级关系(标题→段落→子段落)
              └─ 输出:结构化文档对象

版面分析(Layout Analysis)深度解析

版面分析是 DeepDoc 的第一步,也是最关键的一步——它决定了后续所有处理步骤的输入质量。

核心任务:给定一个 PDF 页面图像,识别出页面中每个区域的类型和边界。

检测的区域类型

区域类型 说明 处理方式
文本(Text) 正文段落 直接提取文本,按段落分块
标题(Title) h1/h2/h3 层级标题 作为分块边界标记
表格(Table) 包含行列结构的数据区 调用表格结构恢复模块
图片(Figure) 插图、图表 OCR 提取文字说明 + 图片描述
页眉(Header) 页码、章节标记 通常过滤掉
页脚(Footer) 页码、版权信息 通常过滤掉
脚注(Footnote) 底部注释 保留,关联到引用位置
列表(List) 有序/无序列表 保持列表完整性

技术实现:RAGFlow 使用基于深度学习的目标检测模型(类似 YOLO / Mask R-CNN 的架构)来做版面分析。模型在大量标注了区域类型的文档数据集上训练,能够识别不同排版风格下的区域边界。

类比:版面分析像”看一眼就知道这页纸上哪里是标题、哪里是正文、哪里是表格”——你不需要逐字阅读,只需要看排版就能判断。DeepDoc 的版面分析模型就是在模拟这个”一眼看排版”的认知过程。

版面分析的难点

难点一:复杂排版。双栏排版、图文混排、表格内嵌图片——这些情况下区域的边界不清晰。双栏排版中左栏末尾和右栏开头在空间上不相邻,但在语义上是连续的。

难点二:表格边界识别。有些表格没有明显的边框线,只靠对齐和间距来暗示行列关系。版面分析需要正确识别出”这是一个表格”而不仅仅是”这是一段文本”。

难点三:跨页元素。一个表格可能横跨两页,版面分析需要把两个页面上的表格片段关联起来。

OCR 管线深度解析

当版面分析识别出图片区域或扫描件时,DeepDoc 会调用 OCR 引擎提取文字。

OCR 处理流程

输入图像
  │
  ├─ 1. 图像预处理
  │     └─ 去噪(高斯模糊 / 中值滤波)
  │     └─ 倾斜校正(检测文本行角度,旋转校正)
  │     └─ 二值化(灰度 → 黑白,增强对比度)
  │
  ├─ 2. 文本检测(Text Detection)
  │     └─ 检测图像中所有文字区域的边界框
  │     └─ 模型:DBNet / PSENet 等场景文字检测模型
  │
  ├─ 3. 文本识别(Text Recognition)
  │     └─ 对每个检测到的文字区域,识别具体文字内容
  │     └─ 模型:CRNN / SVTR / TrOCR 等识别模型
  │     └─ 支持中英文混合识别
  │
  ├─ 4. 后处理
  │     └─ 拼写纠错(针对 OCR 常见错误)
  │     └─ 文本行排序(按照阅读顺序排列)
  │     └─ 置信度过滤(低置信度结果标记待人工校验)
  │
  └─ 输出:提取的文字内容 + 位置信息

OCR 的特殊挑战

挑战一:低质量扫描件。旧文档的扫描件可能模糊、有噪点、墨迹不均匀。DeepDoc 的图像预处理步骤尝试缓解这些问题,但极端低质量的扫描件仍然可能产生大量 OCR 错误。

挑战二:中英文混排。合同、技术文档经常出现中英文混排——一段中文中夹杂英文术语、人名、编号。OCR 引擎需要在中英文之间正确切换识别模式。RAGFlow 的 OCR 模型针对中英文混合场景做了专门优化。

挑战三:手写文字。手写体识别是 OCR 中最难的子问题之一,目前 RAGFlow 的 OCR 主要针对印刷体,手写体识别率较低。

挑战四:印章遮挡。中国合同文档中常见红色印章覆盖在文字上方,影响 OCR 识别。DeepDoc 有印章检测和去除的预处理步骤。

OCR 与简单文本提取的本质区别

简单文本提取(如 PyPDF2、pdfplumber)只读取 PDF 内嵌的文本层。对于”原生 PDF”(由 Word/LaTeX 生成的),这种方法效果不错。但对于”扫描件 PDF”(由扫描仪生成的图片 PDF),内嵌文本层可能:

DeepDoc 的 OCR 管线在简单文本提取失败时自动接管,确保即使是扫描件也能获得高质量的文本内容。

表格结构恢复深度解析

表格结构恢复是 DeepDoc 最有价值也最技术密集的模块。

核心任务:给定一个表格区域的图像,恢复出完整的行列关系,包括跨行跨列信息。

为什么表格处理这么难?

日常类比:你看到一张 Excel 截图,人眼很容易看出”第一行是表头,第二行第三行是数据,’合计’跨了三列”。但计算机看到的是一堆像素——它需要从像素中推断出哪些像素组成单元格、哪些单元格属于同一行、哪些单元格跨了多列。

传统方法(如 pdfplumber、Camelot)基于线条检测——寻找水平线和垂直线来推断行列边界。但这种方法在以下场景完全失效:

RAGFlow 的做法是使用深度学习模型直接从图像预测表格结构,不依赖线条检测。

表格结构恢复流程

表格区域图像
  │
  ├─ Step 1: 表格检测
  │     └─ 确认区域确实是表格(而非图片或文本)
  │     └─ 输出:表格边界框
  │
  ├─ Step 2: 行列结构预测
  │     └─ 模型预测每个单元格的行列位置
  │     └─ 输出:N×M 的网格结构
  │
  ├─ Step 3: 跨行跨列识别
  │     └─ 识别哪些单元格跨了多行或多列
  │     └─ 输出:每个单元格的 (row_start, row_end, col_start, col_end)
  │
  ├─ Step 4: 单元格内容提取
  │     └─ 对每个单元格区域做 OCR 或文本提取
  │     └─ 输出:每个单元格的文字内容
  │
  └─ Step 5: 结构化输出
        └─ 组装成 HTML table
        └─ 或者输出 JSON 结构
        └─ 保留完整的行列关系

表格提取的具体示例

原始 PDF 中的一个表格:

┌──────────┬──────────┬───────────────────────┐
│ 指标     │ 2024 年  │ 2023 年               │
├──────────┼──────────┼──────────┬────────────┤
│          │          │ 上半年   │ 下半年     │
├──────────┼──────────┼──────────┼────────────┤
│ 营收     │ 100 亿   │ 40 亿    │ 60 亿      │
│ 净利润   │ 20 亿    │ 8 亿     │ 12 亿      │
└──────────┴──────────┴──────────┴────────────┘

传统文本提取可能输出:

指标 2024年 2023年 上半年 下半年 营收 100亿 40亿 60亿 净利润 20亿 8亿 12亿

所有文字混在一起,行列关系完全丢失。如果按 500 字切分,”营收”和”100 亿”可能分属不同 chunk。

DeepDoc 表格结构恢复后输出(HTML):

<table>
  <tr><td>指标</td><td>2024 年</td><td colspan="2">2023 年</td></tr>
  <tr><td></td><td></td><td>上半年</td><td>下半年</td></tr>
  <tr><td>营收</td><td>100 亿</td><td>40 亿</td><td>60 亿</td></tr>
  <tr><td>净利润</td><td>20 亿</td><td>8 亿</td><td>12 亿</td></tr>
</table>

这个 HTML 表格保留了完整的行列关系——检索时”营收”和”100 亿”始终在一起,LLM 可以准确回答”2024 年营收是多少”。

表格识别的难点

难点一:跨行跨列。上述示例中”2023 年”跨了两列(colspan=2)。深度学习模型需要正确预测这种跨越关系。

难点二:嵌套表格。某些复杂文档中存在表格内嵌套子表格的情况,层级关系复杂。

难点三:表格内图片。某些表格的单元格中包含小图标或 sparkline(迷你图表),需要特殊处理。

公式提取

学术论文和技术文档中经常出现数学公式。公式提取的挑战在于:

RAGFlow 的公式提取流程:

1. 版面分析识别公式区域
2. 公式识别模型将图像转为 LaTeX
3. LaTeX 作为 chunk 内容的一部分保留
4. 检索时 LaTeX 与自然语言混合检索

这使得 RAGFlow 在学术论文场景下有显著优势——用户问”傅里叶变换的公式是什么”,RAGFlow 能召回包含完整 LaTeX 公式的 chunk,而不是一堆乱码符号。

DeepDoc 与简单文本提取的本质区别

维度 简单文本提取(PyPDF2 等) DeepDoc 深度解析
表格 文字堆叠,行列关系丢失 保留完整行列结构(HTML table)
图片文字 完全丢失 OCR 提取
扫描件 空白或乱码 深度学习 OCR
版面信息 丢失 区域类型标注(标题/段落/表格/图片)
公式 乱码符号 LaTeX 表示
跨页表格 截断 自动关联
页眉页脚 混入正文 过滤
处理速度 极快(毫秒级/页) 慢(秒~分钟级/页)
适用场景 简单纯文本文档 企业复杂文档

模板驱动分块

核心思想:不同文档类型需要不同分块策略

RAGFlow 的第二个核心创新是模板驱动分块。传统 RAG 系统对所有文档使用同一种分块策略(通常是固定长度 + overlap),但不同类型的文档结构差异巨大——学术论文和法律法规的分块逻辑不可能一样。

类比:你去裁缝店做衣服。如果裁缝对所有人都用同一套模板——不管你是高矮胖瘦——做出来的衣服大概率不合身。RAGFlow 的做法是准备了多种”衣服模板”:学术论文有论文模板、法律文书有法规模板、产品手册有手册模板。每种模板根据文档的结构特征定义不同的分块逻辑。

内置知识库模板

RAGFlow 为不同文档类型预置了分块模板:

模板名称 适用文档类型 分块逻辑 特殊处理
通用(General) 混合文档 按段落 + 语义边界切分 无特殊处理
问答(Q&A) FAQ 文档、客服话术 每个问答对作为一个 chunk 问题和答案绑定,不拆分
手册(Manual) 产品手册、操作指南 按章节层级(h1/h2/h3)切分 保留操作步骤的完整性
论文(Paper) 学术论文 摘要/引言/方法/实验/结论分别切分 公式区域保留 LaTeX
书籍(Book) 长篇书籍 按章节 + 小节切分 章节摘要自动生成
法律(Law) 法律法规 按条款切分 条款编号与正文绑定
演示(Presentation) PPT/Keynote 每页幻灯片作为一个 chunk 图片文字 OCR + 演讲者备注
表格(Table) Excel/CSV 每行/每条记录作为一个 chunk 列名作为上下文保留
图片(Picture) 图片集合 每张图片 OCR 作为一个 chunk 图片描述生成

Q&A 模板深度解析

Q&A 模板是最能体现”模板驱动”价值的案例。

问题:很多企业知识库的核心内容是 FAQ(常见问题解答)文档。一个 FAQ 条目包含一个问题和对应的答案,二者构成不可分割的语义单元。

传统分块的问题:按 500 字切分,一个长答案可能被切成两半——前半部分在一个 chunk,后半部分在另一个 chunk。检索时只召回了前半部分,LLM 给出不完整的答案。更糟的情况是,问题在一个 chunk 的末尾,答案在下一个 chunk 的开头——检索时可能只召回问题没召回答案,或只召回答案没召回问题。

Q&A 模板的处理

输入 FAQ 文档:
  Q: 如何重置密码?
  A: 步骤一:点击登录页面的"忘记密码"链接。
     步骤二:输入注册时使用的邮箱地址。
     步骤三:查收重置密码的邮件,点击链接。
     步骤四:设置新密码并确认。

Q&A 模板分块:
  Chunk 1: {
    "question": "如何重置密码?",
    "answer": "步骤一:点击登录页面的"忘记密码"链接。步骤二:输入注册时使用的邮箱地址。步骤三:查收重置密码的邮件,点击链接。步骤四:设置新密码并确认。"
  }
  → 整个问答对作为一个不可分割的 chunk

Q&A 模板还支持多种 FAQ 格式的自动识别

RAGFlow 会自动检测 FAQ 文档的格式并选择对应的解析逻辑。

法律模板深度解析

法律文书的分块逻辑与通用文档完全不同:

法律模板的处理:

输入法律文档:
  第三十二条  有下列情形之一的,用人单位可以解除劳动合同:
    (一)在试用期间被证明不符合录用条件的;
    (二)严重违反用人单位的规章制度的;
    (三)严重失职,营私舞弊,给用人单位造成重大损害的;
    ...

法律模板分块:
  Chunk 1: {
    "article": "第三十二条",
    "content": "有下列情形之一的,用人单位可以解除劳动合同:\n(一)在试用期间被证明不符合录用条件的;\n(二)严重违反用人单位的规章制度的;\n(三)严重失职,营私舞弊,给用人单位造成重大损害的;\n...",
    "references": ["第十五条"]  // 自动识别的引用关系
  }

条款编号与正文绑定,引用关系被提取出来用于后续的知识图谱构建。

论文模板深度解析

学术论文有非常明确的结构:摘要(Abstract)→ 引言(Introduction)→ 相关工作(Related Work)→ 方法(Method)→ 实验(Experiment)→ 结论(Conclusion)。

论文模板按这些结构切分,每个章节作为独立 chunk。特殊处理包括:

模板选择的自动化

RAGFlow 支持两种模板选择方式:

方式一:用户手动指定。创建知识库时选择对应的模板类型。

方式二:自动检测。RAGFlow 根据文档的特征自动推断最合适的模板:

自动检测逻辑:
  1. 文件后缀 → 初步筛选
     PDF → 可能是论文/法律/通用
     DOCX → 可能是手册/通用
     XLSX → 表格模板
     PPTX → 演示模板

  2. 内容特征 → 精确匹配
     包含 "第X条" → 法律模板
     包含 "Abstract" "Introduction" → 论文模板
     包含 "Q:" "A:" → Q&A 模板
     包含 "步骤一" "步骤二" → 手册模板

  3. 置信度不足时 → 回退到通用模板

检索管线

双路混合检索

RAGFlow 的检索管线是 BM25 + 向量双路混合,这是 RAG 领域的标准做法。与 WeKnora 的三路检索(BM25 + 向量 + 知识图谱)相比少了一路知识图谱,但设计上更简洁。

检索流程

用户查询 q
  │
  ├─ BM25 关键词检索
  │     └─ 对查询做分词
  │     └─ 在倒排索引中查找匹配文档
  │     └─ 返回 top-K_BM25 结果
  │
  ├─ 向量语义检索
  │     └─ 对查询做 embedding
  │     └─ 在向量库中做 ANN 搜索
  │     └─ 返回 top-K_Vector 结果
  │
  └─ 权重融合
        └─ final_score = w × vector_score + (1-w) × bm25_score
        └─ w 可配置(默认 0.7)
        └─ 按融合分数排序,返回 top-N

权重融合 vs RRF 融合

RAGFlow 使用简单权重融合,WeKnora 使用 RRF 融合。两者的核心区别:

权重融合(RAGFlow)

final_score = w × vector_score + (1-w) × bm25_score

直接对不同路的分数做加权平均。问题:BM25 分数和向量余弦相似度不在同一量纲——BM25 分数范围可能是 [0, 30],余弦相似度范围是 [0.5, 0.99]。直接加权的结果被 BM25 的绝对值主导。

RAGFlow 的解决方案是对各路分数做归一化(min-max normalization),将分数映射到 [0, 1] 区间后再加权。但这引入了新的问题:归一化方式的选择本身就是一个超参数,不同归一化方式在不同数据集上表现差异大。

RRF 融合(WeKnora)

\[\text{RRF}_{\text{score}}(d) = \sum_i \frac{1}{k + rank_i(d)}\]

完全忽略分数的绝对值,只看排名。排名天然是归一化的——第 1 名就是第 1 名,不管分数是 0.99 还是 25.7。这消除了量纲不一致的问题。

结论:RRF 融合在理论上更优雅、在实践中更鲁棒。但 RAGFlow 选择权重融合也有其理由——实现简单、参数可解释性强(”语义权重 70%、关键词权重 30%”比”k=60”更容易向用户解释)、在大多数场景下效果差异不大。

Rerank 精排

RAGFlow 支持可选的 Rerank 步骤,使用 Cross-Encoder 模型对融合后的 top-N 结果做精排。

RAGFlow 的 Rerank vs WeKnora 的复合 Rerank

维度 RAGFlow WeKnora
模型 单 Cross-Encoder 模型 Cross-Encoder 模型
信号数 1(模型分) 3(0.6 模型分 + 0.3 基础分 + 0.1 来源分)
鲁棒性 中(模型失准无兜底) 高(基础分和来源分兜底)
可选性 可选(可跳过) 必须
来源感知 有(source_credibility)

RAGFlow 的 Rerank 是单模型打分——如果 Rerank 模型对某些专业术语判断失误,没有其他信号兜底。WeKnora 的三信号复合 Rerank 在这方面更鲁棒。

但 RAGFlow 的设计取舍是合理的:文档解析质量已经从源头保证了 chunk 质量,Rerank 的边际收益相对较小。与其在 Rerank 上投入工程资源,不如继续打磨 DeepDoc。


Graph RAG 实现

从文档到知识图谱

RAGFlow 在 2025 年引入了 Graph RAG 功能,支持从文档中自动构建知识图谱,并将其作为检索增强的额外信号。这是 RAGFlow 从”纯文档解析 RAG”向”知识图谱增强 RAG”演进的重要一步。

Graph RAG 的构建流程

文档 chunks
  │
  ├─ Step 1: 实体抽取(Entity Extraction)
  │     └─ 使用 LLM 从每个 chunk 中提取命名实体
  │     └─ 实体类型:人物/组织/地点/概念/产品/事件...
  │     └─ 输出:每个 chunk 的实体列表
  │
  ├─ Step 2: 关系抽取(Relation Extraction)
  │     └─ 使用 LLM 识别实体间的关系
  │     └─ 关系类型:属于/创建/位于/包含/影响...
  │     └─ 输出:(实体A, 关系, 实体B) 三元组列表
  │
  ├─ Step 3: 实体消歧(Entity Resolution)
  │     └─ 合并指代同一实体的不同表述
  │     └─ "腾讯" = "Tencent" = "腾讯公司"
  │     └─ 使用语义相似度 + 规则匹配
  │
  ├─ Step 4: 图谱存储
  │     └─ 存入图数据库(Neo4j / NetworkX)
  │     └─ 实体为节点,关系为边
  │
  └─ Step 5: 图谱索引
        └─ 建立实体 → chunk 的倒排索引
        └─ 预计算常用遍历路径

LLM 驱动的实体关系抽取

RAGFlow 的 Graph RAG 和 WeKnora 的 PMI 知识图谱采用了完全不同的构建策略:

维度 RAGFlow Graph RAG WeKnora PMI 图谱
抽取方式 LLM 驱动(GPT-4/Claude 等大模型) 统计驱动(PMI 点互信息)
实体质量 高(理解语义,能识别隐含实体) 中(依赖共现频率,可能遗漏低频实体)
关系质量 高(理解语义,能识别复杂关系) 低(只知道”有关联”,不知道”什么关系”)
构建成本 高(每次抽取消耗 LLM token) 低(纯统计计算,无需 LLM 调用)
构建速度 慢(受 LLM API 限流) 快(本地计算)
可扩展性 受 LLM 成本限制 随文档量线性增长
适用场景 小规模高质量知识库 大规模文档库

RAGFlow Graph RAG 的 Prompt 设计(伪代码):

ENTITY_EXTRACTION_PROMPT = """
从以下文本中提取所有命名实体和它们之间的关系。

文本:{chunk_text}

请以 JSON 格式输出:
{{
  "entities": [
    {{"name": "实体名", "type": "人物/组织/概念/..."}},
    ...
  ],
  "relations": [
    {{"source": "实体A", "relation": "关系类型", "target": "实体B"}},
    ...
  ]
}}
"""

这个 Prompt 让 LLM 同时完成实体抽取和关系抽取,一次调用拿到所有信息。代价是每次调用都消耗 LLM token——如果知识库有 10,000 个 chunk,每个 chunk 一次 LLM 调用,成本可能达到数百美元。

Graph RAG 检索模式

RAGFlow 的 Graph RAG 支持两种检索模式:

模式一:实体扩展检索。从查询中提取实体,在图谱中找到关联实体,用关联实体扩展查询。

查询:"RAGFlow 的文档解析用了什么技术?"
  → 提取实体:["RAGFlow", "文档解析"]
  → 图谱遍历:RAGFlow --使用--> DeepDoc
              文档解析 --包含--> 版面分析
              文档解析 --包含--> OCR
              文档解析 --包含--> 表格识别
  → 扩展查询:["RAGFlow", "文档解析", "DeepDoc", "版面分析", "OCR", "表格识别"]
  → 用扩展后的查询做向量检索 → 召回更全面

模式二:子图检索。从查询实体出发,提取相关子图,将子图结构作为额外上下文注入 LLM。

查询:"DeepDoc 和 WeKnora IMA 的区别?"
  → 提取实体:["DeepDoc", "WeKnora IMA"]
  → 图谱遍历:找到 DeepDoc 和 WeKnora IMA 之间的关联路径
  → 提取子图:包含两个实体的关联节点和边
  → 将子图信息作为额外上下文注入 LLM prompt

Graph RAG 的局限

RAGFlow 的 Graph RAG 目前仍处于较早阶段,有以下局限:

局限一:构建成本高。LLM 驱动的实体关系抽取成本随文档量线性增长,大规模知识库的图谱构建成本可能不可接受。

局限二:图谱质量依赖 LLM。LLM 的抽取结果不稳定——同样的文本,不同时间调用可能产出不同的实体和关系。图谱质量的一致性难以保证。

局限三:增量更新困难。文档更新时,需要重新抽取实体关系并合并到现有图谱中。实体消歧在增量场景下更加困难——新抽取的”腾讯”和图谱中已有的”腾讯公司”是否是同一实体?

局限四:与 WeKnora 图谱相比深度不足。WeKnora 的 PMI 图谱虽然关系语义较弱(只知道”有关联”),但构建成本低、可扩展性好、增量维护简单。RAGFlow 的 LLM 驱动图谱虽然关系语义更强,但成本和可维护性是短板。


多轮对话与引用追踪

多轮对话机制

RAGFlow 支持基于知识库的多轮对话,核心是上下文管理——将之前的对话历史作为额外上下文注入当前查询。

多轮对话流程

用户第 1 轮:"RAGFlow 支持哪些文件格式?"
  → 检索知识库 → 召回相关 chunk → 生成答案 + 引用来源

用户第 2 轮:"它和 Dify 在文档解析上有什么区别?"
  → 上下文管理:
     ├─ 当前查询:"它和 Dify 在文档解析上有什么区别?"
     ├─ 对话历史:"RAGFlow 支持哪些文件格式?" + 答案
     └─ 指代消解:"它" → "RAGFlow"
  → 改写查询:"RAGFlow 和 Dify 在文档解析上有什么区别?"
  → 检索知识库 → 生成答案 + 引用来源

指代消解是多轮对话的核心技术难题——用户说”它”,系统需要知道”它”指代的是上一轮对话中的哪个实体。RAGFlow 使用 LLM 做指代消解:将对话历史和当前查询一起送给 LLM,让 LLM 输出消解后的查询。

引用追踪(Citation)

RAGFlow 的另一个亮点功能是引用追踪——生成的答案中每个断言都标注了来源 chunk。

引用追踪的实现

1. 检索阶段:记录每个 chunk 的来源文档、页码、位置
2. 生成阶段:在 Prompt 中要求 LLM 标注引用来源
   Prompt: "请基于以下参考内容回答问题。在回答中,用 [1] [2] 标注每个信息的来源。"
3. 后处理:将 [1] [2] 映射到具体的 chunk 信息
   [1] → 来源: 年报2024.pdf, 第 12 页, 第 3 段
   [2] → 来源: 财务报告.docx, 第 5 页, 表格 2
4. 前端展示:答案中的引用标注可点击,跳转到原文对应位置

引用追踪的价值在于可验证性——用户可以点击引用标注查看原文,确认答案是否准确。这在企业场景中特别重要——财务数据、法律条文、技术规范等不能容忍幻觉的场景,引用追踪提供了”交叉验证”的能力。


Agent 编排

RAGFlow 提供了基于图的 Agent 编排能力,允许用户定义多步骤的检索-推理流程。

Agent 编排架构

用户查询
  │
  └─ Agent Graph
       │
       ├─ Start Node: 接收用户查询
       │
       ├─ Retrieval Node: 调用知识库检索
       │     └─ 可配置检索参数(知识库、top-K、权重)
       │
       ├─ LLM Node: 调用 LLM 生成/推理
       │     └─ 可配置模型、Prompt、温度
       │
       ├─ Conditional Node: 条件判断
       │     └─ "检索结果是否充分?" → 是/否分支
       │
       ├─ Rewrite Node: 查询改写
       │     └─ 当检索不充分时改写查询重新检索
       │
       └─ End Node: 输出最终答案

RAGFlow 的 Agent 编排相比 Dify 的可视化 Workflow 更轻量——节点类型较少,但与 RAG 的集成更紧密。适合定义”检索-判断-再检索-生成”这类 RAG 专用的推理流程。

与 WeKnora 的对比

维度 RAGFlow Agent WeKnora Agent Dify Workflow
编排方式 Graph 定义 API/MCP 被外部调用 可视化 DAG
节点类型 检索/LLM/条件/改写 无内建编排 丰富(30+ 节点类型)
RAG 集成 原生深度集成 N/A 知识检索节点
适合场景 RAG 专用的多步推理 被其他 Agent 框架调用 通用 LLM 应用

与竞品的差异化矩阵

能力维度 RAGFlow WeKnora Dify AnythingLLM FastGPT
文档解析深度 极高(DeepDoc) 高(IMA)
支持格式数 20+ 15+ 10+ 8+ 10+
表格识别 深度(行列+跨行跨列) 深度(IMA) 基础 基础 基础
OCR 能力 深度学习 OCR IMA OCR 插件 基础 基础
检索路数 2 路(BM25+向量) 3 路(BM25+向量+图谱) 2 路(BM25+向量) 1 路(向量) 2 路(向量+$text)
融合策略 权重融合 RRF(k=60) 加权融合 单参数加权
知识图谱 LLM 驱动(实验性) PMI 自动构建
Rerank 单模型 三信号复合(0.6/0.3/0.1) 单模型 单参数
分块策略 模板驱动(9 种模板) 4 级自适应 固定大小 固定大小 固定大小
引用追踪 有(chunk 级溯源) 无原生 基础
Agent 编排 Graph-based API/MCP 可视化 DAG 简单 可视化
向量库支持 4+(Milvus/ES/Chroma/Qdrant) 10 种 6+ 11 1-2
开发语言 Python Go TS/Python Node.js TypeScript
部署门槛 高(4C8G+) 中(2C4G+) 中(2C4G+) 极低(1C2G)
社区规模 83K star 14.3K star 144K star 61K star 28K star

RAGFlow 的竞争身位

核心结论:RAGFlow 在”文档解析”这个维度上是赛道第一,但这个领先不是全方位的——在”检索质量”和”平台生态”维度上分别弱于 WeKnora 和 Dify。


源码关键实体索引

Python 模块 / 文件 核心功能 关键类/函数
deepdoc/parser/ 格式适配器路由 ParserFactory, get_parser()
deepdoc/parser/pdf_parser.py PDF 深度解析核心 PDFParser, parse(), 调用版面分析+OCR+表格
deepdoc/parser/docx_parser.py Word 文档解析 DocxParser, 提取段落/表格/图片
deepdoc/parser/excel_parser.py Excel 解析 ExcelParser, 按行提取+列名保留
deepdoc/parser/ppt_parser.py PPT 解析 PptParser, 每页提取+OCR
deepdoc/vision/layout.py 版面检测模型 LayoutRecognizer, detect()
deepdoc/vision/ocr.py 深度学习 OCR OCRRecognizer, recognize()
deepdoc/table/table_structure.py 表格结构恢复 TableStructureRecognizer, recognize()
deepdoc/formula/ 公式提取与 LaTeX 转换 FormulaRecognizer, to_latex()
rag/retrieval/hybrid.py BM25 + 向量混合检索 HybridRetriever, retrieve()
rag/retrieval/bm25.py BM25 关键词检索 BM25Retriever, search()
rag/retrieval/vector.py 向量语义检索 VectorRetriever, search()
rag/chunking/intelligent.py 基于文档结构的智能分块 IntelligentChunker, chunk()
rag/chunking/template.py 模板驱动分块 TemplateChunker, 各种模板实现
rag/rerank/ 可选 Rerank Reranker, rerank()
rag/graph/ Graph RAG 构建与检索 GraphBuilder, GraphRetriever
api/apps/ 后端业务逻辑入口 Flask 路由,知识库/对话/文档管理
agent/ Agent 编排 AgentGraph, 节点定义与执行
web/ 前端 React 应用 知识库管理/对话/Agent 编排 UI

关键调用链

文档摄入调用链:
  api/apps/document_app.py (上传接口)
    → deepdoc/parser/ (格式适配)
      → deepdoc/vision/layout.py (版面分析)
      → deepdoc/vision/ocr.py (OCR)
      → deepdoc/table/table_structure.py (表格识别)
    → rag/chunking/template.py (模板分块)
    → rag/embedding/ (向量化)
    → Milvus/ES (存储)

检索调用链:
  api/apps/conversation_app.py (对话接口)
    → rag/retrieval/hybrid.py (混合检索)
      → rag/retrieval/bm25.py (BM25)
      → rag/retrieval/vector.py (向量)
    → rag/rerank/ (Rerank)
    → LLM 生成 + 引用标注

本地代码结构

ragflow/
├── deepdoc/                    # 文档深度解析引擎(核心)
│   ├── parser/                 # 各格式解析器
│   │   ├── pdf_parser.py       # PDF 解析(版面分析+表格识别)
│   │   ├── docx_parser.py      # Word 解析
│   │   ├── excel_parser.py     # Excel 解析
│   │   ├── ppt_parser.py       # PPT 解析
│   │   ├── markdown_parser.py  # Markdown 解析
│   │   ├── html_parser.py      # HTML 解析
│   │   ├── image_parser.py     # 图片解析(OCR)
│   │   └── ...                 # 20+ 格式
│   ├── vision/                 # 视觉模型(版面检测/OCR)
│   │   ├── layout.py           # 版面分析模型
│   │   ├── ocr.py              # OCR 识别模型
│   │   └── layout_recognizer.py # 版面检测器封装
│   ├── table/                  # 表格结构恢复
│   │   ├── table_structure.py  # 表格结构识别模型
│   │   └── main.py             # 表格处理入口
│   ├── formula/                # 公式提取
│   └── utils/                  # 工具函数
├── rag/                        # RAG 检索模块
│   ├── retrieval/              # BM25 + 向量混合检索
│   │   ├── hybrid.py           # 混合检索器
│   │   ├── bm25.py             # BM25 检索
│   │   └── vector.py           # 向量检索
│   ├── chunking/               # 基于解析结果的智能分块
│   │   ├── intelligent.py      # 智能分块
│   │   └── template.py         # 模板驱动分块
│   ├── rerank/                 # 可选 Rerank
│   ├── graph/                  # Graph RAG
│   └── embedding/              # 向量化
├── api/                        # 后端 API 服务(Flask)
│   └── apps/                   # 业务逻辑入口
├── agent/                      # Agent 编排
├── web/                        # 前端界面(React)
├── docker/                     # 容器化部署
└── conf/                       # 配置文件

竞赛贡献切入点

RAGFlow 本身不是犀牛鸟直接贡献项目(那是 WeKnora 的位置),但 RAGFlow 的技术思想可以为竞赛贡献提供灵感。以下方向是将 RAGFlow 的技术优势迁移到 WeKnora 的可行路径:

方向一:DeepDoc 思想迁移——增强 WeKnora 的文档解析

WeKnora 目前使用 IMA 引擎做文档解析,但在表格结构恢复和公式提取方面可能不如 DeepDoc 深入。可以参考 DeepDoc 的表格结构恢复模型,为 WeKnora 贡献更精细的表格处理能力。

具体贡献

难度:高。需要理解深度学习模型并做跨语言移植。

方向二:模板驱动分块思想迁移——增强 WeKnora 的自适应分块

WeKnora 有 4 级自适应分块(auto → heading → heuristic → recursive → legacy),但没有 RAGFlow 那样针对不同文档类型的专门模板。可以为 WeKnora 贡献 Q&A / 法律 / 论文等模板分块 Plugin。

具体贡献

难度:中。模板分块的逻辑相对简单,核心挑战是 Plugin 的 EventManager 集成。

方向三:引用追踪功能

RAGFlow 的引用追踪(Citation)是一个用户价值很高的功能——用户可以点击答案中的引用标注跳转到原文。WeKnora 目前没有原生引用追踪功能。

具体贡献

难度:中低。引用追踪的实现相对简单,核心是元数据传递和 Prompt 设计。

方向四:RAGFlow + WeKnora 集成评估

RAGFlow 的 DeepDoc 做极致文档解析 + WeKnora 的三路检索做极致检索质量——两者组合是否 1+1>2?这是一个有学术价值的实验问题。

具体贡献

难度:中。需要搭建两套系统并准备评估数据集,但不需要深度修改源码。

方向五:Graph RAG 改进

RAGFlow 的 Graph RAG 目前使用 LLM 驱动的实体关系抽取,成本高且不稳定。可以探索将 WeKnora 的 PMI 统计方法与 RAGFlow 的 LLM 方法结合——PMI 做初始图谱构建(低成本),LLM 做关系类型标注(高精度)。

具体贡献

难度:中高。需要理解两种图谱构建方法并做融合设计。


交叉引用

相关页面 关系
RAG 知识库全景 RAGFlow 在 5 项目比较中的定位
跨项目深度分析 文档解析能力 / 检索管线的跨项目比较
WeKnora 精读 RAGFlow 文档解析 vs WeKnora 检索深度的互补分析
WeKnora 竞赛贡献指南 RAGFlow 技术思想迁移到 WeKnora 的具体路径
Agentic RAG 模式 RAGFlow Agent 编排在 6 种模式中的位置
RAG 评估方法论 RAGAS 评估如何应用于 RAGFlow vs WeKnora 对比
RAG Agent 集成 RAGFlow 作为检索后端与 Agent 框架的集成模式
选型决策树 什么场景选 RAGFlow(PDF/表格密集 → RAGFlow)
Memory vs RAG 边界 D 线(RAG)与 B 线(Memory)的分工——RAGFlow 处理外部文档检索,Memory 系统处理对话记忆
腾讯记忆生态 RAGFlow 在腾讯 DB-Agent-Memory 生态中的定位——文档理解层,与 WeKnora 检索层互补

局限性与场景边界

处理速度瓶颈

DeepDoc 的深度解析带来处理速度的代价。具体数据(参考值,取决于硬件和文档复杂度):

文档类型 页数 DeepDoc 处理时间 简单文本提取时间
纯文本 PDF(10 页) 10 ~5 秒 <1 秒
含表格 PDF(10 页) 10 ~30 秒 <1 秒
扫描件 PDF(10 页) 10 ~60 秒 N/A(提取为空)
复杂年报 PDF(50 页) 50 ~5 分钟 <5 秒
Markdown 文档 - <1 秒 <1 秒

对于需要实时索引更新的场景(如知识库频繁编辑),DeepDoc 的处理速度是瓶颈。RAGFlow 的应对策略是异步处理——文档上传后放入任务队列,后台解析完成后通知用户。

纯文本文档的”杀鸡用牛刀”问题

对于纯文本文档(如 Markdown 笔记、代码注释),DeepDoc 的深度解析反而是过度处理——额外的版面分析步骤没有价值但增加了延迟。

RAGFlow 的应对策略是格式适配器路由——根据文件后缀选择解析器。Markdown 文件直接走 markdown_parser.py(简单解析),不经过 DeepDoc 的版面分析管线。

检索管线深度不足

RAGFlow 的检索管线(BM25 + 向量 + 权重融合 + 单模型 Rerank)在文档质量已经很好的场景下(如结构化的 Markdown 知识库),与 WeKnora 的三路检索 + RRF + 复合 Rerank 相比,检索质量有明显差距。具体差距体现在:

社区与生态

RAGFlow 的 83K star 说明社区活跃度高,但在以下方面不如 Dify:


学习建议

源码阅读路线

如果你是第一次接触 RAGFlow 的源码,建议按以下顺序阅读:

  1. 先读 deepdoc/parser/——理解各种格式如何被适配和路由
  2. 再读 deepdoc/vision/layout.py——理解版面分析的核心逻辑
  3. 然后读 deepdoc/table/table_structure.py——理解表格结构恢复,这是 DeepDoc 最有技术深度的模块
  4. 接着读 deepdoc/vision/ocr.py——理解 OCR 管线的实现
  5. 再读 rag/chunking/template.py——理解模板驱动分块的设计
  6. 然后读 rag/retrieval/hybrid.py——理解双路混合检索的实现
  7. 最后读 rag/graph/——理解 Graph RAG 的构建与检索

每个模块大约需要 1-2 小时精读。总计约 10-15 小时。

对比学习路线

为了更深入理解 RAGFlow 的设计取舍,建议与 WeKnora 做对比阅读:

阅读维度 RAGFlow 模块 WeKnora 模块 对比重点
文档解析 deepdoc/ IMA 引擎 哪些场景谁的解析更好?
分块策略 rag/chunking/template.py pkg/chunker/ 模板驱动 vs 自适应降级链
检索融合 rag/retrieval/hybrid.py pkg/fusion/ 权重融合 vs RRF
Rerank rag/rerank/ pkg/rerank/ 单信号 vs 三信号
知识图谱 rag/graph/ pkg/retriever/graph/ LLM 驱动 vs PMI 统计

实践建议

  1. 部署 RAGFlow:用 Docker Compose 一键部署,上传一份含表格的 PDF 体验 DeepDoc 的效果
  2. 对比实验:同一份 PDF 分别用 RAGFlow 和 WeKnora 解析,对比 chunk 质量
  3. 模板定制:尝试为特定文档类型(如公司内部模板)定制分块模板
  4. Graph RAG 实验:上传一组相关文档,构建知识图谱,对比 Graph RAG 和普通检索的效果差异
  5. RAGAS 评估:用 RAGAS 对 RAGFlow 和 WeKnora 做端到端评估,量化文档解析对检索质量的边际贡献

进阶研究方向


证据等级

来源 标签
RAGFlow 源码 deepdoc/rag/ 目录 [源码]
RAGFlow GitHub README / 官方文档 [文档]
deep-dive-weknora.md RRF/Rerank 参数 [已有]
rag-knowledge-landscape.md 横评 [已有]
deep-dive.md 跨项目分析 [已有]
Graph RAG 论文(微软) [社区]
DeepDoc 技术博客 [社区]
未实测 以源码/docs/社区为准