nlp:知识库检索和dify知识库创建

目录标题

一、知识库检索

知识库检索有全文检索、语义检索、混合检索三种方式

全文检索:基于关键词+倒排索引技术。

语义检索:基于向量+相似度计算。 余弦相似度

混合检索:将全文检索和语义检索的结果进行汇总,再次排序,得到最终检索结果

全文检索线:

离线:文档 → 分词 → 建倒排索引

在线:query → 分词 → 查倒排索引 → 打分(BM25) → 结果

全文检索是一种能够直接从海量的非结构化文本数据(如文章、报告、邮件等)中快速查找出包含特定词汇或短语的信息的技术。它的核心思想类似于书籍末尾的索引,通过预先建立"词汇-文档"的映射关系,实现高效的内容搜索。

全文检索系统的工作流程可以概括为两个核心阶段:索引构建 和 查询检索:

索引构建 (Indexing):这是搜索前的准备工作,也是最关键的一步。系统会对待搜索的文档集合进行处理:

  • 分词:首先,将连续的文本切分成有意义的词汇单元。这对于中文尤为关键,例如,将"全文检索技术很棒"切分为"全文"、"检索"、"技术"、"很棒"。
  • 创建倒排索引:建立一个"倒排索引"。这就像一本书的索引表,记录每个词语出现在哪些文档中,以及出现的位置和频率。当用户搜索时,系统无需扫描所有文档,只需直接查找这个索引表,就能瞬间知道哪些文档包含关键词。

查询检索 (Search):当用户输入查询关键词时,系统执行以下操作:

  • 查询处理:对查询词进行同样的分词处理。
  • 索引查找:在倒排索引中查找这些分词后的词汇,找到包含它们的文档集合。
  • 相关性排序:最后,系统使用相关性排序算法(如 BM25)对结果进行评分排序,将最符合用户需求的文档排在前面

语义检索线:

离线:文档 → 切块 → embedding模型编码 → 存向量库

在线:query → embedding编码 → 向量相似度检索 → 结果

混合检索:

就是同时执行全文检索和向量检索

从查询结果中选择匹配用户问题的最佳结果。 混合的策略一般分两种

权重:用户自己通过数值设定关键词和语义的比重,在进行一次排序

rerank:通过rerank模型,把两种检索方法检索到的结果进行混合,再进行一次排序。

用一个类比帮你记

  • 全文检索 = 图书馆的关键词卡片目录:按"书名里有没有这个词"找书。快、准(对专有名词/编号),但不懂同义词。
  • 语义检索 = 一个读过所有书的馆员:你说"讲孤独的书",他能找到《百年孤独》即使书里没"孤独"二字。懂语义,但可能召回不准、成本高。
  • 混合检索 = 卡片目录 + 馆员一起上,结果合并。

二、混合检索重点分析

疑问1: 是不是全文查出来是段落,语义查出来都是向量?rerank怎么区分两个结果选择,他们没法公用一套打分吧

全文检索和语义检索返回的"东西"本质上是一样的:都是文档片段(段落/Chunk)。区别只在于它们内部计算相似度的方式:全文检索靠词频统计(BM25),语义检索靠向量距离。最终返回给下一环节的,都是带有一个分数的候选段落列表。

至于 Rerank 如何区分并选择:你说得对,它们确实没法公用一套原始打分。所以标准做法是分两步走:先用一种"不看分数只看排名"的方法把两路结果粗粗合并,再用 Rerank 模型对合并后的候选段落重新打一套统一的、真正可比的分数。

第一步:不用分数,用排名来合并(RRF)

既然 BM25 的分数(可能无上界)和向量余弦相似度(0~1)没法直接比大小,就先别比分数了。业界通用的 RRF(倒数排名融合) 只看排名位次。

它的逻辑很朴素:一个文档如果在全文检索里排第 1,在语义检索里排第 3,那它大概率不错;另一个文档如果只在全文检索里排第 20,那它大概率不如前者。RRF 给每个文档算一个融合分: 1 / ( k + 排名 ) 1 / (k + 排名) 1/(k+排名),排名越靠前,贡献越大,然后把两边的贡献加起来。这样就能把两路结果合并成一个候选段落列表(比如取前 20~30 个),完全绕开了"分数不可比"的问题。

