同一句回答分成三块,为什么算成三次推理?
一段流式回答可以分多次到达。如果评测把每个片段都当作一次模型调用,文本没有变化,推理次数却会随分块方式变化。这时,先检查计数的对象,比先解释模型行为更有用。
我把这个公开问题整理成一个可离线运行的样例:固定两个源码快照,给它们相同的合成输入,保留接收事件、转换结果和最终计数。目标很窄:看清“输出事件”和“逻辑请求”在这条路径上怎样被混用,以及候选实现在哪些边界上仍然缺少信息。
先固定回答,再改变分块
最小对照只有一句 Hello world。保持最终文本相同,分别拆成一块、两块和三块,经过选定的接收、事件判断、转换与评测方法。
| 固定源码 | 1 块 | 2 块 | 3 块 | 最终文本 |
|---|---|---|---|---|
| 原问题基线 | 1 | 2 | 3 | Hello world |
| 上游未合并候选 | 1 | 1 | 1 | Hello world |
这里检查的是一条约定:同一次生成仅改变传输分块,不应改变逻辑推理次数。候选在这个对照中满足约定,基线不满足。数字不能解释真实服务成本,也不能推出候选的整个分支都已正确。
难点在于保留请求边界
直接丢弃 partial 事件看起来简单,但片段里也可能带着 usage;思考文本切换到答案、文本后接工具调用,都可能产生多个输出段。只按保留下来的最终片段计数,仍然可能把同一请求拆开,或者丢掉元数据。
这次观察的候选利用仍保留边界的原始事件序列重建计数,而不是只数投影后的评测事件;它区分作者、连接及完成、中断、工具响应、新输入等边界。诊断同时保留一个“给合并文本补上 model_version,再过滤 partial”的朴素版本作为负面对照:它能通过最简单的分块检查,却仍会在部分跨段场景里多计,且会丢失 partial 事件携带的 usage。
另一条容易被汇总掩盖的差别是 None 与 0。没有保留下来的 usage 是未知;显式报告零是一个数值。错误事件后没有可见模型载荷,也不能据此断言远端从未尝试请求。usage 缺失时,报告保留 null;零个可观测调用仍不代表零次远端请求。
原评测器的整体分数是每个 invocation 计数的平均值。诊断额外输出的 total_count 是求和,两者分别标记,不能混用。
这个样例实际运行了什么
诊断读取固定版本的原始 Python 文件,校验 12 个 Git blob,再用 AST 选出所需方法,在新的类外壳中执行未改写的方法体。GenAI/Pydantic 数据模型和部分框架服务由小型数据对象替代。替身支持本次需要的构造、复制和序列化,不提供完整类型校验、字段别名或框架语义。
因此,这份结果能说明选定方法在这些输入下的行为。它没有验证真实 Runner、子代理生命周期、数据库持久化、远端事件顺序或旧版严格 schema 读取器。音频夹具只有六个任意字节 abcdef;它检查接收器输出的字节保留,没有进行可解码语音或听感测试。
本地 Python 3.12.14 运行了 62 项标准库测试,全部通过,覆盖 50 个合成样例。样例包括文本与字节分块、usage 位置、工具边界、不同作者与连接、两次 invocation、中断和重复标记。测试中还故意恢复按事件计数、删去用户输入边界或中断边界,确认目标样例产生偏离预期的计数。
50 个样例中有 4 个标为已知限制或失败可观测性检查。它们通过,表示记录下来的行为符合声明的预期;不能解读成修复了 50 个问题。
保留下来的失败边界
- 已完成回答被重放:相同载荷在完成标记之后再次出现,仍可能被计为新请求。没有更强的请求身份信息,不能声称 exactly-once。
- 边界丢失:两次真实请求可能被合并为一次。诊断没有猜测缺失的请求 ID。
- 只收到部分文本就断开:可以看到一次已开始的生成和不完整答案,不能把它记成成功会话。
- 错误或取消前没有模型载荷:可观察计数为零,仍不足以确定实际尝试了多少次远端请求。
两个固定快照还包含前置 PR 和其他分支差异。这是选定核心路径的前后对照,没有逐一隔离并验证所有改动。上游保存评测结果的可选 schema 字段及兼容性,也仍需在真实框架和读写端中另行检查。
下载后怎样复核
下载 Live trace 计数诊断包 · SHA-256 校验值
约 204 KiB,133 个文件。包含完整脚本、合成夹具、逐步事件报告、源码快照、LICENSE 和 NOTICE;不含缓存或录音。
先将 ZIP 与校验文件放在同一目录,用 sha256sum -c SHA256SUMS 检查(macOS 可用 shasum -a 256 -c SHA256SUMS),再解压运行:
cd voice-trace-diagnostic
python3 -B -S verify.py
python3 -B -S diagnose.py --variant candidate --assert-chunk-invariance --output rerun/candidate
python3 -B -S diagnose.py --variant baseline --assert-chunk-invariance --output rerun/baseline
候选命令应退出 0;基线命令应退出 1,显示分块不变性不成立。最后一条命令的失败是有意保留的证据。新输出分别写入 rerun/candidate 与 rerun/baseline,reports/results.json 保留打包时的完整对照;verify.py 会更新本地的测试结果记录。脚本预计可在 Python 3.11+ 运行,但此次只实测了 3.12.14。上述命令无需第三方包、API key、模型下载或网络。
先读包内 README.md 与 provenance.json。随后可从 fixtures.py 查看输入与独立语义预期,从 reports/traces/ 追到发出的事件和转换结果,再核对 reports/results.json。golden/summaries.json 是回归快照,重新生成它不能替代对预期语义的审查。保留的 upstream_repro.py 需要真实 ADK 环境,本次未运行。
固定来源与贡献范围
- 原问题 #7351 与公开最小示例;评测负责人对一次推理的口径说明。
- 基线:d312c0e;候选:970c239,对应 PR #7427。
- 前置变更:PR #7323。截至 2026-10-11 检查时,这两条 PR 都仍开放且未合并。
上游问题报告与修复由 yang0228 提出,并有 Google ADK 维护者澄清口径和参与审查。下载包保留 Google 的版权头、Apache-2.0 许可证及来源。这里新增的工作是可离线执行的诊断外壳、合成输入、边界检查和可追溯证据;没有把上游报告的整套测试、安装包测试或生产效果当作本次实测。
这个小样例最有用的地方,是让一个计数结论能一路追溯到具体输入和事件。再往前走,需要完整框架、真实传输与持久化的验证;当前的通过结果到这里为止。