• v1.3.8 0e29deac1a

    iomgaa released this 2026-09-14 15:36:08 +08:00 | 39 commits to main since this release

    流式中段沉默的计量与应对(issue #27 / #28):generation_ms 口径重定义为净生成时间(扣除所有超阈值中段沉默)并配 stall_ms/stall_count 归因字段与遥测两列;另加一条默认关闭的中段沉默对冲(主路首 token 之后相邻增量 chunk 间隔超阈值时,向异源并发再发一次)。两键均不设时行为逐字等于 1.3.7(默认关闭回归门: 既有 unit/contracts 全套件语义断言一行未改)。

    行为变更: generation_ms 口径重定义(1.3.7 墙钟 → 本版净生成时间)

    Warning

    同一字段,两版口径不同。 1.3.7 的 generation_ms 是赢家那次 transport 调用的完整墙钟(中段沉默全部计入);本版起是净生成时间 = 墙钟 − Σ(所有 > {SCOPE}__STREAM__STALL_THRESHOLD_MS 的相邻增量 chunk 沉默),仍含 TTFT 与尾部(末 chunk → 流结束归活跃侧,墙钟基底口径的有意选择)。还原公式: 墙钟 = generation_ms + stall_ms(stall_ms 为 None 时墙钟 = generation_ms)。

    语义突变在一般情形下违反「字段只增不删不改名」精神,本次由人类以「窗口期最小代价」裁决放行(2026-09-11),依据三行: 该字段 1.3.7(2026-09-10)才引入、发布仅 2 天;消费者唯一(提出本需求的下游 Terminal-Bench,三参考项目均未消费);遥测 DB 从未存过 generation_ms,无历史账本纵向断裂。字段名「裸生成时间」原本承诺的就是净口径,本次重定义是兑现名字而非推翻承诺。max_inter_token_ms(单次最大相邻间隔)原语义一字不动——它与 generation_ms 是两个口径,不能互算。

    项 口径
    计入沉默的间隔 相邻增量 chunk(content 或 reasoning_content 均计,与看门狗/首 token 活性口径一致)间隔严格大于阈值(恰好等于不减);空 chunk / usage 帧 / SSE keepalive 不计时;chunk 边界是传输/解析缓冲产物而非 token 边界,本口径不假装是 ITL
    stall_ms: int | None 赢家路超阈值中段沉默总额(毫秒);与 stall_count 成对报告(只报净数无法行动)
    stall_count: int | None 超阈值相邻间隔个数
    None 条款(照 vLLM 排除条款) 非流式 / 增量 chunk <2 → 两字段 None 且 generation_ms 不退减(= 原墙钟);None = 「无沉默观测」而非 0,下游预算公式以 stall_ms is None 为分支条件
    对冲赢家 三值全部取赢家路;已完成但落选的对冲输家其沉默在其 attempt 遥测行(可按 logical_call_id join 还原);被取消的输家无 TransportResult、hedge_cancelled 行 stall 恒 None
    与业界基准口径的区隔 NVIDIA TTFT/ITL/E2EL 与 vLLM 的基准口径均不扣除沉默——扣沉默是本库自造口径,与基准数字比较时不得混用

    遥测两列(纯增量,可空)

    遥测表 llm_calls 末尾追加 stall_ms / stall_count 两可空列(INSERT 字段 36 → 38,物理列 37 → 39),落库值与 CallStats 快照同源(retry 层已取整的 int)。旧行 NULL 不回填(NULL 表达「补列之前根本没记过这件事」);auto 档幂等补列(先探测后 ALTER),manual 档按现有列裁剪写入并点名缺列,补列 SQL 由 telemetry_schema_sql() 自取。generation_ms 仍不进遥测列——要墙钟用 latency_ms 或 generation_ms + stall_ms 还原。TelemetryRecorder.record_llm_call 协议同步加两个无默认值 keyword-only 参数: 自建 recorder 未跟进会在装配期被形状闸当场拒绝(不是运行期静默丢行),**fields 形态不受影响;emit_cache_hit / emit_terminal_failure 与失败/取消 attempt 行两列恒 NULL。

    中段沉默对冲(默认关闭;无业界公开先例)

    新键 {SCOPE}__HEDGE__STALL_AFTER_S: 主路首 token 之后相邻增量 chunk 间隔超此阈值 → 向异源并发再发一路,先回者赢、输家取消。编排/记账/遥测全部复用 1.3.7 对冲语义(异源排除、完整准入、拿不到配额静默放弃、hedge_cancelled 遥测行、两败只计一次重试预算)。诚实标注: 业界对中段沉默的落地形态收敛为「看门狗掐流 → 重试」,「中段沉默触发并发副本」在任何主流网关/库中均无公开先例——本能力属超业界现状能力,启用前请理解其语义。

    请先读这三句:

    # 承诺 展开
    1 默认关闭,开启即用配额换延迟 不设该键时行为逐字等于 1.3.7。下游实测(Terminal-Bench 4407 次成功调用)沉默 >20s 占 19.0%——触发率远高于首 token 对冲(ttft >20s 仅 3/4407),开启后约两成调用会在触发窗口内 in-flight 翻倍
    2 输家可能已被上游计费,取消止不住 与 1.3.7 同一性质: 输家按 est 保留预扣(闸内保守记账,不是上游真实计费的计量);取消止得住等待,止不住上游已经烧掉的钱。对账靠 hedge_cancelled 遥测行按 logical_call_id join
    3 独立于 HEDGE__AFTER_S 生效,仅流式 chat 两阈值各自独立,可独设可组合;仅设 STALL_AFTER_S 时首 token 前的沉默不触发(窗在首 token 到达后才开);仅设它且请求非流式 → 逐字走单路(中段沉默无非流式概念,等价未配置);Embedding/OCR scope 配了任一对冲键 → 装配期 warning 后静默退化

    与看门狗的交互及不对称声明(运维「挂起率」统计须知): 主路沉默超 INTER_TOKEN_TIMEOUT_S 被看门狗掐死 → 照常进 Transient 重试链并喂熔断失败计数(1.3.6 起既有语义),对冲路已在跑时本轮不因主路之死而败(等副路裁定,主路 attempt 记账照常);对冲输家被取消 → 不喂熔断(1.3.7 已批准语义)。同为源沉默事件、两种处置,本版不改任一。

    配置面

    键 值域 缺省 守卫
    {SCOPE}__STREAM__STALL_THRESHOLD_MS 正整数毫秒 1000 仅改计量口径,不改任何行为;调整接口三层同权(env 键 / GatewaySettings.stall_threshold_ms / GatewayClient(stall_threshold_ms=...)),无 per-call 覆盖,不做自适应(防与对冲阈值耦出反馈环)
    {SCOPE}__HEDGE__STALL_AFTER_S 有限正数秒 未设 = 关闭 装配守卫: ≥ min over sources of (inter_token_timeout_s or timeout_s)(有效最小值,对冲窗永不开)→ ValueError;≥ call_deadline_s → ValueError;单源 scope 设阈值 → warning 允许

    GatewayClient(...) 直传 hedge_stall_after_s / stall_threshold_ms 两 keyword-only 参数走同一份装配守卫;from_settings/from_env 照常透传。

    Downloads