当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > Embedding 批量请求的长度和失败重试设计

Embedding 批量请求的长度和失败重试设计

来源:17golang原创 2026-10-17 00:02:55 0浏览 收藏

Embedding 批量请求最容易出问题的地方,不是“批量越大越快”这么简单,而是三类限制经常被混在一起:一次放多少条、每条允许多长、整个请求体能有多大。稳妥的设计是先用 token 预算切批,再把超时、限流和服务暂不可用与输入过长、鉴权错误分开处理。这样即使一批只成功了一部分,也能按原始索引补偿,不会把向量写错位置。

官方地址:https://huggingface.co/docs/huggingface_hub/main/package_reference/inference_client

把 batch_size 当成并发参数,把单条 token 上限当成输入参数,把请求体预算当成传输参数;重试只覆盖可恢复故障,并且每次重试都携带原始索引。

先把三个长度限制拆开

以 Hugging Face 的 InferenceClient.feature_extraction 为例,接口可以接收单条文本,也可以接收多条文本列表;具体模型或推理服务还可能有自己的最大输入长度和请求大小。文档里的 truncate 只说明服务支持截断时可以控制输入处理,并不等于所有模型都有相同的 token 上限。

因此,批处理器至少要维护三个变量:

  • max_items:一次最多放多少条,用来控制响应数量与单次内存。
  • max_tokens:单条文本允许的 token 预算,超出时截断、拆分或进入人工处理队列。
  • max_request_tokens:整批估算 token 总量,用来避免短文本数量过多或长文本混在一起。
文本队列、单条 token、批大小、请求体预算、Embedding 服务和向量结果的关系说明图
图1:Embedding 批次预算说明图,展示不同长度约束如何共同决定请求边界。这是静态说明图,不是截图或运行证据。

这三个限制不要写成一个“万能 batch_size”。例如固定 32 条,在短句场景可能浪费吞吐;同样的 32 条换成长文,又可能让请求体过大。更可靠的切批条件是“达到条数上限或达到 token 预算,满足任一条件就结束当前批次”。

按 token 预算组装批次

如果服务 SDK 能返回 tokenizer 的精确计数,优先使用它;没有 tokenizer 时只能使用保守估算,并把最终的超限错误当成输入失败处理。下面的示例刻意把估算器作为依赖注入,便于替换成真实模型 tokenizer:

from dataclasses import dataclass

@dataclass
class TextItem:
    # 原始序号用于把向量和输入稳定配对。
    index: int
    text: str

def build_batches(items, estimate_tokens, max_items=16, max_request_tokens=4096):
    # 任意一条文本都不能单独超过整批预算。
    batch, used_tokens = [], 0
    for item in items:
        tokens = estimate_tokens(item.text)
        if tokens > max_request_tokens:
            # 交给上层做截断或失败记录,避免静默丢失语义。
            raise ValueError(f"item {item.index} exceeds token budget")
        reaches_limit = batch and (
            len(batch) >= max_items or used_tokens + tokens > max_request_tokens
        )
        if reaches_limit:
            # 先产出已装满的批次,再重新计算当前条目。
            yield batch
            batch, used_tokens = [], 0
        batch.append(item)
        used_tokens += tokens
    if batch:
        # 最后一批可能不足 max_items,但仍然需要发送。
        yield batch

实际项目中,estimate_tokens 应与目标 Embedding 模型使用同一套分词规则;字符数只能作为粗略保护。对超长输入,不要在批处理器里悄悄截断后继续写入生产向量,至少要记录截断方向和原始长度,否则排查召回变化时没有依据。

把错误分成可重试和不可重试

重试策略要看错误是否会因为等待而改变。超时、限流、服务暂不可用通常可以有限重试;输入过长、参数不合法、鉴权失败则应立即进入失败队列。Hugging Face 文档列出的异常包括 InferenceTimeoutError 和非 503 的 HTTP 错误,接入层应把 SDK 异常映射成自己的错误类别,而不是对所有异常统一重试。

指数退避的重点不是“多试几次”,而是给服务恢复时间,并给每个批次设置上限。下面的代码使用伪造的 embed 调用表示供应商 SDK,展示重试边界和索引保留:

