跳到正文
Together AI Blog·· 26 天前精选AI 评分62

Together AI 推出模型上线 Rollout 功能,支持金丝雀、蓝绿与滚动三种策略

Canary rollouts: upgrade models in production without downtime

AI 导读

Together AI 发布 Rollout 功能,可在同一 endpoint 上把流量从源部署迁移到目标部署,提供金丝雀、蓝绿和滚动三种策略,并支持指标门禁、暂停、恢复、提升与取消。

推荐理由

原文给出金丝雀、蓝绿、滚动三种上线策略的完整机制与真实回滚演示,可迁移到自有推理服务的模型切换流程。

正文 · AI 翻译

更换模型是常见做法

如果你在生产环境中运行模型,你早已知道需要换入新的检查点或新的模型系列:开放模型生态发展迅速,候选模型通常在评估中表现优异,或承诺更高的吞吐量。你希望它能无故障地服务每一位用户,并且如果表现令人失望,还能有回滚的办法。通常的选项都迫使你做出取舍:

  • 硬切换:将端点指向新模型,所有用户同时暴露在新模型下。如果 p95 延迟翻倍,你会从仪表盘上发现,或者更糟——从客户那里得知,然后在压力下回滚到一个冷启动的旧模型上。
  • 自行搭建的分阶段切换:再部署一个实例,外加一个脚本,在你盯着 Grafana 的同时逐步调整流量百分比,还得记得在把流量切回去之前先把旧部署扩容回来。

这两种方案都把人工作为安全机制置于环路之中。Rollout 将这一机制移入平台:你描述源、目标、步骤以及“健康”的定义,平台在每个阶段都按照这个计划执行。

Rollout 的工作原理

一次 rollout 会在同一端点的两个部署之间迁移流量:一个源(当前正在服务的部署)和一个目标(你明天想要服务的部署)。你可以从三种策略中选择一种:

  • 金丝雀:流量按你定义的分阶段百分比迁移(例如 10% → 50% → 100%;默认阶梯为 5% → 25% → 50% → 100%),步骤之间有等待期和可选的指标检查。
  • 蓝绿:一次带门控的 0% → 100% 切换。你可以把它看作单步金丝雀。
  • 滚动:原地、逐个副本替换,保持总容量不变。最适合容量受限的场景,尤其是无需流量爬坡的同模型配置变更。

以下是每个金丝雀步骤内部发生的过程:

我们有意选择这样的顺序;每一项都防止了一类事故:

  1. 目标在任何流量迁移之前先扩容。新部署没有容量就意味着没有重定向的请求:rollout 会先停住。
  2. 健康门控在流量切换之前运行。流量只会到达引擎已加载并正在应答的副本,而不仅仅是已启动的副本。
  3. 在切换与排空之间有一段传播等待。路由缓存先收敛,然后才移除任何源容量。
  4. 源在流量迁移之后才排空。扩容时容量先于流量;缩容时流量先于容量。
  5. 等待期和指标门控在步骤被记录为完成之前进行。出现回退的步骤绝不会被标记为通过。

通过 API 或控制台创建的 rollout 处于 PENDING 状态,在你明确启动之前不会做任何事(CLI 的 rollout 命令会一步完成创建和启动)。这种创建/启动两步式设计是有意为之,因为你可以先创建 rollout、审查它(或让队友审查),然后在真正盯着看的时候再启动它。

上图中的两个状态值得说明:

  • PAUSED 意味着是你按下了暂停。rollout 会精确停在当前位置,并从同一步骤恢复。
  • SYSTEM_PAUSED 意味着平台发现了问题,例如指标门控失败、容量不足或指标缺失,于是停下来等待人工批准。它会暂停、通知你并等待;取消始终是你的决定。

不存在让流量处于悬置状态的FAILED终态:一次发布要么以COMPLETED结束(目标开始服务),要么以CANCELED结束(分流冻结在原处,然后你反向运行发布以回退)。

单步剖析

