长文本分块策略
了解固定大小分块、按句子边界分块和语义分块方法
长文本分块策略 是 CoddyKit 上的免费 AI Prompt Engineering 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Prompt Engineering 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Prompt Engineering 课程共包含 4 节课。
长文档为何具有挑战性
LLM 具有上下文窗口——一次最多可以处理的词元数量。GPT-4 支持 12.8 万个词元,克劳德支持 20 万个词元,但许多文档甚至超过这些限制。更重要的是,研究表明,模型在非常长的上下文中的准确性往往会下降。分块是指在处理文档之前,将文档拆分成较小部分的做法。
固定大小分块
固定大小分块不考虑内容边界,每隔 N 个词元(或字符)切分一次文本。这是最简单的策略,不需要语义理解。
典型的分块大小为500–1000 个词元。分块易于建立索引和检索,但可能在句子中间切分,导致边界处的语义丢失。
import tiktoken
def fixed_chunk(text, max_tokens=1000):
enc = tiktoken.get_encoding('cl100k_base')
tokens = enc.encode(text)
chunks = []
for i in range(0, len(tokens), max_tokens):
chunk_tokens = tokens[i:i + max_tokens]
chunks.append(enc.decode(chunk_tokens))
return chunks
chunks = fixed_chunk(long_document)
print(f'Total chunks: {len(chunks)}')固定大小分块的权衡
优点:
- 实现简单——不需要自然语言处理
- 分块大小可预测——更容易管理应用程序接口成本
- 处理速度快
缺点:
- 会切断句子和段落边界
- 句子被拆到不同分块后,检索时会丢失上下文
- 不适合摘要——分块可能在论述中途结束
按句子边界分块
按句子边界分块会在自然的句子或段落断点处切分文本。每个分块都在句号处结束,确保不会把句子截成两半。这样生成的分块更易读,也更连贯。
使用句子分割器(spaCy 或 NLTK)检测边界,然后不断组合句子,直到分块达到目标大小。
import spacy
nlp = spacy.load('en_core_web_sm')
def sentence_chunk(text, max_tokens=1000):
doc = nlp(text)
sentences = [sent.text.strip() for sent in doc.sents]
chunks, current, count = [], [], 0
for sent in sentences:
word_count = len(sent.split())
if count + word_count > max_tokens and current:
chunks.append(' '.join(current))
current, count = [], 0
current.append(sent)
count += word_count
if current:
chunks.append(' '.join(current))
return chunks语义分块
语义分块更进一步——它会在主题发生变化时切分文本。通过嵌入相邻句子并测量 cosine_similarity,我们可以检测讨论何时转向新的主题。
当相似度低于阈值时,插入分块边界。这样生成的分块在主题上更连贯,非常适合检索增强生成(RAG)。
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
model = SentenceTransformer('all-MiniLM-L6-v2')
def semantic_chunk(sentences, threshold=0.75):
embeddings = model.encode(sentences)
chunks, current = [], [sentences[0]]
for i in range(1, len(sentences)):
sim = cosine_similarity(
[embeddings[i-1]], [embeddings[i]]
)[0][0]
if sim < threshold:
chunks.append(' '.join(current))
current = []
current.append(sentences[i])
if current:
chunks.append(' '.join(current))
return chunks三种策略比较
以下是并列比较,可帮助您进行选择:
- 固定大小:速度最快,边界准确性最低——用于简单流程
- 按句子边界:保留句子的完整性——适用于连贯性重要的场景
- 语义:主题连贯性最佳——适用于精确检索至关重要的 RAG
在实际应用中,语义分块需要计算嵌入,因此会增加延迟。请根据检索准确性要求进行选择。
面向检索任务的分块
对于检索增强生成(RAG),分块会成为搜索的基本单位。系统会对用户查询进行嵌入,然后检索最相似的分块,并将其注入提示词。
较小的分块(200–400 个词元)可以提高检索精度——每个分块都包含一个明确集中的观点。较大的分块(800–1000 个词元)能提供更多上下文,但可能将无关内容与相关段落混在一起。
import openai
import numpy as np
client = openai.OpenAI(api_key='sk-...')
def embed(text):
resp = client.embeddings.create(
model='text-embedding-3-small',
input=text
)
return np.array(resp.data[0].embedding)
def retrieve(query, chunks, top_k=3):
q_emb = embed(query)
scores = [(i, np.dot(q_emb, embed(c))) for i, c in enumerate(chunks)]
scores.sort(key=lambda x: x[1], reverse=True)
return [chunks[i] for i, _ in scores[:top_k]]重叠:连接分块边界
减少边界错误的一种实用方法是:在分块之间添加重叠。将分块 N 的最后 100–200 个词元重复放在分块 N+1 的开头。
重叠可以确保跨越边界的句子至少在一个分块中完整出现。这对于检索尤其重要——关于跨越边界主题的查询可以匹配包含重叠内容的分块。
按分块丰富元数据
每个分块都应携带元数据,以便后续步骤引用其来源:
source:文件名或网址page:页码chunk_index:在文档中的位置section:章节或标题
这些元数据会与嵌入向量一起存储在向量数据库(松果、色度、维维特)中,并随检索到的分块一同返回,以便 LLM 引用来源。
def fixed_chunk_with_overlap(text, max_tokens=1000, overlap=200):
enc = tiktoken.get_encoding('cl100k_base')
tokens = enc.encode(text)
chunks = []
step = max_tokens - overlap
for i in range(0, len(tokens), step):
chunk_tokens = tokens[i:i + max_tokens]
chunks.append(enc.decode(chunk_tokens))
if i + max_tokens >= len(tokens):
break
return chunks选择正确的策略
快速决策指南:
- 速度优先、内容为连续文本:按句子边界分块
- 检索准确性至关重要:使用小分块(300 个词元)进行语义分块
- 总结书籍或报告:按句子边界分块,使用较大的分块(800 个词元)和映射-归约
- 法律/技术文档:使用语义分块,以保持条款完整
在确定策略之前,请始终在具有代表性的查询集上测量检索召回率。
def chunk_with_metadata(text, source='doc.pdf', page=1):
chunks = fixed_chunk_with_overlap(text)
return [
{
'text': chunk,
'metadata': {
'source': source,
'page': page,
'chunk_index': i
}
}
for i, chunk in enumerate(chunks)
]选择合适的策略
快速决策指南:
- 速度优先,内容为连续文本:按句子边界分块
- 检索准确率至关重要:使用较小分块(300 个词元)进行语义分块
- 总结书籍或报告:按句子边界分块,使用较大分块(800 个词元),并采用映射-归约
- 法律文档或技术文档:进行语义分块,以便将条款保持在一起
在确定采用某种策略之前,请务必在具有代表性的查询集上测量检索召回率。
知识检查
当相邻句子嵌入向量之间的余弦相似度低于某个阈值时,哪种分块策略会拆分文本?
回顾:分块策略
您已经学习了三种核心分块策略:
- 固定大小:每 N 个词元进行分割——速度快、简单、不考虑边界
- 句子边界:在自然的句子断点处分割——内容连贯、复杂度适中
- 语义:通过嵌入相似度识别主题变化并进行分割——最准确、成本最高
在文本块之间添加重叠可以减少边界错误,并始终附加元数据(来源、页码、索引),以支持引用和可追溯性。下一课将介绍映射-归约摘要模式。
常见问题解答
「长文本分块策略」课时是免费的吗?
是的 — 「长文本分块策略」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Prompt Engineering 课程的其余内容,请升级到 CoddyKit PRO。 AI Prompt Engineering 课程共包含 4 节课。
「长文本分块策略」这节课中我会学到什么?
了解固定大小分块、按句子边界分块和语义分块方法 你通过在浏览器中直接运行的动手代码来练习 AI Prompt Engineering,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Prompt Engineering 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Prompt Engineering 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「长文本分块策略」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Prompt Engineering 课中编写并运行代码吗?
能。每节 AI Prompt Engineering 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。