RAG 入门-面试官问你,RAG 为什么要切块?

发布时间:2026/6/24 8:43:44

RAG 入门-面试官问你,RAG 为什么要切块? 为什么要切块的有以下几点原因大模型的上下文有 token 的长度限制切块可以突出表示某个向量的特征如果说某个大文本的向量能表示10个特征那么这个向量表达就会很模糊会影响检索精度嵌入模型有限制大多数主流的 Embedding 模型如 text-embedding-3-small通常只能处理 512 或 8192 个 Token省钱大模型 api 是按 toekn 收费的省时间上下文长度越长大模型处理的时间越长怎么切块目前常用的切块方法有 5 种下面我们逐一介绍1. 固定切块CharacterTextSplitter最简单的切块方式按固定字符数分割文本。这种切块方式很简单但是缺点也很明显很容易切断语义完整性比如一个句子被切分成了两个块那么这个句子的语义就会丢失。文件名01-固定切块.pyfrom langchain_community.document_loaders import TextLoader from langchain_text_splitters import CharacterTextSplitter loader TextLoader(../99-doc-data/黑悟空/黑悟空wiki.txt) data loader.load() text_splitter CharacterTextSplitter( chunk_size100, # 每个块的大小 chunk_overlap5 # 块之间的重叠大小 ) chunks text_splitter.split_documents(data) for chunk in chunks: print( 切块分页 ) print(chunk.page_content)参数说明chunk_size100每个块最多 100 个字符chunk_overlap5相邻块之间重叠 5 个字符避免信息丢失优点实现简单速度快块大小可控缺点容易在句子中间断开破坏语义完整性适用场景结构简单的文本、需要快速处理的场景2. 递归切块RecursiveCharacterTextSplitter按优先级递归尝试不同的分隔符保持文本结构。文件名02-递归切块.pyfrom langchain_community.document_loaders import TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter loader TextLoader(../99-doc-data/黑悟空/黑悟空wiki.txt) data loader.load() # 定义分割符列表按优先级依次使用 separators [ \n\n, # 双换行符段落分隔 \n, # 单换行符行分隔 。, # 中文句号 ., # 英文句号 , # 中文感叹号 !, # 英文感叹号 , # 中文问号 ?, # 英文问号 , # 中文分号 ;, # 英文分号 , # 中文逗号 ,, # 英文逗号 , # 空格 # 最后按字符分割 ] recursive_text_splitter RecursiveCharacterTextSplitter( chunk_size100, chunk_overlap5, separatorsseparators, length_functionlen ) r_chunks recursive_text_splitter.split_documents(data) for chunk in r_chunks: print( 递归切块分页 ) print(chunk.page_content)工作原理先尝试用\n\n段落分割如果块还是太大用\n行分割如果还是太大用。句号分割依此类推直到满足chunk_size优点保持文本结构段落、句子比固定切块更智能适用范围广缺点仍可能在不合适的地方断开适用场景普通文章、博客、没有明确标题的文本3. 代码切块Language-specific Splitter专门为代码设计的切块器保持代码结构完整。文件名03-代码切块.pyfrom langchain_text_splitters import Language, RecursiveCharacterTextSplitter GAME_CODE class CombatSystem: def __init__(self): self.health 100 self.stamina 100 def update(self, delta_time): self._update_stats(delta_time) self._handle_combat() class InventorySystem: def __init__(self): self.items {} self.capacity 20 def add_item(self, item_id, quantity): if item_id in self.items: self.items[item_id] quantity else: self.items[item_id] quantity python_splitter RecursiveCharacterTextSplitter.from_language( languageLanguage.PYTHON, chunk_size1000, chunk_overlap0 ) py_docs python_splitter.create_documents([GAME_CODE]) for i, chunk in enumerate(py_docs, 1): print(f\n--- 第 {i} 个代码块 ---) print(chunk.page_content)支持的主流的20多种语言工作原理 按类、函数、方法等代码结构分割保持代码的完整性和可读性优点保持代码结构完整不会在函数中间断开支持多种编程语言缺点仅适用于代码适用场景代码文档、技术教程、API 文档4. 语义切块SemanticChunker最智能的切块方式根据语义相似度分割文本。文件名04-LangChain-语义分块-DeepSeek.pyfrom langchain_community.document_loaders import TextLoader from langchain_experimental.text_splitter import SemanticChunker from langchain_huggingface import HuggingFaceEmbeddings # 1. 加载文档 loader TextLoader(../99-doc-data/黑悟空/黑悟空wiki.txt, encodingutf-8) docs loader.load() # 2. 设置嵌入模型用于计算语义相似度 embeddings HuggingFaceEmbeddings( model_nameBAAI/bge-small-zh-v1.5, model_kwargs{device: cpu}, encode_kwargs{normalize_embeddings: True} ) # 3. 创建语义分块器 semantic_splitter SemanticChunker( embeddingsembeddings, breakpoint_threshold_typepercentile, # 使用百分位数阈值 breakpoint_threshold_amount90 # 90% 不相似度时分割 ) # 4. 执行语义分块 semantic_chunks semantic_splitter.split_documents(docs) for i, chunk in enumerate(semantic_chunks, 1): print(f\n--- 第 {i} 个语义块 ---) print(f长度: {len(chunk.page_content)} 字符) print(f内容: {chunk.page_content[:200]}...)工作原理首先将文本按句子分割然后计算相邻句子的语义相似度使用 embedding如果相似度低于阈值时创建新的分块示例对比传统分块可能在句子中间断开块1: 黑神话悟空是一款动作游戏。游戏基于西游 块2: 记改编。主角是孙悟空的转世。语义分块保持语义完整块1: 黑神话悟空是一款动作游戏。游戏基于西游记改编。 # 游戏介绍 块2: 主角是孙悟空的转世。 # 角色介绍参数说明breakpoint_threshold_typepercentile使用百分位数阈值推荐breakpoint_threshold_amount9090% 不相似度时分割85块很多细粒度90块适中推荐95块较少粗粒度优点保持语义连贯性自动识别主题边界检索质量最高缺点速度慢比传统分块慢 50 倍需要 embedding 模型适用场景问答系统、长文档分析、高质量检索5. 按段落和标题切块最推荐最实用的切块方式按文档的自然结构标题、段落分割。文件名05-按段落标题切块.py2.1 Markdown 标题切块from langchain_text_splitters import MarkdownHeaderTextSplitter markdown_document # 黑神话悟空 ## 游戏简介 《黑神话悟空》是一款动作角色扮演游戏。 ## 游戏玩法 ### 战斗系统 游戏的战斗系统流畅爽快。 ### 技能系统 玩家可以学习72变等经典技能。 # 定义要按哪些标题级别切块 headers_to_split_on [ (#, 一级标题), # H1 (##, 二级标题), # H2 (###, 三级标题), # H3 ] # 创建 Markdown 标题切块器 markdown_splitter MarkdownHeaderTextSplitter( headers_to_split_onheaders_to_split_on, strip_headersFalse # 保留标题在内容中 ) # 执行切块 md_chunks markdown_splitter.split_text(markdown_document) for chunk in md_chunks: print(f内容: {chunk.page_content}) print(f元数据: {chunk.metadata}) # 包含标题层级信息输出示例内容: # 黑神话悟空 元数据: {一级标题: 黑神话悟空} 内容: ## 游戏简介 《黑神话悟空》是一款动作角色扮演游戏。 元数据: {一级标题: 黑神话悟空, 二级标题: 游戏简介} 内容: ### 战斗系统 游戏的战斗系统流畅爽快。 元数据: {一级标题: 黑神话悟空, 二级标题: 游戏玩法, 三级标题: 战斗系统}2.2 段落切块from langchain_text_splitters import RecursiveCharacterTextSplitter # 段落之间用双换行符分隔的文本 paragraph_document 《黑神话悟空》是一款动作角色扮演游戏。 游戏采用虚幻引擎5开发画面表现力极强。 玩家在游戏中扮演孙悟空的转世。 # 优先按段落双换行符分割 paragraph_splitter RecursiveCharacterTextSplitter( separators[\n\n, \n, 。, , ], chunk_size500, chunk_overlap50 ) chunks paragraph_splitter.split_text(paragraph_document)2.3 混合切块推荐# 先按标题切块 md_chunks markdown_splitter.split_text(markdown_document) # 再对大块进行段落切分 final_chunks [] for header_chunk in md_chunks: if len(header_chunk.page_content) 200: # 块太大再按段落切分 sub_splitter RecursiveCharacterTextSplitter( separators[\n\n, \n, 。, , ], chunk_size200, chunk_overlap20 ) sub_chunks sub_splitter.split_text(header_chunk.page_content) # 保留标题元数据 for sub_chunk in sub_chunks: from langchain_core.documents import Document final_chunks.append(Document( page_contentsub_chunk, metadataheader_chunk.metadata )) else: final_chunks.append(header_chunk)优点保持逻辑完整性每个块都有明确的主题元数据包含标题信息便于溯源

相关新闻