RAG深度解析:分块、向量化、召回、重排,才是“蒸馏同事skill”的关键

茶饮消息
05-06 08:38 来自北京市

最近AI圈又开始流行一种很魔幻的东西:同事.skill。

而后就是产品经理.skill、运营总监.skill、销售冠军.skill,这些都还算正常,最离谱的是我还看到了法外狂徒张三.skill这种东西...

怎么说呢,这东西有点疯,比如你真的敢让一个写着精通刑法、刑诉法的skill,来给你做法律判断吗?

更进一步,如果有人跟你说:我已经把公司最强客服、最强销售蒸馏成了一个skill,你会相信吗?

你如果相信,那么今天的问题就很大了,会被内行笑话的。

因为你真拆开看就会发现,很多所谓的蒸馏同事,蒸馏出来的不是一个人的完整能力,而是他工作中最容易整理、也最容易自动化的那一部分。

这部分内容不叫判断力,也不存在什么经验,它更接近一个词:Workflow。

换句话说,skill可以教AI怎么做,却不一定能让AI知道为什么这么做。

如果你真的想去蒸馏某个人的某部分知识,那么一定离不开今天的主角:RAG:

为什么需要RAG

很多人对Skills有误解,以为他能很好的完成知识库的功能,这种想法是比较浅的,就现在的技术范式来说:

skill解决的是流程复制,那么RAG解决是知识调用

skill告诉模型第一步做什么、第二步做什么、RAG告诉模型做这件事时,需要参考哪些资料、哪些历史经验,以及这些信息从哪里来。

这两者一组合,就真的有点蒸馏那个意思了,比如:

你公司有个销冠,,大家都说他厉害,于是你准备蒸馏这个销冠,你会怎么做?

大概率是整理他的话术、跟进流程、异议处理方式等,然后写成一堆规则文档,再喂给模型。

这样做有没有价值?

当然有,但问题是——这只是他的外显动作,不是他的真实能力。因为真正的销冠,脑子里还有另一套系统:

公司所有产品的细节参数

不同行业客户的采购习惯

历史成交案例

哪些承诺能给,哪些不能给

...

这些隐性的知识,才决定他为什么说这句话,为什么给这个报价。而这些内容,当然不可能全部写进一个prompt里。所以你最后一定会发现:

skill负责复刻动作,RAG负责补足认知

所以,很多所谓的同事.skill,要变成真正能工作的AI同事,至少需要三层能力:

Workflow层:知道这件事该怎么做;

Knowledge层:知道做这件事要参考什么资料;

Judgement层:知道在复杂情况下如何权衡;

Skill主要解决第一层,RAG主要解决第二层,第三层则取决于模型能力、业务边界和人类兜底机制。

受小龙虾OpenClaw的影响,Skills的书写大家已经很熟悉了,那RAG到底怎么做?

今天我们不抽象讲概念,直接拿一个最常见的工具来说:Dify知识库。

PS:本来这里是想用AI Coding的,但经过学员反馈,很多公司实际在运转的依旧是Dify和Coze体系,所以这里还是用Dify算了...

只是要注意:Dify在这里不重要,知识库的思维都是这套,写代码也行

Dify实现AI知识库

现在很多企业都在想办法落地AI知识库,常见做法是把散落在各处的手册、文档、FAQ集中起来,让大模型来回答员工或客户的问题。

能做这种工作的方法很多,最常见的就是Coding,除此之外也有一些低代码平台如Coze、Dify、FastGPT、RAGFlow等,就我的使用经验来说,当前Dify是比较均衡的:

有完整的知识库管理;

编排体验比较好;

开源≈可控性;

能私有化部署;

对企业场景比较友好;

PS:不得不说,就算是低代码平台的知识库,其实也不好用、不太友好

但如今Agentic RAG的框架还没看到比较好又开源的,如果NoteBookLM开源,我会无脑推

为什么我们会说不好用呢?因为很多同学在配置Dify知识库的时候,都会卡在这些选项上:

怎么设置分块?

索引模式选高质量还是经济?

检索方式选向量检索、全文检索,还是混合检索?

Top K到底填3、5还是10?

Score阈值设置为0.5还是0.7?

Rerank模型要不要打开?

