【速通RAG实战:索引】5.RAG分块策略与Embedding技术
在RAG(检索增强生成)系统中,分块策略与Embedding技术是构建高效索引的关键环节。
1. 分块策略的核心作用
在RAG系统里,原始文档往往篇幅较长,直接将其作为一个整体进行处理会面临诸多问题。一方面,大语言模型处理长文本时能力有限,可能无法有效理解和利用其中的信息;另一方面,在进行向量检索时,长文本生成的向量可能无法精准地反映文本的局部语义信息,导致检索结果不准确。
因此,合理的分块策略能够将文档拆分成合适大小的文本块,便于后续处理和检索。
- 分块(Chunking)将文档拆分为独立语义片段,直接影响 RAG 系统的召回率和生成质量。
- 核心目标:平衡语义完整性与计算效率,避免信息冗余或丢失上下文。
2. 分块策略类型与适用场景
策略 | 特点 | 适用场景 | 问题 |
---|---|---|---|
固定大小分块 | 按固定字符数切分(如512字符) | 同质化文档(新闻、博客) 基准测试 | 可能切断语义单元(如“大模/型”) |
重叠分块 | 相邻块部分重叠(如20字符) | 法律文档、技术手册 需保留上下文完整性 | 冗余存储、计算复杂度高 |
递归分块 | 按分隔符(如段落、句子)逐层拆分 | 长文档(研究报告、法律文本) | 可能模糊语义边界 |
文档特定分块 | 根据格式(Markdown、Python代码)定制切分 | 结构化文档(代码、Markdown) | 依赖格式规范,不通用 |
语义分块 | 基于 NLP 技术(spaCy、NLTK)切分语义单元 | 上下文敏感分析(复杂文档) | 计算资源消耗大 |
混合分块 | 结合多种策略(如固定分块+语义分块) | 多格式动态数据 需平衡速度与准确性 | 实现复杂,调优难度高 |
3. 分块策略实战(LangChain)
1.动态切换分块策略
- 关键代码:动态切换分块策略
from langchain.text_splitter import (RecursiveCharacterTextSplitter, MarkdownTextSplitter, SpacyTextSplitter )# 递归分块示例(默认) text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=128 )# 语义分块(需安装spacy模型) # text_splitter = SpacyTextSplitter( # chunk_size=512, # chunk_overlap=128, # pipeline="zh_core_web_sm" # )# Markdown分块 # text_splitter = MarkdownTextSplitter(chunk_size=512)
2.固定大小分块
def fixed_length_chunks(text, chunk_size=500):return [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]
3.基于段落分块
def paragraph_chunks(text):return text.split('\n\n') # 假设段落以两个换行符分隔
4.递归字符分块
from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200,length_function=len
)
chunks = text_splitter.split_text(text)
4. Embedding 技术核心
Embedding技术是将文本转换为向量表示的过程。在RAG系统中,通过将文本块转换为向量,可以利用向量空间的数学性质进行高效的检索。例如,计算向量之间的相似度(如余弦相似度),从而找出与查询最相关的文本块。
- 嵌入模型作用:将文本映射为高维向量,捕捉语义关系,支持向量检索。
- 模型评估指标:
- MTEB/C-MTEB 榜单:检索任务优先参考 Retrieval Average。
- 模型大小(GB)、最大 Token 数(512)、嵌入维度(平衡效率与精度)。
5. Embedding 实战(SentenceTransformers)
-
关键代码:加载模型与生成嵌入
from sentence_transformers import SentenceTransformer# 加载中文BGE模型(本地或自动下载) embedding_model = SentenceTransformer('BAAI/bge-small-zh-v1.5')# 文本块生成嵌入向量 embeddings = [] for chunk in all_chunks:embedding = embedding_model.encode(chunk, normalize_embeddings=True)embeddings.append(embedding)
1. OpenAI Embeddings
- 特点:性能优秀,能够生成高质量的向量表示,适用于各种自然语言处理任务。但使用时需要调用OpenAI的API,可能会产生一定的费用,并且受限于API的调用频率和数据安全等问题。
- 使用示例(Python):
import openai import osopenai.api_key = os.getenv("OPENAI_API_KEY")def get_openai_embedding(text):response = openai.Embedding.create(input=text,model="text-embedding-ada-002")return response['data'][0]['embedding']
2. Hugging Face Sentence Transformers
- 特点:提供了多种预训练的模型,如
all-MiniLM-L6-v2
等,这些模型在计算效率和性能上取得了较好的平衡,并且可以本地部署,避免了调用外部API的问题。 - 使用示例(Python):
from sentence_transformers import SentenceTransformermodel = SentenceTransformer('all-MiniLM-L6-v2') embedding = model.encode('This is a sample sentence.')
3. 开源领域特定模型
- 特点:针对特定领域(如医疗、法律、代码等)训练的模型,能够更好地捕捉领域内的语义信息。例如,
BioBERT
在生物医学领域表现出色,CodeBERT
在代码相关的文本处理中具有优势。 - 使用示例(以BioBERT为例):
from transformers import AutoTokenizer, AutoModel import torchtokenizer = AutoTokenizer.from_pretrained("dmis-lab/biobert-base-cased-v1.1") model = AutoModel.from_pretrained("dmis-lab/biobert-base-cased-v1.1")text = "This is a medical text." inputs = tokenizer(text, return_tensors='pt') outputs = model(**inputs) embedding = torch.mean(outputs.last_hidden_state, dim=1).squeeze().detach().numpy()
6.优化Embedding的策略
- 多模态Embedding:结合文本、图像、音频等多种模态的信息进行Embedding,以获取更丰富的语义表示。例如,在处理包含图片和文字说明的文档时,可以将图像特征和文本特征融合在一起。
- 微调Embedding模型:在特定的数据集上对预训练的Embedding模型进行微调,使其更好地适应具体的应用场景。例如,在医疗问答系统中,可以使用医疗领域的文档对通用的Embedding模型进行微调。
- 动态Embedding:根据文本的上下文信息动态调整Embedding的表示,以更好地捕捉文本的语义变化。例如,使用基于Transformer的模型(如BERT)来生成上下文相关的Embedding。
7. 模型选型建议
- 中文场景:优先选择 BGE 系列(如
bge-small-zh-v1.5
),兼顾精度与效率。 - 生产环境:
- 小模型优先(如
bge-small
),降低延迟。 - 高精度场景使用大模型(如
bge-large
)。
- 小模型优先(如
8. 依赖安装与配置
-
分块依赖:
pip install spacy nltk python -m spacy download zh_core_web_sm # 中文语义分块
-
嵌入模型依赖:
pip install sentence-transformers
9.总结与选型
- 分块策略:根据文档类型选择策略(固定分块为基线,语义分块为最优)。
- 嵌入模型:参考 MTEB 榜单,结合业务场景测试模型性能。