
摘要
A/B 实验允许你将端点的实时流量拆分为一个对照组和最多 20 个变体的固定队列,每个队列按百分比分配流量。这使你能够衡量候选模型在真实用户中以你选择的曝光水平表现如何。通过一次调用即可提升变体的流量比例,你可以使用蓝绿部署来推广获胜者。删除实验会将 100% 的流量返回给对照组,无需事后进行任何客户端或路由逻辑更改来撤销。下面我们将在实时端点上运行一个实验,创建 95%/5% 的流量分配,提升到 80%/20% 和 50%/50%,然后删除并检查每个阶段观察到的流量份额。
在生产环境中为 LLM 实施 A/B 测试
迟早每个团队都会想回答同一个问题:新模型与当前模型相比,对用户真的更好吗? 不是在基准测试上更好,而是在留存率、点赞率、任务完成率等你的产品实际衡量的指标上更好。
影子流量无法回答这个问题。影子流量告诉你候选模型在延迟、错误、吞吐量方面操作上是健全的,但其响应被丢弃;没有用户会对其采取行动。质量问题需要真实暴露给最终用户,让一部分用户使用模型 B,然后比较发生的情况。
通常团队会在应用层自行构建,使用以下某种组合:
- 客户端代码中的功能标志或基于用户 ID 的哈希取模 100。
- 客户端切换的两个端点(或两个硬编码的模型字符串)。
- 某个电子表格解释 A 组与 B 组的含义。
这可行,但它将你的实验与基础设施纠缠在一起,会在以后造成伤害:路由逻辑随应用程序一起发布,队列拆分可能因客户端缓存决策而漂移,即使实验“结束”后,分支代码也会长期存在,因为没人确定删除它是否安全。
Together AI 平台允许你在端点级别运行 A/B 实验逻辑。
工作原理
A/B 实验附加到端点,并声明成员,恰好有一个对照组和一个或多个变体,每个成员指向一个部署,每个成员都有一个 percent 设置,必须总和为 100,控制流量路由。

端点路由器的工作方式是,每当基础流量向对照组发送请求时,实验会在各分支之间重新采样并重新分配,使得 95% 留在对照组,5% 流向变体。
准确地说,机制是:实验细分了对照组在基础流量拆分中的份额。 路由首先通过权重拆分解析请求;当获胜者是 A/B 实验的对照组时,请求会根据各分支的百分比在实验分支中重新采样。由于对照组是拆分成员中唯一的入口点,因此各分支的百分比就是绝对流量份额。还值得注意的是,如果对照组的拆分权重为零,则实验没有可细分的内容,因此整个实验不会收到任何流量。

重要的是,变体部署绝不能出现在端点的流量拆分中,平台要求变体权重为零;只有控制组位于基础拆分中。实验将完全拥有路由到变体的流量;其百分比
就是其流量份额。如果变体还能从拆分中获取容量加权的流量,你的测量结果就会悄然出错。一种思考方式是,你应该将变体设置为影子部署:创建后,READY
,权重为零,然后让实验百分比设置路由到它。另一个重要点是,A/B 百分比是真正的固定流量份额,总和为 100%,并且与副本数量无关。我们特意将其与流量拆分权重(按就绪副本计算并跟随容量)区分开来。实验是一种测量工具;你希望在测量时拆分保持恒定,而不是随自动缩放而漂移。
创建 95/5 实验:
你的客户端不会注意到这个实验,因为表面上相同的端点名称、API 和密钥保持不变。在后端,5% 的请求现在将由变体候选者应答。
底层机制:提升、测量、结束
提升是重新发送成员集
没有单独的“提升”API,更新将替换整个成员列表,这保持了心智模型的简单性(实验始终与其成员所表示的一致),并使每次提升都成为明确可审查的更改:
更新由 etag 保护,因为如果队友在你编写更新时提升了实验,你的更新将被拒绝,而不是静默覆盖他们的更新。

使用这种 API 设计,你仍然需要做出常见的曝光选择,即路由多少流量到 B 组:

使用最多 20 个变体成员,你还可以运行多路测试,例如,你想尝试一个全精度端点以及三个其他量化变体(V1、V2、V3)。只要百分比总和仍为 100% 且恰好有一个控制组,这将按预期工作。