...

其实熟悉RAG的同学就懂了,这些问题不仅是Dify会遇到,你写代码也懵逼啊...

进一步,这些问题看起来相互独立,其实互相关联性挺大的,要完整回答这些问题,就得搞清楚RAG的完整链路...

这套链路大致分为两个阶段:

离线阶段:数据入库

在线阶段:检索生成

离线阶段主要做:

文档解析→数据清洗→文档分块→向量化→建索引

在线阶段主要做:

用户提问→查询改写/知识库选择→召回→重排→Top K过滤→拼接上下文→大模型生成回答

只有理解完这条链路,再去看Dify的配置项,就不会觉得它们是孤立参数,而是一组有因果关系的控制点了。

下面我们用一个非常常见的场景来讲:

AI客服场景

假设我们用Dify搭了一个智能客服,上传了一份产品售后手册。

我们希望用户问下面这些问题时,客服助手能准确回答:

怎么退货?

订单超过7天还能退吗?

SKU-20260315这款商品支持换货吗?

大促订单是否支持无理由退款?

海外订单退货运费谁承担?

这类问题看起来简单,但背后其实涉及:

售后政策;

商品规则;

订单状态;

SKU特殊规则;

大促活动条款;

如果没有RAG,模型只能靠通用知识回答,那么大家可能就会看到这种正确而无用的废话了:

一般情况下,商品是否支持退货取决于商家的售后政策,建议您查看订单详情或联系客服。

这句话没有错,但对企业来说没有任何价值,企业要的是:

根据《售后政策》第3.2条,普通商品签收后7天内支持无理由退货;

但SKU-20260315属于定制类商品,不支持无理由退货。

如商品存在质量问题,可在签收后15天内申请售后。

这才是RAG要解决的问题:基于企业自己的知识,给出有依据的回答。

要实现这种效果的话,就首先要进入第一步,离线阶段:数据入库

数据上传

我们上传一份产品售后PDF,页面显示嵌入处理中...

很多人看到这几个字,以为系统只是在把文档存进去。其实不是,这背后就复杂了,Dify至少要完成四件事:

解析;

清洗;

分块;

索引;

这四步任何一步出问题,都会影响后面的检索质量和回答质量。而且这里要先强调一个非常重要的判断:

知识库效果的上限,往往不是由模型决定的,而是由入库质量决定的

很多团队知识库效果不好,第一反应是换模型、调Top K、调Score阈值、换向量数据库。

但真实情况大概率是:文档从一开始就没处理好。

第一步:先把文档读出来

系统拿到我们上传的PDF文件后,首先要做的是把它变成纯文本,这一步是最容易出问题的地方。

PDF不像Markdown那样天然就是结构化文本,一份PDF里可能混着:

正文;

表格;

页眉页脚;

水印;

图片说明;

脚注;

目录;

页码;

扫描图片;

...

解析器需要把这些东西分辨清楚,只保留真正有价值的正文内容,这里其实就可以用所谓的skill去处理了,虽然挺“大材小用”的...

如果是Word导出的PDF,解析效果通常还不错,因为底层有文本层可以直接提取。

但如果是扫描件生成的PDF,本质上就是一张图片,系统需要先OCR,把图片里的文字识别出来,这个过程天然容易出错:比如:

“0”被识别成“O”;

“SKU-20240315”被识别错;

表格里的列关系丢失;

页眉页脚被当成正文;

两栏排版被解析成错乱顺序;

...

这也是为什么同样是上传PDF,有的知识库效果很好,有的却总是答非所问。

这跟大模型无关,而是它拿到的原始文本从一开始就不干净。这里也有个重要启示:

知识库的质量跟你处理的细节是成正相关的

如果你对知识库效果要求很高,最好在上传之前就把文档格式处理好。

一般来说,适合知识库的文档格式优先级是:

文档类型 适合程度 原因 Markdown 很高 结构清晰,标题、段落、列表天然可解析 纯文本 很高 解析稳定,但结构信息较少 Word 较高 如果格式规范,解析效果不错 PDF 中等 取决于是否有文本层,扫描件风险很高 Excel 较低 表格语义容易丢失 PPT 较低 信息分散,依赖视觉布局 图片/扫描件 很低 依赖OCR,错误率较高

