spark streaming消费rocketmq的几种方式
豢缎狼汲什么是切块?为什么要切块?
简单来说,切块就是把“长篇大论”切成“语义胶囊”。
它把成千上万字的文章,按照一定的逻辑(比如每 500 字一段,或者按段落)切分成一个个独立的小块。这样,AI 在处理信息时,就不需要每次都“读全集”,而是“精准点餐”。
那为什么要切块的?有以下几点原因:
大模型的上下文有 token 的长度限制
切块可以突出表示某个向量的特征,如果说某个大文本的向量能表示10个特征,那么这个向量表达就会很模糊,会影响检索精度
嵌入模型有限制,大多数主流的 Embedding 模型(如 text-embedding-3-small)通常只能处理 512 或 8192 个 Token
省钱,大模型 api 是按 toekn 收费的,省时间,上下文长度越长,大模型处理的时间越长
怎么切块?
目前常用的切块方法有 5 种,下面我们逐一介绍:
1. 固定切块(CharacterTextSplitter)
最简单的切块方式,按固定字符数分割文本。这种切块方式很简单,但是缺点也很明显:很容易切断语义完整性,比如:一个句子被切分成了两个块,那么这个句子的语义就会丢失。
文件名: 01-固定切块.py
from 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_size=100, # 每个块的大小
chunk_overlap=5 # 块之间的重叠大小
)
chunks = text_splitter.split_documents(data)
for chunk in chunks:
print("====== 切块分页 ======")
print(chunk.page_content)
参数说明:
chunk_size=100:每个块最多 100 个字符
chunk_overlap=5:相邻块之间重叠 5 个字符(避免信息丢失)
优点:
实现简单,速度快
块大小可控
缺点:
容易在句子中间断开
破坏语义完整性
适用场景: 结构简单的文本、需要快速处理的场景
2. 递归切块(RecursiveCharacterTextSplitter)
按优先级递归尝试不同的分隔符,保持文本结构。
文件名: 02-递归切块.py
from 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_size=100,
chunk_overlap=5,
separators=separators,
length_function=len
)
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-代码切块.py
from 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(
language=Language.PYTHON,
chunk_size=1000,
chunk_overlap=0
)
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.py
from 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", encoding="utf-8")
docs = loader.load()
# 2. 设置嵌入模型(用于计算语义相似度)
embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-small-zh-v1.5",
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
# 3. 创建语义分块器
semantic_splitter = SemanticChunker(
embeddings=embeddings,
breakpoint_threshold_type="percentile", # 使用百分位数阈值
breakpoint_threshold_amount=90 # 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_type="percentile":使用百分位数阈值(推荐)
breakpoint_threshold_amount=90:90% 不相似度时分割
85:块很多(细粒度)
90:块适中(推荐)
95:块较少(粗粒度)
优点:
保持语义连贯性
自动识别主题边界
检索质量最高
缺点:
速度慢(比传统分块慢 50 倍)
需要 embedding 模型
适用场景: 问答系统、长文档分析、高质量检索
5. 按段落和标题切块(最推荐)
最实用的切块方式,按文档的自然结构(标题、段落)分割。
文件名: 05-按段落标题切块.py
2.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_on=headers_to_split_on,
strip_headers=False # 保留标题在内容中
)
# 执行切块
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_size=500,
chunk_overlap=50
)
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_size=200,
chunk_overlap=20
)
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_content=sub_chunk,
metadata=header_chunk.metadata
))
else:
final_chunks.append(header_chunk)
优点:
保持逻辑完整性
每个块都有明确的主题
元数据包含标题信息,便于溯源
缺点:
需要文档有明确的结构
适用场景: 说明书、论文、技术文档、Markdown 文档
切块方法对比
以下各种切块策略对比,可以根据使用场景来选择,当然了,也可以多种组合使用,比如技术文档,先基于 markdown 分段,然后再使用递归或者代码切块。
切块策略 速度 质量 适用场景 推荐度
固定切块 ??? ?? 简单文本、快速处理、要求较低的需求 ??
递归切块 ??? ???? 普通文章、博客、无明显分段的文章 ????
代码切块 ??? ???? 代码文档、技术教程 ????
语义切块 ? ????? 问答系统、长文档 ????
段落标题切块 ??? ????? 说明书、论文、Markdown、HTML 格式文档 ?????
学习路径
更多推荐




所有评论(0)