清晨六点,日料店的主厨阿杰收到一条三米长的蓝鳍金枪鱼。这是他见过最完美的食材——油花分布均匀,肉质紧实发亮。可他很快发现一个尴尬的事实:案板只有一米长,冰柜门只有三十厘米宽,而店里的客人每人只想吃两三片刺身。无论这条鱼多珍贵,他都得先把它切成适合料理的小块。切得太大,冰柜放不下,餐盘也装不下;切得太小,鱼肉纹理断裂,入口就散了。 在 AI 的世界里,“金枪鱼”就是那些动辄几万字的长文档,“冰柜门”是大模型有限的上下文窗口,“客人的餐盘”是检索系统希望命中精准答案的需求。文档分块(Chunking),就是决定如何“下刀”的刀法。切得好不好,直接决定后面“端上桌的菜”——检索结果与生成答案——是否美味。这一篇,我们跟着阿杰学学几种主流刀法:拿尺子量着等距切(固定长度分块)、顺着纹理切(语义分块)、先粗后细层层切(递归分块),以及如何根据“食材”和“食客”调整刀工参数。

岗位关联

掌握文档分块策略,是 RAG 应用开发者入行必修的“刀工课”。分块好坏直接决定检索召回率与回答质量,决定你搭建的知识库问答系统是“入口即化”还是“咬到鱼刺”。

目录
  1. 可视化演示
  2. 分块必要性
  3. 固定长度分块
  4. 语义分块
  5. 递归分块
  6. 参数调优
  7. 文档类型适配
  8. 嵌入与下游考量
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示RAG系统中的文档分块策略:固定长度分块(按字符数切割可能截断语义)、语义分块(基于句子相似度保持内容连贯)、递归分块(层级结构逐层细分平衡粒度),通过步进控件对比三种策略的优劣。

本节配有交互动效(进入视口后自动加载,约 3KB)。

固定长度分块:按字符数切割 固定窗口:每N字符切一块,实现简单高效 语义截断:可能切断句子,破坏上下文完整性 chunks = split(doc, size=N, overlap=M) 固定长度分块速度快但召回率受截断影响

分块必要性

阿杰做了个大胆的尝试:把整条三米金枪鱼直接塞进冰柜。结果当然很惨——鱼尾卡在门外,鱼身挤变了形,冰柜门根本关不上。他突然明白:不管这条鱼多完美,要先让它“进得了门”,才有后面的料理。这里的门,就是 AI 大模型的上下文窗口——模型一次能阅读的文本量上限,通常以 token(基本语言单位)计数。一份几万字的企业年报,换算成 token 后远超窗口能容纳的量,模型要么报错,要么“只看开头”,后面的内容全被忽略。

既然不能整条进,那就要切。分块的第一个目的,就是适配上下文窗口,把长文本切成模型放得下的小段。第二个目的是优化检索粒度:用户问“去年的营收是多少”,如果答案是整份年报中的一句话,我们当然希望检索系统能找到承载这句话的那个小块,而不是把整份年报都拉出来。第三个目的是保持语义完整性:切出来的每一块,最好本身就是一个相对完整的话题,这样检索命中时,模型看到的是“一块完整的鱼腹肉”,而不是一块带着碎骨的边角料。

N=⌈LS⌉N = \left\lceil \frac{L}{S} \right\rceil

1. 文档长度 L:这条“金枪鱼”从头到尾总共包含的 token 数,也就是文档的总长度。

LL

2. 块大小 S:每一块分块的目标 token 数上限,对应“冰柜门”的宽度。

SS

3. 向上取整符号:文档长度除以块大小如果不是整数,最后那块零头也要单独成块,不能扔掉。

⌈⋅⌉\left\lceil \cdot \right\rceil

4. 分块总数 N:整条鱼最终被切成的块数,分块策略的第一步就是算出这个数。

N=⌈LS⌉N = \left\lceil \frac{L}{S} \right\rceil

阿杰看着公式点点头:只有先把鱼切成“冰块柜放得下、客人一口吃得下”的尺寸,这道料理才可能开始。分块不是偷懒的取巧,而是所有后续环节的地基——地基没打好,后面检索、生成都白搭。

固定长度分块