以下是对单个金丝雀步骤中所发生情况的拆解,基于本文末尾的那次运行(Qwen2.5-7B → Qwen3.5-9B,各用一张 H100)。

传播等待是为了防止过期的全局路由缓存把请求发送到正在缩容的源端。等待时长会增长为指标窗口加上数据摄入延迟。冷启动主导了第一步;后续步骤向一个已经在服务且已预热的目标准入副本。

策略速览

三种策略都运行在同一个引擎和同一套健康门控之上;它们的区别在于流量如何迁移、重叠期需要多少额外容量,以及是否存在用于指标门控的等待窗口。

金丝雀蓝绿滚动
流量模式按你选择的份额逐步推进(默认 5% → 25% → 50% → 100%),每一步都保持一个等待窗口一次切换,0% → 100%,在目标健康后执行逐个副本,流量跟随副本比例
额外容量接近源端规模;目标在源端排空该份额之前先增长一步两个部署都保持满规模,直到源端排空每一步为源端的副本数;步骤中途多一个副本
典型时长一次冷启动加上每一步的等待(有指标门控时每步至少 390 秒)一次冷启动加上 30 秒传播;几分钟每个副本一次冷启动;在大型部署上最慢
指标门控有,每一步之后无(没有等待窗口)无
如何回退取消会冻结当前份额,然后反向运行发布反向运行发布;--final-source-replicas 1让旧模型保持预热以便即时回退反向运行发布
最适合在承接 100% 流量之前基于实时流量进行测量最快的切换,当你能够短暂承受双倍容量时在 GPU 占用不变的情况下进行同模型引擎或配置变更

‍

创建发布

以下是一个三步金丝雀发布,从服务你当前模型的部署迁移到服务候选模型的部署,并带有一个延迟回归门控。该 CLI 以tg的形式随together Python 包(2.34.0 或更新版本)提供。你传入目标部署;当恰好有一个部署在接收流量时源端会被推断出来,否则传入--source:

    
# 1. Create AND start the rollout in one command.
#    Intervals and windows are seconds with an "s" suffix ("600s", not "10m").
tg beta endpoints rollout $TARGET_DEPLOYMENT_ID \
  --source $SOURCE_DEPLOYMENT_ID \
  --canary \
  --steps 10,50,100 \
  --interval 600s \
  --metric router_latency --metric-stat p95 \
  --metric-max-regression 10 --metric-direction higher-is-worse \
  --metric-window 300s

# 2. Watch it move: pass the rollout ID printed under "Active Rollout",
#    or the endpoint ID for the endpoint summary
tg beta endpoints get $ROLLOUT_ID
tg beta endpoints get $ENDPOINT_ID

# 3. Control it: pass the endpoint ID plus exactly one control flag
tg beta endpoints rollout $ENDPOINT_ID --pause --reason "holding for review"
tg beta endpoints rollout $ENDPOINT_ID --resume
tg beta endpoints rollout $ENDPOINT_ID --promote
tg beta endpoints rollout $ENDPOINT_ID --cancel --reason "latency regression on target"
    

源端会缩容到零副本,并在发布完成时停止(--final-source-replicas默认为 0),目标端落地时以源端的副本数作为其下限(--final-target-replicas)。CLI 为每次发布附加一个指标门控;如需多条规则,请使用控制台或 API。

通过 REST API 的同样操作,其中创建和启动是分开的调用,且一次发布可以携带多条指标规则:

    
# 1. Create the rollout. It comes back in state PENDING; save its "id" (rol_...) as $ROLLOUT_ID.
curl -s -X POST \
  "https://api.together.ai/v2/projects/$PROJECT_ID/endpoints/$ENDPOINT_ID/rollouts" \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceDeploymentId": "'$SOURCE_DEPLOYMENT_ID'",
    "targetDeploymentId": "'$TARGET_DEPLOYMENT_ID'",
    "canary": {
      "steps": [{"traffic": 10}, {"traffic": 50}, {"traffic": 100}],
      "stepInterval": "600s"
    },
    "metrics": [{
      "name": "router_latency",
      "stat": "METRIC_STAT_TYPE_PERCENTILE",
      "percentile": 95,
      "regressionCheck": {
        "direction": "REGRESSION_DIRECTION_HIGHER_IS_WORSE",
        "maxRegressionPercent": 10
      },
      "window": "300s"
    }]
  }'

