01

RAG 基础与局限

为什么 AI 需要"外挂记忆",以及朴素 RAG 为何还不够好

想象一位过度自信的顾问

你雇了一位顾问,他只读过 2023 年以前的书。你问他今天股价,他自信给出一个答案——但那是编造的。这就是没有外部知识的 LLM 的状态:训练截止日期之后的事情一概不知,但还是会"合理猜测"。

RAG 的诞生就是为了解决这个问题:先搜索,再回答。

🧠

幻觉问题

LLM 在不确定时会"合理编造"——看起来正确但完全错误的答案

📅

知识截止日期

训练数据有时间边界,最新事件、内部文档一概不知

🔒

私有数据隔离

公司内部文档、合同、代码库不在训练数据里——也不该在

朴素 RAG 的工作流程

基础 RAG 其实很简单:把文档切成小块,存到向量数据库,用户提问时找最相似的块,拼到提示词里。

1

文档切块

2

向量化存储

3

语义检索

4

注入提示词

5

LLM 生成

⚠️
朴素 RAG 的三个致命弱点

固定大小切块破坏语义完整性;PDF/表格等复杂格式解析失真;检索只看语义相似,忽略关键词精确匹配——这三个问题让朴素 RAG 在企业场景下成功率不足 60%。

RAGFlow 怎么解决这些问题?

RAGFlow 的核心主张是:文档理解质量决定 RAG 质量。它不像大多数 RAG 框架那样把解析当作预处理步骤,而是把它做成核心竞争力。

🔬
DeepDoc 解析引擎

视觉 AI 识别 PDF 布局,表格、图表、公式分别处理,不再"文字乱炖"

🎯
智能分块策略

按语义和文档结构分块,保留表格行、代码块的完整性

⚖️
混合检索

向量语义检索 + 关键词全文检索,互为补充,融合排序

知识点检测

你的公司每天都有新政策文件发布,你想让 AI 客服立刻知道最新政策。哪种方案最合适?

你用朴素 RAG 处理公司 PDF 财务报告,发现 AI 经常回答错误财务数字。最可能的原因是什么?

02

RAGFlow 架构全景

认识这个系统的每个"角色"——以及他们如何分工协作

这就是你上传一份 PDF 后发生的事情

想象你经营一家图书馆。你的工作不只是把书放上架——你要先对每本书编目,建索引,写摘要,标注关键词。有人问问题时,你还要判断哪些书最相关,摘录关键段落,再给出综合答案。RAGFlow 就是一个自动化"图书馆员"。

🖥️
Web UI
📋
任务队列
🔬
DeepDoc
🗄️
存储层
点击"下一步"开始追踪文件的旅程

系统的主要组成部分

前端层

🌐
React Web UI

API 层

Flask API
📋
Celery 任务队列

核心引擎层

🔬
DeepDoc 解析引擎
🔢
Embedding 服务

存储层

🔍
Elasticsearch
💾
MySQL + MinIO
点击任意组件查看详细说明

一段真实的检索代码

当你在对话框提问时,RAGFlow 实际运行的检索逻辑是这样的:

CODE

def retrieval(question, kb_ids, embd_mdl,
             rerank_mdl=None, top=1024):
    embs, _ = embd_mdl.encode([question])
    ans = settings.docStoreConn.search(
        "ragflow_*",
        query_vector=embs[0],
        highlight=True
    )
    if rerank_mdl:
        ans = rerank_mdl.rerank(question, ans)
    return ans
            
PLAIN ENGLISH

定义一个"检索"函数,接收问题、知识库ID和向量化模型

把用户的问题转成数字向量(就像把问题翻译成机器语言)

在 Elasticsearch 里搜索:找哪些文档块和这个问题向量最接近

在所有以"ragflow_"开头的知识库索引里搜

用向量相似度作为主要排序依据

同时高亮显示匹配的关键词(用于展示给用户)

如果配置了重排序模型,对结果进行精细排序

返回最终排序结果

知识点检测

RAGFlow 用 Celery 异步任务队列处理文档解析,而不是在 API 请求里直接处理。这样做最主要的原因是什么?

03

文档解析流水线

DeepDoc 如何读懂 PDF、Word、Excel——让 AI 看到的和人看到的一样

为什么文档解析这么难?

想象把一张精心排版的报纸扫描成图片,然后让人从图片里"重建"报纸的文字结构。你必须判断:哪些文字是标题?哪些是正文?哪些数字属于表格的哪一行?

对于 PDF,计算机看到的不是"段落和表格",而是一堆"某坐标某字体某大小的字符"。把这些字符还原成有意义的结构,就是 DeepDoc 要解决的核心问题。

💡
关键洞察:垃圾进,垃圾出

RAGFlow 的核心哲学是"文档理解质量决定一切"。如果解析阶段把表格变成乱码、把图表扔掉,后续再好的检索也无法补救。因此 RAGFlow 把大量工程资源投入解析层,而不是检索层。

DeepDoc 的解析步骤

1
版面分析(Layout Analysis)

用视觉 AI 模型识别 PDF 页面的布局区域:标题区、正文区、表格区、图片区、页眉页脚

2
OCR 文字识别

对扫描版 PDF 或图片区域进行OCR,提取文字内容

3
表格结构识别

专门的模型识别表格的行列结构,确保行与列数据正确对应,不会"混行"

4
语义分块

根据文档结构(章节、段落、表格单元)而非固定字数进行分块,每个块是一个完整语义单元

5
元数据提取

记录每个块的来源(文件名、页码、位置),回答时可以精确引用来源

文件格式与对应处理器

