文本分割的方法

Table of Contents

长文本分割是构建高效检索系统的重要步骤,好的分割方法需要兼顾语义完整性和块大小适中。我们要避免简单的固定长度切分导致语义丢失的问题:


1. 基于句子分割

方法

使用自然语言处理工具将文本分割成句子,然后再组合成适当大小的块。

实现示例

import nltk
from nltk.tokenize import sent_tokenize

# 下载 punkt 分词器(首次运行需要)
nltk.download('punkt')

def split_text_by_sentences(text, chunk_size=300):
    sentences = sent_tokenize(text)
    chunks = []
    current_chunk = ""

    for sentence in sentences:
        # 如果当前块加上新句子的长度超过 chunk_size,则开始新块
        if len(current_chunk) + len(sentence) > chunk_size:
            chunks.append(current_chunk.strip())
            current_chunk = sentence
        else:
            current_chunk += " " + sentence

    # 添加最后一个块
    if current_chunk:
        chunks.append(current_chunk.strip())

    return chunks

# 示例使用
text_chunks = split_text_by_sentences(pdf_text, chunk_size=300)
print(f"分割后的块数: {len(text_chunks)}")
print(text_chunks[:3])  # 打印前 3 个块

2. 基于段落分割

方法

如果文本格式包含段落信息(如 PDF 提取结果),可以优先按照段落分割,确保块的语义完整性。

实现示例

def split_text_by_paragraphs(text, chunk_size=300):
    paragraphs = text.split("\n\n")  # 假设段落以双换行分隔
    chunks = []
    current_chunk = ""

    for paragraph in paragraphs:
        if len(current_chunk) + len(paragraph) > chunk_size:
            chunks.append(current_chunk.strip())
            current_chunk = paragraph
        else:
            current_chunk += " " + paragraph

    if current_chunk:
        chunks.append(current_chunk.strip())

    return chunks

# 示例使用
text_chunks = split_text_by_paragraphs(pdf_text, chunk_size=300)
print(f"分割后的块数: {len(text_chunks)}")
print(text_chunks[:3])  # 打印前 3 个块

3. 滑动窗口法

方法

使用滑动窗口技术创建有重叠的块,保证查询时的上下文信息完整性。

实现示例

def sliding_window_split(text, chunk_size=300, overlap=50):
    chunks = []
    for i in range(0, len(text), chunk_size - overlap):
        chunk = text[i:i + chunk_size]
        chunks.append(chunk.strip())
    return chunks

# 示例使用
text_chunks = sliding_window_split(pdf_text, chunk_size=300, overlap=50)
print(f"分割后的块数: {len(text_chunks)}")
print(text_chunks[:3])  # 打印前 3 个块

4. 基于文本分层分割

方法

如果文本格式复杂(如技术文档、论文),可以结合标题、章节等结构信息,优先按结构分割。

示例

def split_text_by_structure(text, chunk_size=300):
    # 假设标题以 "## " 开头
    sections = text.split("## ")
    chunks = []

    for section in sections:
        if len(section) > chunk_size:
            chunks.extend(sliding_window_split(section, chunk_size=chunk_size, overlap=50))
        else:
            chunks.append(section.strip())

    return chunks

# 示例使用
structured_text = "## Introduction\nThis is the intro.\n## Methodology\nThis is the method section."
text_chunks = split_text_by_structure(structured_text, chunk_size=100)
print(f"分割后的块数: {len(text_chunks)}")
print(text_chunks)  # 打印分割结果

5. 结合 NLP 工具的智能分割

方法

使用 NLP 工具(如 spaCy)按语义分割文本,例如按句子或语义段落进行分割。

实现示例

import spacy

# 加载 spaCy 模型
nlp = spacy.load("en_core_web_sm")

def split_text_by_semantics(text, chunk_size=300):
    doc = nlp(text)
    chunks = []
    current_chunk = ""

    for sentence in doc.sents:
        if len(current_chunk) + len(sentence.text) > chunk_size:
            chunks.append(current_chunk.strip())
            current_chunk = sentence.text
        else:
            current_chunk += " " + sentence.text

    if current_chunk:
        chunks.append(current_chunk.strip())

    return chunks

# 示例使用
text_chunks = split_text_by_semantics(pdf_text, chunk_size=300)
print(f"分割后的块数: {len(text_chunks)}")
print(text_chunks[:3])  # 打印前 3 个块

比较与选择

方法 优点 缺点
句子分割 简单直观,语义完整 对长句子可能不够灵活
段落分割 保留段落语义 段落过长时需进一步分割
滑动窗口法 保证上下文信息完整 存在重复信息,可能增加存储成本
文本分层分割 适合结构化文本 依赖文本中有明显结构标记
NLP 智能分割 结合语义分析,效果更智能 需要加载 NLP 模型,速度较慢

最佳实践

  1. 如果文本语义结构较好(如技术文档、论文),优先基于段落或结构分割
  2. 如果需要精确检索上下文,滑动窗口法 是很好的选择。
  3. 对通用场景,结合 NLP 工具的智能分割 是最强大的方法。

建议根据具体的文本内容选择合适的分割方法,同时可以结合分割方法优化 RAG 系统的性能!

Comments |0|

Legend *) Required fields are marked
**) You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Category: 似水流年