免费POC, 零成本试错
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


您应该为您的 RAG 系统使用哪种分块技术?

发布日期:2025-09-10 15:47:46 浏览次数: 1527
作者:老肖说两句

微信搜一搜,关注“老肖说两句”

推荐语

RAG系统的性能关键在分块技术,本文详解8种策略助你优化检索效果。

核心内容:
1. 分块技术对RAG系统性能的决定性影响
2. 8种主流分块策略的优缺点对比
3. 选择分块技术的实战决策框架

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

在人工智能领域迅猛发展的今天,检索增强生成(RAG)系统已成为构建可靠且上下文感知应用的基石,这些应用由大型语言模型(LLM)驱动。RAG 系统通过检索外部知识库(如向量数据库)中的相关信息,来弥合 LLM 与外部知识之间的差距,从而提升模型的响应质量。然而,在实现高效 RAG 系统时,一个最关键却常常被忽略的步骤是“分块”(chunking)——即将大型文档分解成更小、更易消化的片段的过程。



为什么分块如此重要?LLM 的上下文窗口有限,通常限制了一次能处理的文本量。糟糕的分块策略可能导致上下文不完整、检索无关信息,甚至生成幻觉输出。相反,精心选择的分块策略能显著提升检索准确性、响应相关性和整体系统性能。事实上,分块对 RAG 效果的影响往往大于嵌入模型或向量存储的选择。

本文将探讨八种流行的分块策略,借鉴行业最佳实践。我们将涵盖每种策略的描述、优缺点、理想使用场景,以及适用的代码示例。最后,我们提供一个决策框架,帮助您为 RAG 系统选择合适的技术。

 

  1. 1. 固定大小分块(基于令牌或字符)

固定大小分块是最简单的方法,将文本分割成预定义长度的块(例如 512 个令牌),并可选地添加重叠(10-20%)以保持边界间的上下文连续性。

优点:实现简单、计算高效,适合快速原型开发。  

缺点:忽略语义结构,可能在句子或想法中间截断,导致上下文碎片化。  

何时使用:适用于统一的无结构数据,如日志、短笔记,或在实时应用中优先考虑速度而非精度。

代码示例(Python)




from
 typing import List



import
 re





def
 word_splitter(source_text: str) -> List[str]:



    source_text = re.sub("\s+", " ", source_text)



    return
 re.split("\s", source_text)





def
 get_chunks_fixed_size_with_overlap(text: str, chunk_size: int, overlap_fraction: float = 0.2) -> List[str]:



    text_words = word_splitter(text)



    overlap_int = int(chunk_size * overlap_fraction)



    chunks = []



    for
 i in range(0, len(text_words), chunk_size):



        chunk_words = text_words[max(i - overlap_int, 0): i + chunk_size]



        chunk = " ".join(chunk_words)



        chunks.append(chunk)



    return
 chunks


2. 递归分块

这种方法使用分隔符的层次结构(例如,双换行符分段落,然后单换行符分句子),递归地分割文本,直到块符合所需大小。

优点:比固定大小更尊重文档结构,减少了不自然的断点。  

缺点:仍基于规则,可能无法捕捉深层语义;编码稍复杂。  

何时使用:适用于半结构化文本,如博客文章、新闻或研究论文,这些文本存在逻辑断点。

代码示例(Python)




from
 typing import List





def
 recursive_chunking(text: str, max_chunk_size: int = 1000) -> List[str]:



    if
 len(text) <= max_chunk_size:



        return
 [text.strip()] if text.strip() else []



    separators = ["\n\n", "\n", ". ", " "]



    for
 separator in separators:



        if
 separator in text:



            parts = text.split(separator)



            chunks = []



            current_chunk = ""



            for
 part in parts:



                test_chunk = current_chunk + separator + part if current_chunk else part



                if
 len(test_chunk) <= max_chunk_size:



                    current_chunk = test_chunk



                else
:



                    if
 current_chunk:



                        chunks.append(current_chunk.strip())



                    current_chunk = part



            if
 current_chunk:



                chunks.append(current_chunk.strip())



            final_chunks = []



            for
 chunk in chunks:



                if
 len(chunk) > max_chunk_size:



                    final_chunks.extend(recursive_chunking(chunk, max_chunk_size))



                else
:



                    final_chunks.append(chunk)



            return
 [chunk for chunk in final_chunks if chunk]



    return
 [text[i:i + max_chunk_size] for i in range(0, len(text), max_chunk_size)]


3. 内容感知分块

内容感知分块基于自然内容单元(如句子、段落或章节)进行分割,使用分隔符或 NLP 工具。

优点:保持逻辑完整性,提升检索相关性。  

缺点:依赖一致的格式;对结构不良的数据无效。  

何时使用:适用于格式化文档,如报告、书籍或法律文本。

代码示例:使用 NLTK 库进行句子分割:




import
 nltk



nltk.download('punkt')





def
 sentence_chunking(text: str) -> List[str]:



    sentences = nltk.sent_tokenize(text)



    return
 sentences  # 如需进一步组合以达到所需大小