阿杰拿起一把长刀和一把尺子。他决定用最省事的办法:每隔三厘米就下一刀,像切黄瓜片一样,把鱼切成大小完全一致的等宽段。这就是固定长度分块(Fixed-size Chunking):设置一个固定的 token 数作为块大小,从头到尾按字数等距切开。它的好处显而易见——实现极其简单,速度飞快,几乎不用思考,也不依赖任何额外工具。对于格式混乱、没有明显结构的原始文本,它往往是唯一“先跑起来再说”的选择。

但问题很快出现了。阿杰发现有一刀正好切在鱼腹的一块完美刺身上,把肉和筋膜切成了两半。对应的场景是:一个完整句子的主语在上一块、谓语在下一块,甚至一个关键数字被一刀切开。检索时如果只命中后半块,模型就会看到一句没头没尾的话。为了补救,阿杰想到了“切完第一片后,第二刀稍微往回退一点”——这就是重叠窗口(Overlap):相邻两块共享一小段文本,让被切断的上下文有机会在邻居块中“接回来”。

N=⌈L−OS−O⌉N = \left\lceil \frac{L - O}{S - O} \right\rceil

1. 重叠量 O:相邻两块之间共享的 token 数,相当于第二刀往回退的距离。

OO

2. 有效步长:每切出一块新内容,刀口实际向前推进的距离是块大小减去重叠量。

S−OS - O

3. 实际有效长度:整条鱼可以“不浪费”地被切成多块时,总长度等效于文档长度减去重叠量。

L−OL - O

4. 分块总数 N:用等效总长度除以有效步长并向上取整,得到最终块数。

N=⌈L−OS−O⌉N = \left\lceil \frac{L - O}{S - O} \right\rceil

阿杰掂了掂手里的鱼块:固定长度分块像“用尺子切菜”,快但粗心。它能让你快速把文档切成小块,但那些被拦腰截断的句子,就像断了筋膜的刺身,口感总差一截。于是阿杰开始寻找一种“更懂鱼”的刀法。

语义分块

阿杰请来一位“纹理大师”。大师不急着下刀,而是提着一盏灯细细照过鱼身,观察筋膜和油花的分界——哪里的肉是一块整体,哪里是两块肌肉的天然分界。这种“顺着纹理下刀”的思路,对应 AI 里的语义分块(Semantic Chunking):不再按字数硬切,而是先理解内容的自然边界,在语义转折处下刀。

具体怎么做?先让嵌入模型(Embedding Model)把每个句子转换成一个向量。向量是高维空间中的坐标,语义越接近的句子,坐标方向越一致。然后计算相邻两个句子向量的余弦相似度(Cosine Similarity):相似度高,说明这两句在讲同一件事,应该留在同一个块里;相似度突然降低,说明话题切换了,这里就是天然的切割点。这样切出的块,大小不一,但每一块内部话题连贯、结构完整。

sim(si,sj)=ei⋅ej∥ei∥ ∥ej∥\text{sim}(s_i, s_j) = \frac{\mathbf{e}_i \cdot \mathbf{e}_j}{\|\mathbf{e}_i\| \, \|\mathbf{e}_j\|}

1. 句子向量:嵌入模型把第 i 个句子变成的向量,方向代表它的“语义朝向”。

ei,ej\mathbf{e}_i, \mathbf{e}_j

2. 分子点积:两个向量的点积反映它们方向的一致程度,一致则数值大。

ei⋅ej\mathbf{e}_i \cdot \mathbf{e}_j

3. 分母模长乘积:把长度差异归一化掉,让比较只看方向不看长短。

∥ei∥ ∥ej∥\|\mathbf{e}_i\| \, \|\mathbf{e}_j\|

4. 余弦相似度:最终结果落在 -1 到 1 之间,越接近 1 表示两句话越像在“同一块肉”上。

sim(si,sj)\text{sim}(s_i, s_j)

阿杰看着大师手起刀落,每一块刺身都完整保留了鱼肉的纹理。他明白:语义分块更聪明,但它需要额外的嵌入模型参与计算,耗时更长、成本更高——就像请大师看鱼,不是每桌菜都值得这个价钱。

递归分块

