跳到主要内容

Chonkie — 架构与原理

30 秒导读: Chonkie 是一个专注做一件事的库——把长文本切成「块(chunk)」,好让你喂给 RAG(检索增强生成)系统。它的卖点是(核心安装 ~49MB)和(热点路径用 Rust 扩展 chonkie-core 实现)。除了 11 种切块策略,它还提供一条 Pipeline,把「抓文件 → 切块 → 加重叠/嵌入 → 写进向量库」串成一行链式调用。

1. 这是什么(零基础也能懂)

一句话定义: Chonkie 是一个 Python 文本分块(chunking)库——输入一段长文本,输出一串带元数据的小块 Chunk

解决什么问题 / 给谁用

做 RAG 的人都会遇到同一个麻烦:大模型上下文有限,你不能把整本手册塞进去。于是要先把文档切成小块,把每块做成向量存进数据库,检索时只取最相关的几块喂给模型。

切块听起来简单,真做起来全是坑:

  • 按固定字数硬切,会把一句话从中间劈开,检索质量暴跌。
  • 想「按语义切」,又得自己写嵌入、算相似度、找边界,代码越堆越多。
  • 每个向量库、每个嵌入厂商的 API 都不一样,胶水代码写到吐。

Chonkie 的定位就是:「just works」的切块——给你一组从笨到聪明的切块器,加一套统一的下游接口,让你不必反复造轮子。

它能做什么(功能)

  • 11 种切块器:从最朴素的「按 token 数硬切」,到「递归按段落/句子降级切」,到「按语义相似度切」,到「让 LLM 帮你判断在哪切」。
  • 统一的 token 抽象:字符级、词级、字节级内置;HuggingFace tokenizers、OpenAI tiktoken 等按需加载。
  • Refinery(精炼):切完之后再加块间重叠、或顺手把嵌入算好。
  • Handshake(握手):一行把块写进 Chroma / Qdrant / pgvector / Pinecone 等 10+ 向量库。
  • Pipeline:把上面这些用链式 API 串起来,支持同步 / 异步 / 批量。
  • REST API 服务:chonkie serve 起一个 FastAPI 服务,把切块能力当 HTTP 接口用。

用起来什么样

最小例子——三步走:

# 示意,非源码(但贴近 README 真实用法)
from chonkie import RecursiveChunker

chunker = RecursiveChunker() # 1. 选一个切块器(默认递归切)
chunks = chunker("Chonkie is the goodest boi! My favorite chunking hippo.") # 2. 直接当函数调用

for chunk in chunks: # 3. 拿到一串 Chunk
print(chunk.text, chunk.token_count) # 每块有文本、token 数、原文起止位置

注意第 2 步:切块器实例可以直接当函数调用(chunker(text)),这是 BaseChunker.__call__ 提供的语法糖(src/chonkie/chunker/base.py:95-116)。

复杂一点,用 Pipeline 把多步串起来:

# 示意,非源码(贴近 README)
from chonkie import Pipeline

pipe = (Pipeline()
.chunk_with("recursive", chunk_size=2048, recipe="markdown") # 切块
.refine_with("overlap", context_size=128) # 加块间重叠
.refine_with("embeddings", embedding_model="...")) # 算嵌入

doc = pipe.run(texts="...") # 一次跑完;doc.chunks 就是结果

一句话直觉 / 类比

把 Chonkie 想成文档的切菜机:你换不同刀头(切块器),它就用不同手法把一大块「食材(文本)」切成大小合适的「块(chunk)」;Pipeline 则是整条流水线——洗、切、调味、装盘(写库)一气呵成。

本节不碰底层。下一章起,我们从「11 种刀头到底差在哪」开始,由浅入深。

2. 顶层全景(它大概怎么转)

Chonkie 的内部用一条叫 CHOMP 的流水线组织(作者自己的缩写,见 src/chonkie/pipeline/pipeline.py:19)。一份文本从进到出,顺序固定:

输入文本 / 文件


┌───────────┐ 抓取数据(文件、目录)
│ Fetcher │ ← 可选,直接传 texts 时跳过
└─────┬─────┘