第二步:Rerank 用一套统一标准重新打分

拿到合并后的候选列表后,Rerank 模型登场。它和前面两种检索都不一样:它把用户问题和每一个候选段落放在一起,同时输入模型进行深度比对(Cross-Encoder 架构)。

这时,模型输出的就是一个统一的、绝对的相关性分数(比如 0 到 1),表示"这个段落到底能不能回答这个问题"。这个分数是 Rerank 模型自己算的,跟 BM25 无关,也跟向量相似度无关,全场只有这一套标准,所以可以直接用来排序和筛选,挑出最靠前的几个段落送给大模型。

总结

全文和语义检索负责广撒网 ,捞出可能相关的段落;RRF 负责不分、只比名次 地把两路结果粗粗混在一起;Rerank 负责用一套新标准对混好的候选段落做最终的精挑细选。这样就不需要让 BM25 和向量分数去"硬融"了。

疑问2: 混合检索,如果不用rerank,用权重,那score阈值怎么设置,全文减速和语义检索没有一套同意打分,怎么设置阈值啊。

BM25 分数和向量相似度分数不在一个尺度上,不能直接设一个统一阈值。 所以做法不是"设一个阈值",而是先各自归一化到同一尺度,再加权融合,最后对融合分设阈值。

举个例子:

一、为什么不能直接设阈值(先看问题)

假设用户 query 是"如何重置路由器密码"。

全文检索(BM25)返回的原始分数:

段落 BM25 分
段落A 18.3
段落B 12.1
段落C 5.4

BM25 分数无上界 ,取决于词频、文档长度、语料统计,可能 5 分也可能 50 分,没有绝对含义。

语义检索(余弦相似度)返回的原始分数:

段落 余弦相似度
段落A 0.82
段落C 0.76
段落B 0.61

余弦相似度在 -1~1(实际常 0~1),尺度完全不同。

问题:你能设"阈值 = 0.7"吗? 对余弦可以,对 BM25 完全没意义(18.3 和 0.7 没法比)。所以原始分不能直接加权,也不能直接设阈值。


二、第一步:各自归一化到 0,1

对每一路结果内部做 Min-Max 归一化(只用本次召回的这批候选,不是全局):

s ′ = s − s m i n s m a x − s m i n s' = \frac{s - s_{min}}{s_{max} - s_{min}} s′=smax−smins−smin

全文检索归一化(min=5.4, max=18.3):

段落 原始 BM25 归一化
A 18.3 (18.3-5.4)/(18.3-5.4) = 1.00
B 12.1 (12.1-5.4)/12.9 = 0.52
C 5.4 0.00

语义检索归一化(min=0.61, max=0.82):

段落 原始余弦 归一化
A 0.82 1.00
C 0.76 (0.76-0.61)/0.21 = 0.71
B 0.61 0.00

现在两路分数都在 0,1,尺度统一了,可以比较、可以加权、可以设阈值。

⚠️ 注意: Min-Max 依赖"本批候选的 max/min",如果某路只召回 1 条,max=min 会除零,实践中要加保护(如固定用历史分位数,或对单条直接给 1.0)。


三、第二步:加权融合

设权重:全文 0.4,语义 0.6(语义通常权重高些,但可调)。

f i n a l = w 全文 ⋅ s 全文 ′ + w 语义 ⋅ s 语义 ′ final = w_{全文} \cdot s'{全文} + w{语义} \cdot s'_{语义} final=w全文⋅s全文′+w语义⋅s语义′

段落 全文归一化 语义归一化 融合分 = 0.4×全文 + 0.6×语义
A 1.00 1.00 0.4×1.0 + 0.6×1.0 = 1.00
B 0.52 0.00 0.4×0.52 + 0.6×0 = 0.21
C 0.00 0.71 0.4×0 + 0.6×0.71 = 0.43

排序:A(1.00) > C(0.43) > B(0.21)。


四、第三步:对「融合分」设阈值

现在融合分在 0,1,这才是有意义、可设阈值的分数。

  • 设阈值 0.4 → 保留 A、C,丢弃 B。
  • 设阈值 0.5 → 只保留 A。