阿杰的师傅终于来了。老师傅的刀法很特别:他先用大刀把金枪鱼分成鱼头、鱼身、鱼尾三大段,然后小心地把鱼身分成腹肉、背肉和中落,最后才把腹肉切成适合刺身的薄片。每一步都依托着鱼本身的天然分层。这种“先粗分、再细分”的思路,就是递归分块(Recursive Chunking)。

递归分块的核心是层级结构:文档天然存在着从大到小的分隔符——章节标题、段落、句子。算法按优先级依次尝试这些分隔符:先按章节切,如果切出来的块仍然太大,就再按段落切;段落还太大,就继续按句子切,直到每一块都小于目标块大小。这种“分隔符优先”的做法,让切割线永远落在文档自身的结构边界上,而不是像固定长度那样从半路穿过。因为切分过程保留了父子路径(如“第三章 > 3.2 节 > 第 2 段”),每块的“出身”也一并留存,方便下游恢复上下文。

D=⌈log⁡kN⌉D = \left\lceil \log_k N \right\rceil

1. 第一层切出的块数 N:按最粗的分隔符(如章节)切出的初步块数。

NN

2. 分支因子 k:平均每一块继续细分为 k 个子块,k 越大切得越细。

kk

3. 对数运算:如果每次切分都变成 k 倍多块,那么切 d 层后块数是 k 的 d 次方,反向求解层数用对数。

log⁡kN\log_k N

4. 递归深度 D:需要向下切多少层,才能让最底层的块小到满足要求,结果向上取整。

D=⌈log⁡kN⌉D = \left\lceil \log_k N \right\rceil

阿杰惊叹:老师傅没有多花一分力气,每一刀都顺理成章。递归分块就像这套刀法——尊重文档自身的结构,先粗后细,既保证了每一块的粒度合适,又保留了完整的“家族谱系”,是最适合结构化长文档的优雅解法。

参数调优

阿杰开始试吃自己切的刺身。有的块太大,客人一口塞不进嘴里,嚼起来还混着各种部位的味道;有的块太小,两三口就没了,客人根本尝不出这是金枪鱼的哪块肉。他意识到:块大小和重叠率不是随便定的,必须反复试,找到自家食客最喜欢的“入口尺寸”。

块大小决定检索的粒度。块太大,一块里包含多个主题,检索时噪声多,精确度下降;块太小,单个块信息量不足,上下文不完整,生成答案时模型“看不够”。经验上,常见的选择从 128 到 2048 token 不等,取决于文档类型和模型窗口。重叠率则是冗余与安全的权衡——重叠越多,上下文越不容易断,但存储和计算成本也随之上升,宝贵的窗口被重复内容占据。调优的方法不是拍脑袋,而是实验评估:准备一份有标准答案的测试集,分别用不同的块大小和重叠率跑一遍检索,对比召回率与回答质量,让数据说话。

U=SS+OU = \frac{S}{S + O}

1. 块大小 S:每个块的有效内容长度,也就是“刺身”本身的肉量。

SS

2. 重叠量 O:每个块多带的“配菜”长度,它们是为了防护语义断裂而额外预留的。

OO

3. 总消耗长度:一个块真正占用的窗口空间是有效内容加重叠部分。

S+OS + O

4. 窗口利用率 U:有效内容在总消耗中的占比,重叠越大,利用率越低,信息越冗余。

U=SS+OU = \frac{S}{S + O}

阿杰在案板边贴了一张表,记录每次试吃的效果。他悟出一个道理:参数调优不是追求“最大”或“最小”,而是像调火候一样,找到那个刚好的区间——既不让鱼块散架,也不让食客吃得满嘴都是葱丝。

文档类型适配

这天店里到了三种不同的“食材”:一整条金枪鱼(长篇报告)、一盒鱼籽(订单流水记录)、一块豆腐(结构化的 JSON 配置文件)。阿杰若用同一套刀法处理它们,场面会非常尴尬。文档分块也一样:不同文档类型必须用不同策略。