# 2. Start it:   POST .../rollouts/$ROLLOUT_ID/start   -d '{}'
# 3. Watch it:   GET  .../rollouts/$ROLLOUT_ID
    

API 严格要求的几点:percentile是整数(95,而不是 "p95"),枚举值带有完整前缀(METRIC_STAT_TYPE_*、REGRESSION_DIRECTION_*、THRESHOLD_OPERATOR_*),时长是类似"600s"的 protobuf 字符串,而目录之外的指标名称会被拒绝并返回 400,其中列出支持的名称。排空源端是默认行为,因此无需为其传入任何参数。

回归检查可以这样理解:在每个门控处,将目标在过去 5 分钟内的 p95 路由器延迟(在路由器处测量的每请求时长,以毫秒计)与源端的进行比较。如果目标差超过 10%,则不要继续。

Python SDK

用 Python 执行同样的发布,使用together包(2.34.0 或更新版本)。这里的字段名是 snake_case,而在传输时是 camelCase;SDK 会进行转换。

    
from together import Together

client = Together()  # reads TOGETHER_API_KEY

rollout = client.beta.endpoints.rollouts.create(
    endpoint_id=ENDPOINT_ID,
    project_id=PROJECT_ID,
    source_deployment_id=SOURCE_DEPLOYMENT_ID,
    target_deployment_id=TARGET_DEPLOYMENT_ID,
    canary={"steps": [{"traffic": 10}, {"traffic": 50}, {"traffic": 100}], "step_interval": "600s"},
    metrics=[{
        "name": "router_latency", "stat": "METRIC_STAT_TYPE_PERCENTILE", "percentile": 95,
        "regression_check": {"direction": "REGRESSION_DIRECTION_HIGHER_IS_WORSE", "max_regression_percent": 10},
        "window": "300s",
    }],
)  # state: PENDING

client.beta.endpoints.rollouts.start(rollout.id, project_id=PROJECT_ID, endpoint_id=ENDPOINT_ID)

# later: .retrieve / .pause / .resume / .promote / .cancel take the same (id, project_id, endpoint_id)
    

控制发布

每次 rollout 都接受相同的四个控制项。一个 endpoint 最多只能有一个活跃的 rollout,因此 CLI 只需传入 endpoint ID,你很少需要用到 rollout ID。每个控制项在被接受后立即返回;轮询 tg beta endpoints get(或 GET endpoint)直到 rollout 达到你预期的状态。当 rollout 处于活跃状态时(包括暂停期间),endpoint 的流量拆分会被锁定,其 source 和 target 无法被停止或删除。

暂停

rollout 进入 PAUSING,让任何正在进行的步骤活动完成,然后保持在当前的流量拆分和副本数,状态为 PAUSED。两个 deployment 都继续提供服务。暂停可以持续数天;平台绝不会自动恢复操作员发起的暂停。

CLI

tg beta endpoints rollout $ENDPOINT_ID --pause --reason "holding for review"

REST

POST …/rollouts/$ROLLOUT_ID/pause
{"reason": "holding for review"}

恢复

从同一步骤继续,对 PAUSED 和 SYSTEM_PAUSED 均适用。如果某个 gate 被触发,它会基于最新数据重新评估;该步骤不会被跳过。

CLI

tg beta endpoints rollout $ENDPOINT_ID --resume

REST

POST …/rollouts/$ROLLOUT_ID/resume
{}

提升

跳过剩余的 canary 步骤,完整执行最后的 100% 步骤:target 扩容到其最终规模,流量切换,传播等待和 soak 运行,然后 source 排空。被跳过的步骤记录为 SKIPPED。并非瞬时完成:在一次步骤间隔为 10 分钟的测试运行中,在第 0 步执行提升仍然要等待最后一步的完整 soak。