不同格式有不同的解析逻辑,RAGFlow 为每种格式准备了专门的处理器:

deepdoc/parser/ 文档解析器集合
pdf_parser.py 版面分析 + OCR,支持扫描版和原生 PDF
docx_parser.py Word 文档,保留标题层级和表格结构
excel_parser.py Excel 表格,每行作为独立语义单元处理
html_parser.py HTML 页面,清理 DOM 结构提取纯内容
markdown_parser.py Markdown,按标题层级分块

组件们的"工作对话"

当一份 PDF 进入系统,幕后的组件是这样协作的:

知识点检测

你上传了一份扫描版财务报告(扫描仪扫的图片),RAGFlow 说能识别。哪个功能使这成为可能?

04

检索与重排序

如何找到真正相关的内容,而不只是"看起来像"的内容

两种"搜索思维"

想象你在找一位老同学。方法一:在同学录里搜名字"张伟"(关键词)。方法二:描述他的特征"那个总戴眼镜、喜欢打篮球的高个子"(语义)。两种方法各有优缺:名字精确但找不到外号;特征灵活但可能找到多个相似的人。

RAGFlow 的混合检索同时用两种方法,然后把结果合并。

🔢

向量检索(语义)

把问题和文档都转成向量,找"意思最近"的内容。能处理同义词、换种说法等情况。但对精确术语、数字、缩写不敏感。

🔤

全文检索(关键词)

经典的 BM25 算法,精确匹配关键词。对专有名词、产品编号、条款编号等效果极好。但不能理解语义,不知道"车"和"汽车"是同一个东西。

⚖️

混合融合(RRF)

倒数排名融合算法,把两个排序列表合并为一个综合排名。取两种方法各自的优势,互补短板。

重排序:第二轮精筛

第一轮检索用速度换精度——快速找出前 100 个候选块。但"候选"不等于"最佳"。重排序模型会对这 100 个候选做精细的相关性评分,选出最好的 5-10 个交给 LLM。

就像招聘:HR 先从简历堆里快速筛出 100 份(第一轮检索),再由用人部门仔细面试前 10 名(重排序),最终决定录用谁(发给 LLM)。

CODE

class DefaultRerank:
    def rerank(self, query, chunks,
                batch_size=16):
        pairs = [[query, c] for c in chunks]
        scores = self.model.compute_score(pairs)
        ranked = sorted(
            zip(chunks, scores),
            key=lambda x: x[1],
            reverse=True
        )
        return [c for c, _ in ranked]
            
PLAIN ENGLISH

定义重排序类和方法,接收用户问题和候选文档块

batch_size=16 表示每次处理16个,避免显存溢出

把问题和每个文档块组成"问题+答案"对

让重排序模型给每对打一个相关性分数

按分数从高到低排序...

把文档块和分数打包在一起再排序

按分数降序(最相关的排最前)

只返回文档块,丢掉分数(用户不需要看原始分数)

知识点检测

你在查询产品质检数据库:"SK-2023-A7 的不良率是多少?"你期望哪种检索方式找到最精确的答案?

05

生产部署模式

把 RAGFlow 从演示环境变成可靠的企业级服务

RAGFlow 的 Docker 架构

RAGFlow 使用Docker Compose 启动整套服务。一条命令,七个服务同时运行:

ragflow 核心 API + Web 服务,处理所有业务逻辑
elasticsearch 存储和检索所有向量索引,RAGFlow 的检索引擎
minio 对象存储,保存上传的原始文档文件
mysql 关系数据库,存储用户信息、知识库配置、对话记录
redis 缓存和任务队列,Celery 用它传递异步任务
infinity 可选的自托管向量数据库,替代外部 Elasticsearch

关键配置项解读

.env 配置

# LLM 模型配置
LLM_FACTORY=OpenAI
OPENAI_API_KEY=sk-xxx
LLM_MODEL=gpt-4o

# Embedding 模型
EMBEDDING_MODEL=BAAI/bge-large-zh

# 存储配置
ES_HOST=elasticsearch
MINIO_HOST=minio:9000
            
PLAIN ENGLISH

注释:LLM 模型配置

使用 OpenAI 作为 LLM 提供商(也可换成 Ollama、DeepSeek 等)

你的 OpenAI API 密钥(保密!不要提交到代码库)

具体使用哪个模型(gpt-4o 最强但贵,gpt-3.5-turbo 便宜)

注释:Embedding(向量化)模型配置

使用 BAAI 的中文优化 Embedding 模型,中文场景效果更好

注释:存储配置

Elasticsearch 服务地址(Docker 网络里的服务名)

MinIO 对象存储地址和端口

生产环境要考虑的三件事

💾

数据持久化

Docker 容器重启后数据默认消失。必须把 Elasticsearch、MySQL、MinIO 的数据目录挂载到主机磁盘。

📈

资源规划

DeepDoc 解析时 CPU 密集,Elasticsearch 需要充足内存(建议 8GB+)。生产环境至少 16GB RAM,有 GPU 更好(加速 OCR 和 Embedding)。

🔒

访问控制

RAGFlow 自带RBAC 权限管理。生产环境务必修改默认密码,配置 HTTPS,限制 MinIO 和 Elasticsearch 的外部访问。

💡
对 AI 开发者的实用建议

告诉 AI 帮你部署 RAGFlow 时,指定"生产环境配置",要求生成包含 Volume 挂载和资源限制的 docker-compose.yml。这样生成的配置文件才是真正可用的,而不是演示版。

综合检测

你的 RAGFlow 服务器需要重启,重启后发现所有上传的文档和知识库都消失了。原因是什么,如何预防?