结构化文档——如 Markdown、HTML、JSON——有清晰的层级和标签,最适合递归分块,按标题、段落、列表项逐层切分,每一块的“路径”都能还原。非结构化文本——如合同扫描件转出的纯文本、客服聊天记录——没有可用分隔符时,语义分块是更好的选择,靠相似度找到隐藏的话题边界;如果计算资源有限,固定长度加重叠也能应急。混合内容最考验功力:一篇产品文档里既有大段文字说明,又有表格和代码块。通常需要对不同内容分派不同策略——表格按行成块,代码按函数成块,说明文字按段落成块——最后再统一入库。

Sopt=min⁡(Smodel,Stopic)S_{\text{opt}} = \min\left(S_{\text{model}}, S_{\text{topic}}\right)

1. 模型上限:嵌入模型或大模型能接受的最大 token 数,对应“容器能装多少”。

SmodelS_{\text{model}}

2. 主题长度:文档中一个完整话题(如一个章节、一个表格)的平均长度。

StopicS_{\text{topic}}

3. 取最小值:块大小必须同时满足两者,取较小的那个才能既放得进容器又不拆散主题。

min⁡(⋅,⋅)\min(\cdot, \cdot)

4. 最优块大小:面向当前文档类型的最合适切分尺寸。

SoptS_{\text{opt}}

阿杰把鱼籽一颗一颗码进小盒,把豆腐用模具扣成方块,把金枪鱼按纹理切开——每一种食材都找到了自己的归宿。他也记住了今天的道理:好的寿司师傅对食材有敬畏,好的分块策略同样对文档类型有感知。

嵌入与下游考量

最后一道关卡,是“端上桌”的动作。阿杰切好的鱼块,要先装进外送餐盒(嵌入模型),再根据客人点的菜(查询),从冰柜里挑出最合适的几盒,连同配菜一起送到后厨(大模型生成)。这里有两个隐藏的限制。

第一,嵌入模型窗口限制。嵌入模型在把文本变成向量时,同样有输入长度上限。如果块大小接近甚至超过这个上限,嵌入结果的质量会明显下降——就像餐盒塞得太满,盖子合不上,鱼肉在配送途中被挤坏。第二,上下文保真与检索召回率。检索系统从向量库中找出最相似的块之后,通常还会带上它前后的邻居块(k 个相邻块),组成一块“完整的刺身拼盘”再交给大模型。带多少邻居,取决于大模型的剩余窗口。窗口允许的上下文总长度,直接决定了最终能拼进多少内容——而分块的粒度,又决定了“召回率”的上限。

C=(k+1)⋅SC = (k + 1) \cdot S

1. 单块大小 S:检索命中的那个块本身的长度。

SS

2. 邻居数量 k:为补全上下文,额外挑选的前后相邻块的数量。

kk

3. 总块数:命中的 1 块加上 k 个邻居块,一共是 k+1 块。

k+1k + 1

4. 上下文总长 C:最终拼进大模型提示的文本总长度,必须不超过剩余窗口。

C=(k+1)⋅SC = (k + 1) \cdot S

阿杰把刺身拼盘端上桌,客人一口下去,满口留香。他总结出今天的终极心法:分块不是孤立的切鱼动作,而是要打通“冰柜容量—餐盒上限—餐桌大小”一整条链路。只有做到窗口适配、语义完整、检索精准三位一体,这条金枪鱼才算真正物尽其用。

AI 应用场景

企业知识库问答系统

阶段:文档加载与处理(索引构建前最重要的一道工序)

解决的问题:传统做法是把整份《员工手册》塞进提示词,既超出窗口限制,又让模型难以定位具体条款,回答经常张冠李戴。AI 方案先把手册按章节递归分块,再让员工用自然语言提问,检索系统直接从对应章节命中答案,准确率和响应速度都大幅提升。

具体案例:某大型制造企业将 2000 页的设备维修手册导入 RAG 系统,按“章节 > 小节 > 操作步骤”递归分块,并将块路径(第几章第几节)作为元数据一同存储。维修工询问“主轴异响如何排查”时,系统精准返回相关步骤块与上下文,维修效率提升 65%。

学术论文智能检索

阶段:文档加载与处理(语义分块的应用场景)

解决的问题:论文 PDF 每段长度差异大,固定长度分块会把“方法”和“实验”两个话题搅在一起,检索“这个模型用了什么损失函数”时命中的却是结论段落。语义分块按话题边界切分,让每一块只讲一件事。

