莅耸 发表于 2025-11-20 20:15:04

Langchain Splitter源码阅读笔记(一)CharacterTextSplitter

一、TextSplitter

TextSplitter继承自BaseDocumentTransformer,是一个抽象类,不能直接创建实例。
 
核心(内部)属性有:
_chunk_size: 每块大小
_chunk_overlap: 每块之间的重叠区大小
_length_function: 计算大小的方法,可以传递token计算的函数,也可以传别的比如普通的len()
_keep_separator: Boolean 分块后是否保留分割符
_add_start_index: Boolean 是否在分割后返回的文档元数据中保存每块第一个字符在原始文档中的index
_strip_whitespace: Boolean 分割后是否去掉前后的空格
 
核心方法:
split_text(self, text: str) -> List(str)
分割方法,抽象方法,要在具体的子类中根据分割算法实现。
create_documents(self, texts: list, metadatas: list) -> list
传入文本和可选的元数据信息,返回将文本调用split_text分割后,创建的Document格式数据,doc.page_content是文本,metadata是创建的元数据,根据是否_add_start_index自动保存index
split_documents(self, documents: Iterable) -> list
将传入的document列表分割,返回分割后的document列表,内部就是对每个document调用create_documents创建文档,组合返回。
--------以下为内部方法---------
_join_docs(self, docs: list, separator: str) -> str 
注意这个参数里的docs是字符串列表,就是根据传入的分割符合并字符串列表为一个长字符串,给下面的_merge_splits使用
_merge_splits(self, splits: Iterable, separator: str) -> list
把分割得过于细的小块合并成更接近self._chunk_size的块,并确保相邻块之间有self._chunk_overlap大小的重叠内容。
def _merge_splits(self, splits: Iterable, separator: str) -> list:
2         # We now want to combine these smaller pieces into medium size
3         # chunks to send to the LLM.
4         separator_len = self._length_function(separator)
5
6         docs = []
7         current_doc: list = []
8         total = 0
9         for d in splits:
10             len_ = self._length_function(d)
          # 默认先在current_doc里面append(d),直到满足下面的if,往docs里面加入值
11             if (
12               total + len_ + (separator_len if len(current_doc) > 0 else 0)
13               > self._chunk_size
14             ):
15               if total > self._chunk_size:
16                     logger.warning(
17                         "Created a chunk of size %d, which is longer than the "
18                         "specified %d",
19                         total,
20                         self._chunk_size,
21                     )
22               if len(current_doc) > 0:
23                     doc = self._join_docs(current_doc, separator)
24                     if doc is not None:
25                         docs.append(doc)
26                     # Keep on popping if:
27                     # - we have a larger chunk than in the chunk overlap
28                     # - or if we still have any chunks and the length is long
29                     while total > self._chunk_overlap or (
30                         total + len_ + (separator_len if len(current_doc) > 0 else 0)
31                         > self._chunk_size
32                         and total > 0
33                     ):
34                         total -= self._length_function(current_doc) + (
35                           separator_len if len(current_doc) > 1 else 0
36                         )
37                         current_doc = current_doc
38             current_doc.append(d)
39             total += len_ + (separator_len if len(current_doc) > 1 else 0)
40         doc = self._join_docs(current_doc, separator)
41         if doc is not None:
42             docs.append(doc)
43         return docsView Code这个方法的核心是,每当current_doc满足chunk_size时,先把current_chunk里面的字符join后塞进docs,然后,不是直接清空curent_chunk,而是依次从current_chunk头部移除文本单元,直到current_chunk的文本长度小于_chunk_overlap。此时current_chunk里面的文本就是新块的开头,也是两块之间的重叠值。
二、CharacterTextSplitter

这个类继承自上面的TextSplitter,增加了separator属性和is_separator_regex(分割符是否为正则表达式)属性。实现了父类的抽象方法split_text。
这个类里的split_text方法调用了自定义的_split_text_with_regex()方法,对传入的文本text进行分割。先看代码:
1 # CharactorTextSplitter类内部 2 def split_text(self, text: str) -> list: 3         """Split into chunks without re-inserting lookaround separators.""" 4         # 1. Determine split pattern: raw regex or escaped literal 5         sep_pattern = ( 6             self._separator if self._is_separator_regex else re.escape(self._separator) 7         ) 89         # 2. Initial split (keep separator if requested)10         splits = _split_text_with_regex(11             text, sep_pattern, keep_separator=self._keep_separator12         )13 14         # 3. Detect zero-width lookaround so we never re-insert it15         lookaround_prefixes = ("(?=", "(?

敕码 发表于 2025-11-30 01:39:17

谢谢楼主提供!

崔和美 发表于 2025-12-16 06:15:11

鼓励转贴优秀软件安全工具和文档!

矛赓宁 发表于 2025-12-25 05:50:35

收藏一下   不知道什么时候能用到

黎娅茜 发表于 2026-1-2 22:06:53

这个有用。

啦汇 发表于 2026-1-6 13:23:04

谢谢分享,试用一下

材部 发表于 2026-1-19 12:36:52

谢谢楼主提供!

昆拗干 发表于 2026-1-20 01:41:51

用心讨论,共获提升!

喳谍 发表于 2026-1-21 04:48:13

鼓励转贴优秀软件安全工具和文档!

汪玉珂 发表于 2026-1-22 09:38:09

东西不错很实用谢谢分享

穆望 发表于 2026-1-24 09:34:20

感谢发布原创作品,程序园因你更精彩

韶侪 发表于 2026-1-25 10:52:47

不错,里面软件多更新就更好了

瘴锲如 发表于 2026-1-26 10:23:42

很好很强大我过来先占个楼 待编辑

采序 发表于 2026-1-26 12:20:09

用心讨论,共获提升!

驶桐柢 发表于 2026-1-28 01:57:21

前排留名,哈哈哈

摹熹 发表于 2026-1-29 02:16:25

谢谢楼主提供!

役魅肋 发表于 2026-2-1 07:33:15

感谢,下载保存了

背竽 发表于 2026-2-2 05:00:44

鼓励转贴优秀软件安全工具和文档!

党新苗 发表于 2026-2-3 05:49:47

前排留名,哈哈哈

岑韬哎 发表于 2026-2-7 08:01:43

感谢分享,下载保存了,貌似很强大
页: [1] 2
查看完整版本: Langchain Splitter源码阅读笔记(一)CharacterTextSplitter