┌───────────┐ 预处理 / 清洗 → 产出 Document
│ Chef │ ← 没指定时自动补一个 TextChef
└─────┬─────┘

┌───────────┐ ★核心★ 把 Document.content 切成 list[Chunk]
│ Chunker │ ← 11 种策略,本库的价值所在
└─────┬─────┘

┌───────────┐ 后处理:加块间重叠 / 算嵌入(可多个)
│ Refinery │
└─────┬─────┘

┌──────────────────────┐
│ Porter / Handshake │ 导出 JSON / 写进向量数据库
└──────────────────────┘

怎么读这张图:从上到下是数据流;每一格是一类「组件」。Pipeline.run自动把你乱序声明的步骤重排成这个顺序(_reorder_steps,src/chonkie/pipeline/pipeline.py:484-517),所以你写 .refine_with(...).chunk_with(...) 也不会错。

各组件一句话职责

组件干什么在哪
Fetcher从文件/目录读原始数据src/chonkie/ 各 fetcher(@fetcher 注册)
Chef把原始数据洗成 DocumentMarkdownChef/TextChef
Chunker把文本切成 Chunk(核心)src/chonkie/chunker/
Refinery给块加重叠 / 嵌入src/chonkie/refinery/
Porter导出到 JSON / HF datasets@porter 注册的组件
Handshake写进向量数据库src/chonkie/handshakes/
Tokenizer统一的 token 计数/编解码src/chonkie/tokenizer.py
chonkie-coreRust 扩展,跑切分/合并/峰值检测热点外部依赖(pyproject.toml:52)

主线走一遍(高层)

以默认的 RecursiveChunker("...") 调用为例,不进代码:

  1. 你传入字符串 → __call__ 判断是单串还是批量(base.py:95)。
  2. 单串走 chunk() → 递归地按「段落 → 句子 → 停顿符 → 词 → token」逐级把文本切碎(recursive.py:190)。
  3. 真正「切在哪」和「把碎片合并回 chunk_size 大小」这两个热点,下沉到 Rust chonkie_core(base.py:48-61recursive.py:187)。
  4. 产出一串 Chunk,每个带 text / start_index / end_index / token_count(src/chonkie/types/base.py:16-41)。

这条「Python 编排 + Rust 干重活」的分工,是理解 Chonkie 性能与代码结构的总钥匙。

3. 阅读地图(建议顺序)

这个项目子系统多,拆成了 5 章,由浅入深:

  1. 01-chunkers.md — 切块器全景 先把 11 种切块器一次看全:各自切什么、何时用、共享的 BaseChunker 主线(批量/异步/Document 模式)。想快速选型,只读这章就够。

  2. 02-recursive-deep-dive.md — 递归切块逐行走读 Chonkie 的默认主力。多级降级规则 RecursiveRules、Rust 合并 merge_splits、偏移量计算的小聪明。

  3. 03-semantic-and-agentic.md — 语义切块 & LLM 切块 SemanticChunker 怎么用嵌入相似度 + Savitzky-Golay 滤波找边界;SlumberChunker 怎么让 LLM 通过二分窗口判断「在第几段切」。

  4. 04-pipeline-and-registry.md — 流水线与注册表 CHOMP 流水线的步骤重排、装饰器注册表如何把组件挂上去、参数怎么被自动拆成「构造参数 vs 调用参数」。

  5. 05-ecosystem-and-core.md — 适配器生态 & Rust 引擎 tokenizer / embeddings / genie / handshake 这些「可插拔后端」用同一套适配器模式;以及 chonkie-core 这层 Rust 到底承担了什么。


给 agent 的提示: 若任务是「选哪个切块器 / 各切块器差异」→ 读第 1 章;「递归切块为何这样切」→ 第 2 章;「语义/LLM 切块原理」→ 第 3 章;「Pipeline 怎么组装、怎么扩展自定义组件」→ 第 4 章;「换 tokenizer / 嵌入厂商 / 向量库」→ 第 5 章。每章末尾有「代码地图」三列表,可凭符号名直接 grep 跳源码。