在知识库检索Agent相关文章发布后,有用户提出疑问:为何文档处理这一关键环节未被详细介绍?文档处理,特别是其中的文档分段技术,是智能问答与知识检索流程中至关重要的基础环节。为回应读者的需求,本文将结合Dify等平台的实际处理逻辑,深入探讨文档分段技术。
首先,本文将聚焦于核心步骤:文档分段(Text Chunking)。这项技术看似简单地将长文本切分,却直接决定了后续检索的精度与回答的质量。

手动实现文档分段方法
本节将探讨手动实现多种文本分段的代码。尽管已有Langchain等成熟框架可用,但自定义实现具有独特的优势。成熟框架虽然功能强大,但其高度封装的特性可能带来局限。手动实现则提供了三大核心优势:更高的灵活性、系统稳健性,以及更快的故障排查速度。
本文将介绍五种文本分段方法的实现原理及其优劣。
基础版文本分段方法
按字符数量分段
字符级分段是最为简单直接的方法,但其缺点也十分明显。直接依据字符数量上限进行分段会破坏文本内容的逻辑连贯性和语义完整性,从而增加RAG(检索增强生成)系统的检索难度。因此,这种方法在实际应用中并不常用。
def segment_by_char_count(text: str, max_chars: int = 500, overlap: int = 0) -> list[str]:
chunks = []
start = 0
while start < len(text):
end = start + max_chars
chunks.append(text[start:end])
start = end - overlap
return chunks
— 以下是字符级分段的测试结果 —
待分段文本:
在过去的十年中,人工智能经历了爆发式的增长。
从最初的图像识别、语音识别,到如今的大语言模型(Large Language Models),AI 的能力已经远远超出了人们的预期。
它不仅能够生成文本、理解语义,还能进行逻辑推理、编写代码,甚至参与艺术创作。
然而,AI 的发展也带来了新的挑战。
数据安全、隐私保护、模型可解释性,这些议题正在成为研究者和监管机构关注的重点。
For example, when a model generates a medical diagnosis, how can we ensure that its reasoning process is transparent and trustworthy? This question is not only technical but also deeply ethical.
未来的人工智能将不再仅仅依赖模型的规模,而是更关注“智能的组织结构”。
换句话说,AI 将像人类一样学会“协作”和“记忆”。
一个智能体(agent)可以调用另一个智能体的能力,共同完成复杂任务。
这正是当前 Agentic AI 研究的方向。
分段结果:
---- Chunk 0 ----
在过去的十年中,人工智能经历了爆发式的增长。
从最初的图像识别、语音识别,到如今的大语言模型(Large Language Models),AI 的能力已经远远超出了人们的预期。
它不仅能够生成文本、理解语义,还能进行逻辑推理、编写代码,甚至参与艺术创作。
然而,AI 的发展也带来了新的挑战。
数据安全、隐私保护、模型可解释性,这些议题正在成为研究者和监管机构关注的重点。
For example, when a model generates a medical diagnosis, how can we ensure that its reasoning proce
---- Chunk 1 ----
ss is transparent and trustworthy?
This question is not only technical but also deeply ethical.
未来的人工智能将不再仅仅依赖模型的规模,而是更关注“智能的组织结构”。
换句话说,AI 将像人类一样学会“协作”和“记忆”。
一个智能体(agent)可以调用另一个智能体的能力,共同完成复杂任务。
这正是当前 Agentic AI 研究的方向。
按句子分段
句子分段是字符级分段的进阶方法,它充分考虑了句子完整性对检索效率的重要性。该方法首先依据标点符号对文本内容进行分割,进而在满足chunk大小限制的前提下,将完整的句子添加至chunk中。同时,对于单个句子长度超出chunk限制的情况,会采用滑动窗口技术进行字符级切分,以确保内容不被过度截断。
import re
from typing import List
def split_sentences_multilang(text: str) -> List[str]:
# 中文标点 + 英文句号/问号/感叹号 + 换行段落
sentence_endings = r"([。!?!?]|(?<!w).(?=s|$)|
{2,})"
parts = re.split(sentence_endings, text)
sentences, buffer = [], ""
for p in parts:
if not p:
continue
buffer += p
# 如果是句子终结或段落
if re.match(sentence_endings, p):
sentences.append(buffer.strip())
buffer = ""
if buffer.strip():
sentences.append(buffer.strip())
return sentences
def segment_by_sentence_multilang(text: str, max_chars: int = 500, overlap: int = 0) -> List[str]:
sentences = split_sentences_multilang(text)
chunks = []
buffer = ""
for sent in sentences:
sent = sent.strip()
if not sent:
continue
# 单句过长,回退到字符滑窗切分
if len(sent) > max_chars:
if buffer:
chunks.append(buffer)
buffer = ""
buffer_len = 0
start = 0
while start < len(sent):
end = start + max_chars
chunks.append(sent[start:end])
start = max(end - overlap, start + 1) # 保证前进
continue
if len(buffer) + len(sent) <= max_chars:
buffer += sent
else:
chunks.append(buffer)
buffer = sent
if buffer:
chunks.append(buffer)
# overlap 处理
if overlap > 0:
overlapped = []
for i, c in enumerate(chunks):
if i == 0:
overlapped.append(c)
else:
ov_text = chunks[i-1][-overlap:] if overlap < len(chunks[i-1]) else chunks[i-1]
overlapped.append(ov_text + c)
chunks = overlapped
return chunks
— 以下是句子级分段的测试结果 —
待分段文本:
在过去的十年中,人工智能经历了爆发式的增长。
从最初的图像识别、语音识别,到如今的大语言模型(Large Language Models),AI 的能力已经远远超出了人们的预期。
它不仅能够生成文本、理解语义,还能进行逻辑推理、编写代码,甚至参与艺术创作。
然而,AI 的发展也带来了新的挑战。
数据安全、隐私保护、模型可解释性,这些议题正在成为研究者和监管机构关注的重点。
For example, when a model generates a medical diagnosis, how can we ensure that its reasoning process is transparent and trustworthy?
This question is not only technical but also deeply ethical.
未来的人工智能将不再仅仅依赖模型的规模,而是更关注“智能的组织结构”。
换句话说,AI 将像人类一样学会“协作”和“记忆”。
一个智能体(agent)可以调用另一个智能体的能力,共同完成复杂任务。
这正是当前 Agentic AI 研究的方向。
从以下分段结果可以看出,句子级分段有效避免了句子或英文单词被截断的风险:
---- Chunk 0 ----
在过去的十年中,人工智能经历了爆发式的增长。
从最初的图像识别、语音识别,到如今的大语言模型(Large Language Models),AI 的能力已经远远超出了人们的预期。
它不仅能够生成文本、理解语义,还能进行逻辑推理、编写代码,甚至参与艺术创作。
然而,AI 的发展也带来了新的挑战。
数据安全、隐私保护、模型可解释性,这些议题正在成为研究者和监管机构关注的重点。
---- Chunk 1 ----
For example, when a model generates a medical diagnosis, how can we ensure that its reasoning process is transparent and trustworthy?
This question is not only technical but also deeply ethical.
未来的人工智能将不再仅仅依赖模型的规模,而是更关注“智能的组织结构”。
换句话说,AI 将像人类一样学会“协作”和“记忆”。
一个智能体(agent)可以调用另一个智能体的能力,共同完成复杂任务。
---- Chunk 2 ----
这正是当前 Agentic AI 研究的方向。
按语义分段
仅依赖句子级别的分段难以实现高召回率和精准度。这种方法未充分考虑句子间的语义关系,仅以不截断句子和接近chunk字符上限为目标,一股脑地将内容打包。这不仅增加了召回chunk中的噪声,导致无关内容增多,浪费计算资源,还可能为大型语言模型(LLM)提供过多无关信息,从而影响其生成回答的质量和准确性。
因此,在句子分段的基础上,通过计算句子间的语义相似度,可以实现基于语义的分段。实践表明,语义分段能够满足大部分文档内容处理的需求。
为确保数据安全,可采用本地部署的Embedding模型,其代码实现如下所示:
from sklearn.metrics.pairwise import cosine_similarity
XINFERENCE_MODEL = "bge-large-zh-v1.5"
XINFERENCE_API_URL = "http://localhost:9997/v1/embeddings"
def get_xinference_embeddings(texts, model=XINFERENCE_MODEL, api_url=XINFERENCE_API_URL):
"""调用 Xinference 获取文本向量"""
payload = {"model": model, "input": texts}
headers = {"Content-Type": "application/json"}
response = requests.post(api_url, headers=headers, json=payload)
response.raise_for_status()
data = response.json()
# 确保兼容返回格式
embeddings = [item["embedding"] for item in data.get("data", [])]
return np.array(embeddings)
def segment_by_semantic(text: str, threshold: float = 0.7, max_chars: int = 500, overlap: int = 0):
"""
基于语义相似度分段,同时控制 chunk 最大长度
"""
sentences = segment_by_sentence_multilang(text) # 使用多语言句子分割
embeddings = get_xinference_embeddings(sentences)
chunks, buffer = [], [sentences[0]]
buffer_len = len(sentences[0])
for i in range(1, len(sentences)):
sim = cosine_similarity([embeddings[i-1]], [embeddings[i]])[0][0]
# 当前句子长度
sent_len = len(sentences[i])
# 超长句子单独处理
if sent_len > max_chars:
# 先输出当前 buffer
if buffer:
chunks.append("".join(buffer))
buffer = []
buffer_len = 0
# 字符滑窗切分超长句
start = 0
s = sentences[i]
while start < len(s):
end = start + max_chars
chunks.append(s[start:end])
start = max(end - overlap, start + 1)
continue
# 判断是否与前一句语义相似且长度不超 max_chars
if sim > threshold and buffer_len + sent_len <= max_chars:
buffer.append(sentences[i])
buffer_len += sent_len
else:
# 输出当前 buffer
if buffer:
chunks.append("".join(buffer))
buffer = [sentences[i]]
buffer_len = sent_len
if buffer:
chunks.append("".join(buffer))
# overlap 处理(可选)
if overlap > 0:
overlapped = []
for i, c in enumerate(chunks):
if i == 0:
overlapped.append(c)
else:
prev = overlapped[-1]
ov_text = prev[-overlap:] if overlap < len(prev) else prev
overlapped.append(ov_text + c)
chunks = overlapped
return [c for c in chunks if c]
— 以下是语义分段的测试结果 —
待分段文本:
在过去的十年中,人工智能经历了爆发式的增长。
从最初的图像识别、语音识别,到如今的大语言模型(Large Language Models),AI 的能力已经远远超出了人们的预期。
它不仅能够生成文本、理解语义,还能进行逻辑推理、编写代码,甚至参与艺术创作。
然而,AI 的发展也带来了新的挑战。数据安全、隐私保护、模型可解释性,这些议题正在成为研究者和监管机构关注的重点。
For example, when a model generates a medical diagnosis, how can we ensure that its reasoning process is transparent and trustworthy?This question is not only technical but also deeply ethical.
未来的人工智能将不再仅仅依赖模型的规模,而是更关注“智能的组织结构”。
换句话说,AI 将像人类一样学会“协作”和“记忆”。
一个智能体(agent)可以调用另一个智能体的能力,共同完成复杂任务。
这正是当前 Agentic AI 研究的方向。
分段结果:
---- Chunk 0 ----
在过去的十年中,人工智能经历了爆发式的增长。
从最初的图像识别、语音识别,到如今的大语言模型(Large Language Models),AI 的能力已经远远超出了人们的预期。
它不仅能够生成文本、理解语义,还能进行逻辑推理、编写代码,甚至参与艺术创作。
然而,AI 的发展也带来了新的挑战。数据安全、隐私保护、模型可解释性,这些议题正在成为研究者和监管机构关注的重点。
For example, when a model generates a medical diagnosis, how can we ensure that its reasoning process is transparent and trustworthy?This question is not only technical but also deeply ethical.
未来的人工智能将不再仅仅依赖模型的规模,而是更关注“智能的组织结构”。
换句话说,AI 将像人类一样学会“协作”和“记忆”。
一个智能体(agent)可以调用另一个智能体的能力,共同完成复杂任务。
---- Chunk 1 ----
这正是当前 Agentic AI 研究的方向。
Markdown格式文档分段
在探讨完通用文本分段方法后,接下来将关注具有规范结构的文件类型,如Markdown、HTML或代码脚本。对于此类文件,通常可依据其自身的结构进行分段。以下是Markdown格式文件分段的代码实现示例:
import re
def segment_markdown(
text: str,
max_chars: int = 1000,
overlap: int = 100
) -> list[str]:
"""
Args:
text (str): Markdown 文本
max_chars (int): 每个 chunk 的最大字符长度
overlap (int): 上一个 chunk 尾部在下一个 chunk 中重叠的字符数(防止上下文割裂)
Returns:
list[str]: 分段后的 Markdown 文本列表
"""
lines = text.splitlines()
chunks, current_chunk = [], []
current_length = 0
for line in lines:
# 遇到标题(H1-H6)时,强制开始一个新的块
if re.match(r"^#{1,6}s", line):
if current_chunk:
chunk_text = "
".join(current_chunk).strip()
chunks.append(chunk_text)
current_chunk = [line]
current_length = len(line)
else:
# 普通文本行
if current_length + len(line) + 1 > max_chars:
# 达到 chunk 上限,切分
chunk_text = "
".join(current_chunk).strip()
chunks.append(chunk_text)
# 处理 overlap:取上一个 chunk 的尾部部分作为新起点
if overlap > 0 and len(chunk_text) > overlap:
overlap_text = chunk_text[-overlap:]
current_chunk = [overlap_text, line]
current_length = len(overlap_text) + len(line)
else:
current_chunk = [line]
current_length = len(line)
else:
current_chunk.append(line)
current_length += len(line) + 1
# 追加最后的chunk
if current_chunk:
chunks.append("
".join(current_chunk).strip())
return [c for c in chunks if c]
— 以下是Markdown格式分段的测试结果 —
待分段文件内容:
# 人工智能的起源与发展
人工智能(Artificial Intelligence, AI)这一概念最早诞生于20世纪50年代。
最初的研究者们试图让计算机模拟人类思考的过程,例如推理、学习与决策。
然而,受限于算力与数据的匮乏,这一阶段的AI发展相对缓慢。
## 机器学习的崛起
进入21世纪后,机器学习(Machine Learning)成为AI的核心方向。
它不再依赖人工设定规则,而是通过数据驱动模型的自我学习。
这标志着AI从“编程智能”迈向了“学习智能”。
# 现实挑战与伦理思考
AI的发展带来了巨大的社会影响。
隐私泄露、算法歧视、虚假信息传播等问题,正在成为亟需解决的现实挑战。
与此同时,AI的应用边界也在被不断讨论——它是否应该参与教育、医疗甚至法律判断?
## 可解释性与安全性
一个重要议题是模型的可解释性(Explainability)。
人类希望理解模型为何得出某个结论,尤其是在关键领域如医学诊断或司法判决。
因此,提高AI的可解释性与安全性,是未来研究的重点方向。
## 人机协作与未来愿景
未来的AI不会取代人类,而会成为人类的协作者。
人机协同(Human-AI Collaboration)将推动知识创造、科学研究乃至社会治理的新模式。
这种“共智”模式,或许才是人工智能的真正终极形态。
分段结果:
---- Chunk 0 ----
# 人工智能的起源与发展
人工智能(Artificial Intelligence, AI)这一概念最早诞生于20世纪50年代。
最初的研究者们试图让计算机模拟人类思考的过程,例如推理、学习与决策。
然而,受限于算力与数据的匮乏,这一阶段的AI发展相对缓慢。
---- Chunk 1 ----
## 机器学习的崛起
进入21世纪后,机器学习(Machine Learning)成为AI的核心方向。
它不再依赖人工设定规则,而是通过数据驱动模型的自我学习。
这标志着AI从“编程智能”迈向了“学习智能”。
---- Chunk 2 ----
# 现实挑战与伦理思考
AI的发展带来了巨大的社会影响。
隐私泄露、算法歧视、虚假信息传播等问题,正在成为亟需解决的现实挑战。
与此同时,AI的应用边界也在被不断讨论——它是否应该参与教育、医疗甚至法律判断?
---- Chunk 3 ----
## 可解释性与安全性
一个重要议题是模型的可解释性(Explainability)。
人类希望理解模型为何得出某个结论,尤其是在关键领域如医学诊断或司法判决。
因此,提高AI的可解释性与安全性,是未来研究的重点方向。
---- Chunk 4 ----
## 人机协作与未来愿景
未来的AI不会取代人类,而会成为人类的协作者。
人机协同(Human-AI Collaboration)将推动知识创造、科学研究乃至社会治理的新模式。
这种“共智”模式,或许才是人工智能的真正终极形态。
进阶版文本分段方法
LLM文本分段
基于大型语言模型(LLM)实现的分段策略,允许模型首先理解内容的深层语义,再据此决定如何进行文本分块。这种方法不再仅仅依赖句号或行数等表层特征,而是能识别出哪些语句围绕同一主题展开,以及哪些小标题下的内容构成一个完整的语义单元。
import re
import json
base_url = "http://localhost:8977/v1/chat/completions"
api_key = "xxxxxxx"
def segment_by_llm(text: str, max_chars: int = 800, overlap: int = 0) -> list[str]:
"""
使用大模型理解文本语义后进行分块。
"""
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
system_prompt = """你是一个文本分块专家,请将输入文本分成语义完整、长度适中的段落。
每个段落应尽量保持上下文连贯。
请输出 JSON 格式,如:
[
{"chunk_id": 1, "content": "第一段文本"},
{"chunk_id": 2, "content": "第二段文本"}
]
"""
user_prompt = f"以下是要分块的文本(建议每块不超过 {max_chars} 字):
{text[:6000]}" # 限制输入长度避免超限
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": user_prompt})
payload = {
"model": "Qwen3-32B",
"messages": messages,
"temperature": 0.6
}
response = requests.post(base_url, headers=headers, json=payload)
result = response.json()
content = result["choices"][0]["message"]["content"]
# 尝试提取 JSON
json_match = re.search(r"[.*]", content, re.S)
if not json_match:
return [text] # fallback
try:
chunks_data = json.loads(json_match.group(0))
chunks = [c["content"].strip() for c in chunks_data if "content" in c]
except Exception:
chunks = [text]
return chunks
— 以下是LLM分段的测试结果 —
待分段文本:
# 人工智能的起源与发展
人工智能(Artificial Intelligence, AI)这一概念最早诞生于20世纪50年代。
最初的研究者们试图让计算机模拟人类思考的过程,例如推理、学习与决策。
然而,受限于算力与数据的匮乏,这一阶段的AI发展相对缓慢。
# 现实挑战与伦理思考
AI的发展带来了巨大的社会影响。
隐私泄露、算法歧视、虚假信息传播等问题,正在成为亟需解决的现实挑战。
与此同时,AI的应用边界也在被不断讨论——它是否应该参与教育、医疗甚至法律判断?
分段结果:
---- Chunk 0 ----
# 人工智能的起源与发展
人工智能(Artificial Intelligence, AI)这一概念最早诞生于20世纪50年代。
最初的研究者们试图让计算机模拟人类思考的过程,例如推理、学习与决策。
然而,受限于算力与数据的匮乏,这一阶段的AI发展相对缓慢。
---- Chunk 1 ----
# 现实挑战与伦理思考
AI的发展带来了巨大的社会影响。
隐私泄露、算法歧视、虚假信息传播等问题,正在成为亟需解决的现实挑战。
与此同时,AI的应用边界也在被不断讨论——它是否应该参与教育、医疗甚至法律判断?
尽管LLM分段在语义和逻辑理解上比传统基于规则的分段方法更为深入,但其应用仍面临一些挑战:
-
每个文档都要调用模型,成本较高;
-
可能会出现chunk太大或者太碎的情况;
-
难以调试或者标准化;

本文全面介绍了文档分段的各项内容,从可精准控制的基于规则的基础方法,逐步深入到大模型时代更为智能、理解上下文的进阶分段策略。期望这些内容能为构建高效的检索问答系统奠定坚实基础。
