RAG组件:文本Chunk生成

       前面我们介绍了RAG知识库搭建的一些关键步骤,包括分词器、Embedding词嵌入、向量数据库存储,其实还忽略了一个比较重要的步骤,就是在分词器之前,还需要进行文本切分;

       如果我们想要创建一个RAG知识库,想必这个知识库的信息量是比较大的,如果这些知识都是一些文本信息的话,那能称之为库,文本的字数应该也在十万级别,甚至更多;那针对这些海量的文本信息,我们一次性将它输入给分词器是不可能的,即便Embedding可以接受这么大的token同时输入,那输出也只是一个高维向量,这也违背了做知识库的初心;所以我们需要在进入分词器之前,将这些海量的文本进行切分,将切分好的文本块逐一或者批量进行向量化,这样才会获得海量的语义向量数据;

       但是,即便是简单的数据切分也是有很多需要注意的点,不可以盲目的随意乱切,下面就简单说一说关于切分数据块的一些小细节,作为整个RAG知识库创建的一个补充。

一、切分要点 

       在搭建RAG(Retrieval-Augmented Generation)知识库时,文本切块是一个非常重要的步骤。切块的质量会直接影响到后续的检索和生成效果。以下是一些注意事项:

  1. 保持语义完整性

    • 切块时要尽量保证每个块包含完整的语义信息,避免将一句话或一个段落拆分成多个块,从而导致上下文丢失。
    • 例如,不要在句子中间断开,而应该以句号、分号等标点符号为边界。
  2. 控制块的大小

    • 块的大小需要根据模型的最大输入长度来调整。通常块的大小建议在100-500个token之间。
    • 过大的块可能导致模型无法处理完整内容,过小的块则可能丢失重要上下文信息。
  3. 重叠窗口

    • 在切块时可以设置一定的重叠窗口(overlap),这样可以避免因切割导致的信息断裂。
    • 例如,两个相邻的块可以有50-100个token的重叠部分。
  4. 保留元信息

           如果原始文档中有一些重要的结构化信息(如标题、章节号、时间戳等),在切块时应尽量保留这些信息,以便后续检索时能更好地理解上下文。
  5. 处理特殊格式

           对于包含表格、代码、列表等内容的文档,需要特别注意这些格式的处理方式,确保它们在切块后仍然可读且有意义。
  6. 多语言支持

           如果知识库中包含多语言内容,切块时需要考虑不同语言的语法和语义特点。例如,中文没有空格分隔符,因此分词工具可能更合适。
  7. 去噪处理

           在切块前应对文本进行清洗,去除无关的噪声(如HTML标签、广告内容、重复内容等),以提高切块质量。
  8. 测试与调优

           切块策略需要经过实际测试和调优,观察其对检索和生成效果的影响,并根据结果不断优化。

二、常用工具

       目前也有很多工具可以帮助高效率的进行数据切分,下面就列几个比较常用的切分工具:

2.1 LangChain

       LangChain 是一个流行的框架,专门用于构建基于语言模型的应用程序。它提供了灵活的文本切块功能;

  • 特性:
    • 支持多种切块策略(按字符数、按句子、按段落)。
    • 可以设置重叠窗口。
    • 支持多语言处理。
  • 文档地址:LangChain
  • 代码示例:
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 示例长文本
long_text = """
在构建RAG知识库时,文本切块是一个非常重要的步骤。
切块的质量会直接影响到后续的检索和生成效果。
通常情况下,我们需要根据语义完整性、块大小等因素来设计切块策略。
此外,我们还需要考虑多语言支持、特殊格式处理等问题。
为了实现高效的切块,可以使用LangChain等工具。
"""

# 初始化切分器
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=50,  # 每个块的最大字符数
    chunk_overlap=10,  # 块之间的重叠字符数
    length_function=len,  # 使用len函数计算长度
    separators=["\n\n", "\n", "。", ",", " ", ""]  # 分隔符优先级列表
)

# 对文本进行切分
chunks = text_splitter.split_text(long_text)

# 打印切分结果
for i, chunk in enumerate(chunks):
    print(f"Chunk {i + 1}:\n{chunk}\n")

2.2 Hugging Face Transformers

       Hugging Face 提供了 Tokenizer 工具,可以用于按token切分文本;

  • 特性:
    • 支持多种预训练模型的分词器
    • 可以自定义最大长度和重叠窗口
  • 代码示例:
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
text = "This is a long document that needs to be chunked."
tokens = tokenizer.tokenize(text)
chunks = [tokens[i:i+10] for i in range(0, len(tokens), 10)]  # 按10个token切块

2.3  NLTK

       NLTK 是一个经典的自然语言处理库,适合处理英文文本;

  • 特性:
    • 提供句子分割、词性标注等功能
    • 可以结合正则表达式实现复杂的切块逻辑
  • 代码示例:
import nltk
nltk.download('punkt')

from nltk.tokenize import sent_tokenize

text = "This is the first sentence. This is the second one."
sentences = sent_tokenize(text)  # 按句子切块

