当处理长篇文本时,将文本分割成较小的块可以更好地处理和分析。下面详细介绍这个过程的工作原理和步骤:
文本分割器的工作原理
-
分割文本为小块:
- 初始步骤是将整个文本按语义相关性分割成较小的、有意义的块(通常是句子或段落)。这一过程利用分隔符,如段落标记(“\n\n”)、换行符(“\n”)、空格(" ")等,以尽可能保持语义相关的片段在一起。
-
合并小块:
- 将这些较小的块组合成更大的块,直到块的大小达到某个特定的限制(例如,字符数或标记数)。这一步的目的是在一定大小范围内保持块的语义完整性。
-
确定块大小:
- 一旦块的大小达到指定的限制,该块就被视为独立的文本片段。块大小的限制可以根据应用需求进行调整,如设定最大字符数或最大标记数。
-
创建重叠块:
- 为了保持上下文连贯性,每个块可以包含一部分前一个块的内容(重叠)。这种重叠可以确保在处理这些块时,上下文信息不丢失。
示例代码
下面是一个使用 RecursiveCharacterTextSplitter
进行文本分割的示例代码:
from langchain_text_splitters.character import RecursiveCharacterTextSplitter
# 清理文本以确保没有非 UTF-8 字符
def clean_text(text):
return text.encode("utf-8", errors="ignore").decode("utf-8")
# 示例文本
text = "This is a long document\n\nthat we can split up.\nHere is another line."
cleaned_text = clean_text(text)
# 创建一个递归字符文本分割器对象
text_splitter = RecursiveCharacterTextSplitter(
separators=["\n\n", "\n", " ", ""], # 按这些分隔符递归分割文本
chunk_size=20, # 块大小限制为 20 个字符
chunk_overlap=5, # 块之间重叠 5 个字符
length_function=len, # 使用 len 函数来测量块的大小
is_separator_regex=False, # 不使用正则表达式作为分隔符
)
# 分割文本
split_texts = text_splitter.split_text(cleaned_text)
# 打印分割后的文本
for i, split_text in enumerate(split_texts):
print(f"Part {i + 1}: {split_text}")
具体步骤说明
-
按分隔符分割文本:
- 初始文本:“This is a long document\n\nthat we can split up.\nHere is another line.”
- 使用分隔符列表 [“\n\n”, “\n”, " ", “”] 依次尝试分割文本。
- 例如,首先按 “\n\n” 分割,得到两个段落:
- “This is a long document”
- “that we can split up.\nHere is another line.”
-
检查块大小并进一步分割:
- 如果某个段落的字符数超过 20,则进一步按下一级分隔符(“\n”)分割。如果仍然超长,则按空格(" “)分割,最后按字符(”")分割,直到块的大小符合要求。
- 例如,第一个段落 “This is a long document” 超过 20 个字符,则按空格分割为:
- “This is a long”
- “document”
-
处理重叠:
- 保证上下文连贯性,每个块之间会有 5 个字符的重叠。例如,第二个块 “document” 实际包含了前一个块的末尾 5 个字符,所以实际内容为 “is a long document”。
最终结果
Part 1: This is a long
Part 2: is a long document
Part 3: that we can split
Part 4: can split up.
Part 5: Here is another line.
通过这种方式,文本被分割成较小的、语义相关的块,同时通过重叠保持块之间的上下文连贯性。这种方法特别适用于需要处理长文本但又希望保持文本语义完整性的应用场景。