跳到主要内容

RAGFlow — 这是什么 / 全景图 / 阅读地图

30 秒导读: RAGFlow 是一款开源的 RAG(检索增强生成)引擎。它的核心赌注是「深度文档理解」——先像人一样把 PDF、扫描件、表格、幻灯片"看懂"成有版面结构的块,再切块、建索引;检索时走全文 + 向量双路召回并融合重排,最后让大模型基于命中块作答并回填可点击的引用。给谁用:想把一堆杂乱文档变成「能带出处问答的知识库 / Agent」的开发者和企业。

本章只讲大盘该跳哪一章,不深入任何单一机制的代码——细节都在 01–04 四章里。


1. 这是什么(零基础也能懂)

一句话定义: RAGFlow = 「把文档喂进去 → 得到一个能带引用回答问题的知识库 / Agent」的一整套开源引擎。

它想解决的痛点。 普通 RAG 的效果天花板,往往不在"用哪个大模型",而在最前面那一步:文档被切碎的质量。一份财报 PDF 里有跨页表格、多栏排版、图表、脚注;粗暴地按字数切块,会把一句话腰斩、把表格搅烂,后面的检索再准也救不回来。RAGFlow 的立场是:Quality in, quality out——先把文档读懂,后面才有戏(README「Key Features」)。

四个卖点,落到具体机制。 README 的「Key Features」是四句营销话,这里把每句翻成"它到底做了什么":

README 卖点白话背后的具体机制(哪章讲)
Deep document understanding不是纯文本抽取,而是用视觉模型识别版面、表格结构、OCRdeepdoc/:布局识别 + 表格结构识别 + OCR(01)
Template-based chunking按"文档是什么类型"(论文/手册/法条/QA/表格…)选不同切块策略,可解释、可人工干预rag/app/ 下十几个模板(0102)
Grounded citations答案里每句话尽量挂上"来自哪个块"的引用,减少幻觉、可溯源Dealer.insert_citations(03)
Multiple recall + fused rerank同一个问题走全文检索 + 向量检索两路,先在存储层融合,再二次重排Dealer.search / Dealer.rerank(03)

用起来什么样(直觉版):

  1. 建一个知识库,把文档拖进去 → RAGFlow 后台解析、切块、算向量、写索引(写入线)。
  2. 页面上能看到每个块长什么样,可手工改——这就是"可解释切块"。
  3. 提问 → 引擎双路召回、重排、把命中块塞进 prompt、大模型作答,答案里带可点回原文的引用(读取线)。

一句话类比: 把 RAGFlow 想成一个特别较真的图书管理员——先把每本书拆成"读得懂的段落卡片"(而不是按页撕),再给每张卡片同时建"关键词目录"和"语义地图";你来问问题,他两套索引都查一遍、综合排序,取几张最相关的卡片给你,并在答案旁标清楚是哪张卡片说的


2. 顶层全景(它大概怎么转)

RAGFlow 的一切都可以归到两条线上。理解了这两条线,整个项目的目录就有了坐标。

2.1 两条主线

写入线(Ingestion / 慢、离线): 文档进来,变成一堆带向量、带索引的"块"存起来。

读取线(Retrieval / 快、在线): 问题进来,找到最相关的块,让大模型作答并回填引用。

怎么读下面这张图:上半是写入线(从左到右),下半是读取线(从左到右);中间的 Doc Store 是两条线的交汇点——写入线把块写进去,读取线从里面查出来。

┌──────────────── 写入线(离线 / task_executor 后台 worker)────────────────┐
│ │
原始文档 │ ① 深度文档理解 ② 模板分块 ③ 分词+向量 ④ 写索引 │
PDF/Word/PPT ───► │ deepdoc/ 解析 ─► rag/app/ 选模板 ─► 中英分词+embedding ─► ┌──────────┐│
扫描件/表格/网页 │ (布局/OCR/表格) 切成"讲得通的块" 稀疏词权+稠密向量 │ Doc Store ││
│ │ 文档+向量 ││
└──────────────────────────────────────────────────────────► │ +全文索引 ││
└────┬─────┘│
┌──────────────── 读取线(在线 / ragflow_server Quart API)──────────┼──────┘
│ ▼
用户问题 ───► │ ① 查询理解/扩展 ② 双路召回 ③ 融合+重排 ④ 引用回填 ► 带引用的答案
"去年营收?" │ rag/nlp/query.py 全文 + 向量 存储层融合 Dealer 交给 LLM
│ (同义词/词权) (两路candidates) + Dealer二次重排 .insert_citations
└────────────────────────────────────────────────────────────────────────┘

