WeKnora 分块(Chunking)完全指南:自适应三层策略、参数调优与实战配置
【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora
导读
本文以 WeKnora 开源项目的官方分块指南(docs/CHUNKING.md)为骨架,结合仓库内internal/infrastructure/chunker分块器源码与internal/handler/chunker_debug.go预览端点实现,系统讲解 WeKnora 在上传文档后进行向量化(embedding)之前如何切片、默认参数为何如此设定、以及何时应该调整。读完本文,你将掌握 WeKnora 的四档策略选择逻辑(auto/heading/heuristic/legacy)、核心与父子(Parent-Child)分块的参数含义与推荐取值、针对不同嵌入模型(Embedding Model)的tokenLimit配置表、UI 预览调试方法,以及通过 REST API 写入分块配置的完整请求格式。
为什么分块(Chunking)如此重要
检索增强生成(RAG)的工作机制是:把文档切成小片(chunk),对每一片做向量化后写入向量索引;查询时再拉取最相关的切片交给 LLM 生成答案。因此文档的切片方式——块大小、重叠量、切点落在哪里——直接决定检索召回率(recall)与最终答案质量。
据项目文档引用的 Vecta 2026 年 2 月基准(覆盖 50 篇学术论文的实证结论):约 512 token、约 15% 重叠的递归式(recursive)切分是单一参数调节下的最强基线,端到端准确率可达 69%,优于语义分块(semantic chunking)和过度设计的混合方案。WeKnora 正是以此为地基,再在文档本身提供结构线索时叠加更聪明的分层策略。
源码佐证:这一默认值并非拍脑袋定的。在 internal/infrastructure/chunker/splitter.go 中,
DefaultChunkSize = 512(约 100–130 个英文 token / 约 300 个中文字符)、DefaultChunkOverlap = 80(约占 ChunkSize 的 15%),注释明确写明其依据正是 Vecta 2026 年 2 月基准,并将历史版本中三种不同的重叠默认值(Go 的 64、knowledge 服务的 50、Python docreader 的 100)统一收敛为 80,作为整个 chunker 包以及 knowledge 服务的唯一数据源。
自适应三层分块(Adaptive 3-tier Chunking)
WeKnora 将分块策略设计为自适应(adaptive)三层结构。每套知识库(Knowledge Base)可以通过编辑器侧边栏的Chunking面板,或 KB 配置 API 上的strategy字段设置:
| 策略 | 何时被选用 | 具体行为 |
|---|---|---|
auto(推荐) | 新建 KB 的默认值 | 先对文档做画像(profiling),再从下述链路中挑选最强的一层。 |
heading | Markdown 风格结构 | 沿#/##/###标题边界切分。每个 chunk 在 embedding 时会前置一个面包屑上下文头(如# Top > ## Section)。 |
heuristic | PDF 风格结构 | 沿换页符(form-feed / 分页符)、编号章节、多语言章节标记(德 / 英 / 中)、全大写标题、视觉分隔线等信号切分。 |
legacy(等价于recursive) | 其他任何情况,或作为兜底 | 纯基于分隔符的递归切分器——新版已修复优先级递归与重叠量计算问题。 |
文档画像器(Profiler)与校验器(Validator)
整个流程首先运行一个文档画像器,统计结构性信号计数:Markdown 标题数量、换页符数量、各语言的章节标记、全大写行、视觉分隔线、空行簇(blank-line bursts)等。auto策略根据这些计数决定采用哪一层;随后由校验器(Validator)拒绝明显损坏的输出(例如 heading 切分器产出 200 个单行 chunk),并自动降级到下一层,保证总能返回可用的结果。
源码佐证:策略常量与降级逻辑定义在 internal/infrastructure/chunker/strategy.go(
StrategyAuto/StrategyHeading/StrategyHeuristic/StrategyRecursive/StrategyLegacy)。Split函数通过resolveChainWithProfile解析出 tier 链后逐层尝试,ValidateChunks校验失败即记录 rejection 并继续下一层;链上最后兜底的永远是legacy递归切分器,保证"总会返回非空结果"。文档画像逻辑位于 internal/infrastructure/chunker/profiler.go,各层切分器分别在heading_splitter.go与heuristic_splitter.go中实现。
设置参考(Settings Reference)
核心参数(Core)
| 设置项 | 取值范围 | 默认值 | 适用场景建议 |
|---|---|---|---|
| Chunk size(块大小) | 100–4000 字符 | 512 | 默认值适用于大多数场景。FAQ / 原子化问答建议 200–400;叙事型长文建议 1000–2000。 |
| Chunk overlap(块重叠) | 0–500 字符 | 80(约 15%) | FAQ 与结构化记录建议 0;常规文档用默认 80;论证型文本(推理跨越多个块)建议 150–200。 |
| Separators(分隔符) | 字符串列表 | ["\n\n", "\n", "。", "!", "?", ";", ";"] | 顺序很重要——切分器优先尝试高优先级分隔符,只有当某段仍然超长时才回退到低优先级分隔符。 |
父子分块(Parent-Child Chunking)
WeKnora 提供两级检索机制:**子块(child chunks)**尺寸小,负责向量匹配(embedding for vector match);**父块(parent chunks)**尺寸大,检索命中后被回传给 LLM 作为上下文。
| 设置项 | 取值范围 | 默认值 | 说明 |
|---|---|---|---|
| Enable parent-child(启用父子分块) | 开关 | 开 | 超过 10 页的文档推荐开启。简短 FAQ 可关闭以减半存储成本。 |
| Parent chunk size(父块大小) | 512–8192 字符 | 4096(约 1000 英文 token) | 长上下文 LLM(Claude、GPT-4-Turbo)可调大;本地 4k 上下文的 LLM 建议调小到 1024–2048。 |
| Child chunk size(子块大小) | 64–2048 字符 | 384(约 95 英文 token) | Q&A 式精确匹配建议 128–256;若嵌入模型支持 1000+ token(如 E5 / BGE-large)可调到 512–1024。 |
源码佐证:
ChunkingConfig结构体完整定义了上述字段及其语义注释,见 internal/types/knowledgebase.go:EnableParentChild开启后"大父块提供上下文、小子块用于向量匹配,检索匹配子块但返回父块内容";ParentChunkSize默认 4096、ChildChunkSize默认 384,仅在开启父子分块时生效。Chunk结构体(internal/infrastructure/chunker/splitter.go)同时提供EmbeddingContent()方法:embedding 时在 chunk 内容前拼接ContextHeader(面包屑上下文),而Content本身保持与原文逐字符一致,从而保留位置不变量。
高级参数(Advanced)
| 设置项 | 取值范围 | 默认值 | 何时设置 |
|---|---|---|---|
| Token limit(Token 上限) | 0–8192 | 0(关闭) | 当你的嵌入模型有较小的 token 上限时启用,具体见下表。 |
| Languages(语言) | de/en/zh(可多选) | 空(自动检测) | 语料同质化时显式设置,可收窄 heuristic 模式的匹配范围。 |
各嵌入模型对应的 Token 上限配置表
| 嵌入模型 | Token 上限 | 推荐的tokenLimit设置 |
|---|---|---|
OpenAItext-embedding-3-small/large | 8191 | 0(保持关闭) |
| Anthropic Voyage-3 | 32000 | 0 |
| Jina-embeddings-v3 | 8192 | 0 |
Cohereembed-multilingual-v3 | 512 | 400 |
| BGE-base / BGE-large / E5-large | 512 | 400 |
Sentence-Transformerall-MiniLM-L6-v2 | 256 | 200 |
经验法则:任何 token 上限超过 2000 的现代嵌入模型,tokenLimit一律保持 0(关闭);对小型嵌入模型则建议设为模型硬上限的 80%,这样即使是信息密度更高的 CJK(中日韩)内容,块也始终能放得下。
源码佐证:
TokenLimit字段语义在 internal/types/knowledgebase.go 中定义为"以近似 token 数限制块大小,0 = 使用 ChunkSize 作为字符数"。预览端点则通过chunker.ApproxTokenCountFromRuneLen依据检测到的语言估算每个块约消耗多少 token(见 internal/handler/chunker_debug.go),语言混合文本按首选检测语言估算。
用例预设(Use-case Presets)
文档给出了七类典型工作负载的推荐组合,可直接作为配置起点:
| 工作负载 | 策略 | ChunkSize | Overlap | 父子分块 |
|---|---|---|---|---|
| FAQ / Q&A 知识库 | auto(很可能落到 legacy) | 200–400 | 0 | 关 |
| Markdown 文档 / Wiki | auto(落到 heading) | 512 | 80 | 开 |
| 带分页的 PDF 报告 | auto(落到 heuristic) | 800–1200 | 100–150 | 开 |
| 长篇叙事(书籍、文章) | auto(落到 recursive) | 1000–2000 | 150–200 | 开 |
| 代码文档 | legacy | 800 | 100 | 可选 |
| 混合语言语料 | auto,languages 留空 | 512 | 80 | 开 |
| 表格报告 / CSV 衍生数据 | legacy | 400 | 0 | 关 |
在 UI 中调试(Debugging in the UI)
知识库编辑器的Chunking侧边栏底部有一个"Test with sample text"(用示例文本测试)折叠面板,操作流程:
- 粘贴一段 Markdown / 纯文本片段(最大 64 KB);
- 点击Run preview(运行预览);
- 面板将展示:
- 选中的策略层(以彩色标签呈现);
- 被拒绝的层及原因(例如 "too many tiny chunks");
- 文档画像(标题计数、换页符、章节标记、检测到的语言);
- 完整 chunk 集合的尺寸统计(平均 / 最小 / 最大 / 标准差);
- 每个 chunk 的卡片:字符数与近似 token 数、位置区间、章节面包屑(若设置了)、内容预览。
该预览以只读方式运行,通过 goroutine 隔离的切分过程执行(5 秒超时)——不写数据库、不调用 embedding API。可以在触发重新上传之前,用同一段样本来比较不同配置的效果。
源码佐证:上述能力对应
POST /api/v1/chunker/preview端点,实现在 internal/handler/chunker_debug.go。实现细节值得注意:输入上限previewMaxChars = 64 * 1024(按 rune 计数),返回 chunk 上限previewMaxChunks = 500(但统计量始终基于完整chunk 集合计算后再截断,保证 avg/min/max/stddev 具有代表性);由于切分器是纯 CPU 密集型且不接受context.Context,处理器把切分放进 goroutine,超时(previewTimeout = 5s)时返回 504,但工作 goroutine 会自然跑完——64k 字符上限正是针对重复认证请求下 goroutine 堆积的主要缓解措施(见文件头部安全注释)。请求体PreviewChunkingRequest接受text与 snake_case 的chunking_config;响应体包含selected_tier、tier_chain、rejected(拒绝原因)、profile(文档画像)、chunks与stats六个部分。
通过 API 配置分块
有三个端点可以写入分块配置。其中KB-config 更新端点与编辑器 UI 直接关联,使用camelCase命名并在documentSplitting信封内传递:
PUT /api/v1/initialization/config/:kbId Authorization: Bearer <jwt> Content-Type: application/json { "documentSplitting": { "chunkSize": 512, "chunkOverlap": 80, "separators": ["\n\n", "\n", "。", "!", "?", ";", ";"], "strategy": "auto", "tokenLimit": 0, "languages": ["de", "en"], "enableParentChild": true, "parentChunkSize": 4096, "childChunkSize": 384 } }服务端对strategy、tokenLimit、languages这三个字段使用基于指针的 DTO:请求体中省略它们表示"不更改";显式发送空字符串 / 0 / 空数组则重置为默认值。
KB CRUD 端点(POST /api/v1/knowledge-bases、PUT /api/v1/knowledge-bases/:id)接受相同字段,但使用snake_case并放在chunking_config信封下:
{ "chunking_config": { "chunk_size": 512, "chunk_overlap": 80, "strategy": "auto", "token_limit": 0, "languages": ["de", "en"], "enable_parent_child": true, "parent_chunk_size": 4096, "child_chunk_size": 384 } }预览端点POST /api/v1/chunker/preview同样使用 snake_case 形式,此外还多一个text字段用于携带待切分的样本。
源码佐证:分块配置在内核中的完整字段模型(含 YAML / JSON 双标签、默认值与语义注释)见 internal/types/knowledgebase.go;预览端点请求/响应结构与上述 snake_case 字段一一对应,见 internal/handler/chunker_debug.go。
已知权衡(Known Trade-offs)
- Tier-1 heading-aware 分块的代价与收益:会在 embedding 输入前追加章节面包屑,每个块多消耗约 5% 的 token,但在结构化文档上可减少约 30–50% 的块数量(在存储与查询时的 token 上净省)。
- 切换策略不会自动重建索引:修改 KB 的
strategy后,必须重新上传受影响的文件(或在 UI 中触发重新索引),新的分块才会生效。 - PDF 的 OCR 伪影无法靠切分器修复:竖排版式文本被逐字符拆散成独立行的坏结果,属于解析器(parser)侧的限制。heuristic 层仍会将块对齐到页面边界,可缓解最坏情况。
recursive策略值的存在:API 层面为了完整性而保留recursive这个取值,但 UI 有意隐藏了它——它在功能上几乎等同于legacy,多一个下拉选项反而会稀释用户在自动 / Markdown / heuristic / legacy 四档间的清晰选择。
源码佐证:
recursive与legacy的关系可以在策略常量中找到呼应——internal/infrastructure/chunker/strategy.go 同时定义了StrategyRecursive与StrategyLegacy,而Split的兜底逻辑注释明确说明"链失败时回退到 legacy 切分器,即原始 Tier 3 实现"(见 internal/infrastructure/chunker/strategy.go)。
相关参考
- 分块器核心实现:internal/infrastructure/chunker/splitter.go(默认值常量、Chunk 结构体、递归切分)
- 自适应策略选择:internal/infrastructure/chunker/strategy.go(策略常量、tier 链降级、诊断信息)
- 文档画像器:internal/infrastructure/chunker/profiler.go
- 预览端点实现与安全设计:internal/handler/chunker_debug.go
- 分块配置数据结构:internal/types/knowledgebase.go
- 知识库处理服务(含构建切分配置的调用链):internal/application/service/knowledge_process_config.go
- 服务端测试(覆盖策略与诊断逻辑):internal/infrastructure/chunker/strategy_diagnostics_test.go、internal/infrastructure/chunker/splitter_test.go
- 官方指南原文:docs/CHUNKING.md
【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考