第二步,清洗

文档被正确读出来之后,还不能直接进入知识库。

我们上传的售后手册PDF,可能每一页都有页眉、页脚,正文中还有一堆网址、邮箱、版权声明、水印文案......

这些内容对回答用户问题没有任何帮助。如果不清理掉,后面分块的时候就会被切进知识片段里,最终污染检索结果。

比如用户问:超过7天还能退货吗?

系统本来应该召回退货时效规则。结果因为每一页都有一段版权声明:本文档归XX公司所有,未经授权不得复制传播。如果这些内容大量重复,就会进入很多chunk,影响向量表示,甚至在检索结果中反复出现。

所以Dify在分块之前会做数据清洗,比如去掉:

连续空格;

多余换行符;

制表符;

URL;

电子邮件;

一些明显无意义字符;

...

这里也是需要特别注意的,不管是Dify还是其他知识库平台,系统自带的清洗能力都是有限的。它能处理一些通用噪音,但处理不了所有业务噪音,比如:

过期条款;

重复政策;

错误版本;

内部讨论备注;

不适合对外暴露的信息;

表格转文本后的结构错乱;

制度之间的冲突;

...

这些东西更多需要我们在上传前处理。对应到实际操作,就是一个很朴素的原则:

不要把未经整理的资料一股脑上传到知识库,数据处理越细致,后面效果越好

很多团队RAG技术说的倒是头头是道,但一到数据处理就容易烦躁,最后搞得很粗糙,最终的结果就是在做垃圾进,垃圾出。

文档质量不行,后面再好的Embedding模型、Rerank模型、向量数据库,都只是把垃圾更快地找出来。

PS:所以我们才说,好的RAG 80%的时间在搞数据呢

第三步:chunk

清洗完成后,系统会把一篇完整文档切成若干个小片段,这一步叫Chunking,也就是文档分块。

很多人第一次接触RAG时不理解为什么要切?原因很简单:

检索时,系统不可能把整篇文档都返回给大模型,而是只返回跟用户问题最相关的几个片段

如果不分块,检索的最小单位就是整篇文档,那用户问一个很小的问题,比如:

订单超过7天还能退吗?

系统可能把整份几十页的售后手册都塞给模型。这样会带来几个问题:

上下文太长;

无关信息太多;

成本太高;

响应变慢;

模型注意力被干扰;

关键信息反而被淹没;

...

所以分块的本质是:定义知识检索的最小返回单位。

但所有的分块都是个麻烦事,因为他的效果好不好只能不停测试,纯靠经验,分块有一个经典两难:太大,不精准;太小,不完整。

如果切得太大,一个片段里包含多个主题,向量模型在把它转成向量的时候,语义表达会变得模糊。比如一个chunk里同时写了:

退货规则;

换货规则;

发票规则;

运费规则;

...

那这个chunk的向量到底表示什么?它试图同时表示很多件事,结果哪件事都表示不精准。

反过来,如果切得太小,一个片段只有半句话,也不行。比如:

超过7天后

单独看这一句没有任何意义。模型不知道超过7天后怎么样,是不能退,还是可以换,还是要人工审核。所以好的分块要满足几个要求:

语义完整:每个块最好能独立表达一个完整意思;

长度合适:不能超过Embedding模型的输入限制;

粒度适中:既不能太粗,也不能太碎;

上下文连贯:边界处的信息不能被切断;

检索友好:用户问一个问题时,相关块能被稳定召回;

只不过这里看起来建议很多,真的如何切还是要不停的做测试,这也是为什么RAG项目一周出60分Demo,经常半年后还是60分的原因...

以下是一些常见分块策略,大家可以好好看看,这块很容易懵逼的:

常见分块策略

一、固定长度分块

固定长度分块最简单。比如每500个token切一块。

优点是:

实现简单;

速度快;

适合快速验证;

缺点也很明显:

不理解语义;

可能把一句话切断;

可能把一个表格切烂;

可能把标题和正文分开;

比如原文是:

商品签收后7天内支持无理由退货,但定制类商品、虚拟商品、已拆封影响二次销售的商品除外。

如果固定长度刚好切在中间,就可能变成:

