当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > Embeddings 怎样分块长文本

Embeddings 怎样分块长文本

来源:17golang原创 2026-10-25 11:57:26 0浏览 收藏

长文档直接做 Embeddings,问题通常不在“向量不够多”,而在一个块里混入了多个主题,或者把关键定义截在了两个块之间。我的做法是先按标题和段落保留语义边界,再用 token 预算兜底,最后用少量重叠覆盖跨段关系。Embeddings API 的输入按 token 计费,当前文档列出的第三代模型最大输入为 8192 token,所以分块预算不能只看字符数。

官方地址:https://developers.openai.com/api/docs/guides/embeddings

要点速览
  • 先按标题、段落、句子切分,token 上限只负责兜底。
  • overlap 用来保留跨块语义,不是越大越好;可先从 10%~15% 的块长度试起。
  • 每个向量必须保存来源、位置、版本和分块参数,方便回溯与重建。
更稳的起点不是固定“每 500 字一块”,而是先保证一个块只回答一个相近问题,再在模型上限内调节长度。检索问答效果应由真实问题集决定,不能只凭块数或向量维度判断。

先把分块目标定成可检索的证据单元

一个好块应当能独立表达一个小主题:例如“退款条件”和“退款操作步骤”可以相邻,但不要把整章产品介绍、异常处理和价格说明塞进同一个向量。建议给块保留 doc_id、chunk_id、标题路径、字符区间、版本号和正文原文。这样召回后可以展示上下文,也能在文档更新时只重建变动部分。

长度要用 tokenizer 估算,而不是把中文字符数当成 token 数。以当前文档为例,8192 token 是模型输入的上限,不代表检索块应该贴着上限;还要给查询、元数据拼装和后续生成留出空间。工程上可以先把单块预算放在 400~900 token,再用评测集观察是否出现“命中标题、缺少定义”或“召回内容过宽”。

按语义边界切分,超长时再递归降级

切分顺序可以是标题路径 → 段落 → 句子 → 词或字符。先尝试把完整段落放入当前块;放不下时再拆句,单句仍超长才做硬切。下面的示例省略具体 tokenizer 实现,但把分块的关键边界写清楚,实际项目中应替换为与所选模型匹配的计数器。

def split_text(paragraphs, max_tokens=700, overlap_tokens=80):
    # paragraphs 已按标题路径整理;tokenize 应使用项目实际模型的 tokenizer
    chunks, current = [], []
    current_tokens = 0
    for paragraph in paragraphs:
        paragraph_tokens = tokenize(paragraph)
        if len(paragraph_tokens) > max_tokens:
            # 超长段落继续按句子拆分,避免直接截断定义
            sentences = split_sentences(paragraph)
        else:
            sentences = [paragraph]
        for sentence in sentences:
            sentence_tokens = tokenize(sentence)
            if current and current_tokens + len(sentence_tokens) > max_tokens:
                chunks.append("\n".join(current))
                # 只保留尾部少量句子,形成可控的语义重叠
                current = keep_tail_by_tokens(current, overlap_tokens)
                current_tokens = count_tokens(current)
            current.append(sentence)
            current_tokens += len(sentence_tokens)
    if current:
        chunks.append("\n".join(current))
    return [chunk for chunk in chunks if count_tokens(chunk) >= 40]

这里的 700 和 80 只是可调参数,不是通用答案。法律条款、接口参数表和故障排查步骤的最佳边界往往不同;如果一个块经常被召回却缺少前置定义,应优先调整语义切分,而不是盲目增加 overlap。

Embeddings 长文本分块的标题路径、段落、句子和 token 预算边界说明图
图1:Embeddings 分块结构说明图,展示语义层级与 token 预算之间的静态关系,不是运行截图。

overlap 只补跨块关系,别把重复文本扩大成噪声

重叠适合处理“上一段定义、下一段条件”这类跨边界信息。可以从目标块长度的 10%~15% 开始,观察相邻块是否重复太多、向量库体积是否明显上涨。短文档不需要强行重叠;表格、代码和编号清单也不宜按普通句子切开,最好把表头或前置说明随块保存。

分块完成后先做三项清理:去掉空白和纯导航文本;合并过短且主题相同的尾块;对同一版本的重复内容做指纹去重。每个块写入向量库时,同时保存 source_start、source_end 和 chunker_version,否则以后很难解释“为什么这次命中了另一段”。

批量生成向量,再用检索反馈调参数

解释文本块、批量 Embeddings 返回、向量库元数据和检索上下文的静态关系。
图2:向量化与检索上下文结构说明图,展示结果如何回到原文位置。

OpenAI 文档说明 Embeddings 返回的是浮点数向量,可保存到向量数据库用于检索;输入也可以按数组批量提交。批量处理时要保持输入块与返回结果的索引一一对应,并把模型名、分块版本和生成时间写进记录。

from openai import OpenAI

client = OpenAI()
chunks = [{"chunk_id": "doc-7-003", "text": "退款条件与例外说明"}]

# 一次提交同一批文本,按返回顺序绑定 chunk_id;生产环境还要记录模型与版本
response = client.embeddings.create(
    model="text-embedding-3-small",
    input=[item["text"].replace("\n", " ") for item in chunks],
)
records = []
for item, embedding in zip(chunks, response.data):
    # metadata 与向量一起保存,召回后才能回到原文位置
    records.append({"id": item["chunk_id"], "vector": embedding.embedding,
                    "metadata": {"chunker_version": "v1"}})

评测时不要只看向量数量。准备一组真实查询,记录正确块是否在前几名、定义是否与条件同时出现、回答是否需要跨三个以上块才能完成。若命中内容过碎,增大块长度或合并相邻主题;若命中内容总是混杂,缩短块并加强标题路径元数据。这样调参才有明确方向。

现象优先调整不要先做
命中标题但缺少定义语义边界、少量 overlap直接把块扩大到模型上限
每次召回都带大量重复降低 overlap、做指纹去重继续增加召回数量
旧文档内容被召回版本过滤与增量重建只改相似度阈值

相关问题

中文长文本一定要按字数切吗?

不一定。字数只能做粗略限制,最终应以目标模型 tokenizer 的 token 数为准,并优先保留标题、段落和句子边界。

overlap 越大,检索效果越好吗?

不是。过大的 overlap 会制造重复向量和重复上下文;从较小比例开始,用真实查询集验证更稳妥。

分块后还要保存原文吗?

要保存。向量只适合相似度检索,回答和审计仍需要原文、来源位置、版本及分块参数来回溯。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Responses tools 怎样串联工具结果Responses tools 怎样串联工具结果
上一篇
Responses tools 怎样串联工具结果
ONNX 形状推断怎样保留符号维度
下一篇
ONNX 形状推断怎样保留符号维度
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    684次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    699次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    749次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    714次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    551次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码