具体案例:某科研团队将 500 篇自然语言处理论文按章节切分后,再用语义分块对“相关工作”和“实验”两部分精细切割。查询“BERT 在中文任务上的表现对比”时,系统能精准命中对应实验描述块,答案中不再混入无关的参考文献内容。

Python 演示

python103 行
"""文档分块策略演示 三种主流分块方法的极简实现"""import reimport math  def fixed_size_chunk(text, size, overlap=0):    """固定长度分块 均匀切块 可设置重叠"""    tokens = text.split()    chunks = []    start = 0    step = size - overlap    while start < len(tokens):        end = min(start + size, len(tokens))        chunk = " ".join(tokens[start:end])        chunks.append(chunk)        if end >= len(tokens):            break        start += step    return chunks  def _tokenize(sentence):    """极简分词 统计词频 得到词袋向量"""    vec = {}    for token in re.findall(r"\w+", sentence.lower()):        vec[token] = vec.get(token, 0) + 1    return vec  def _cosine_sim(vec_a, vec_b):    """计算两个词袋向量的余弦相似度"""    common = 0    for token in vec_a:        if token in vec_b:            common += vec_a[token] * vec_b[token]    norm_a = math.sqrt(sum(v * v for v in vec_a.values()))    norm_b = math.sqrt(sum(v * v for v in vec_b.values()))    if norm_a == 0 or norm_b == 0:        return 0.0    return common / (norm_a * norm_b)  def semantic_chunk(sentences, threshold=0.3):    """语义分块 相似度低于阈值处下刀"""    if not sentences:        return []    chunks = []    current = sentences[0]    for i in range(1, len(sentences)):        sim = _cosine_sim(_tokenize(sentences[i - 1]),                          _tokenize(sentences[i]))        if sim < threshold:            chunks.append(current)            current = sentences[i]        else:            current += " " + sentences[i]    chunks.append(current)    return chunks  def recursive_chunk(text, delimiters=None, size=200):    """递归分块 按层级分隔符逐层细化"""    if delimiters is None:        delimiters = ["\n\n", "\n", "。"]    for delimiter in delimiters:        pieces = text.split(delimiter)        if len(pieces) > 1:            chunks = []            for piece in pieces:                if len(piece.split()) > size:                    chunks.extend(fixed_size_chunk(piece, size))                else:                    chunks.append(piece)            return chunks    return fixed_size_chunk(text, size)  def main():    """主流程 用一份示例文档跑三种策略"""    text = (        "文档分块是RAG系统的重要预处理步骤。合理分块能显著提升检索效果。"        "固定长度分块实现简单但可能切断语义。语义分块通过向量相似度保持连贯。"        "递归分块则利用文档的天然层级结构。选择策略需要结合文档类型。"        "嵌入模型的窗口大小也会影响分块决策。下游生成任务同样需要考量。"        "推荐让每个块自成主题且包含完整上下文。"    )    print("=== 1 固定长度分块(size=10, overlap=2)===")    for i, chunk in enumerate(fixed_size_chunk(text, 10, 2)):        print("块%d: %s" % (i, chunk))     sentences = re.split(r"(?<=[。!?])", text)    sentences = [s for s in sentences if s.strip()]    print("\n=== 2 语义分块(threshold=0.3)===")    for i, chunk in enumerate(semantic_chunk(sentences)):        print("块%d: %s" % (i, chunk))     print("\n=== 3 递归分块(按句号切分)===")    for i, chunk in enumerate(recursive_chunk(text)):        print("块%d: %s" % (i, chunk))  if __name__ == "__main__":    main()
目的:用一份示例文档演示三种分块策略的效果差异,直接运行即可对比输出。
  1. tokens = text.split()把文本切成词序列,固定长度分块按词数计数。
  2. step = size - overlap每次向前移动的步长,重叠让相邻块共享词,减少语义断裂。
  3. chunks.append(chunk)把切好的块累积进结果列表,等待后续嵌入入库。
  4. _tokenize(sentence.lower())将句子转成小写词频向量,这是极简版“语义纹理探测器”。
  5. sim < threshold相似度低于阈值的点就是话题切换处,也就是下刀的位置。
  6. text.split(delimiter)按层级分隔符尝试切分,优先使用文档自身的结构边界。
  7. len(piece.split()) > size如果某块仍超过目标大小,说明还要继续向下细分。
  8. chunks.extend(fixed_size_chunk(piece, size))递归到底时用固定长度兜底,保证不会无限切分。