块1:

商品签收后7天内支持无理由退货,但定制类商品、

块2:

虚拟商品、已拆封影响二次销售的商品除外。

这两个块单独看都不完整。所以固定长度分块不太适合严肃生产场景,除非文档本身高度规整。

二、语义边界分块

更常见的是按自然语言边界分块,比如:

按段落;

按句号;

按换行;

按标题;

这种方式比固定长度更合理,因为它尽量在自然边界上切。

比如Dify的通用分段法,默认分段标识符是双换行符,也就是优先按段落切,这符合大多数文档的写作习惯。

一个段落通常表达一个相对完整的意思,所以按段落切比按固定字符数切更安全。

三、递归分块

现实文档不会都那么规整。有些段落特别长,一个段落可能几千token。这时候只按段落切就不够了。

所以很多系统会采用递归分块策略:

先尝试按大边界切,比如章节、段落;

如果还是太长,再按句子切;

如果句子还是太长,再按空格切;

最后实在不行,才按字符切;

这其实就是尽量保留语义边界,不得已再降级。

Dify在分段最大长度超过限制时,也会采用类似思路:先尽量按自然边界切,最后才使用更粗暴的方式。

这比简单固定长度要靠谱得多。

四、结构感知分块

如果文档结构比较明确,比如Markdown、HTML、技术文档,就可以按结构分块。比如:

一级标题;

二级标题;

代码块;

表格;

FAQ问答对;

列表项;

这种方式非常适合技术文档、产品手册、制度文档。比如FAQ文档,最理想的分块方式不是按500 token切,而是按一个完整Q&A切:

Q:订单超过7天还能退吗?

A:普通商品签收超过7天后不支持无理由退货,但如存在质量问题,可在15天内申请售后。

这个块天然就是一个完整知识单元。如果你把Q和A切开,检索效果就会明显下降。

五、智能语义分块

更高级的方式是用模型判断语义边界。

比如通过Embedding计算相邻句子的语义相似度,当语义突然变化时,说明话题发生切换,可以在这里切分。

或者直接让大模型阅读文本,判断哪些内容应该放在同一个chunk。

这种方式效果可能更好,但成本更高,也更复杂。所以一般适合:

高价值知识库;

文档复杂;

对准确率要求很高;

数据规模没有特别大;

对于大多数企业知识库,一开始不需要这么复杂。先把文档整理好,再用递归分块或结构化分块,通常已经能解决大部分问题。

只不过,往往做到一定阶段会发现,还是得请专家按照智能语义做分块,甚至引入更复杂的树形分块逻辑。

好,至此我们回归Dify。

Dify:三个核心参数

Dify提供了通用分段法,里面有三个关键参数:

分段标识符;

分段最大长度;

分段重叠长度;

分段标识符

分段标识符决定在哪里切。默认是双换行符,也就是按段落边界切。

如果你的文档有自己的分隔标记,也可以自定义。比如:

FAQ文档可以用“Q:”作为边界;

Markdown文档可以按标题切;

政策文档可以按“第X条”切;

客服话术可以按“场景:”切;

这里的核心是让系统尽量按业务语义切。比如售后政策里经常有这种结构:

第1条:退货范围

第2条:退货时效

第3条:不支持退货的情形

第4条:退货运费承担

如果你能按“第X条”切,效果通常比纯粹按段落切更好。因为每一条本身就是一个规则单元。

分段最大长度

分段最大长度决定每块最大多大。Dify默认是1024 token。

这个值不是越大越好:块越大,上下文越完整,但检索越不精准、块越小,检索越精准,但信息可能不完整。

一般来说,可以从下面这个经验出发:

文档类型 建议块大小 FAQ 200-500 tokens 客服话术 300-700 tokens 产品说明 500-1000 tokens 技术文档 500-1200 tokens 法务/制度文档 600-1200 tokens 学术/长报告 800-1500 tokens

但要注意,这只是建议,正如我们之前说的:效果好不好,只能不停的做测试。所以真的好不好还是要看后续的观测指标,比如:用户的问题能不能稳定召回完整答案。下面给个案例:

订单超过7天还能退吗?

最理想的chunk里应该同时包含:

普通商品退货时效;

