langchain txt 文档按字数分块,按指定字符分块

文章介绍了使用RecursiveCharacterTextSplitter按字数和指定字符分块的方法,以及CharacterTextSplitter按单个分隔符分块的用法,特别提到了如何处理换行符和调整chunk_size以适应不同情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

RecursiveCharacterTextSplitter 按字数分块

CharacterTextSplitter 指定单个分隔符分块


txt 有多行,我的这份数据有 67 行,样例如下:

字段1\t值1\n

字段2\t值2\n

...

RecursiveCharacterTextSplitter 按字数分块

按照每 100 个字分块,每块允许重叠字数为 20,可以看到结果被分为了 135 个块

from langchain.text_splitter import CharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter


# 方法1 读取
filepath = 'data/专业描述.txt'
with open(filepath, encoding='utf8') as f:
    state_of_the_union = f.read()

# 方法2 读取
state_of_the_union = TextLoader(filepath, encoding='utf8').load()

# 按块分割
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,  # 指定每块大小
    chunk_overlap=20,  # 指定每块可以重叠的字符数
    length_function=len,
    is_separator_regex=False,
)
texts = text_splitter.create_documents([state_of_the_union])
# texts = text_splitter.split_documents(raw_documents)
print(texts)

其实这个也可以按照指定字符去分割,按顺序分割它们,直到块足够小。默认列表是 ["\n\n", "\n", " ", ""],指定 separators 参数

from langchain.text_splitter import CharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter


# 方法1 读取
filepath = 'data/专业描述.txt'
with open(filepath, encoding='utf8') as f:
    state_of_the_union = f.read()

# 方法2 读取
state_of_the_union = TextLoader(filepath, encoding='utf8').load()

# 按块分割
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,  # 指定每块大小
    chunk_overlap=20,  # 指定每块可以重叠的字符数
    length_function=len,
    is_separator_regex=False,
    separators=['\n', '\n\n']  # 指定按照什么字符去分割,如果不指定就按照 chunk_size +- chunk_overlap(100+-20)个字去分割
)
texts = text_splitter.create_documents([state_of_the_union])
# texts = text_splitter.split_documents(raw_documents)
print(texts)

在这里我指定了 \n 换行负去分割,可以看到被分割为了我的数据行数 67 行

为什么我里面还有一个 \n\n 呢,且用的是列表,假如我的数据有某一行换行是两个 \n\n,那我指定一个 \n 就会有问题,所以相当于加了一个选择,分割符号以 \n 或者 \n\n 去进行分割;

想再加其他分隔符只需要加到列表中就可以了,所以好处是可以指定多个分隔符!

下面这种方法就只能指定一个分隔符。

CharacterTextSplitter 指定单个分隔符分块

以 \n 为分隔符,得到 67 块

from langchain.text_splitter import CharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter


# 方法1 读取
filepath = 'data/专业描述.txt'
with open(filepath, encoding='utf8') as f:
    state_of_the_union = f.read()

# 方法2 读取
state_of_the_union = TextLoader(filepath, encoding='utf8').load()

text_splitter = CharacterTextSplitter(
    separator="\n",
    chunk_size=100,
    chunk_overlap=20,
    length_function=len,
    is_separator_regex=True,
)
texts = text_splitter.create_documents([state_of_the_union])
# texts = text_splitter.split_documents(raw_documents)
print(texts)

当按照指定字符分割时,发现命名指定了字符却没有分割,chunck_size 导致的

例如我想以 \n 分割每一行,chunck_size=100, chunck_overlap=20

而我的一行字数为:123456789

9个字符,远远小于 100,那么不会按照指定字符分割了,按照 chunck_size 分割了,需要调小它,例如这里调小为 

chunck_size=3,chunck_overlap=0,就可以正常按照我指定的字符分割了

### 关于 LangChain4j 中 RAG 的分块实现 在 LangChain4j 的 RAG(检索增强生成)实现中,分块是一个重要的预处理步骤。它将文档分割成较小的部分以便更好地进行向量化和存储。这种技术可以显著提高检索效率以及模型的理解能力。 #### 文档加载与解析 首先,通过 `FileSystemDocumentLoader` 加载文件,并使用合适的 `DocumentParser` 将其转换为可操作的结构化数据[^2]: ```java Path documentPath = Paths.get(VectorTest.class.getClassLoader().getResource("rag/terms-of-service.txt").toURI()); DocumentParser documentParser = new TextDocumentParser(); Document document = FileSystemDocumentLoader.loadDocument(documentPath, documentParser); System.out.println(document.text()); ``` 此部分代码展示了如何从指定路径读取文档并将其解析为文本形式。 #### 分块逻辑 为了支持更高效的检索,在实际应用中需要对文档内容进行分块处理。虽然当前引用未提及具体分块方法,但在常见的实践场景下,可以通过以下方式完成分块: 1. **基于字符长度** 使用滑动窗口的方式按固定字符数切分文档。 ```java public List<String> splitByCharacter(String text, int chunkSize) { List<String> chunks = new ArrayList<>(); for (int i = 0; i < text.length(); i += chunkSize) { int end = Math.min(text.length(), i + chunkSize); chunks.add(text.substring(i, end)); } return chunks; } ``` 2. **基于语义单元** 利用自然语言处理工具识别句子边界或其他语义单位作为切割依据。这种方式能够保留上下文信息,更适合复杂应用场景。 ```java import org.apache.commons.lang3.StringUtils; public List<String> splitBySentence(String text, int maxChunkLength) { String[] sentences = StringUtils.splitPreserveAllTokens(text, ".!?"); List<String> chunks = new ArrayList<>(); StringBuilder currentChunk = new StringBuilder(); for (String sentence : sentences) { if (currentChunk.length() + sentence.length() <= maxChunkLength) { currentChunk.append(sentence).append(" "); } else { chunks.add(currentChunk.toString().trim()); currentChunk = new StringBuilder(sentence.trim()).append(" "); } } if (!currentChunk.toString().isEmpty()) { chunks.add(currentChunk.toString().trim()); } return chunks; } ``` 以上两种方法分别适用于不同需求下的分块任务。前者简单高效但可能会破坏语义连贯性;后者则更加注重保持原文本的意义完整性[^3]。 #### 向量化与存储 经过分块后的每一段文字都需要被转化为数值表示形式存入数据库供后续查询使用。这一过程中会涉及到嵌入层的应用——即将字符串映射到高维空间中的矢量点集。最终这些矢量会被保存至专门设计的支持快速近似最近邻搜索的数据结构当中去。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值