常见误区

误区“分块就像把鱼切大块一点,肉多客人吃得饱,检索也更容易命中吧?把块大小设成 2048 甚至 4096,总比小块信息全。”

正解块越大,单块里包含的无关主题越多,检索时的“噪声”越大。比如一块包含了业绩、员工、产品三个话题,查询“公司去年营收”时,这块虽然命中但大量内容与问题无关,生成答案时容易被带偏。块大小要匹配文档的主题粒度,而不是越大越好。就像给客人端上一整盘混杂了所有部位的鱼肉,反而尝不出那块最好的腹肉。

为何常见:人直觉上认为“信息多 = 答案准”,忽略了检索系统需要的是“精准”而非“量大”。

误区“固定长度分块又快又简单,我能用一行代码解决分块,语义分块那些花哨方法都是浪费时间。”

正解固定长度分块的最大隐患是切断句子和段落,导致无数半截的“语义孤儿块”。对有明显层级结构的文档(Markdown、HTML)而言,这种刀法尤其浪费——明明有章节边界不用,偏要从句子中间穿过。处理非结构化文本可以应急,但遇到结构化文档、代码、表格,必须换成递归分块或语义分块。

为何常见:初学者接触的第一个分块示例通常是固定长度,工具库默认参数也常是它,容易形成路径依赖。

误区“重叠区能防止句子被截断,那我把重叠设成块大小的一半,甚至完全重叠,上下文肯定最完整。”

正解重叠是“用冗余换安全”的手段。重叠过大,一方面每块重复内容占满宝贵的模型窗口,真实有效信息变少;另一方面存储向量数量不变但内容大量重复,检索时可能返回几乎相同的块,浪费召回名额。重叠率通常设在 10% 到 20% 之间比较合理,具体要看文档句子的平均长度。

为何常见:只看到重叠能“接上断句”的好处,没算清冗余带来的窗口和成本代价。

误区“语义分块最聪明,用了嵌入模型和向量相似度,肯定比固定长度高级,那就全部用它。”

正解语义分块需要先嵌入每一个句子,计算成本和时间开销明显更高;对短文本或本身结构明确的文档,反而杀鸡用牛刀。另外它依赖嵌入模型的语义捕捉能力,模型不好时边界判断同样会出错。合适的做法是:结构化文档用递归,无结构长文用语义,简单场景用固定长度加重叠,按需组合。

为何常见:人们容易把“技术更高级”等同于“效果更好”,忽略成本与场景匹配度。

面试题

Q1. 在 RAG 系统中,为什么必须对长文档进行分块?

单选题 · easy

  • A.为减少文档的磁盘占用
  • B.为适配窗口并提升检索准确← 正确答案
  • C.为了让文档排版更整齐
  • D.为了对文档内容进行加密

答案:B。大模型有上下文窗口限制,长文档放不进去;同时检索系统需要精准定位答案所在的小块。分块就是为了适配窗口 + 提升检索准确度,相当于把整条金枪鱼切成冰柜放得下、客人一口吃得下的刺身块。A、D 与分块目的无关,C 是表面效果而非原因。

Q2. 固定长度分块最明显的缺点是什么?

单选题 · easy

  • A.实现过于复杂难部署
  • B.可能切断句子致语义不完整← 正确答案
  • C.会显著增加嵌入的计算成本
  • D.无法处理任何非结构化文本

答案:B。固定长度按 token 数等距切开,完全不看句子和段落边界,刀刃很可能从句子中间穿过,导致语义断裂,形成“没头没尾”的块。它实现简单,所以 A 错;成本增加不显著,C 错;非结构化文本正是它的适用场景之一,D 错。

Q3. 固定长度分块中设置“重叠窗口”的主要目的是什么?

单选题 · mid

  • A.让切出的块数量更少
  • B.减少截断造成的语义损失← 正确答案
  • C.提高嵌入模型的推理速度
  • D.让每块文本长度严格一致