特殊商品例外;

质量问题特殊处理;

大促订单规则;

...

如果块太小,只召回一句“超过7天不支持退货”,可能会漏掉“质量问题可售后”的例外条件。这就会导致回答不完整,甚至产生业务风险。

分段重叠长度

分段重叠是为了解决一个很现实的问题:关键信息刚好被切断了怎么办?比如:

块1:

普通商品签收后7天内支持无理由退货。

块2:

但定制类商品、虚拟商品、已拆封影响二次销售的商品除外。

如果用户问:

定制商品能退吗?

块1和块2都可能不够完整,重叠的意思是,相邻两个片段之间共享一部分内容。

这样即使边界切得不够完美,也至少有一个片段包含完整上下文。

Dify默认重叠50 token,官方建议一般设为最大长度的10%-25%。

比如最大长度1000 token,那么重叠可以设置在100-250 token之间。

但也不能重叠太多。重叠过多会带来几个问题:

存储变多;

向量化成本变高;

检索结果重复;

大模型看到大量相似片段;

最终回答可能变啰嗦;

以上就是Dify知识库从设计角度想要解决的问题,其他知识库大差不差,而Dify这里还提供了个特别的能力:

父子分块

除了通用分段法,Dify还提供了父子分块。这个能力很重要,因为它解决了RAG里一个非常核心的矛盾:

检索需要小块,生成需要大块。

这里有个矛盾:小块语义更聚焦,更容易精准匹配用户问题,比如用户问:

SKU-20240315支持换货吗?

如果有一个小块刚好写着:

SKU-20240315属于定制类商品,不支持无理由退货,但支持质量问题换货。

这个小块会非常容易被召回。

但如果只把这个小块丢给模型,模型可能缺上下文,不知道这个规则属于哪个政策、是否有适用范围、是否有时间限制。

所以生成回答时,模型又需要更完整的上下文。父子分块的思路就是:

入库时同时切成大块和小块;

检索时用小块匹配;

命中后返回对应的大块给模型;

换句话说:

用小块提高召回精度,用大块保证回答完整性

这很有点树形结构,和知识图谱的意思,是处理复杂场景的利器

这非常适合长文档、制度文档、产品手册、技术文档。比如一章售后政策是父块,其中每一条规则是子块。

用户问题先命中某一条规则,然后系统把整个相关章节返回给模型

这比单纯大块或单纯小块都更稳。

如果你做的是企业知识库,我很建议优先关注父子分块,尤其是文档比较长、规则之间有关联的时候。并且市面上有些类似的开源框架,比如:PageIndex,之前使用效果一般般,现在怎么样大家可以自己去试试。

检索模块

分块完成后,这些知识片段还只是一堆文本,文本本身没法被高效语义检索,接下来要做的,就是给它们建立索引。

Dify里有两种常见选择:

高质量模式;

经济模式;

这两个名字有点产品化,我们翻译成技术语言就很好理解:

高质量模式:向量索引;

经济模式:关键词索引;

高质量模式:向量化

如果选了高质量模式,系统会调用我们指定的Embedding模型,把每个知识片段转换成一组数字,也就是向量:

向量是用数学方式表示文本语义,语义相近的文本,向量距离也更近

比如:怎么退货、商品退换流程、售后申请方式,这几句话字面上不完全一样,但语义接近,Embedding模型会把它们映射到相近的位置。

这样用户问怎么退货时,即使文档里没有完全一样的关键词,也能找到商品退换流程。

这是向量检索比传统关键词检索强的地方。但这里有一个非常关键的工程原则:文档和查询必须使用同一个Embedding模型,也就是:

离线阶段,文档chunk被Embedding模型转成向量

在线阶段,用户问题也要被同一个模型转成向量

只有这样,它们才在同一个语义空间里,才能比较距离。

如果文档用模型A向量化,查询用模型B向量化,那就像两套坐标系,检索结果会非常不稳定。

这也是RAG系统里一个常见坑,不瞒各位,最初我在这里栽过跟头...

经济模式:关键词索引

如果选了经济模式,系统不做向量化,而是用分词器从每个片段中提取关键词,建立关键词索引。

中文里常见的是Jieba分词。这种方式的优点是:

不需要调用Embedding模型;

成本低;

入库速度快;

对精确词匹配友好;

但缺点也很明显:它只能做字面匹配,不理解语义。

比如用户问:

怎么退货?

文档里写的是:

商品退换流程。

关键词不一致,可能就匹配不到。

但如果用户问:

SKU-20240315支持换货吗?

关键词检索反而很有优势,因为SKU、订单号、产品型号、人名、编号这类精确信息,向量检索不一定敏感,关键词检索通常更稳定。

所以经济模式不是完全没用。它适合:

成本极度敏感;

文档规模不大;

查询以精确关键词为主;

只是做简单搜索;

不需要复杂语义理解;

先阶段还流行一种做法,用经济模式筛选前会用模型去做关键词的泛化比较,这样也既能追求精确性又能追求泛化性,是我们在工作中常见的手段。

这里有个特别重要的点要说下:

索引模式是源头决策,不是后面调Top K、调Score阈值就能补回来的

比如你一开始选了经济模式,后面再问为什么用户换种说法就搜不到,为什么同义词匹配不上,为什么语义召回效果不好,那就不好回答了...

因为系统从一开始就没有把知识放进语义空间里。

建索引

向量化完成后,还没结束。

因为这些向量如果只是简单存起来,用户每问一个问题,系统都要把问题向量和库里的所有chunk一个个比较。

如果你的知识库只有几百个chunk,问题不大;但如果你的知识库有几十万、几百万个chunk,搜索就非常慢了。

所以系统还需要建索引,索引的作用很简单:

让系统更快找到可能相关的知识。

有索引的知识库,就像书有了目录、章节和页码,可以先定位到售后政策,再定位到退货规则,再找具体条款。

向量数据库里常见的HNSW、IVF、PQ、FAISS这些词,本质上都是在解决同一个问题:

如何在大量向量里,又快又准地找到相似内容。

但对Dify用户来说,不需要一开始就深入这些算法,你只要先理解一件事:

Embedding决定能不能理解语义,索引决定能不能高效检索

到这里,离线阶段才算真正结束。

我们上传的售后手册,已经从一份PDF,变成了可以被搜索、可以被召回、可以被大模型引用的一组知识片段。

接下来,就进入用户真正感知到的部分:

提问→答案

当用户问:

SKU-20260315这款商品超过7天还能退吗?

一个健壮的RAG系统又会进入链路:

用户提问→查询改写/知识库选择→召回→重排→TopK过滤→拼接上下文→大模型生成回答

第一步:查询改写

用户的问题往往不是标准检索语句。比如用户问:

这个东西过了7天还能不要了吗?

人能理解他大概率是在问退货,但知识库里可能写的是:

商品签收后7天内支持无理由退货。

这时候如果直接检索,效果可能不稳定。

所以很多RAG系统会先做查询改写,把用户口语化、模糊化的问题,改写成更适合检索的表达。比如改写成:

商品签收超过7天是否支持退货

或者进一步拆成几个检索意图:

退货时效;

超过7天;

无理由退货;

特殊商品例外;

这一步的目标不是回答问题,而是让问题更容易搜到正确资料。当然,查询改写也不是越复杂越好。

如果改写过度,反而可能改变用户原意,所以在企业知识库里,查询改写最好只做澄清和标准化,不要替用户脑补太多。

总之一句话:所有的改写都应该往知识库靠。

第二步:知识库选择

企业场景通常不是一个知识库,而是一堆知识库,这会加大检索难度:

产品说明知识库;

售后政策知识库;

物流规则知识库;

...

用户问:

大促订单超过7天还能退吗?

这个问题看起来是售后问题,但它可能同时涉及:

售后政策;

大促活动规则;

订单时效规则;

如果系统只去售后库里找,可能漏掉活动条款、如果系统所有知识库一起搜,又可能召回一堆不相关内容。

所以这里要决定:到底先判断问题属于哪个知识库,还是直接全库检索?

一般来说有两种方式:

第一种是先让模型判断问题属于哪个知识库,再去对应知识库检索。优点是结果更干净、成本更低、缺点是如果判断错了,后面就直接漏掉答案。

