
RAG分块策略深度对比:语义分块 vs 文档感知 vs 层级分块
为什么分块策略如此重要? 在RAG系统中,分块(Chunking)是影响检索质量的第一道关卡。同样的文档、同样的Embedding模型、同样的LLM,仅仅因为分块策略不同,检索准确率可以相差30%以上。 核心矛盾在于:块太大,检索精度下降(噪声多);块太小,上下文不足(语义不完整)。 好的分块策略要在这两端之间找到最优解。 六种分块策略全面对比 1. 固定大小分块(Fixed-Size Chunking) 最简单的策略:按固定token数切分,带overlap。 from langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=512, chunk_overlap=50, separators=["\n\n", "\n", "。", "!", "?", ",", " "], ) chunks = splitter.split_text(document) 参数 推荐值 说明 chunk_size 256-1024 取决于文档类型,技术文档建议512 chunk_overlap 10-20% 防止语义在切分边界断裂 优点:实现简单、速度快、可预测 缺点:可能在句子中间切断,破坏语义完整性 适用:快速原型、均匀文本(如日志、评论) 2. 语义分块(Semantic Chunking) 不按固定大小切,而是按语义相似度断点切。当相邻句子的语义相似度低于阈值时,在此处分块。 from semantic_chunker import SemanticChunker from langchain_openai import OpenAIEmbeddings # 基于Embedding相似度的语义分块 chunker = SemanticChunker( OpenAIEmbeddings(model="text-embedding-3-large"), breakpoint_threshold_type="percentile", # 或 "standard_deviation" breakpoint_threshold_amount=95, # 百分位阈值 ) chunks = chunker.split_text(document) 工作原理: 句子1 → 句子2 → 句子3 → 句子4 → 句子5 0.92 0.88 0.45↓ 0.91 0.87 ↑ 语义断点(相似度骤降) 在这里切分 # 自定义语义分块实现 import numpy as np from sklearn.metrics.pairwise import cosine_similarity def semantic_chunk(text, embeddings_model, threshold=0.5): """基于句子间语义相似度的自适应分块""" sentences = split_into_sentences(text) # 计算每对相邻句子的相似度 embeddings = [embeddings_model.embed(s) for s in sentences] similarities = [ cosine_similarity([embeddings[i]], [embeddings[i+1]])[0][0] for i in range(len(embeddings) - 1) ] # 找到相似度低于阈值的位置作为断点 chunks = [] current_chunk = [sentences[0]] for i, sim in enumerate(similarities): if sim < threshold: chunks.append(" ".join(current_chunk)) current_chunk = [sentences[i + 1]] else: current_chunk.append(sentences[i + 1]) chunks.append(" ".join(current_chunk)) return chunks 优点:语义完整、适应文档结构 缺点:计算开销大(每句话都要Embedding)、块大小不可控 适用:长文章、研究报告、新闻 ...

