Skip to content

fix(lane): 流式 usage 逐帧重复块改为逐字段取最大值,修复 input 被放大 30–1400x (issue #105) - #115

Merged
LAGcomcom merged 1 commit into
LAGcomcom:masterfrom
ghshhf:fix/streaming-usage-dedup
Oct 23, 2026
Merged

LAGcomcom merged 1 commit into
LAGcomcom:masterfrom
ghshhf:fix/streaming-usage-dedup

Conversation

@ghshhf

@ghshhf ghshhf commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

解决的问题

issue #105:流式响应里重复的 usage 块被逐帧相加,input 被放大 30–1400 倍,客户端每轮都误触发上下文压缩。

根因

readSSE(internal/lane/http.go) 把每个 SSE 帧的 usage 用 Usage.Merge 朴素 += 累加。流式 usage 是累计快照(不是 delta),当上游在多个帧重复发送同一份完整 usage(OpenAI include_usage 下常见),或中继每帧重发时,累加就把同一数值加了很多遍。

改动

  • 新增 Usage.MergeMax:逐字段取最大值而非相加。
  • readSSE 改用 MergeMax。

为什么不是「替换 last-wins」:Anthropic 把 input(message_start) 与 output(message_delta) 拆到两个不同帧,直接替换会丢掉 input。MergeMax 同时正确覆盖三种情形:重复整块→数值不变;跨帧拆分→两字段都保留;累计增长→取最新。Merge(累加)保留给 recovery 路径合并两次独立真实请求的用量。

测试

新增 usage_test.go 覆盖上述三种情形;go build ./... 与 go test ./internal/lane/... 全部通过。

Closes #105

此前 readSSE 把每个 SSE 帧的 usage 用 Usage.Merge 朴素 += 累加。当上游在
多个帧里重复发送同一份完整 usage(OpenAI include_usage 下常见),或中继把
usage 每帧重发时,input 会被放大 30–1400 倍,客户端据此误触发上下文压缩。

但流式 usage 是累计快照而非 delta,且 Anthropic 把 input(message_start) 与
output(message_delta) 拆到两帧——直接「替换 last-wins」会丢掉 input。故新增
Usage.MergeMax:逐字段取最大值。这样重复整块→数值不变、跨帧拆分→两字段都
保留、累计增长→取最新。Merge(累加)仍保留给 recovery 合并两次真实请求。

新增 usage_test.go 覆盖三种情形。
@LAGcomcom
LAGcomcom merged commit 0ebdb56 into LAGcomcom:master Oct 23, 2026
3 checks passed
LAGcomcom added a commit that referenced this pull request Oct 23, 2026
@LAGcomcom

Copy link
Copy Markdown
Owner

感谢细致的定位!issue #105 的根因分析(逐帧重复的累计 usage 快照被逐帧累加)完全正确,帮了大忙。我们已经按这个思路实现并合入 7eb328b:流式 usage 逐字段取最大值聚合,relay 自定义供应商路径同步覆盖,另外把 OpenAI 嵌套在 prompt_tokens_details 里的 cached_tokens 也补上了。欢迎继续反馈!

@ghshhf
ghshhf deleted the fix/streaming-usage-dedup branch November 3, 2026 14:49
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.

流式响应里重复的 usage 块被逐帧相加,input 被放大 30-1400 倍,客户端每轮都触发压缩

2 participants