2.2 两类进程(谁在跑这两条线)

RAGFlow 运行时是两种进程,靠 Redis 消息流解耦——这是理解代码布局的第二把钥匙:

进程入口文件角色跑哪条线
API 服务api/ragflow_server.pyQuart(异步 Flask 风格)Web 服务,处理前端/SDK 请求、鉴权、发起任务读取线(在线问答)+ 把"该解析的文档"作为任务丢进 Redis
后台 workerrag/svr/task_executor.py从 Redis 流里取任务、干重活(解析/切块/向量/写库)写入线(离线入库)

两者不直接调用,而是通过 Redis 队列传递任务:API 端把待处理文档写成一条任务消息,worker 端 collect() 用消费者组从队列里 queue_consumer 拉取(rag/svr/task_executor.py:199 附近,REDIS_CONN.get_unacked_iterator / queue_consumer)。好处:入库是重活,可以独立扩多个 worker,不拖慢在线问答。

前端/SDK ──HTTP──► ragflow_server (Quart API)
│ 写任务

[ Redis 流队列 ]
│ 拉任务(消费者组)

task_executor (后台 worker) ──► Doc Store

2.3 部件职责表

下面这张表是"目录 → 干什么"的路由。想深挖某块,按最后一列跳章。

部件目录/文件干什么深入章节
深度文档理解deepdoc/parser/deepdoc/vision/把各种格式解析成带版面结构的块:PDF/DOCX/PPT/Excel/HTML 解析器 + 布局识别 + OCR + 表格结构识别01
分块模板rag/app/(naive.pypaper.pymanual.pylaws.pyqa.pytable.py…)按文档类型选切块策略,每个模板一个 chunk() 函数0102
写入线编排rag/svr/task_executor.py(build_chunksembeddingdo_handle_task)驱动"解析→切块→分词→向量→写库"的后台流水线02
混合检索核心rag/nlp/search.py(Dealer)双路召回 + 重排 + 引用回填的中枢03
查询理解rag/nlp/query.py(FulltextQueryer)、rag_tokenizer.pyterm_weight.pysynonym.py把问题变成带词权、同义词的全文查询 + 稠密向量03
存储抽象common/doc_store/(doc_store_base.py)、rag/utils/es_conn.py统一 Elasticsearch / Infinity / OpenSearch / OceanBase 的检索接口(全文+向量+融合)0203
层次摘要召回rag/raptor.pyRAPTOR:对块做递归聚类+摘要,建一棵"越往上越抽象"的树,提升长文档召回04
知识图谱rag/graphrag/从块里抽实体/关系建图,支持图谱式召回与实体消歧04

2.4 一条问答从头到尾(高层,不进代码)

问题 "去年营收多少?"

▼ ① 查询理解:分词、算词权、扩同义词 → 全文查询;同时算问题的稠密向量
│ rag/nlp/query.py: FulltextQueryer.question
▼ ② 双路召回:全文(MatchText)+ 向量(MatchDense)一起丢给 doc store
│ rag/nlp/search.py: Dealer.search
▼ ③ 存储层融合:FusionExpr("weighted_sum") 把两路分数按权重合成候选池
│ (ES/Infinity/OceanBase 内部完成,权重如 text:dense = 0.05:0.95)
▼ ④ Dealer 二次重排:token 相似度 × 向量余弦(可叠外部 rerank 模型)
│ rag/nlp/search.py: Dealer.rerank / rerank_by_model
▼ ⑤ 取 top-N 块塞进 prompt,大模型作答,逐句回填引用
│ rag/nlp/search.py: Dealer.insert_citations

答案 + 可点回原文的引用

注意"双重排序"这个设计: 融合发生两次——第一次在 doc store 内部把全文/向量两路分数加权合成(Dealer.search 里构造 FusionExpr,rag/nlp/search.py:191 附近),第二次在 Python 层用 token 相似度和向量余弦再排一遍(Dealer.rerank,rag/nlp/search.py:474)。这就是 README 说的 "multiple recall + fused rerank"。细节见 03


3. 阅读地图(四章,由浅入深)

建议顺序就是数据流的顺序:先看文档怎么被读懂(01)→ 怎么入库(02)→ 怎么被检索(03)→ 进阶召回(04)