CLI

tg beta endpoints rollout $ENDPOINT_ID --promote

REST

POST …/rollouts/$ROLLOUT_ID/promote
{}

取消

将当前流量拆分冻结为 endpoint 的固定权重,并以 CANCELED 结束 rollout。不会缩容任何内容;两个 deployment 继续按冻结的份额提供服务,直到你编辑拆分或运行反向 rollout。在 0% 时被取消的 target 会保持运行但没有流量;如果不再需要,将其缩容到零或删除。

CLI

tg beta endpoints rollout $ENDPOINT_ID --cancel --reason "latency regression on target"

REST

POST …/rollouts/$ROLLOUT_ID/cancel
{"reason": "latency regression on target"}

反向 rollout

没有回滚动词。要将流量移回,在取消后或完成后,创建一个 source 和 target 互换的新 rollout,然后启动它。任何策略都适用,且相同的 gate 也适用。取消后,默认的 canary 阶梯会跳过新 target 已经通过的步骤,默认的最终副本数是该对的合并数量。

CLI

tg beta endpoints rollout $OLD_SOURCE_ID --source $OLD_TARGET_ID --canary

REST

POST …/rollouts        (with the two IDs swapped)
POST …/rollouts/$NEW_ROLLOUT_ID/start

对已完成的 rollout(COMPLETED 或 CANCELED)的控制会被拒绝。使用 tg beta endpoints rm $ROLLOUT_ID 从历史记录中删除已完成或从未启动的 rollout;删除记录不会改变它留下的流量拆分。

底层机制:配置 gate

指标 gate

指标 gate 是 canary 的功能:blue-green 和 rolling 仍然运行健康 gate,但分阶段的指标比较需要 canary 的步骤结构才有意义。Gate 在三个 router 侧指标的封闭目录上评估,对 source 和 target 进行相同的测量(任何其他指标名称在创建时会被拒绝):

  • router_error_rate:router 5xx 响应除以所有推理响应,以 0-1 的比例表示(0.02 表示 2%)
  • router_latency:在 router 处测量的每请求持续时间,以毫秒为单位。它是双峰的(中位数尝试通常是快速拒绝),因此应基于 p95 或更高值设置 gate,而不是均值
  • inflight_requests:每个就绪副本的并发请求数,在窗口内取平均(阈值按副本大小,而非整个集群)

每条规则使用两种检查之一:

  • regressionCheck(相对):“target 不得比 source 差超过 N%。”这是延迟的合适默认值,因为它能自我校准:你不需要知道绝对的 p95,只需知道新模型不应使其退化。设置 direction,让平台知道哪个方向更好/更差。
  • thresholdCheck(绝对):“target 必须满足 operator, value”(例如错误率 < 0.01)。当你拥有硬性 SLO,或者 source 本身可能不健康、相对比较会按曲线评分时,使用此选项。

两个配方覆盖大多数服务:

    
// Latency-sensitive service: don't ship anything meaningfully slower
{
  "name": "router_latency",
  "stat": "METRIC_STAT_TYPE_PERCENTILE",
  "percentile": 95,
  "regressionCheck": {
    "direction": "REGRESSION_DIRECTION_HIGHER_IS_WORSE",
    "maxRegressionPercent": 10
  },
  "window": "300s"
},
// Error-budget shop: hard ceiling regardless of what the source is doing
{
  "name": "router_error_rate",
  "stat": "METRIC_STAT_TYPE_AVG",
  "thresholdCheck": {
    "operator": "THRESHOLD_OPERATOR_LT",
    "value": 0.01
  },
  "window": "300s"
}
    

时间窗口

三个时长相互作用,所以请把它们都记住:

  • window(默认 5m):在比较指标时,门控回溯查看的时间范围。
  • stepInterval(默认 3m):每个步骤在其流量水平上等待多久后门控才运行。
  • 指标摄取延迟(约 90 秒):从请求被处理到其数据点可被查询之间的时间。