第二种是多知识库一起检索,然后合并结果。优点是不容易漏、缺点是召回结果更杂,后面重排压力更大,这里一般建议是:

场景 建议 HR、财务、法务边界很清楚 可以先做知识库选择 售后、物流、活动规则经常交叉 优先多库检索 项目早期还没摸清问题分布 先多库检索,再慢慢优化路由

RAG里有个原则很重要:前面可以多召回一点,特别注意不要一开始就把正确答案排除掉。

第三步:召回

确定去哪找之后,就进入真正的召回。召回就是从知识库里先捞出一批可能相关的候选片段。

这一步几乎就是能拿出多少就拿多少出来,召回阶段追求的是:快,并且别漏掉关键数据。

Dify这里主要提供三种检索方式:

向量检索;

全文检索;

混合检索;

一、向量检索

向量检索是把用户问题转成向量,然后去向量数据库里找最相近的chunk。

它擅长处理语义相似。比如用户问:

怎么退货?

文档里写:

商品退换流程如下。

虽然字面不一样,但意思接近,向量检索有机会命中。

这就是向量检索的优势:用户怎么说不重要,意思接近就有机会搜到。

但它也有短板。比如用户问:

SKU-20260315支持换货吗?

SKU这种编号本身没有太多语义,向量检索不一定敏感,它可能会召回一堆换货规则,但没有命中这个具体SKU。

二、全文检索

全文检索依赖关键词匹配,对精确词非常友好,比如:

SKU;

订单号;

合同编号;

错误码;

...

只要文档里出现了这些词,它就容易找到,当他是没有语义能力的。

三、混合检索

很多大聪明应该都想到了,对:我全要,所以出了混合检索。Dify的混合检索,就是同时走这两路,然后把结果合并。

在大多数企业知识库场景里,如果只求交差拿尾款,无脑选择混合检索就好。

尤其是客服、售后、技术支持、内部制度问答这类场景,用户问题通常不是纯语义,也不是纯关键词,而是两者混在一起。

而且这东西在初期数据量不大的时候,表现挺不错的...

第四步:重排

召回之后,系统手里会有一批候选片段。但候选片段只是可能相关,不代表真的最相关。比如用户问:

Python异步编程最佳实践

系统可能召回:

Python异步编程指南;

Python编程最佳实践;

JavaScript异步编程最佳实践;

这三个都沾边,但真正最相关的是第一个。

召回阶段很难做这么细的判断,因为它追求的是快和全,所以后面需要重排。重排的作用是:把召回回来的候选片段,再按照和用户问题的真实相关性重新排一遍。

你可以这么理解:召回是海选,重排是复试。

PS:总而言之,大家也看出来模型项目开发的特性了,也不过是用更多的Token判断去拿到更精准的结果

综上,在做切片和索引的时候就一定要追求相关性被更多的被找出、而在做重排时候,又要保证拿到真正需要的数据

Rerank模型

这里如果使用Rerank模型,系统会把用户问题和候选chunk一起交给重排模型,让它判断每个chunk到底和问题有多相关。

它比单纯向量相似度更细,因为它不是只比较两个向量距离,而是会更深入地看问题和文本之间的匹配关系。

所以Rerank通常能明显提升最终效果,代价也很清楚:成本和效率。

所以要不要开Rerank,取决于场景。如果只是内部知识助手,可以先不开,把链路跑通。

如果是客服、售后、法务、医疗、金融、技术支持这种对准确性要求高的场景,还是尽量开。这些场景里,答错的成本通常比多花一点调用成本高得多。

第五步:Top K过滤

重排之后,系统会得到一组排好序的片段,但不是所有片段都要给大模型:Top K决定最多给模型几个片段。

比如Top K=3,就只取前三个片段拼进上下文。很多人觉得Top K越大越好,这其实不对。

大模型不是看到越多资料就越聪明。如果你塞进去10个片段,其中3个相关,7个不相关,模型反而可能被噪音带偏。

PS:说白了,还是因为不确定性,需要大量的重试所致

比如,在政策类知识库里,不同规则经常有适用范围:

普通商品支持7天无理由;

定制商品不支持无理由;

大促商品按活动规则执行;

质量问题可以走售后;

海外订单运费另算;