2.4 spaCy

       spaCy 是一个高效的NLP库,支持多种语言;

  • 特性:
    • 提供句子分割、命名实体识别等功能
    • 支持自定义管道处理
  • 代码示例:
import spacy

nlp = spacy.load("en_core_web_sm")
text = "This is a sample text. It contains multiple sentences."
doc = nlp(text)
sentences = [sent.text for sent in doc.sents]  # 按句子切块

2.5 BeautifulSoup

       如果你的文档包含HTML或其他标记语言,BeautifulSoup 是一个强大的工具,可以帮助你提取纯文本并进行切块;

  • 特性:
    • 支持解析HTML、XML等格式
    • 可以去除标签、提取特定部分
  • 代码示例:
from bs4 import BeautifulSoup

html_doc = "<p>This is a paragraph.</p><p>Another paragraph.</p>"
soup = BeautifulSoup(html_doc, 'html.parser')
text = soup.get_text()  # 提取纯文本

注:如果以上方法均不能满足需求,也可以自己编写合适的脚本进行切分; 

三、总结

       在选择切块工具时,应根据具体的文档类型、语言特点和应用场景进行选择。对于大多数场景,LangChain 和 Hugging Face 的工具链是非常不错的选择。同时,在切块过程中,务必注意语义完整性、块大小控制和重叠窗口的设置,以确保最终的知识库能够高效地支持检索和生成任务。

### RAG 架构中文本分块方法的实现 在检索增强生成(Retrieval-Augmented Generation, RAG)架构中,文本分块是一种关键的技术手段,用于提高系统的效率和准确性。通过合理的文本分块策略,可以显著减少计算资源消耗并提升模型的表现。 #### 前沿项目与常见策略 目前存在多种文本分块策略可供选择,这些策略各有优劣,适用于不同的应用场景[^1]。以下是几种常见的文本分块方式及其适用场景: - **固定长度分块**:将文档按照固定的字符数或词数切分为多个片段。这种方式简单易行,但在处理复杂结构化数据时可能丢失重要信息。 - **基于句法分析的分块**:利用自然语言处理工具解析句子间的逻辑关系,从而划分出具有独立意义的小段落。此方法能够较好地保留原文含义,但实施起来较为复杂[^2]。 - **智能体式分块**:这是一种先进的动态分块技术,依靠预训练的语言模型或其他形式的人工智能算法来自适应地决定最佳切割位置。相比传统规则驱动的方法更加灵活精准[^2]。 - **后期分块(Late Chunking)**:不同于前期即完成全部内容拆解的做法,“后期分块”是在查询阶段才执行具体操作的一种延迟机制。这样不仅可以降低内存占用率而且有助于聚焦于最相关部分的数据提取过程[^3]。 #### 动态调整依据 为了达到最优效果,在实际部署过程中往往需要考虑以下几个方面来进行个性化定制化的参数调节工作: - 数据特性: 不同领域内的资料可能存在巨大差异因此要针对特定类型的素材制定专门方案; - 查询模式: 用户提问习惯也会影响最终呈现样式所以应该观察历史记录找出规律加以运用 ; - 性能指标: 平衡速度与质量之间的取舍也是不可忽视的一环. 下面给出一段 Python 示例代码展示如何使用 Hugging Face Transformers 库配合 FAISS 向量数据库来创建一个简单的 RAG 系统框架下的文本分块功能模块: ```python from transformers import AutoTokenizer, DPRContextEncoder, DPRQuestionEncoder import faiss import numpy as np def create_chunks(texts, tokenizer, max_length=512): chunks = [] for text in texts: tokens = tokenizer.tokenize(text) current_chunk = "" for token in tokens: if len(tokenizer(current_chunk + token)['input_ids']) <= max_length: current_chunk += token else: chunks.append(current_chunk.strip()) current_chunk = token if current_chunk != "": chunks.append(current_chunk.strip()) return chunks tokenizer = AutoTokenizer.from_pretrained('facebook/dpr-ctx_encoder-single-nq-base') texts = ["这是一个测试例子用来说明如何进行文本分块.", "..."] # 替换为您的真实文本列表 chunks = create_chunks(texts, tokenizer) # 将chunk转换成向量表示以便后续索引建立... context_model = DPRContextEncoder.from_pretrained('facebook/dpr-ctx_encoder-single-nq-base') vectors = context_model(**tokenizer(chunks, padding=True, truncation=True, return_tensors="pt")).pooler_output.detach().numpy() index = faiss.IndexFlatL2(vectors.shape[1]) faiss.normalize_L2(vectors) index.add(vectors) print("Index built successfully with", index.ntotal, "entries.") ``` 上述脚本定义了一个函数 `create_chunks` 来按指定的最大长度对输入文本集合做初步分割;接着加载了 Facebook 提供的一个上下文编码器实例作为特征映射组件,并把得到的结果存入到 Faiss 中形成高效的近似最近邻搜索结构以支持快速检索服务。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值