你必须等待至少 window + ingestion lag 的时间,这样门控的整个回溯期才会落在当前步骤的稳定状态内。如果你等待的时间短于你的窗口,门控就会比较那些部分描述先前流量分配的指标。平台会为你强制执行这一点:如果你请求的等待时间对你的窗口来说太短,它会自动增加。但最好还是在设计时就考虑到:5m 的窗口需要 6.5m 的等待时间。使用默认的 5m 窗口时,平台会将默认的 3m 间隔增加到 390 秒(6 分 30 秒);如果你设置自己的 stepInterval,请至少设为 window + 90s。

回归时会发生什么

默认情况下,触发的门控会路由到 SYSTEM_PAUSED,这意味着系统会暂停以等待审查。发布会在当前分配比例处保持(爆炸半径保持在你金丝雀百分比所对应的水平),由你决定:恢复(门控重新评估)、提升或取消。

没有自动中止:确认的回归总是会让发布停下来等待人工处理,因为将流量移回本身就是一项应该有人关注的变化。可恢复的原因(如容量不足或指标管道缺口)则不同:平台会每 15 分钟重试一次,最多持续 3 小时,之后才会让发布保持暂停状态等待你处理。平台还会防范误报:在因回归而暂停之前,系统会在约 90 秒内重新查询多次,以确保它看到的不是摄取延迟或暂时性波动;而无法获取可信数据的门控会以 METRICS_UNAVAILABLE 暂停,而不是被计为回归。

平台保证什么

所有三种策略都通过相同的步骤引擎运行,因此这些保证同样适用于金丝雀、蓝绿和滚动发布。

1. 容量永远不会被向下取整。目标副本数向上取整,源副本数向下取整,因此同等规模的替换永远不会比开始时拥有更少的副本。滚动发布在步骤中途增加一个副本;蓝绿发布会短暂地让两个部署都以完整规模运行。你的自动扩缩器在计划之外添加的副本会被保留。

2. 流量永远不会落到尚未就绪的容量上。每个步骤都按同一顺序运行:扩缩目标、检查健康、切换流量、等待 30 秒让路由收敛、排空源、等待、评估门控、记录步骤。在等待期间发生回归的步骤永远不会被记录为通过。

3. 每一侧始终拥有其份额所需的副本。只有当目标拥有足够多的就绪副本以承担新份额时,流量才会转移,并且源永远不会被排空到低于其剩余份额。如果某个副本死亡且无法再按该分配比例提供服务,发布会保持其能够维持的最大分配比例,并以 UNDER_SERVED 暂停。

4. 发布会提高下限;它不会与你的自动扩缩器对抗。每个步骤只写入每个部署的最小副本数,不写其他内容,只有一个例外:目标的最大副本数会被提升一次,以便它能够承载整个端点,并保持提升状态。源的最大副本数在排空期间会随其份额缩减。如果你将最大副本数降低到低于该步骤所需,发布会以 POLICY_INFEASIBLE 暂停,而不是覆盖你的设置。

5. 门禁始终会给出裁决。当目标值处于源值的百分比预算范围内时,回归检查通过。没有源数据则通过;在越高越差的指标上,源值为零而目标值非零则失败;其他任何源值为零的情况都通过。阈值检查忽略源值,将目标值与你的设定值进行比较。

6. 门禁只读取当前步骤的流量,且只读取足够的部分。等待时间至少为指标窗口加上约 90 秒的摄取延迟,因此 300 秒的窗口意味着 390 秒的等待。p95 需要窗口内有 20 个请求,p99 需要 100 个;少于这个数量时,发布将暂停为 METRICS_UNAVAILABLE。错误率和在途请求各需要 1 个。

边缘情况

1. 如果目标没有可用的 GPU 容量怎么办?

发布会在开始前预先检查整个流程的可行性,并且在每次扩容时再次检查。容量不足会以 CAPACITY_EXHAUSTED 类别将发布暂停为 SYSTEM_PAUSED。此时没有任何东西被移动,你的源端也未受影响。恢复时会重新检查容量,如果容量已释放则继续。容量问题通常是暂时的,所以暂停胜过失败。

