文章摘要中文RAG项目经常使用“每500个字符切一段”或“每300个Token切一段”但字符数与Token数并不是同一个概念不同模型的Tokenizer也可能给出不同结果。分块过小会丢失条件过大则降低检索精度并增加上下文成本。本文解释字符、Token、句子和语义边界的区别并给出中文制度、合同、产品手册和FAQ的分块参数建议与评测方法。一、为什么字符数和Token数不能混用字符数是字符串长度。例如平台支持经销商收货与终端动销分析。中文字符、标点和英文字符都可以直接统计。Token是模型分词器处理后的单位。同一段内容在不同模型中可能被切成不同数量的Token。影响因素包括模型Tokenizer中文词语英文缩写数字标点JSON代码空格和换行。因此500个中文字符 ≠ 固定500个Token如果向量模型和生成模型使用不同Tokenizer差异还会更大。二、按字符分块的优点与问题优点实现简单不依赖模型Tokenizer速度快参数直观适合预处理和初步切分。示例defsplit_by_chars(text:str,chunk_size:int500,overlap:int80)-list[str]:chunks:list[str][]start0whilestartlen(text):endmin(startchunk_size,len(text))chunks.append(text[start:end])ifendlen(text):breakstartend-overlapreturnchunks问题可能从句子中间切开表格被拆断条款条件和结论分离代码结构损坏无法准确控制模型上下文不同文本密度差异大。字符切分适合作为最后一道长度限制不适合成为唯一规则。三、按Token分块的优点与问题优点更接近模型真实上下文成本便于控制Embedding输入上限便于预算生成上下文中英文混合内容更可控。伪代码defsplit_by_tokens(text:str,tokenizer,max_tokens:int,overlap_tokens:int)-list[str]:tokenstokenizer.encode(text)chunks:list[str][]start0whilestartlen(tokens):endmin(startmax_tokens,len(tokens))chunks.append(tokenizer.decode(tokens[start:end]))ifendlen(tokens):breakstartend-overlap_tokensreturnchunks问题仍可能切断语义依赖具体Tokenizer更换Embedding模型后参数可能变化Token解码可能影响空格和格式处理成本高于字符计数。Token长度控制的是容量不等于保证内容完整。四、真正重要的是语义边界推荐切分优先级文档 → 章节 → 小节 → 条款 → 段落 → 句子 → Token或字符兜底例如制度文件第四章 差旅标准 4.1 交通标准 4.2 住宿标准 4.3 餐饮补贴应该先按章节和条款切分再检查是否超过Token上限。错误做法直接每500字符切开可能把4.2的适用对象留在前一块把金额留在后一块。五、重叠区间有什么作用Overlap用于保留边界上下文。例如Chunk 1……申请人必须在出差前提交审批。 Chunk 2提交审批后由直属负责人审核……如果边界切在中间重叠可以减少信息损失。但重叠不是越大越好。过大重叠会导致索引体积增加相似Chunk重复召回上下文重复Token浪费Reranker结果单一。常见起点Overlap占Chunk的10%—20%但最终应以检索评测为准。六、不同文档类型的建议1. FAQ一问一答天然是Chunk。建议每个FAQ独立 保留分类和关键词 通常不需要重叠2. 企业制度建议按章节 → 条款 → 子条款每个Chunk带制度名称版本章节标题条款编号生效日期。3. 合同建议按条款切分不要把不同责任条款合并。需要保留合同类型甲乙方条款号定义引用附件关系。4. 产品手册建议按功能或操作任务功能说明 前置条件 操作步骤 异常处理不要把多个完全不同功能放在同一Chunk。5. API文档建议按接口MethodPath 请求参数 响应参数 错误码 示例一个接口可以有父子Chunk。6. 表格不要直接按字符切表格。应该保留表头每行带表头语义大表按业务分组必要时转为结构化JSON保留原始页码和表名。七、推荐的两阶段分块第一阶段结构切分Markdown标题 PDF章节 Word样式 条款编号 列表 表格第二阶段长度控制如果结构块超过上限再按句子和Token切分。伪代码defhierarchical_split(document:Document,tokenizer,max_tokens:int400)-list[Chunk]:sectionssplit_by_structure(document)result:list[Chunk][]forsectioninsections:ifcount_tokens(section.text,tokenizer)max_tokens:result.append(to_chunk(section))continuesentencessplit_sentences(section.text)result.extend(merge_sentences_by_token_limit(sentences,tokenizer,max_tokensmax_tokens,overlap_tokens60))returnresult八、父子分块如何兼顾召回和完整性小Chunk更容易精准召回大Chunk更容易提供完整答案。父子分块父Chunk完整章节 子Chunk段落或条款检索对子Chunk生成Embedding → 找到高相关子Chunk → 返回对应父Chunk或邻接内容适合制度合同长产品手册技术文档。要避免父Chunk过大否则上下文又会膨胀。九、参数从哪里开始以下只是起始值不是通用答案。文档子Chunk起始范围OverlapFAQ一问一答0制度条款200—450 Token30—60产品手册300—600 Token50—100合同单个完整条款视引用关系API文档单接口或子模块少量代码函数或方法通常不用固定Overlap如果Embedding模型对长文本支持更好也不代表应该无限扩大Chunk。十、如何评测分块质量准备真实问题每个问题标注正确文档 正确条款 答案所需最小证据比较不同参数300 Token50重叠 500 Token80重叠 父子分块 语义分块指标Answer-Bearing RecallKMRR重复Chunk比例平均上下文Token答案正确率忠实度查询延迟。十一、字符数是否完全没用不是。字符数适合快速预估输入长度保护文本清洗不绑定模型的基础规则发现异常超长内容。推荐结构边界决定怎么切 Token决定是否超限 字符数负责快速保护和监控十二、常见错误1. 所有文档使用同一参数FAQ、合同和代码不应使用相同规则。2. 只看Chunk平均长度还要看是否包含完整答案。3. 重叠设置过大造成重复召回。4. 忽略标题和MetadataChunk正文短但缺少章节语义。5. 更换Embedding模型后不重测Tokenizer和语义能力都可能变化。总结中文RAG分块不应该在“字符还是Token”之间二选一。更合理的方式是先按文档结构和语义边界切分 → 再用Token控制模型上限 → 用字符数做保护 → 通过真实问题评测参数决定效果的核心不是Chunk恰好有多少字而是答案所需的条件和结论是否完整地留在同一个可检索单元中。