Qwen Code `/stats` 会话生成时序指标(TTFT / Generation Time / TPS)设计与实现解析 📅 发布时间:2026/9/12 4:35:39 👁 浏览次数: Qwen Code/stats会话生成时序指标TTFT / Generation Time / TPS设计与实现解析【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code/stats是 Qwen Code 终端内置的会话统计入口它同时支持交互式 Session 面板与非交互式文本输出。本文围绕设计文档 2026-07-24-generation-stats.md 展开讲解 TTFT首字延迟、Generation Time生成耗时与 TPS吞吐三类指标的语义定义、从底层流式生成器到/stats界面的完整数据链路并结合仓库源码给出可验证的实现依据。读完本文你将掌握 Qwen Code 中生成时序指标的计算口径、排除规则与兼容性边界并能在实际使用中正确解读/stats的 Generation Metrics 输出。背景为什么需要独立的生成时序指标Issue #4252 提出一个明确诉求/stats需要把“生成时序”与两类既有指标区分展示会话墙钟时间session wall time会话从开始到结束的整体耗时受用户思考、工具执行等环节影响端到端 API 延迟end-to-end API latency一次模型请求从发起到完成的总时长包含网络排队、首字等待与后续生成。在这项改动之前底层时序数据其实已经存在只是没有通向/stats的“最后一公里”已有能力位置说明ttftMs首字时序loggingContentGenerator.ts从请求派发到首个用户可见流式 chunk 的耗时sampling_ms/output_tokens_per_secondsession-tracing.tsendLLMRequestSpan推导出的生成阶段耗时与吞吐ApiResponseEvent请求级事件types.ts已携带请求时长、模型、prompt id 与输出 token 数进入UiTelemetryService本次改动补上的正是缺失环节把已有的 TTFT 值接入/stats所使用的“无内容会话指标”content-free session metrics让生成时序在交互与非交互两种模式下都能呈现。指标语义与计算公式对于每一个成功且带 TTFT 的流式响应定义三个指标TTFTTime To First Token即已有的ttftMs测量值表示从请求派发到首个用户可见流式内容出现的时间。源码中ttftMs只在首个包含用户可见内容的 chunk 上捕获见下文排除了仅含 role / usageMetadata 的中间 chunk。Generation Time生成耗时max(0, duration_ms - ttft_ms)从首个用户可见流式内容出现到流结束。TPStokens per secondoutput_token_count / generation_time_seconds仅在生成耗时为 0 时不可用。会话级聚合口径SessionMetrics.generation见 uiTelemetry.ts按需惰性创建lazily created包含两类数据最近一次已完成的请求样本last模型名、TTFT、生成耗时、输出 token 数聚合计数timedRequests已计时的请求总数totalTtftMs所有计时请求的 TTFT 之和totalGenerationDurationMs吞吐合格throughput-eligible请求的生成耗时之和totalThroughputOutputTokens吞吐合格请求的输出 token 之和。对应的会话级派生指标为会话平均 TTFTtotalTtftMs / timedRequests所有计时请求的算术平均会话 TPStotalThroughputOutputTokens / (totalGenerationDurationMs / 1000)加权吞吐而非各请求 TPS 的均值。零生成耗时generationDurationMs 0的请求只计入 TTFT 统计不进入 TPS 计算的两侧分子分母都不含以此避免除零并防止短请求被过度加权。这一口径在 uiTelemetry.ts 的聚合逻辑中完整实现先校验ttft_ms存在、有限且非负再计算generationDurationMs Math.max(0, event.duration_ms - event.ttft_ms)仅当generationDurationMs 0时才累加生成耗时与输出 token。与端到端延迟、采样耗时的关系在 session-tracing.ts 的 span 属性推导中存在同源的sampling_ms Math.max(0, duration - ttftMs)与本文的 Generation Time 公式一致当sampling_ms 0且有输出 token 数时还会写入output_tokens_per_second。值得注意的是该处代码注释记录了一次 Phase 4a 的缺陷修复旧公式duration - ttft - setup会重复扣除requestSetupMsPhase 4b 起开始填充导致重试请求的采样耗时被错误钳制为 0——这印证了“生成时序 总时长 − 首字耗时”这一口径在工程上需要小心维护。数据流从流式生成器到/stats设计文档给出了端到端数据流LoggingContentGenerator.loggingStreamWrapper - ApiResponseEvent(ttft_ms) - logApiResponse - UiTelemetryService - SessionMetrics.generation - SessionContext - /stats第一跳loggingStreamWrapper捕获 TTFTLoggingContentGenerator是包裹底层ContentGenerator的装饰器loggingContentGenerator.ts。在loggingStreamWrapper的迭代循环中// Capture TTFT on the first stream chunk that contains user-visible // content. hasUserVisibleContent skips role-only / usageMetadata-only // chunks, so TTFT reflects model produced something the operator can // attribute to user-perceived latency. if (ttftMs undefined hasUserVisibleContent(response)) { ttftMs Date.now() - startTime; }关键实现细节ttftMs是方法内闭包局部变量而非实例字段因为LoggingContentGenerator被多个并发的generateContentStream调用共享每个ContentGenerator一个实例实例字段会造成并发串扰判定函数hasUserVisibleContent跳过仅含 role / usageMetadata 的 chunk保证 TTFT 反映“模型产出可感知内容”的时刻流结束后ttftMs通过safelyLogApiResponse传给ApiResponseEvent构造函数loggingContentGenerator.ts事件定义在 types.ts其中ttft_ms字段注释为 Time from stream dispatch to first user-visible content.。第二跳endLLMRequestSpan的 Span 属性同一份ttftMs还会在 span 收尾时写入 trace 属性endLLMRequestSpan设置ttft_ms、sampling_ms与output_tokens_per_secondsession-tracing.ts供可观测性链路使用。设计文档同时说明后续的 GenAI 对齐补充了标准化的gen_ai.response.time_to_first_chunk属性见 loggingContentGenerator.ts 中performance.now() - requestIssuedAtMs的首 chunk 计时它独立于私有的ttft_ms/stats并不消费该标准属性ApiResponseEvent.ttft_ms的数据流与“首个用户可见输出”语义保持不变。第三跳UiTelemetryService聚合进SessionMetricsUiTelemetryService收到ApiResponseEvent后执行聚合uiTelemetry.tsif ( event.ttft_ms undefined || !Number.isFinite(event.ttft_ms) || event.ttft_ms 0 || ... ) { /* 跳过无 TTFT 的请求不产生生成样本 */ } const generation metrics.generation ?? (metrics.generation createInitialGenerationMetrics()); const generationDurationMs Math.max(0, event.duration_ms - event.ttft_ms); generation.timedRequests; generation.totalTtftMs event.ttft_ms; if (generationDurationMs 0) { generation.totalGenerationDurationMs generationDurationMs; generation.totalThroughputOutputTokens event.output_token_count; } generation.last { model, ttftMs, generationDurationMs, outputTokens };GenerationMetrics与GenerationTimingSample的类型定义位于 uiTelemetry.ts是SessionMetrics上的可选字段generation?: GenerationMetrics。随后SessionContext的 clone/equality 逻辑会复制并比较该可选对象确保交互式面板在每个完成计时的请求后都能刷新对应设计文档 Compatibility 一节的描述。排除规则内部辅助提示词生成指标会排除内部辅助提示词internal helper prompts对应的请求原因有二这些请求不会写入可恢复的会话记录resumable transcript若计入既会让用户困惑也会造成“实时会话”与“恢复后会话”的数值不一致。主对话与子代理subagent请求保持计入与既有会话级模型统计口径一致。源码侧LoggingContentGenerator全程用isInternalPromptId(userPromptId)判别内部请求loggingContentGenerator.ts内部请求不采集响应文本也不产生api_response日志自然不进入生成样本。兼容性边界本次改动刻意保持最小侵入ApiResponseEvent.ttft_ms与SessionMetrics.generation均为增量且可选字段已有记录事件与调用方保持有效不新增第二个计时器不把时序持久化到日/月 token 用量文件不改变导出内容也不改动 daemon / Web Shell 的 stats schema既有日/月记录继续只含 token 与 API 时长数据保持 issue-4479-token-usage-stats-coordination.md 中记录的归属边界非流式响应、以及流式但从未产出用户可见内容的响应保持原行为不创建生成样本。输出呈现交互式与非交互式非交互式文本输出statsCommand.ts的formatGenerationMetricsstatsCommand.ts按“最新请求 会话聚合”两个区块渲染Generation Metrics (Latest Request) Model: model TTFT: duration Generation Time: duration Output Tokens: count TPS: x.x tok/s Requests: count Average TTFT: duration Session TPS: x.x tok/s其中最新请求 TPSlast.outputTokens / (last.generationDurationMs / 1000)生成耗时为 0 时显示—平均 TTFTtotalTtftMs / timedRequests会话 TPStotalThroughputOutputTokens / (totalGenerationDurationMs / 1000)。交互式 Session 面板交互式/stats的 Session 标签页StatsSessionTab渲染同一份SessionContext中的SessionMetrics.generation数据并在每次完成计时的请求后随 context 更新而刷新。新引入的高可见性标签如 “Generation Time”“Average TTFT”“Session TPS” 等覆盖了所有内置语言环境i18n。验证与测试设计文档列出的验证策略在仓库中均有对应测试支撑验证目标测试位置聚合、内部提示词排除、零生成耗时处理、会话隔离与重置uiTelemetry.test.ts、SessionContext.test.tsxTTFT 到达ApiResponseEvent且非可见流不携带 TTFTloggingContentGenerator.test.ts非交互输出与交互 Session 标签渲染statsCommand.test.ts、StatsSessionTab.test.tsx新标签的 i18n 覆盖stats 相关测试中的多语言断言如生成耗时TTFT/TPS归属于生成指标例如 statsCommand.test.ts 验证了“存在流式响应时包含实时生成时序”构造ttftMs: 250、generationDurationMs: 1250、输出 50 token 的样本后断言输出包含TPS: 40.0 tok/s与Session TPS: 40.0 tok/s与公式50 / 1.25 40完全吻合。小结/stats的生成时序指标是一套“复用既有底层测量、补齐汇聚链路”的增量设计TTFT 在LoggingContentGenerator流式包装层捕获经ApiResponseEvent进入UiTelemetryService惰性聚合为SessionMetrics.generation最终由SessionContext驱动交互式 Session 面板与非交互式文本输出。理解max(0, duration_ms - ttft_ms)的生成耗时口径、加权吞吐 总输出 token / 总生成耗时的会话 TPS 口径、以及内部提示词排除规则即可准确解读/stats中每个数字背后的真实含义。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考