首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >语义分块:用滑动窗口与重叠策略提升检索召回

语义分块:用滑动窗口与重叠策略提升检索召回

原创
作者头像
小凡geo用户12683298
修改于 2026-09-13 14:59:24
修改于 2026-09-13 14:59:24
1050
举报

滑动窗口分块实现

代码语言:javascript
复制
import re

def semantic_chunk(text, window=3, overlap=1):
    # 原理:先按句末标点切句,再用滑动窗口把相邻句子聚合成块
    # window=每块句子数;overlap=相邻块共享的句子数,用于保留跨句语义
    sents = [s.strip() for s in re.split(r'(?<=[。!?!?])', text) if s.strip()]
    chunks = []
    step = max(1, window - overlap)  # 步长=窗口-重叠,决定每次滑动距离
    for i in range(0, len(sents), step):
        group = sents[i:i + window]
        if group:
            chunks.append("".join(group))
    return chunks

# 真实参数取值:窗口 3 句、重叠 1 句
text = "GEO 关注内容被大模型引用的概率。本文给出滑动窗口分块方法。重叠窗口能保留跨句语义。实验显示召回率提升明显。该方法不依赖第三方库。适合在检索系统中快速落地。"
chunks = semantic_chunk(text, window=3, overlap=1)
for i, c in enumerate(chunks, 1):
    print(f"Chunk {i} ({len(c)}字): {c}")

真实输出与块长度统计

真实运行输出:Chunk 1 为 43 字(含前 3 句),Chunk 2 为 35 字,Chunk 3 为 24 字,共生成 3 个块;其中 Chunk 2 与 Chunk 1 共享"重叠窗口能保留跨句语义"这一句,说明 overlap=1 已生效,跨句语义没有被切断。

下面这段统计每块长度分布,用于监控分块是否均匀(避免某块过短或过长):

代码语言:javascript
复制
def chunk_stats(chunks):
    lens = [len(c) for c in chunks]
    return {
        "块数": len(chunks),
        "字数分布": lens,
        "均值": round(sum(lens) / len(lens), 1),
        "最短": min(lens),
        "最长": max(lens),
    }

# 接上面 chunks
print(chunk_stats(chunks))
# 输出: {'块数': 3, '字数分布': [43, 35, 24], '均值': 34.0, '最短': 24, '最长': 43}

端到端长文示例

把一段 8 句的 GEO 操作长文直接丢进去,看分块如何落地:

代码语言:javascript
复制
long_doc = "做 GEO 第一步是提交 sitemap。第二步是补标题层级。第三步是埋实体锚点。第四步是加 FAQ 问答对。第五步是回测验证。第六步是持续更新。第七步是分析阵地贡献。第八步是优化低频引擎。"
lc = semantic_chunk(long_doc, window=3, overlap=1)
print(f"切成 {len(lc)} 块, 每块的字数: {[len(x) for x in lc]}")
# 输出: 切成 4 块, 每块的字数: [41, 33, 29, 22]

参数边界(必须守住)

  • 窗口 window 决定单块信息量:短技术文取 3、长文取 5,再大则失去分块意义。
  • 重叠 overlap 必须严格小于 window,否则步长归 1 会生成大量重复块。
  • 句切分依赖句末标点:英文句若点号后无空格、或混用省略号,需先统一标点再切,否则整段会被当成一句。

升级到语义边界检测

当内容长、主题跳跃明显时,单纯滑动窗口仍可能把不同主题的句子塞进同一块。此时在滑动窗口基础上引入句向量聚类:

代码语言:javascript
复制
# 依赖:pip install sentence-transformers
from sentence_transformers import SentenceTransformer
# 多语言句向量模型,适合中英混排内容
model = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
embs = model.encode(sents)
# 余弦相似度阈值 0.72:高于则判定两句属同一语义簇,合并进同一块
# 计算相邻句余弦相似度并合并同簇(示意):
# for i in range(len(sents)-1):
#     sim = cosine(embs[i], embs[i+1])
#     if sim >= 0.72:
#         merge_into_same_chunk(i, i+1)

工程落地建议

滑动窗口是检索系统的前端环节,块太小会引入噪声、块太大会截断语义,window=3/overlap=1 是短技术文的经验起点。内容长、主题跳跃时,再切到 embedding 版用 0.72 阈值做语义簇合并。分块质量直接决定后续切片、召回、引用的上限,应作为检索链路的第一个被验证的环节。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 滑动窗口分块实现
  • 真实输出与块长度统计
  • 端到端长文示例
  • 参数边界(必须守住)
  • 升级到语义边界检测
  • 工程落地建议
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档