2. 我可以无限期暂停吗?

可以。暂停不是保持连接,而是一种一等状态。发布被设计为能够承受多天的暂停,并从中断处精确恢复。

当平台暂停发布时,status.condition 会携带一个类型化的失败类别以及人类可读的 message。这些包括:

类别含义你应该
METRIC_REGRESSION门禁在真实数据上触发检查该步骤的指标读数;如果目标有问题,取消并反向运行发布;如果原因是外部的,则恢复
METRICS_UNAVAILABLE门禁无法获取可信数据检查指标名称/窗口;恢复会重新评估
CAPACITY_EXHAUSTED下一步没有足够的 GPU等待/释放容量,然后恢复
UNDER_SERVED一侧的就绪容量低于当前分流所需恢复容量(自动重试);如果暂停持续则恢复
POLICY_INFEASIBLE自动扩缩容限制无法满足该计划提高目标的最大副本数,然后恢复

文档列出了其余类别以及每个类别的处理方法:发布故障排除。

真实发布演示

以上所有内容在亲眼看过一次实际运行后会更容易让人信服,所以这里展示一次在当前平台上的运行(2026 年 9 月)。我们将一个在线端点从 Qwen2.5-7B-Instruct 升级到 Qwen3.5-9B,各自运行在单块 H100 上,同时整个过程中该端点持续承载稳定的每秒 5 次聊天补全请求,并且每个响应码都被记录。较新的模型是我们想要的;发布要回答的问题是它是否符合旧模型设定的延迟预算。我们给了它 25% 的 p95 预算。

设置。7B 已经在提供服务。我们将 9B 作为同一端点上的第二个部署添加进来,没有流量也没有副本;发布会在需要时启动它。

    
# $MODEL_ID is Qwen/Qwen3.5-9B-FP8. --config is optional when the model has exactly one serving config.
tg beta endpoints deploy $MODEL_ID --endpoint $ENDPOINT_ID --config $CONFIG_ID \
  --min-replicas 0 --max-replicas 0 --traffic-weight 0
    

启动。一条命令创建并启动金丝雀:10% → 50% → 100%,并在每一步之后用门禁在 5 分钟窗口内比较目标的路由器 p95 延迟与源端的延迟。

    
tg beta endpoints rollout $TARGET_DEPLOYMENT_ID --source $SOURCE_DEPLOYMENT_ID \
  --canary --steps 10,50,100 \
  --metric router_latency --metric-stat p95 \
  --metric-max-regression 25 --metric-direction higher-is-worse \
  --metric-window 300s      
    

按时间顺序发生了什么(自发布开始以来的时间):

  • +3:57 9B 完成了冷启动,通过了健康检查,10% 的请求开始落到它上面。发布流程等待 30 秒让路由收敛,然后排空 7B 对应的流量份额,接着进行观察。我们把步进间隔保留在默认值,因此平台将其增长到 390 秒,以覆盖 300 秒的窗口加上数据摄取延迟。
  • +11:00 门禁评估并触发。9B 的 p95 路由延迟为 1,740 毫秒,而 7B 为 734 毫秒,相对于 25% 的预算,这是 137% 的回归。发布流程进入 SYSTEM_PAUSED,仍有 10% 的流量在目标上,且没有任何东西被拆除。这是 tg beta endpoints get $ROLLOUT_ID --json 返回的结果(值以毫秒为单位):
    
"state": "ROLLOUT_STATE_SYSTEM_PAUSED",
"currentTrafficPercent": 10,
"pauseInfo": {
  "reason": "metrics-regression: regression check router_latency failed: target=1740.38 vs source=734.20, regression=137.05% exceeds max=25.00% (direction=REGRESSION_DIRECTION_HIGHER_IS_WORSE)",
  "pausedAt": "2026-09-16T20:50:45Z"
},
"status": {
  "condition": {
    "category": "ROLLOUT_FAILURE_CATEGORY_METRIC_REGRESSION",
    "atStep": 0,
    "metrics": [
	    { 
		    "name": "router_latency", 
		    "stat": "METRIC_STAT_TYPE_PERCENTILE", 
		    "percentile": 95,
		    "check": "METRIC_CHECK_TYPE_REGRESSION",
		    "sourceValue": 734.20, 
		    "targetValue": 1740.38, 
		    "maxRegressionPercent": 25,
		    "direction": "REGRESSION_DIRECTION_HIGHER_IS_WORSE", 
		    "verdict": "METRIC_VERDICT_BREACHED" 
	    }
    ]
  }
}
    