答案:B。重叠窗口让相邻两块共享一段文本,即使某个句子被切断,它的后半部分也很可能出现在相邻块中,检索时可以“接回来”。相当于切刺身时第二刀稍稍回退,避免纹理断裂。它会让块数量变多而非变少,A 错;与推理速度和长度一致性无关,C、D 错。

Q4. 语义分块判断两个句子是否属于同一块的依据是什么?

单选题 · mid

  • A.句子长度的接近程度
  • B.句子间向量的余弦相似度← 正确答案
  • C.句子在文档中的位置先后
  • D.句子中关键词语的数量

答案:B。语义分块先把句子经嵌入模型变成向量,再计算相邻句子的余弦相似度。相似度高说明在讲同一话题,留在同一块;相似度骤降说明话题切换,在此下刀。句子长度、位置先后、关键词数量都不是语义判断的直接依据,A、C、D 错。

Q5. 两个句子向量的余弦相似度越接近 1,说明什么?

单选题 · hard

  • A.两个句子长度越接近
  • B.两个句子的语义越相似← 正确答案
  • C.两个句子的词频越高
  • D.两个句子包含的符号越多

答案:B。余弦相似度衡量两个向量方向的接近程度,归一化后与向量长度无关。值越接近 1,方向越一致,也就是语义越相近,因此适合做语义边界的判断依据。句子长度、词频、符号数量都不是余弦相似度衡量的对象,A、C、D 错。

Q6. 递归分块相比固定长度分块,最主要的优势是什么?

单选题 · mid

  • A.代码实现更加简单
  • B.沿结构切分保留层级← 正确答案
  • C.不需要考虑文档类型
  • D.完全避免语义切断

答案:B。递归分块按“章节→段落→句子”的优先级逐层切分,切割线落在文档自然结构上,并且保留每块在文档中的层级路径。它代码更复杂,A 错;恰恰需要考虑文档类型,C 错;语义切断不能百分百避免,只是大幅减少,D 错。

Q7. 下面哪项不是影响分块策略选择的因素?

单选题 · mid

  • A.文档类型与结构
  • B.嵌入模型上下文长度
  • C.服务器机房地理位置← 正确答案
  • D.下游生成任务需求

答案:C。选择分块策略要综合考虑文档类型、模型窗口大小、下游生成需要的信息量等。而服务器机房地理位置是部署基础设施问题,与文档如何切分没有直接关系。A、B、D 都是摘要中明确提到的决策因素,C 是干扰项。

Q8. 块大小设置过大时,对 RAG 检索最直接的影响是什么?

单选题 · extreme

  • A.嵌向量的维度会变低
  • B.块中噪声多降低检索精确度← 正确答案
  • C.嵌入模型输出结果加密
  • D.文档分块数量明显增多

答案:B。块过大时,一块里往往装了多个话题,查询命中的块虽大但只有少部分相关,这种“噪声稀释”会拉低检索精确度,进而影响生成质量。向量维度由模型固定,不会因块大小改变,A 错;分块数量应减少而非增多,D 错;C 无意义。

Q9. 固定长度分块可能带来哪些问题?

多选题 · mid

  • A.句子可能被截断← 正确答案
  • B.语义完整性被破坏← 正确答案
  • C.上下文信息出现丢失← 正确答案
  • D.效果一定比语义分块差

答案:ABC。固定长度按数切开,句子被拦腰截断、语义完整性被破坏、边界处的上下文信息丢失,都是它的典型问题。但“效果一定更差”太绝对——在结构化不明显或资源受限的场景,固定长度加重叠仍可能是合理选择,所以 D 错。

Q10. 选择 RAG 分块策略时,以下哪些是合理考量?

多选题 · hard

  • A.文档类型适配分块← 正确答案
  • B.嵌入模型窗口限制← 正确答案
  • C.块重叠率的设定← 正确答案
  • D.尽量用最小块保证效率

答案:ABC。分块策略要因“文档类型”而异、受“嵌入模型窗口”约束,并通过“重叠率”在完整性与冗余之间做平衡。而“最小块”会丢失上下文,降低生成质量,不是合理目标,所以 D 错。