阈值怎么定? 不是拍脑袋,常用方法:

  1. 离线调参:在验证集上,用标注的"相关/不相关"段落,画 Precision-Recall 曲线,选使 F1 或 Recall@K 最优的阈值。
  2. 按 Top-K 兜底:不设绝对阈值,直接取融合分最高的 K 条(如 K=5),避免"全被阈值滤掉"导致空结果。
  3. 分位数阈值:取本批融合分的第 70 百分位作为动态阈值。
总结两个疑问

无论是用"权重融合"还是用"Rerank",本质上都是在做重排(Re-ranking / 重新排序),只是它们重排所依赖的"打分标准"不同。

权重:用权重加法公式做重排

rerank: 用神经网络模型做重排。

三、dify的知识库创建

选择数据源
分段模式
通用模式

系统按照用户自定义的规则将内容拆分为独立的分段。当用户输入问题后,系统自动分析问题中的关键词,并计算关键词与知识库中各内容分段的相关度。根据相关度排序,选取最相关的内容分段并发送给 LLM,辅助其处理与更有效地回答。

在该模式下,你需要根据不同的文档格式或场景要求,参考以下设置项,手动设置文本的分段规则。

  • 分段标识符 ,默认值为 \n,即按照文章段落进行分块。
  • 分段最大长度,指定分段内的文本字符数最大上限,超出该长度时将强制分段。默认值为 500 Tokens,分段长度的最大上限为 4000 Tokens;
  • 分段重叠长度,指的是在对数据进行分段时,段与段之间存在一定的重叠部分。这种重叠可以帮助提高信息的保留和分析的准确性,提升召回效果。建议设置为分段长度 Tokens 数的 10-25%;

文本预处理规则,过滤知识库内部分无意义的内容。提供以下选项:

  • 替换连续的空格、换行符和制表符
  • 删除所有 URL 和电子邮件地址

配置完成后,点击"预览区块"即可查看分段后的效果。你可以直观的看到每个区块的字符数。如果重新修改了分段规则,需要重新点击按钮以查看新的内容分段。

父子模式

与通用模式相比,父子模式采用双层分段结构来平衡检索的精确度和上下文信息,让精准匹配与全面的上下文信息二者兼得。

父子分段:

子区块(Child-chunk)则是较小的文本单位(如句子),用于精确检索。

系统首先通过子区块进行精确检索以确保相关性,然后获取对应的父区块来补充上下文信息,

从而在生成响应时既保证准确性又能提供完整的背景信息。

用户问题 用子块匹配

返回给大模型是 父块

索引方法
经济模式

在经济模式下,每个区块内使用 10 个关键词进行检索,降低了准确度但无需产生费用。对于检索到的区块,仅提供倒排索引方式选择最相关的区块。

高质量索引

使用 Embedding 嵌入模型将已分段的文本块转换为数字向量,帮助更加有效地压缩与存储大量文本信息;使得用户问题与文本之间的匹配能够更加精准

检索方法
经济索引
高质量索引
相关推荐
2601_9687931433 分钟前
Python Requests 轻量自动化:无需浏览器,实现真人级账号浏览模拟
开发语言·python·自动化
段一凡-华北理工大学10 小时前
工业智能体:从Codex/Claude到项目实战~系列文章05:从“AI助手“到“工业智能体“:能力跃迁与落地范式
人工智能·python·claude·codex·工业智能体·高炉炼铁智能化
深蓝AI10 小时前
ContextVar 到线程池就丢了?asyncio.to_thread 和 run_in_executor 实测
python
岁月宁静11 小时前
什么是 Agent:从"会聊天"到"会做事"
人工智能·python
岁月宁静12 小时前
AI 应用开发工程师简历怎么写:HR 初筛、技术复筛、面试追问,三道关卡各看什么?
人工智能·python·面试
来让爷抱一个12 小时前
Python 异步里混用同步库,事件循环被卡住的全过程
开发语言·python
小肝一下14 小时前
3.基础语法(3)
python
深蓝AI14 小时前
Python 子进程树:父进程被杀后,孙进程为何还在跑?
python
心祭丫丫15 小时前
【每天一个 Python 小案例17】Python 实现通讯录
开发语言·人工智能·笔记·python·学习