RAG教程-实战篇-第五节 知识检索
如果结果不如你所愿,就在尘埃落定前奋力一搏。——《夏目友人帐》
有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。——《十宗罪》
维持现状意味着空耗你的努力和生命。——纪伯伦
第五节 * 知识检索
CSDN:会员活动入口,
一. 本节目标
上一小节,我们准备好了我们的知识库,这一章节我们来探讨如何根据用户的输入来进行知识检索,以及在检索中我们遇到的问题及处理办法。
再开始之间我们先对上一节中的内容做个补充。(这几天状态不佳,文档的口语化和质量有点水了。理解理解,说清楚即可… )
补充: 上一节中分块大小
| 模型上下文窗口 | 文本类型 | 建议分块大小(中文字) | 重叠窗口(中文字) | 修正/补充说明 |
|---|---|---|---|---|
| 4k Token | 短文档、简洁说明 (如产品手册、FAQ) | 300 - 500 字 | 50 - 100 字 | 数值合理。 4k Token 约等于 600-800 中文字(取决于编码),此分块大小能确保单个窗口内包含 5-10 个切片,适合精准问答。 |
| 8k Token | 中等长度文档 (如论文、研报) | 500 - 800 字 | 100 - 150 字 | 数值合理。 稍大的块有助于保持论文的逻辑连贯性,重叠增加是为了防止跨段落的语义丢失。 |
| 16k+ Token | 长文档、复杂语境 (如书籍、万字财报) | 800 - 1500 字 | 150 - 250 字 | 建议调大。 原数据 1200 字上限略显保守。大窗口模型(如 128k)完全有能力处理更大的上下文,增大块尺寸有助于模型理解长距离依赖关系(如小说情节、长逻辑链条)。 |
🧐 深度检验与补充说明
为了确保数据的严谨性,原数据中的换算关系可以按照以下技术层面的校准:
1. 关于 Token 与中文字的换算
- 原数据假设:4k Token ≈ 3000 字。
- 实际情况:
- 在主流模型(如 GPT-4, Claude 3, Qwen-72B)中,1 个中文字通常占用1.5 到 2 个 Token。
- 因此,4k Token 实际上只能容纳约 2000 - 2600 个中文字,而不是 3000 字。
2. 关于“重叠窗口”的重要性
补充:重叠不仅仅是为了防止切断句子,更是为了**“语义补全”**。
在向量检索中,如果切分点恰好在一个关键概念中间,向量表示会失真。
建议:重叠部分通常设置为分块大小的
10% - 20%
是行业最佳实践。
- 300字块 → 50字重叠 (~16%) ✅
- 800字块 → 150字重叠 (~18%) ✅
- 原数据符合这一黄金法则。
3. 关于“父子索引”策略
对于
16k+ Token
的模型,现在的最佳实践不仅仅是增大分块,而是使用
父子索引:
- 检索小:检索 200 字的小块(为了向量匹配精准)。
- 生成大:找到小块后,把该小块所属的 1000 字大块(父块)发给模型。
- 这样既利用了向量匹配的精准度,又利用了大模型的长窗口理解能力。
二. 检索的本质
在开始实战之前,我们来思考一个内容,检索是什么?他和我们经常说的搜索有啥区别?
这里我整理了一些内容,大家可以参照了解下:
| 维度 | 传统搜索 (如百度/Google) | RAG 检索增强生成 |
|---|---|---|
| 核心目标 | 找文档。帮你找到包含关键词的网页或文件列表。 | 找答案。直接生成一段综合了多方信息的自然语言回答。 |
| 输出形式 | 满足并带有关键字的内容 | 一段完整的文本、代码或表格,通常附带引用来源。 |
| 理解能力 | 侧重字面匹配(关键词)或简单的语义匹配。 | 侧重意图理解。能把“怎么修电脑”和“电脑故障排除”联系起来。 |
| 处理数据 | 数据本身。 | 数据本身。 |
| 解决痛点 | 信息过载,用户需要自己筛选和总结。 | 大模型幻觉(胡说八道)和知识滞后(不知道最新新闻)。 |
(简而言之,通俗易懂 就是查找知识,
一个是关键字(字面值)准确查找,如数据库中的姓名查询,一个是使用算法进行匹配查询
一个字符编码值准确查询,一个使用数学公式进行相似度的查询。
查询的结果都不是唯一且准确的。(当前搜索在全匹配的模式下是准确且唯一的)
)。
RAG 的核心逻辑可以总结为四个字:“先搜,再答”, 从而避免“一本正经地胡说八道”。
三. RAG检索的流程
- 索引阶段 (Indexing):
首先,我们将海量的非结构化数据(如 PDF、Word、Wiki、代码库)进行切片,并通过嵌入模型(Embedding Model)将其转化为计算机能理解的“数字指纹”(即向量),存储在向量数据库中。 - 检索阶段 (Retrieval):
当你提问时,RAG 系统不会直接把问题丢给大模型,而是先做以下几步:- 向量化:把你的问题也变成“数字指纹”。
- 相似度匹配:在向量数据库中,寻找与你的问题“指纹”最相似的文档片段。
- 混合检索 (进阶):为了更精准,现在的 RAG 通常结合关键词检索(精确匹配术语,如错误代码)和语义检索(理解意图),这叫混合检索。
- 增强生成 (Augmented Generation):
系统把你的问题+检索到的相关片段(作为上下文/参考资料)一起打包,发送给大模型。- Prompt 示例:“请根据以下参考资料 [资料A, 资料B…] 回答用户的问题:[你的问题]。”
四. 检索中的问题以及处理措施
4.1 从流程看问题
用户的输入
用户的输入处理是检索阶段最重要的一个环节,不用的用户有不同的语义理解和表述,有些人喜欢客客气气的问题,有些人喜欢跳跃式的问,不管是哪种,不确定性的输入和确定性的输出诉求就是个矛盾对立体。而在应用环节我们唯一能做的就是诱导用户的输入。
相似度匹配
RAG的数据匹配依赖于数据定理(算法),如:欧氏距离,余弦相似度等,它的深入应用场景往往是需要较高的知识场景,90%的企业应用大都不会过多关注这块。往往借助的是已经完成的工具使用即可。
召回数据
相似度匹配的知识向量,并不是唯一的,召回的条数越多,消耗的token和LLM回答的范畴就会变大,受约于成本。力求准确。混合检索和重排也是这块我们常常使用的方法。
LLM处理
生成内容,离不开LLM的处理,LLM根据提供的内容进行回答,提示词的约束和模型文本总结理解能力是产出合理答案的关键,这一阶段能做的就是选择。
4.2 处理措施
用户的输入趋于明确(这一阶段往往需要多余的token来保障输出)
不明确的内容让其变为明确,使我们在这离解决问题的常用手段,可以从以下几个方面(rag 调优的时候还会再次探讨)
- 通过LLM预先分析客户问题的意图(分析时候通过提示词约定范围,防止LLM幻觉”)。
- 通过LLM对客户的问题生成多个相似语境的问题,再让这些问题和原问题一起进行相似度匹配(也就是多路召回技术)
- 在无法确定用户输入或者有明确界定输入内容时候,预先通过用LLM和用户进行多伦问题,以产出合适的输入(也就是引导式补全技术)
召回的处理
在研发中并非召回的数据越多越好,召回的越多先不说检索的时间消耗,在后期处理和整理上也会面临问题,一般我们召回的数量控制在5左右。
为保障更好的评估参数(准确度等)我们会采用混合检索的方式进行。(但并不绝对,要评估)
对召回的数据还会使用重排模型进行重新排序,获取前5.
LLM处理
长下文的内容过多,会使每一次的token消耗变多,文档中非匹配内容的去除也是必要的,保障语义的完整和成本的双重考就。
进行文档压缩。
五. 检索的代码实现
这里我们使用langchain 进行研发,总体方式较为简单,核心代码如下:
retriever = CusParentDocumentRetriever(1, f"col_{1}") multi_query_retriever = MultiQueryRetriever.from_llm( retriever=retriever, # 这里将混合检索作为底层检索器 llm=chat, include_original=True # 包含原始问题 ) # --- 重排序 (Rerank) --- compressor = DashScopeRerank(model="qwen3-vl-rerank", top_n=5) # 压缩器 compressed_retriever = ContextualCompressionRetriever( base_compressor=compressor, base_retriever=multi_query_retriever ) # 检索 docs = compressed_retriever.invoke(query)CusParentDocumentRetriever 代码在上一小节中,这里不再说明。