4. 语义分块

这种高级技术使用嵌入来分组语义相似的句子或段落,通常通过余弦相似度阈值实现。

优点:确保块在上下文中连贯,提升 RAG 准确性。  

缺点:嵌入计算导致高计算成本。  

何时使用:适用于密集的技术内容,如科学论文或代码库,其中含义优先于结构。

代码示例:使用 sentence-transformers:




from
 sentence_transformers import SentenceTransformer, util





model = SentenceTransformer('all-MiniLM-L6-v2')





def
 semantic_chunking(sentences: List[str], similarity_threshold: float = 0.7) -> List[str]:



    embeddings = model.encode(sentences)



    chunks = []



    current_chunk = [sentences[0]]



    for
 i in range(1, len(sentences)):



        sim = util.cos_sim(embeddings[i-1], embeddings[i])



        if
 sim > similarity_threshold:



            current_chunk.append(sentences[i])



        else
:



            chunks.append(' '.join(current_chunk))



            current_chunk = [sentences[i]]



    chunks.append(' '.join(current_chunk))



    return
 chunks


5. 代理分块

利用 LLM 作为“代理”来智能确定块边界,基于提示进行操作。

优点:高度适应性且语义感知,无需固定规则。  

缺点:因 LLM 调用而昂贵且缓慢;可能不一致。  

何时使用:高价值场景,如自定义企业数据,精度至关重要。

代码示例:通过 OpenAI API 提示 LLM:




import
 openai





def
 Agentic_chunking(text: str, max_chunk_size: int) -> List[str]:



    response = openai.ChatCompletion.create(



        model="gpt-4",



        messages=[{"role": "user", "content": f"将此文本分割成不超过 {max_chunk_size} 个字符的连贯块:{text}"}]



    )



    chunks = response.choices[0].message.content.split('\n\n')  # 假设块由双换行符分隔



    return
 chunks


6. 滑动窗口分块

通过在文本上滑动窗口创建重叠块,确保连续上下文。

优点:捕捉边界间信息,减少信息丢失。  

缺点:因冗余而增加存储和检索开销。  

何时使用:叙事或序列数据,如故事、转录或时间序列日志。

代码示例:类似于固定大小,但步长可调:




def
 sliding_window_chunking(text: str, window_size: int, step: int) -> List[str]:



    words = text.split()



    chunks = []



    for
 i in range(0, len(words), step):



        chunk = ' '.join(words[i:i + window_size])



        if
 chunk:



            chunks.append(chunk)



    return
 chunks


7. 层次分块

构建多级结构(例如,文档 > 章节 > 段落 > 句子),用于分层检索。

优点:启用灵活的多分辨率搜索。  

缺点:设置和索引复杂。  

何时使用:大型层次文档,如手册、维基或学术论文。

代码示例:表示为树状结构(简化):




# 使用 BeautifulSoup 等库解析 HTML 或自定义解析器处理层次




def
 hierarchical_chunking(document: dict) -> dict:



    # 假设文档已解析成章节




    hierarchy = {'sections': []}



    for
 section in document['sections']:



        chunks = {'title': section['title'], 'paragraphs': [p for p in section['content'].split('\n\n')]}



        hierarchy['sections'].append(chunks)



    return
 hierarchy


8. 延迟分块

一种新颖方法,首先在长上下文中生成嵌入,然后在嵌入后派生块,以保留完整上下文。

优点:更好地处理长依赖;对某些模型成本效益高。  

缺点:需要兼容的嵌入模型;不普遍适用。  

何时使用:与长上下文 LLM 一起使用,或处理相互连接的叙事,如小说或法律合同。

代码示例:使用专用 API(例如 Cohere):




import
 cohere





co = cohere.Client('your-api-key')





def
 late_chunking(text: str) -> List[str]:



    # 嵌入长文本,然后基于嵌入簇进行分割




    response = co.embed(texts=[text], model='embed-english-v3.0')



    embeddings = response.embeddings[0]



    # 使用聚类(例如 KMeans)定义块




    # 简化:假设后处理分割




    return
 [text]  # 实际实现的占位符


选择分块技术的决策框架

选择合适的分块策略取决于几个因素:

  • • 文档类型和结构:无结构数据使用固定大小或递归;结构化数据使用内容感知或层次。
  • • 计算资源:预算有限时从简单方法如固定大小开始;高性能设置选择语义或代理。
  • • 性能要求:复杂查询的准确性优先语义或延迟分块;速度优先递归。
  • • 数据量:大规模语料库适合层次;重叠上下文适合滑动窗口。
  • • 评估:使用指标如检索召回率、精度或端到端 RAG 基准(例如 RAGAS 框架)测试策略。迭代实验——A/B 测试不同块大小和重叠是关键。

总之,没有一种分块技术适用于所有场景——最佳选择取决于您的数据和用例。通过理解这些策略并应用决策框架,您可以优化 RAG 系统以实现卓越性能。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询