knowledge-vault/sources/references/开发笔记/RAG/大模型私有知识库如何提高准确率?切块是关键.md

433 lines
20 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 前言
RAG 就像我们做开卷考试,在回答考题之前,先翻我们准备的资料(通过检索相关文档来增强自己的能力),这样一来,答题不仅更准确,还能带上更多上下文信息,显得更有深度和针对性。
在 RAG 中我们需要提前预备知识资料然后向量化后存到向量数据库中在回答问题的时候并对问题进行向量化然后去检索我们数据库是否有相似的内容如果相似则召回并把召回的内容一并给到大模型Deepseek然后通过大模型的推理归纳给出相应的答案。
**类似下面步骤:**
**第一步:预备数据** 首先,把我们准备的资料知识文档,“切”成一个个小文档块,然后存到数据库里。如果这些小文档块还生成了对应的“嵌入”(可以理解成一种数学表示),那这个数据库就可以升级成向量存储,方便后续的快速查找。
**第二步:检索** 当用提问时,系统先把问题向量化,并通过向量搜索、全文搜索,或者多模态的方式,去数据库里检索最相关的小文档块。当定位到那些和用户问题最匹配的信息片段后,以上下文的方式喂给大模型,这样大模型不仅能更快找到答案,还能确保回答得更精准、更有针对性,同时也减少了幻觉。
## 面临的挑战 
对于企业或者个人来说,有很多政策条文,或者文献,通常都是很长篇幅的内容。如果把这些很长的篇幅给到大模型,基于现有大模型的计算能力则无法一次性处理,那就需要对文本进行切块,然而切块不是越大越好,在向量化时,长文本面临以下核心挑战:
### 一、语义信息稀释
* **1. 多主题覆盖 **:长文本常包含多个主题或观点,整体向量难以准确捕捉细节语义,导致核心内容被淡化
* **2. 上下文连续性丢失 **:直接平均词向量或使用\[CLS]标记的方式无法有效处理长文本的连贯语义关系,可能割裂上下文逻辑
### 二、计算复杂度与资源消耗
* **1. 注意力机制瓶颈 **Transformer 架构的自注意力层具有 O(n²)复杂度,当处理千字以上的长文本时,计算资源呈指数级增长
* **2. 内存压力 **:生成的高维向量需要大量存储空间,检索时可能降低匹配效率
### 三、文本分块技术限制
* **1. 最优分块尺寸选择 **过大的分块导致语义混杂过小的分块破坏上下文连贯性50%重叠分块虽可缓解但增加存储冗余
* **2. 特殊内容处理**:表格、代码段等非连续文本的分割可能破坏结构化信息,影响后续 QA 效果
### 四、模型架构制约
* **1. 输入长度限制 **:多数预训练模型的最大输入长度在 512-2048 tokens 之间,超出部分需截断或分段处理
* **2. 位置编码失真 **:分块处理会重置位置编码,影响模型对长程依赖关系的捕捉
### 五、质量与效率平衡
* **1. 维度优化困境 **:高维向量提升精度但增加计算成本,低维简化计算却损失语义信息
* **2. 噪声敏感性 **:长文本中拼写错误、口语化表达等噪声对向量质量的影响被放大
## 切块方法论 
在上面我们看到“分块”在 RAG 中起到关键角色和面临的挑战,它直接决定了我们召回知识的准确性,因此选择合适的分块方法尤为重要;有效切割文件的关键在于平衡信息的完整性和管理的便捷性,‌ 可以采用**固定大小分块、语义分块、递归分块、基于文档结构的分块以及基于 LLM 的分块**等多种策略 ‌‌。
* **1. 固定大小分块 **:按预定义的字符数、单词数或 Token 数量对文本进行切分,同时保留一定的重叠部分。这种方法实现简单,但可能会将句子截断,导致信息分散在不同的块中 1。
* **2.语义分块 **:根据有意义的单元对文档进行分段,持续将单元添加到现有块中,直到余弦相似度显著下降。这种方法能够保持语言的自然流畅性。
* **3. ‌递归分块 **:基于内在分隔符(如段落或章节)进行分块。如果某个块的大小超过限制,则将其进一步分割为更小的块。这种方法同样能够保持语言的自然流畅性。
* **4. ‌基于文档结构的分块 **:利用文档的内在结构(如标题、章节或段落)进行分块。这种方法能够保持文档的自然结构,但前提是文档具有清晰的结构。
* **基于 LLM 的分块 **:使用提示工程引导 LLM 生成有意义的分块。这种方法结合了大模型的智能,但可能需要更多的计算资源和时间。
<p
style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"
>
<strong style="font-weight: bold;color: black;">
<span>总结表格如下:</span>
</strong>
</p>
<table style="display: table;text-align: left;">
<thead>
<tr
class="firstRow"
style="border: 0;border-top: 1px solid #ccc;background-color: white;"
>
<th
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;font-weight: bold;background-color: #f0f0f0;"
>
<section><span>分块策略 </span></section>
</th>
<th
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;font-weight: bold;background-color: #f0f0f0;"
>
<section><span>优点 </span></section>
</th>
<th
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;font-weight: bold;background-color: #f0f0f0;"
>
<section><span>缺点 </span></section>
</th>
<th
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;font-weight: bold;background-color: #f0f0f0;"
>
<section><span>典型适用场景 </span></section>
</th>
</tr>
</thead>
<tbody>
<tr style="border: 0;border-top: 1px solid #ccc;background-color: white;">
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<strong style="font-weight: bold;color: black;">
<span>1. 固定大小分块 </span>
</strong>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>✅ 实现简单快速</span></section>
</li>
<li>
<section><span>✅ 计算成本极低</span></section>
</li>
<li>
<section><span>✅ 内存占用稳定</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>❌ 可能切断语义关联</span></section>
</li>
<li>
<section><span>❌ 需反复调试块大小</span></section>
</li>
<li>
<section><span>❌ 对长文本不友好</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>基础问答系统</span></section>
</li>
<li>
<section><span>处理格式统一文档</span></section>
</li>
</ul>
</td>
</tr>
<tr style="border: 0;border-top: 1px solid #ccc;background-color: #F8F8F8;">
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<strong style="font-weight: bold;color: black;">
<span>2.语义分块</span>
</strong>
<section><span></span></section>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>✅ 保留完整语义单元</span></section>
</li>
<li>
<section><span>✅ 提升上下文相关性</span></section>
</li>
<li>
<section><span>✅ 动态适应内容</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>❌ 依赖 NLP 模型质量</span></section>
</li>
<li>
<section><span>❌ 计算资源消耗较高</span></section>
</li>
<li>
<section><span>❌ 处理速度较慢</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>专业领域分析</span></section>
</li>
<li>
<section><span>逻辑推理任务</span></section>
</li>
</ul>
</td>
</tr>
<tr style="border: 0;border-top: 1px solid #ccc;background-color: white;">
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<strong style="font-weight: bold;color: black;">
<span>3. 递归分块</span>
</strong>
<section><span></span></section>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>✅ 多粒度内容覆盖</span></section>
</li>
<li>
<section><span>✅ 冗余信息捕获能力强</span></section>
</li>
<li>
<section><span>✅ 灵活调整层级深度</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>❌ 实现复杂度高</span></section>
</li>
<li>
<section><span>❌ 可能产生信息重复</span></section>
</li>
<li>
<section><span>❌ 需要多层索引管理</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>学术文献处理</span></section>
</li>
<li>
<section><span>法律合同解析</span></section>
</li>
</ul>
</td>
</tr>
<tr style="border: 0;border-top: 1px solid #ccc;background-color: #F8F8F8;">
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<strong style="font-weight: bold;color: black;">
<span>4. 文档结构分块</span>
</strong>
<section><span></span></section>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>✅ 精准定位章节信息</span></section>
</li>
<li>
<section><span>✅ 保持原始逻辑结构</span></section>
</li>
<li>
<section><span>✅ 支持跨块引用</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>❌ 依赖文档格式规范</span></section>
</li>
<li>
<section><span>❌ 处理非结构化数据困难</span></section>
</li>
<li>
<section><span>❌ 需要预解析规则</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>技术手册处理</span></section>
</li>
<li>
<section><span>论文解析系统</span></section>
</li>
</ul>
</td>
</tr>
<tr style="border: 0;border-top: 1px solid #ccc;background-color: white;">
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<strong style="font-weight: bold;color: black;">
<span>5. 基于 LLM 的分块</span>
</strong>
<section><span></span></section>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>✅ 理解深层语义意图</span></section>
</li>
<li>
<section><span>✅ 动态生成最优块结构</span></section>
</li>
<li>
<section><span>✅ 适配复杂任务</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>❌ 推理延迟显著</span></section>
</li>
<li>
<section><span>❌ API 调用成本高</span></section>
</li>
<li>
<section><span>❌ 存在模型幻觉风险</span></section>
</li>
</ul>
</td>
<td
style="font-size: 16px;border: 1px solid #ccc;padding: 5px 10px;text-align: left;"
>
<ul
class="list-paddingleft-1"
style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;"
>
<li>
<section><span>高精度问答系统</span></section>
</li>
<li>
<section><span>跨文</span></section>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
## RAGFlow 支持的切块方法 
结合业务场景与文本特点选择合适分块策略是相对较好的方式,在 RAGFlow 中就支持多种分块的方法,下面表格展示了不同分块方法说明及其支持的文档格式
**分块方法:**
| Template | Description | File format |
| ---------------------- | --------------------------------------------------- | ----------------------------------------------------------------------- |
| **General通用** | 支持的文件格式比较多,需要自己设置对应的分割方式,比较难以控制,需要配合自然语言处理模型才会有好的效果 | DOCX、EXCEL、PPT、IMAGE、PDF、TXT、MD、JSON、EML、HTML, JPEG, JPG, PNG, TIF, GIF |
| **Resume简历** | | DOCX、PDF、TXT |
| **Q\&A (问答)** | 问题描述及问题答案,比较适合做客服问答相关 | EXCEL, CSV/TXT |
| **Manual手册** | 会使用 OCR 分割文档 | PDF |
| **Table表格形式文件** | | EXCEL, CSV/TXT |
| **Paper论文** | | PDF |
| **Book书籍类型** | | DOCX, PDF, TXT |
| **Laws律法相关** | | DOCX, PDF, TXT |
| **Presentation演示文稿** | | PDF, PPTX |
| **Picture图片** | | JPEG, JPG, PNG, TIF, GIF |
| **One完整文件** | 文件不会被切割,直接一个文件给到大模型,有很好的上下文,但是文件长度取决于配置的大模型支持的长度 | DOCX, EXCEL, PDF, TXT |
| **Tag标签** | 需要提前设置标签描述与标签,类似 Q\&A在上面的解析中设置标库用会自动匹配命中的块并增加标签 | EXCEL, CSV/TXT |
## 召回方式也很关键
虽然我们掌握了如何对文档进行分块,但对分块的数据召回也是很关键的步骤,怎么提升数据的召回准确率也是一项亟待解决的问题。
影响数据召回准确率的原因有很多,从单一方面很难甚至可以说根本无法解决这个问题,因此提升数据的准确性就需要从多个方面入手。
**以下是目前主流的一些方式:**
**1. 混合检索方法‌** 同时执行向量检索语义匹配和全文检索关键词匹配通过线性加权或倒序融合RRF合并结果。 引入重排序模型如BGE-Reranker对多路召回结果二次排序优先保留高相关片段
**2. 多路召回策略‌** 采用多模型并行检索如BM25、DPR、Embedding模型覆盖不同粒度的匹配需求。 对于复杂查询,将问题拆解为多个子查询,分别检索后合并结果‌。
**3. 动态参数调整‌** 设置相似度阈值如0.5-0.7),过滤低相关片段;根据业务反馈动态调整分块大小和召回数量‌
在RAGFlow中已使用了上述的方法对数据进行召回增强我们在使用的时候可以对相关参数进行调整验证以达到更好的效果。