决定。 回归是真实的,不是暂时现象:9B 是一个推理模型,在相同的 max_tokens 下,每个请求生成的内容更多。这是一个产品决策,而不是可以继续推进的事情,因此我们取消了并回退。

    
tg beta endpoints rollout $ENDPOINT_ID --cancel --reason "p95 latency regression on the Qwen3.5 target"
# split frozen at 90% / 10%; both deployments keep serving

tg beta endpoints rollout $SOURCE_DEPLOYMENT_ID --source $TARGET_DEPLOYMENT_ID --blue-green
# the 7B takes 100% back, the 9B drains to zero
    
  • +11:09 CANCELED。命令发出后 0.2 秒内,流量分割冻结在 90/10。
  • +17:00 反向发布完成,从开始算起用时 5 分 49 秒:100% 的流量回到 7B,9B 排空至零并停止。其中大部分时间花在第二个 7B 副本的冷启动上,因为取消后,默认的最终副本数是这一对副本的合计数量。

探针的结论 贯穿整个运行过程,包括切换、暂停、取消和反向操作:6,800 个请求,0 个非 200 响应。

审计追踪。 上述每一步都在端点的事件流中,可按发布 ID 过滤:

    
tg beta endpoints events $ENDPOINT_ID --subject-id $ROLLOUT_ID --json
    
20:39:45  rollout.created           canary rollout created: dep_src → dep_tgt, 3 step(s) to 100%
20:39:45  rollout.started           rollout started: step 1 of 3 targets 10% traffic
20:43:42  rollout.traffic_shifted   0% → 10%   target traffic: 0% → 10%
20:50:45  rollout.system_paused     paused automatically at step 1 of 3: a metric check failed
20:50:54  rollout.canceled          cancel requested; traffic will be frozen at the current split
20:50:54  rollout.canceled_complete canceled: traffic frozen at 90%/10% (source/target)

7 月的一次早期运行,使用了一个故意设置得不可能达到的阈值门禁,产生了相同的形态:在 10% 流量时触发,并且在恢复过程中 1,198 个探针请求零错误。

自己试试吧!

1. 在一个端点上部署两个部署。 将你当前的部署保留为源,并将候选者作为目标添加,流量为零。pip install -U together(2.34.0 或更新版本)为你提供了 tg CLI:

    
# A stopped, zero-traffic target; the rollout restarts it when it scales it up.
# Add --config cr_... to pin a specific config revision.
tg beta endpoints deploy $MODEL --endpoint $ENDPOINT_ID \
  --min-replicas 0 --max-replicas 0 --traffic-weight 0
    

2. 使用默认阶梯(5% → 25% → 50% → 100%)和一个 router_latency 回归门禁创建并启动金丝雀发布:

    
tg beta endpoints rollout $TARGET_DEPLOYMENT_ID --canary \
  --metric router_latency --metric-stat p95 \
  --metric-max-regression 10 --metric-direction higher-is-worse
    

3. 观察它 使用 tg beta endpoints get $ENDPOINT_ID(或控制台中的端点 Rollouts 标签页)观察它逐步推进。使用 tg beta endpoints rollout $ENDPOINT_ID --pause | --promote | --cancel 暂停、提升或取消它。

在整个过程中,端点 URL 和你的客户端保持不变;只有它们背后的模型在移动。

📚 文档: 启动发布 · 使用指标对发布设置门禁 · CLI 参考 · API 参考:创建发布

‍

来源:Together AI Blog · together.ai