顺序章节一句话这章讲什么
101-deepdoc-document-understanding.mdDeepDoc 如何用视觉模型把 PDF/表格/扫描件"看懂"成布局块,再按文档类型(rag/app/ 模板)切成"讲得通的块"。RAGFlow 的地基。
202-ingestion-write-path.md入库写入线全过程:task_executor 一个 Task 从解析结果 → 分块 → 中英分词 → 稠密/稀疏向量 → 写进 doc store 建全文+向量索引。
303-hybrid-retrieval-and-rerank.md检索中枢 Dealer:查询理解、全文+向量双路召回、存储层融合、二次重排、引用回填——最核心的一章。
404-advanced-retrieval-raptor-graphrag.md三种进阶召回:RAPTOR 层次摘要树、GraphRAG 知识图谱、查询分解 / TOC 召回,用于长文档和复杂问题。

怎么用这张地图:

  • 只想知道"RAGFlow 凭什么切块比别人好" → 直接读 01
  • 关心"检索/重排/引用怎么实现的" → 03 是主菜。
  • 要做长文档或图谱增强 → 04
  • 想接自己的存储或调优入库 → 02

4. 巧妙之处速览(精华,细节在各章)

这里只点"妙在哪",不展开代码;每条后面标了在哪章看真章。

巧妙点一句话为什么妙看哪章
以"文档理解"为地基大多数 RAG 把功夫花在检索/重排,RAGFlow 认定上游切块质量才是天花板,先重投视觉解析,后面才有 quality out01
模板化、可解释切块不同文档(论文/法条/表格/QA)用不同切块逻辑,且切块结果可视化、可人工改——切块从"黑盒"变"白盒"01
两级融合排序第一级在存储引擎里融合全文+向量(下推、快),第二级在 Python 里 token×向量再排(可控、可插外部 rerank 模型)03
空结果自动降级重试双路命中为空时,自动放宽 min_match、抬高相似度阈值再查一遍(Dealer.searchtotal == 0 分支),避免"一无所获"03
引用回填减少幻觉答案生成后逐句匹配回块,挂上可溯源引用(insert_citations),把"看起来对"变成"能验证"03
存储后端可插拔同一套 DocStoreConnection 抽象适配 ES / Infinity / OpenSearch / OceanBase,DOC_ENGINE 一个环境变量切换02
API/worker 经 Redis 解耦在线问答与离线重活分进程、靠消息流传递,入库可独立横向扩容,不拖慢问答02

5. 代码地图(导航索引)

一张跨章总表:想直接跳进源码时按此定位。符号名比行号抗漂移,优先用 grep 符号名。

主题文件路径关键符号
API 服务入口api/ragflow_server.pyupdate_progresssignal_handlerapp(来自 api.apps)
后台 worker 入口rag/svr/task_executor.pymainhandle_taskdo_handle_taskcollect
写入线:切块/向量rag/svr/task_executor.pybuild_chunksembedding
分块模板(默认)rag/app/naive.pychunk(第 839 行)
分块模板(其它)rag/app/(paper.py/manual.py/laws.py/qa.py/table.py/book.py/presentation.py…)各自的 chunk()
深度文档理解:解析器deepdoc/parser/(pdf_parser.py/docx_parser.py/excel_parser.py/ppt_parser.py/html_parser.py…)*Parser
深度文档理解:视觉deepdoc/vision/layout_recognizer.pyocr.pytable_structure_recognizer.pyrecognizer.py
检索中枢rag/nlp/search.pyDealerDealer.search(:132)、Dealer.retrieval(:573)、Dealer.rerank(:474)、Dealer.rerank_by_model(:513)、Dealer.insert_citations(:242)
TOC/子块召回rag/nlp/search.pyDealer.retrieval_by_toc(:864)、Dealer.retrieval_by_children(:928)
查询理解rag/nlp/query.pyFulltextQueryerFulltextQueryer.question(:42)、hybrid_similarity(:183)、token_similarity(:193)
分词/词权/同义词rag/nlp/rag_tokenizer.pyterm_weight.pysynonym.py
存储抽象基类common/doc_store/doc_store_base.pyDocStoreConnectionMatchTextExprMatchDenseExprFusionExprOrderByExpr
存储后端实现rag/utils/es_conn.pyinfinity_conn.pyopensearch_conn.py
存储后端选择common/settings.pyDOC_ENGINE(:85)、docStoreConn(:90)
RAPTOR 层次摘要rag/raptor.pyRecursiveAbstractiveProcessing4TreeOrganizedRetrieval(:156)
GraphRAG 知识图谱rag/graphrag/search.pyentity_resolution.pyutils.py