如果上下文塞太多,模型可能把规则混在一起,给出一个看似完整但其实不严谨的答案,那么这里给模型多少条数据,就很可能是个综合性选项了。

根据经验,一般可以先这样设置:

场景 Top K建议 FAQ问答 3-5 客服政策 3-6 技术文档 5-8 长文档总结 8-12 多规则综合判断 5-10

如果chunk比较大,Top K就小一点

如果chunk比较小,Top K可以适当大一点

如果用了父子分块,返回的是父块,那Top K不能太大,否则上下文很快就会爆

第六步:Score过滤

除了Top K,还有一个很重要的参数:Score阈值:

Top K是数量控制。

Score阈值是质量控制。

即使某个片段排进了Top K,但如果相关性分数低于阈值,也应该被过滤掉,这个参数主要防止系统硬凑答案。

PS:还是那句话,模型第一步检索希望越多越好,到重排和Score阶段,就希望越少越好了,说白了还是因为模型特性所致,没办法做到特别稳定

比如用户问:

你们公司创始人喜欢喝什么咖啡?

知识库里根本没有相关内容。但检索系统总能找出几个相对最像的片段。如果没有Score阈值,这些片段就会被塞给模型,模型很可能开始硬编。

所以Score阈值的意义是:知识库里没有依据时,不要强行回答。

一般来说:

阈值低,召回更宽,但噪音更多;

阈值高,结果更干净,但可能漏掉答案;

所以初期可以从0.5-0.7之间开始,根据真实日志慢慢调。

如果经常答非所问,就提高阈值。如果明明有答案却经常找不到,就降低阈值。高风险场景里,宁可保守一点:当前知识库中没有找到足够依据,建议转人工处理。

第七步:拼接上下文

经过召回、重排、过滤之后,系统会拿到最终片段,这些片段会被拼接进prompt,和用户问题一起交给大模型。

关于如何拼接虽然已经是最后一步,也是比较简单的一步,但还是有些技巧的,一般至少要告诉模型三件事:

只能基于已提供资料回答;

资料不足时要明确说不知道;

回答时尽量标注依据来源;

比如客服场景里,prompt里最好明确:

请基于以下知识片段回答用户问题。

如果知识片段中没有足够依据,不要编造,请提示转人工。

涉及退货、退款、换货等政策时,必须说明适用条件和例外情况。

这样模型才不会拿通用知识乱补。

全程可观测性

最后,大模型基于用户问题和检索到的知识片段生成回答。理想情况下,它应该做到:

回答用户问题;

引用知识库依据;

说明适用条件;

区分普通情况和例外情况;

资料不足时拒绝乱答;

但这里问题就来了,就是回答的不好怎么办?

RAG项目可观测性和飞轮系统,就是今天留给大家的思考题了

对吧,我们常常说回答的像不像人不重要,但回答得有依据、可追溯、可控制就很重要了。

现在我们再回头看Dify的配置项,就会发现它们不是孤立参数,而是分别控制RAG链路里的不同环节:

配置项 对应环节 本质作用 索引模式 向量化/建索引 决定用语义检索还是关键词检索 分块方式 文档分块 决定知识片段颗粒度 分段最大长度 文档分块 控制chunk大小 分段重叠长度 文档分块 防止边界信息丢失 检索方式 召回 决定按语义找、关键词找,还是两者都用 Rerank 重排 决定候选片段怎么重新排序 Top K 上下文过滤 决定最多给模型多少片段 Score阈值 上下文过滤 决定低相关内容是否丢弃

所以调知识库,不应该上来就问:AI客服回答得很操蛋,该怎么办?

而应该先问:

文档本身干净吗?

chunk切得合理吗?

索引模式选对了吗?

召回方式适合业务问题吗?

是否需要Rerank?

真实问题日志里到底漏召回多,还是噪音多?

如果前面文档质量和分块都没做好,后面再怎么调Top K,都只是修修补补。

所以比较合理的调优顺序是:

文档质量→分块策略→索引模式→检索方式→重排→Top K/Score阈值→Prompt约束

这就是为什么我一直说,知识库不是一个简单功能,而是一个数据工程,Dify只是把这些能力做成了配置界面。

但配置背后的因果关系,你还是得懂!

热点新闻