import random
import time

RETRYABLE = {"timeout", "rate_limit", "service_unavailable"}

def embed_with_retry(batch, embed, max_attempts=3, base_delay=1.0):
    # batch 中的 index 始终跟随文本,不能用返回顺序猜测归属。
    for attempt in range(max_attempts):
        try:
            vectors = embed([item.text for item in batch])
            if len(vectors) != len(batch):
                # 数量不一致不能写库,交给失败队列等待人工处理。
                raise RuntimeError("embedding result count mismatch")
            return [(item.index, vector) for item, vector in zip(batch, vectors)]
        except Exception as exc:
            kind = classify_embedding_error(exc)
            if kind not in RETRYABLE or attempt == max_attempts - 1:
                # 永久失败和耗尽次数的临时失败都保留原始批次。
                raise EmbeddingFailed(batch=batch, cause=exc) from exc
            # 抖动可以避免多个 worker 同时再次撞上限流窗口。
            delay = base_delay * (2 ** attempt) + random.uniform(0, 0.25)
            time.sleep(delay)

def classify_embedding_error(exc):
    # 生产实现应根据 SDK 的状态码和异常类型建立稳定映射。
    if isinstance(exc, TimeoutError):
        return "timeout"
    status = getattr(exc, "status_code", None)
    if status == 429:
        return "rate_limit"
    if status in {502, 503, 504}:
        return "service_unavailable"
    return "permanent"

class EmbeddingFailed(Exception):
    # 保存 batch 与 cause,便于后续按原始序号补偿。
    def __init__(self, batch, cause):
        super().__init__(str(cause))
        self.batch, self.cause = batch, cause
Embedding 请求批次按错误类型分流到退避控制器、失败队列和索引化结果的关系说明图
图2:失败分类结构说明图,展示 Embedding 重试边界与结果索引的静态关系。这是静态说明图,不是截图或运行证据。

示例中的 429、502、503、504 只是常见的接入层映射示例,最终要按实际供应商的响应契约调整。尤其是 400 类输入错误,重试只会放大延迟和费用;如果服务返回明确的 Retry-After,应优先遵守它,并在本地仍保留最大尝试次数。

用索引绑定结果,处理部分成功

向量写入时不要把“第几个返回值”当成业务主键。每条输入都应带有原始序号或稳定文档 ID,批次记录至少包含:批次 ID、输入 ID、估算 token、尝试次数、模型标识和最终状态。

当一批请求返回数量不一致、连接在响应中途断开,或者 SDK 把异常包装得不够清晰时,最安全的动作是整批进入补偿队列,而不是猜测哪些向量已经成功。若供应商明确支持逐项错误返回,则可以只重试失败索引,但仍要保存原始批次快照。

情况处理原因
单条超出长度截断、拆分或失败队列等待不会改变输入长度
429 限流遵守 Retry-After,有限退避窗口恢复后可能成功
服务 503指数退避并限制次数服务状态可能恢复
鉴权失败立即失败并报警重复请求不会修复凭据
响应数量不一致不写库,保留整批快照避免向量与文本错配

常见问题

批大小是不是越大越快?

不是。批次增大通常减少请求次数,但会增加单次延迟、内存和失败重做成本。应先用 token 预算限制,再根据服务延迟和限流反馈调整条数。

可以对所有错误都自动重试吗?

不建议。只重试等待后可能改变的错误;输入过长、参数错误和鉴权失败应直接记录上下文,修正原因后再重新入队。

为什么一定要保存原始索引?

因为批处理可能部分成功、重试后顺序改变,原始索引或稳定文档 ID 才能保证向量回写到正确对象。

把长度预算、错误分类和索引化结果保存放在同一条处理链上,Embedding 批量请求才具备可调、可恢复和可追踪的工程边界。具体上限仍以实际模型和服务商文档为准。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
GitHub Desktop 整理本地提交历史的操作步骤GitHub Desktop 整理本地提交历史的操作步骤
上一篇
GitHub Desktop 整理本地提交历史的操作步骤
下一篇
下一篇
暂无
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    497次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    554次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    579次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    532次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    346次使用