测量:将平台指标与你的产品指标结合
每个请求由特定部署提供服务,并且每个平台指标都按部署可用——因此基础设施侧的比较(延迟、错误、每队列吞吐量)是一个过滤器,而不是一个项目。产品侧是你的:记录哪个部署提供了每个响应(它在响应元数据中),连同你的质量信号——评分、重试、任务完成——连接键就是部署 ID。平台故意不猜测你的质量指标;它使归因变得简单,以便你的分析可以进行判断。
结束:先提升,然后删除
假设实验显示变体获胜。结束它是一个两步过程:
通过滚动发布提升。从控制部署到变体部署运行蓝绿滚动发布。健康门控、传播等待和回滚安全都适用。删除实验。所有实验路由消失,100% 的流量随后遵循端点的基础流量拆分,在滚动发布后,该拆分指向你的获胜者。

如果变体失败,你可以直接删除实验,流量将完全回到对照组。在后端,变体的部署会缩容到零或被删除。
边界情况
变体在实验中途性能下降。爆炸半径有多大?
只有它的队列。部署是独立监控和独立自动缩放的,这意味着表现不佳的变体不会拖累对照组。要修复此问题,你可以重新发送不包含问题变体的成员集合,其用户将在一定传播时间内回到对照组。这也是从5%开始是个好主意的原因。
观察到的份额是否真的与配置的百分比匹配?
在有效流量下,是的!有关实际示例,请查看下面的实验。在小窗口内,你可以预期采样噪声:1000个请求的5%份额是一个小样本。如果你的观察份额偏差很大且持续偏差,请检查上面的设置规则。
A/B实验和灰度发布能否在同一端点上运行?
可以,组合顺序定义为:路由先解析基础拆分,然后进行A/B实验(细分对照组的份额),然后进行灰度发布(在源部署及其灰度目标之间重新采样)。平台仍然强制每个端点只有一个活动灰度发布,但阶段设计为在重叠时可以组合。
队列是否对每个用户保持粘性?
分配使用请求的采样键,例如请求体中的顶级prompt_cache_key
或user
字段,因此携带相同键的请求路由一致,给定用户可以在会话中保持在同一个测试组。没有键的请求实际上按请求随机分配(我们下面的实验测量使用了无键流量,这就是观察份额与百分比如此接近的原因)。如果每个用户的一致性对你的研究很重要,特别是如果你有多轮质量比较,请发送稳定的user
字段。
拆分下的自动缩放会发生什么?
每个成员部署根据其自身的流量份额,按照自己的策略进行缩放。一个5%的变体,边界为1-2,和一个95%的对照组,边界为2-8,是完全正常的形态。你应该独立监控每个队列的副本,这就是我们在下图中捕获的内容。
展示一个完整的A/B实验
我们在一个实时端点上运行了完整的生命周期,从95/5开始,逐步提升到80/20,再提升到50/50,然后删除。我们同时保持稳定的3 RPS流量,每个请求都归属于提供服务的部署。下图显示了变体看到的流量,绿色点捕获变体流量份额:

以下是每个阶段的配置份额与观察到的流量份额:
运行中有三个细节值得指出:
每次提升实际上只需一次调用,你可以使用当前的etag
重新发送完整的成员集合。etag从1 → 2 → 3递增
跨两个 ramp;过期的 etag 会被拒绝,而不是静默覆盖队友的更改。传播很快,但不是即时的。每次更新后我们等待约 75 秒再进行测量;路由层在 30-60 秒的时间尺度上拾取实验更改,与流量拆分更改相同。删除:移除实验后,我们发送了 360 个连续请求,它们全部落在对照组上。除了删除遗留的 cohort 逻辑外,没有其他需要清理的。
以下是控制台在端点的 流量测试 选项卡上显示的实验(A/B 测试和影子测试共享此页面):

自己试试!
你需要一个带有控制部署(正在服务流量)的端点,以及一个候选部署(已创建,READY
,不在流量拆分中)。然后:
- 在 95/5 创建实验。 - 让它运行直到你有足够的量——5% 的全部意义在于收集数据时暴露保持低水平。
- 当数据表明时,通过单次更新进行 ramp。当结果明确时,通过 rollout 进行提升。完成后删除——没有其他需要清理的。
📚 文档: 专用模型推理 → A/B 测试
