fix(core): keep estimated token split summing to total#5420
Conversation
|
@qwen-code /triage |
|
Thanks for the PR! Template looks good ✓ — headings present, reviewer test plan with a concrete failing-then-passing assertion. On direction: this is a clean, obvious bug fix. On approach: the fix is exactly the minimal change — one line per path (non-streaming + streaming), deriving the completion half from the remainder. No scope creep, no unrelated edits. The test directly asserts the invariant that was broken. Nothing to cut. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ — 各节齐全,reviewer test plan 包含了具体的"改动前失败、改动后通过"断言。 方向:这是一个明确的 bug 修复。对两半分别 方案:改动最小化——非流式和流式路径各改一行,用总量减去 prompt 部分得到 completion 部分。无多余改动,无范围蔓延。测试直接断言了被破坏的不变量。无需裁剪。 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
Code ReviewIndependent proposal (written before reading the diff): the fix is obvious — compute one half with No correctness bugs, no security issues, no regressions. Both paths are updated symmetrically. The comment is updated to explain the rationale. The test directly asserts the broken invariant. No AGENTS.md violations — minimal, focused, no abstractions, no scope creep. Nothing to flag. ✅ Test ResultsBefore (main branch, without fix)Running the new test against the original code: Bug confirmed: After (this PR)All 134 tests pass, including the new invariant check. The fix correctly derives 中文说明代码审查独立方案(读 diff 前写出):修复方法显而易见——用 无正确性 bug,无安全问题,无回归。两条路径对称更新,注释解释了原理,测试直接断言被破坏的不变量。无 AGENTS.md 违规——最小化、聚焦、无过度抽象、无范围蔓延。 无需标记的问题。✅ 测试结果改动前(main 分支,无修复): 改动后(本 PR):全部 134 个测试通过,包括新的不变量检查。修复正确地用 — Qwen Code · qwen3.7-max |
|
This is a textbook bug fix — clean, minimal, and correct. The rounding invariant ( The diff is exactly what this bug needs: 2 production lines changed, 1 test added, nothing else. No abstractions, no drive-by refactors, no scope creep. If I had to maintain this in six months, I'd have nothing to complain about. Approving. ✅ 中文说明这是一个教科书式的 bug 修复——干净、最小化、正确。 舍入不变量( diff 正好是这个 bug 所需的:改动 2 行生产代码,添加 1 个测试,无其他内容。无过度抽象,无顺手重构,无范围蔓延。六个月后维护这个代码,不会有任何可抱怨的。 批准。✅ — Qwen Code · qwen3.7-max |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
✅ Local verification — recommend mergeVerified this on a clean worktree (real Scope confirmedTrue diff vs finalPromptTokens = Math.round(totalTokens * 0.7);
finalCompletionTokens = totalTokens - finalPromptTokens; // was Math.round(totalTokens * 0.3)A repo‑wide grep confirms these are the only two sites using the 70/30 estimate, so the fix is complete. The 1) Author's Reviewer Test Plan — reproduced exactly
2) A/B on the compiled converter — both pathsImported the built
Example 3) Real end-to-end under tmuxDrove the bundled
The CLI also issues a background Lint / build
Optional (non‑blocking)Consider adding a sibling assertion for the streaming 🇨🇳 中文版(点击展开)✅ 本地验证 — 建议合并我在一个干净的 worktree 中完成了验证(真实 改动范围确认相对 finalPromptTokens = Math.round(totalTokens * 0.7);
finalCompletionTokens = totalTokens - finalPromptTokens; // 原来是 Math.round(totalTokens * 0.3)全仓 grep 确认整个代码库里使用 70/30 估算的仅有这两处,因此修复是完整的。 1)复现作者的 Reviewer Test Plan
2)对编译产物转换器做 A/B —— 两条路径从
例如 3)tmux 下的真实端到端用打包后的
CLI 还会额外发起一个后台 Lint / 构建两个改动文件 可选(不阻塞合并)建议在单测里为流式 |
What
When an OpenAI-compatible response reports only
total_tokens(no prompt/completion breakdown), the converter estimates a 70/30 split. It rounded each half on its own:so the two halves could add up to more than the real total — e.g.
total = 5gives4 + 2 = 6. This derives the completion half from the remainder instead, in both the non-streaming (convertOpenAIResponseToGemini) and streaming (convertOpenAIChunkToGemini) paths.Why
usageMetadataexposespromptTokenCount,candidatesTokenCountandtotalTokenCount. With the old rounding,promptTokenCount + candidatesTokenCountcould exceedtotalTokenCount, so anything that reconciles the split against the total (billing, logging, telemetry) sees inconsistent numbers.totalTokensis the one real figure we have here, so the split should always add back up to it.Reviewer Test Plan
npx vitest run packages/core/src/core/openaiContentGenerator/converter.test.ts— seekeeps the estimated prompt/completion split summing to total tokens, which feeds{ prompt_tokens: 0, completion_tokens: 0, total_tokens: 5 }and asserts the split sums to 5. It fails before the change (expected 6 to be 5) and passes after.Risk
Low. Only the
total_tokens-only estimate path changes; the prompt half keeps the sameMath.round(total * 0.7)value and the completion half becomestotal - prompt. Cases that already report a real breakdown are untouched.