Skip to content

feat(loop): explicit stream_llm_tokens, and ungate the anthropic protocol - #62

Merged
zhanghanduo merged 1 commit into
mainfrom
feat/explicit-stream-toggle
Oct 6, 2026
Merged

zhanghanduo merged 1 commit into
mainfrom
feat/explicit-stream-toggle

Conversation

@zhanghanduo

Copy link
Copy Markdown
Collaborator

这行是过期遗留

流式原本完全由"运行时有没有人要 delta"决定(reasoning-only 守卫读流、或 observer 声明 wants_llm_delta),然后三个原生协议被无条件压掉:

if getattr(profile, "protocol", "chat_completions") in (
    "anthropic", "responses", "bedrock",
):
    stream_llm_tokens = False

该行没有注释。时间线:

日期 commit 内容
2026-09-01 8266155 引擎抽取,搬来这行禁用
2026-09-02 18c3cd2 / 59d9c0b provider substrate 落地流式逐字 block 列表 —— 思考块文本之后才到的 signature_delta,以及完全没有 delta 的 redacted_thinking 载荷
2026-10-05 20b288f 当代 Claude 回放兼容性补全

禁用比保真能力早一天,此后一个月没人回头看。 test_anthropic_latest_models.py 自 09-02 起就一直对 streaming 双参数化跑 signature 回放、prefix-bound 重试与 reset 提交。

两个后果

(1) 宿主无法表达"传输层要求流式"。 非流式 Anthropic 请求的响应头要等整个生成结束才发,所以网关的 first-byte 超时会把长生成一律掐断。2026-10-05 在 llm-hub 的 "Claude Code" 通道实测同一个 claude-opus-5-5 effort=max 请求:

结果
非流式 502 upstream_unreachable — first byte timeout @ 76s
流式 HTTP 200,首字节 3.9s,生成实际耗时 242s

并发已排除:5 个轻请求在飞全通;5 个重请求在同一个 76s 刻度失败。

新增 LoopConfig.stream_llm_tokens: bool | None = None —— True 流式、False 不流式、None 维持原自动判断。显式值绕过协议闸门,宿主由此自己承担该协议的回放保真责任。

(2) 压制是静默的。 在被闸协议上配了 reasoning_only_* 的 profile,拿到的是"没有守卫、也没有任何提示"。现在自动模式丢掉有人索要的 delta 时会 warning。

闸门按证据收窄,不是一刀全开

UNVERIFIED_STREAM_PROTOCOLS = {"responses", "bedrock"}(已导出):

  • responses 只有一条流式测试,且只覆盖 response.failed 的报错路由 —— 没有回放保真测试
  • bedrock 一条都没有,且走的是另一个 SDK transport

anthropic 退出该集合即本次行为变更。把某个协议从集合里移走,等于去写那个证明它流式回放的测试。

消费者注意

Anthropic 协议的 profile 若设了 reasoning_only_* 或注册了 wants_llm_delta observer,现在真的会走流式 —— 其 client 必须实现 stream,流式被选中后没有回落到 chat 的路径。

ApodexHarness 的 tests/contract/test_streaming_deltas.py 在 docstring 里逐字抄了旧的选择表达式,bump pin 时需同步。

测试

新增 10 个:anthropic 在 observer 要 delta 时流式、两个未验证协议保持非流式且给出警告、显式 True 在任意协议生效、显式 False 压过 observer、无人索要时仍走更省的非流式、守卫本身也触发流式、集合内容钉死。

全量 1911 passed / 2 skipped(origin/main 为 1901,本次 +10);ruff 全清,pyright 改动模块 0 error。按 docs/versioning.md 不动版本号与 CHANGELOG,只加 changes/62.feature.md。

🤖 Generated with Claude Code

流式原本完全由"运行时有没有人要 delta"决定(reasoning-only 守卫读流、或
observer 声明 `wants_llm_delta`),然后三个原生协议被**无条件**压掉:

    if getattr(profile, "protocol", "chat_completions") in (
        "anthropic", "responses", "bedrock",
    ):
        stream_llm_tokens = False

这行没有注释,来自 2026-09-01 引擎抽取(8266155)的搬运,而让流式这一轮能
逐字回放的 provider substrate 工作是 **2026-09-02** 落地的(18c3cd2 /
59d9c0b):`AnthropicClient.stream` 会重建 provider 自己的 block 列表 ——
包括思考块文本之后才到的 `signature_delta`,以及完全没有 delta 的
`redacted_thinking` 载荷。`test_anthropic_latest_models.py` 自那以后一直对
streaming 双参数化跑 signature 回放、prefix-bound 重试与 reset 提交。
**禁用比保真能力早一天,此后一个月没人回头看。**

两个后果,都在这次修掉:

1) 宿主无法表达"传输层要求流式"。非流式 Anthropic 请求的响应头要等整个生成
   结束才发,所以网关的 first-byte 超时会把长生成一律掐断。2026-10-05 在
   llm-hub 的 "Claude Code" 通道实测同一个 claude-opus-5-5 effort=max 请求:
   非流式 **502 upstream_unreachable — first byte timeout @ 76s**,流式
   **HTTP 200**、首字节 3.9s、生成实际耗时 242s。并发已排除(5 个轻请求全通,
   5 个重请求在同一个 76s 刻度失败)。

   新增 `LoopConfig.stream_llm_tokens: bool | None = None`:True 流式、
   False 不流式、None 维持原自动判断。显式值绕过协议闸门 —— 宿主由此自己
   承担该协议的回放保真责任。

2) 压制是静默的。在被闸的协议上配了 `reasoning_only_*` 的 profile,拿到的是
   "没有守卫、也没有任何提示"。现在自动模式丢掉有人索要的 delta 时会 warning。

闸门按证据收窄为 `UNVERIFIED_STREAM_PROTOCOLS = {"responses", "bedrock"}`
(已导出):responses 只有一条流式测试且只覆盖 `response.failed` 的报错路由,
bedrock 一条都没有、且走的是另一个 SDK transport。anthropic 退出该集合即本次
行为变更。把某个协议从集合里移走,等于去写那个证明它流式回放的测试。

消费者注意:Anthropic 协议的 profile 若设了 `reasoning_only_*` 或注册了
`wants_llm_delta` observer,**现在真的会走流式** —— 其 client 必须实现
`stream`,流式被选中后没有回落到 `chat` 的路径。ApodexHarness 的
`tests/contract/test_streaming_deltas.py` 在 docstring 里逐字抄了旧的选择
表达式,bump pin 时需同步。

测试:新增 10 个(anthropic 在 observer 要 delta 时流式、两个未验证协议保持
非流式且给出警告、显式 True 在任意协议生效、显式 False 压过 observer、
无人索要时仍走更省的非流式、守卫本身也触发流式、集合内容钉死)。
全量 1911 passed / 2 skipped(origin/main 为 1901,本次 +10);ruff 与
pyright(改动模块)清。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@zhanghanduo
zhanghanduo merged commit eb1642b into main Oct 6, 2026
5 checks passed
@zhanghanduo
zhanghanduo deleted the feat/explicit-stream-toggle branch October 6, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant