ChunkingService 概览 / ChunkingService Overview
ChunkingService 和相关策略类负责把长文本切成适合 embedding 与检索的文本块。它们位于 Parser 之后、Embedding 之前,是 RAG 摄取质量与召回效果的关键调节点。
本文聚焦模块职责、策略选择、兼容入口和调优方向;具体类、工厂函数和方法签名以 核心服务 API 参考 中的自动渲染结果为准。
何时阅读本页 / When to Read This Page
适合在以下场景阅读本页:
- 需要理解为什么同一份文档会被切成多个 chunk
- 需要在
fixed_size、sentence、paragraph、recursive等策略之间做选择 - 需要判断新代码应直接使用策略类,还是暂时复用兼容性的
ChunkingService - 需要调优块大小、重叠率和语义边界保留方式
关键文件 / Key Files
| 路径 | 作用 |
|---|---|
ai_service/services/chunking.py |
分块策略、策略工厂和兼容服务入口的源码所在 |
| Parser 子系统 | 分块上游,负责产出待切分的纯文本 |
| EmbeddingService 概览 | 分块下游,负责对 chunk 生成向量 |
| IngestionService 概览 | 摄取主流程如何选择并应用分块策略 |
| 核心服务 API 参考 | ChunkingService、get_chunking_service 等对象的源码级说明 |
核心类与函数 / Core Classes and Functions
BaseChunkingStrategy所有分块策略的抽象基类,定义统一的chunk_text()契约。get_chunking_strategy按策略名称和参数返回具体策略实例,是新代码优先使用的入口。validate_chunking_strategy_configuration对策略名称、参数名和运行时可用性做预检,供 API 在持久化前复用。list_chunking_strategy_capabilities产出当前环境下各策略的 capability 元数据,供/chunking-strategiesAPI 和管理台选择器使用。ChunkingService兼容层,内部包装固定大小策略,保留给历史调用路径使用。get_chunking_service兼容服务的单例工厂。
规则:新代码优先使用策略工厂与具体策略类;
ChunkingService主要用于向后兼容。
数据流 / Data Flow
flowchart LR
A[Parsed text] --> B[Resolve chunking strategy]
B --> C{Strategy type}
C -->|fixed_size| D[Uniform chunks with overlap]
C -->|sentence or paragraph| E[Respect sentence or paragraph boundaries]
C -->|recursive| F[Fallback across separator levels]
C -->|semantic family| G[Use semantic boundary heuristics]
D --> H[ChunkResult list]
E --> H
F --> H
G --> H
H --> I[EmbeddingService]
策略选择 / Strategy Selection
系统当前支持的主策略可以这样理解:
| 策略 | 标识 | 适用场景 |
|---|---|---|
| 固定大小 | fixed_size |
通用、稳定、低复杂度的默认场景 |
| 句子级 | sentence |
需要保持句子完整性的文章类文本 |
| 段落级 | paragraph |
结构化文档、说明书、较长段落文本 |
| 递归层级 | recursive |
希望兼顾结构边界和通用鲁棒性 |
| 语义分割 | semantic |
需要实验性语义边界能力的场景 |
| 句子窗口 | sentence_window |
需要句子中心 + 周边上下文的检索场景 |
| 语义切分器 | semantic_splitter |
使用 LlamaIndex 语义边界能力的场景 |
推荐规则
- 不确定时优先从
recursive或fixed_size开始 - 文本叙事性强时优先
sentence - 结构化文档较强时优先
paragraph - 只有在明确接受额外依赖与实验成本时再启用语义类策略
策略参数详解 / Strategy Parameters
Fixed Size(固定大小)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
chunk_size |
int | 512 | 每个 chunk 的目标字符数,控制 chunk 的最大长度 |
chunk_overlap |
int | 50 | 相邻 chunk 之间的重叠字符数,用于减少语义断裂 |
调优建议:
- 增加 chunk_size 可以包含更多上下文,但会降低检索精确度
- 增加 chunk_overlap 可以减少语义断裂,但会增加向量数量和索引成本
- chunk_overlap 必须小于 chunk_size,否则会抛出 ValueError
Sentence(句子级)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
target_size |
int | 512 | 每个 chunk 的目标字符数,作为分组句子的参考上限 |
max_sentences_per_chunk |
int | 10 | 每个 chunk 允许包含的最大句子数,防止 chunk 过长 |
调优建议:
- 适用于需要保持句子完整性的文章类文本
- target_size 是软限制,实际 chunk 大小可能略小于该值
- max_sentences_per_chunk 是硬限制,达到后会强制分割
Paragraph(段落级)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
target_size |
int | 1024 | 每个 chunk 的目标字符数,作为分组段落的参考上限 |
max_paragraphs_per_chunk |
int | 5 | 每个 chunk 允许包含的最大段落数,防止 chunk 过长 |
调优建议:
- 适用于结构化文档、说明书、较长段落文本
- 段落边界通过 \n\n 识别
- target_size 默认较大,适合段落较长的文档
Recursive(递归层级)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
chunk_size |
int | 512 | 每个 chunk 的目标字符数 |
chunk_overlap |
int | 50 | 相邻 chunk 之间的重叠字符数 |
separators |
list[str] | ["\n\n", "\n", ". ", " ", ""] |
分隔符优先级列表,按顺序尝试分割 |
调优建议:
- 适用于希望兼顾结构边界和通用鲁棒性的场景
- separators 按优先级从高到低尝试:先尝试段落分割,再尝试句子分割,最后按字符分割
- 自定义 separators 可以适应特殊文档格式
- chunk_overlap 必须小于 chunk_size
Semantic(语义分割)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
similarity_threshold |
float | 0.7 | 相似度阈值(0-1),低于此值时进行分割 |
min_chunk_size |
int | 200 | 最小 chunk 大小(字符数),防止产生过短的 chunk |
max_chunk_size |
int | 1000 | 最大 chunk 大小(字符数),防止产生过长的 chunk |
调优建议:
- 适用于需要实验性语义边界能力的场景
- 当前实现为简化版本,实际使用句子级分割作为 fallback
- 完整语义分割需要与 EmbeddingService 集成
- similarity_threshold 越高,分割越频繁,chunk 越小
Sentence Window(句子窗口)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
window_size |
int | 3 | 上下文窗口大小,每个句子前后包含的句子数 |
调优建议:
- 适用于需要句子中心 + 周边上下文的检索场景
- 需要 llama-index-core 依赖
- 每个句子都会成为一个独立的 chunk,但检索时会包含窗口内的上下文
- 适合高精度的 QA 工作负载
Semantic Splitter(语义切分器)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
buffer_size |
int | 1 | 缓冲区大小,用于平滑语义边界 |
breakpoint_percentile_threshold |
int | 95 | 断点百分位阈值(0-100),控制分割的激进程度 |
调优建议:
- 适用于使用 LlamaIndex 语义边界能力的场景
- 需要 llama-index-core 依赖
- 使用 EmbeddingService 的嵌入模型,不再依赖 OpenAI
- breakpoint_percentile_threshold 越高,分割越保守,chunk 越大
- buffer_size 越大,边界越平滑,但可能降低分割精度
运行约定 / Runtime Behavior
兼容层与新入口
get_chunking_strategy()是面向新代码的首选入口ChunkingService保留为兼容层,内部默认包装固定大小策略- 在
IngestionService中,可根据任务或知识源配置动态选择具体策略
块大小与重叠
- 块越小,检索定位通常越精确,但上下文碎片化风险越高
- 重叠可以减少语义断裂,但会增加向量数量和索引成本
- 实际最优值依赖文档类型、查询粒度和模型上下文预算
依赖差异
- 基础策略不需要额外依赖
sentence_window和semantic_splitter依赖llama-index-coresemantic_splitter不再走 LlamaIndex 的默认 OpenAI embedding 路径,而是显式注入一个基于EmbeddingService的 LlamaIndex adapter- 这意味着
semantic_splitter的可用性不仅取决于llama-index-core,也取决于仓库当前 embedding 配置是否有效 sentence_window和semantic_splitter只会向 LlamaIndex 转发其原生支持的参数- API 与 Admin UI 现在会在保存知识源默认值、保存 Agent 默认值、以及启动 ingestion 之前做预检;除显式兼容的历史字段外,其它未知参数会直接收到
422 - 对直接 Python 调用而言,
semantic_splitter.target_size仍保留历史兼容行为:构造时会忽略该字段并记录告警;但这条兼容路径不会再通过 API 暴露给运营配置
常见集成模式 / Common Integration Patterns
通过策略工厂创建策略
from ai_service.services.rag.chunking import get_chunking_strategy
chunking_strategy = get_chunking_strategy(
strategy_type="sentence",
params={"target_size": 512, "max_sentences_per_chunk": 10},
)
在保存或执行前做能力预检
from ai_service.services.rag.chunking import validate_chunking_strategy_configuration
validation_result = validate_chunking_strategy_configuration(
strategy_type="semantic_splitter",
params={"buffer_size": 1, "breakpoint_percentile_threshold": 95},
)
if not validation_result.is_valid:
raise ValueError(validation_result.error_message)
暴露策略 capability 给控制台
from ai_service.services.rag.chunking import list_chunking_strategy_capabilities
capability_list = list_chunking_strategy_capabilities()
直接使用兼容服务
from ai_service.services.rag.chunking import get_chunking_service
chunking_service = get_chunking_service()
chunk_results = chunking_service.chunk_text(
text="long text",
document_id="doc-123",
document_name="example.txt",
source_id="source-456",
)
在摄取链路中显式注入
from ai_service.services.rag.chunking import ChunkingService
from ai_service.services.rag.ingestion import IngestionService
custom_chunking_service = ChunkingService(chunk_size=500, chunk_overlap=100)
ingestion_service = IngestionService(chunking_service=custom_chunking_service)
不应在本页重复维护的内容 / What This Page Should Not Duplicate
以下内容应留在 API 参考或配置页,而不是继续堆在模块页中:
- 每个策略类的完整构造参数表
ChunkResult的完整字段清单chunk_text()、estimate_chunk_count()的详细签名- 与源码 docstring 完全重复的策略实现细节