news 2026/9/11 1:13:20

qwen-code 的 `/stats` 生成时序指标(TTFT / Generation Time / TPS):从实现到验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
qwen-code 的 `/stats` 生成时序指标(TTFT / Generation Time / TPS):从实现到验证

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

导读

本文聚焦 qwen-code(An open-source AI coding agent that lives in your terminal)终端 CLI 中/stats命令新增的Generation Metrics(生成时序指标)模块,讲解 TTFT(首 token 延迟)、Generation Time(生成耗时)、Output Tokens、TPS(每秒输出 token 数)以及 Session 级平均 TTFT 与 Session TPS 的数据模型、计算口径与采样过滤规则,并完整还原该功能的自动化验证、手动验证场景与回归检查清单。读者读完可以掌握该指标体系的设计意图、源码位置与可复现的验证方法,为在自己环境中核查或二次开发该功能提供依据。


一、功能背景:/stats里的生成时序指标

/stats是 qwen-code 的内置斜杠命令,提供使用统计仪表盘。它既可以在交互式 TUI 中弹出统计对话框,也可以在非交互式命令面上输出纯文本。在新增 Generation Metrics 之前,/stats的会话统计只有 token 用量、模型用量、工具调用、文件变更等维度,缺少对“生成过程本身有多快”的量化;而 TTFT 等时序数据此前仅存在于 tracing(链路追踪)中。

本文依据的验证文档(.qwen/e2e-tests/2026-07-24-generation-stats.md)正是为这一功能制定的自动化与手动验证基线,核心目标是回答:

  • /stats的 Session 标签页能否展示最新一次请求的生成时序(模型、TTFT、生成耗时、输出 token 数、TPS);
  • 多次请求后,会话级请求计数、平均 TTFT、Session TPS是否正确累计;
  • 在非交互式命令面上,同样的指标能否以文本形式输出;
  • 在各种边界情况下(无流式响应、非流式响应、零耗时、内部 prompt、无用户可见内容)指标不会出现空节、编造数值或 Infinity。

本文所引用的指标实现、测试与验证步骤,均可在当前仓库.qwen/e2e-tests/2026-07-24-generation-stats.mdpackages/core/src/telemetry/uiTelemetry.tspackages/cli/src/ui/commands/statsCommand.tspackages/cli/src/ui/components/StatsSessionTab.tsx及对应测试文件中找到原始依据。


二、数据模型:GenerationMetrics 与 GenerationTimingSample

生成时序指标定义在 packages/core/src/telemetry/uiTelemetry.ts 中,由两个核心接口承载:

export interface GenerationTimingSample { model: string; ttftMs: number; generationDurationMs: number; outputTokens: number; } export interface GenerationMetrics { timedRequests: number; totalTtftMs: number; totalGenerationDurationMs: number; totalThroughputOutputTokens: number; last?: GenerationTimingSample; }
  • GenerationTimingSamplelast字段):最新一次被采样的请求快照,包含模型名、TTFT、生成耗时与输出 token 数,用于“Latest Request”展示;
  • GenerationMetrics的四个累计字段:timedRequests(被采样的请求数)、totalTtftMs(TTFT 累加和)、totalGenerationDurationMs(生成耗时累加和)、totalThroughputOutputTokens(用于计算吞吐的输出 token 累加和)。

它们挂在SessionMetrics的可选字段generation?: GenerationMetrics上,随会话指标一起被统计、查询和重置。默认空值由createInitialGenerationMetrics()生成(timedRequests: 0),确保任何会话初始时都能安全访问。

从源码结构看,GenerationMetrics是一个增量累加模型:每次事件到来时更新累计值并覆盖last快照,因此“Session 级平均值”可由累加值在展示层计算,而无需保存每个请求的历史明细。


三、指标口径:TTFT、Generation Time、TPS 的计算方式

3.1 采样逻辑(core 侧)

在 packages/core/src/telemetry/uiTelemetry.ts 中,#accumulateApiMetrics对每次 API 事件做如下处理:

if ( event.ttft_ms === undefined || !Number.isFinite(event.ttft_ms) || event.ttft_ms < 0 || isInternalPromptId(event.prompt_id) ) { return; } 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: event.model, ttftMs: event.ttft_ms, generationDurationMs, outputTokens: event.output_token_count, };

关键规则可归纳为:

  • TTFT 有效性ttft_ms必须存在(undefined不算)、是有限数值(Number.isFinite)、且不小于 0;duration_ms - ttft_ms可能为负(例如数据上报抖动),因此生成耗时用Math.max(0, ...)夹取到 0;
  • 内部 prompt 排除isInternalPromptId(event.prompt_id)为真时直接返回,不产生采样,保证内部 prompt 不会覆盖最新用户可见的生成样本
  • 零生成耗时不计入吞吐:当generationDurationMs === 0时,请求仍然计入timedRequeststotalTtftMs,但不累加totalGenerationDurationMstotalThroughputOutputTokens,从根上避免除零导致的 Infinity。

TTFT 的原始测量点位于 packages/core/src/core/loggingContentGenerator/loggingContentGenerator.ts:当响应流出现首个用户可见内容时记录ttftMs = Date.now() - startTime;如果流直到结束都没有用户可见内容,则ttftMs保持undefined,进而不会被采样——这与回归检查“A stream with no user-visible content does not create a timing sample”完全对应。

3.2 展示与计算(CLI 侧)

在 packages/cli/src/ui/components/StatsSessionTab.tsx 中,Generation Metrics 区域按以下公式渲染:

指标公式边界处理
最新请求 TPSlast.outputTokens / (last.generationDurationMs / 1000)仅当generationDurationMs > 0时计算,否则不显示(避免 Infinity)
Average TTFTgeneration.totalTtftMs / generation.timedRequests仅当timedRequests > 0时计算,否则不显示
Session TPSgeneration.totalThroughputOutputTokens / (generation.totalGenerationDurationMs / 1000)仅当totalGenerationDurationMs > 0时计算,否则不显示

同样的公式以纯文本形式存在于 packages/cli/src/ui/commands/statsCommand.ts 的formatGenerationMetrics()中(见下文非交互式输出)。三个平均值都遵循“分母为零则不显示”的口径,保证任何极端情况下不会输出 Infinity。

StatsSessionTab.tsx的展示结构为:

  • Latest Request 区:Model(最新模型名)、TTFT、Generation Time、Output Tokens、TPS;
  • Session 区:Requests(timedRequests)、Average TTFT、Session TPS。

会话级指标由 packages/cli/src/ui/contexts/SessionContext.tsx 提供上下文数据,/stats打开时读取的是同一个SessionMetrics,因此 TUI 展示与文本输出口径天然一致。


四、自动化验证:聚焦测试与仓库级校验

验证文档给出了可复现的自动化验证路径,分为两个层次。

4.1 聚焦的 Core 测试

在仓库根目录或packages/core下执行:

cd packages/core npx vitest run src/telemetry/uiTelemetry.test.ts npx vitest run src/core/loggingContentGenerator/loggingContentGenerator.test.ts
  • packages/core/src/telemetry/uiTelemetry.test.ts 覆盖采样逻辑:构造带ttft_ms的事件后断言generation数据正确累计;同时覆盖“缺少 TTFT 或内部 prompt 不产生采样”“duration_ms < ttft_ms时生成耗时夹取为 0”“按会话隔离”“service 重置时清空 generation 指标”等场景;
  • packages/core/src/core/loggingContentGenerator/loggingContentGenerator.test.ts 覆盖 TTFT 测量点,即“首个用户可见内容才记录 TTFT”。

4.2 聚焦的 CLI 测试

cd packages/cli npx vitest run src/ui/commands/statsCommand.test.ts npx vitest run src/ui/components/StatsSessionTab.test.tsx npx vitest run src/ui/contexts/SessionContext.test.tsx npx vitest run src/i18n/mustTranslateKeys.test.ts
  • statsCommand.test.ts:验证/stats命令及其子命令(modeltoolsskillsdailymonthlyexport)的文本输出与参数解析;
  • StatsSessionTab.test.tsx:验证 Session 标签页对 Generation Metrics 的渲染,包括各指标的存在性与格式;
  • SessionContext.test.tsx:验证会话统计上下文的组装与下发;
  • mustTranslateKeys.test.ts:国际化的强制校验,确保Generation MetricsLatest RequestTTFTGeneration TimeOutput TokensTPSAverage TTFTSession TPS等新增文案都有对应的翻译键,避免遗漏。

4.3 仓库级校验

聚焦测试通过后,再执行仓库级校验:

npm run format npm run lint npm run build npm run typecheck

这四步分别对应格式化、静态检查、构建与类型检查,确保新指标代码不影响仓库整体的可维护性与可发布性。


五、手动验证场景:一步一步核对指标

验证文档同时给出了端到端手动验证步骤,可作为功能验收的标准流程:

  1. 启动开发版 CLI,使用流式模型(streaming model),保证响应可产生多 token 输出;
  2. 提交一个 prompt,让其产生多 token 的流式响应;
  3. 打开/stats(交互式 TUI);
  4. Session 标签页确认Generation Metrics显示:
    • 最新模型(latest model);
    • TTFT
    • Generation Time(生成耗时);
    • Output Tokens(输出 token 数);
    • TPS(每秒输出 token 数)。
  5. 提交第二个 prompt,再次打开/stats
  6. 确认:
    • Latest Request 字段已更新为第二个请求的数据;
    • Session 请求计数(Requests)变为 2Average TTFTSession TPS同时包含两次被计时的请求;
  7. 非交互式命令面运行/stats,确认同样的指标以纯文本形式出现(见下一节)。

注意:/stats daily/stats monthly/stats export属于 token 用量统计,不包含生成时序,验证时不应期待它们出现 TTFT/TPS。


六、非交互式输出:文本形式的 Generation Metrics

/stats命令在 packages/cli/src/ui/commands/statsCommand.ts 中根据context.executionMode区分行为:交互式模式下弹出stats对话框;非交互式(non_interactiveacp)模式下返回文本消息。formatGenerationMetrics()生成的文本格式为:

Generation Metrics (Latest Request) Model: <model> TTFT: <formatted duration> Generation Time: <formatted duration> Output Tokens: <count> TPS: <x.x> tok/s Requests: <count> Average TTFT: <formatted duration> Session TPS: <x.x> tok/s

其中:

  • 若尚无任何计时样本(metricslast为空),整段返回空,不会渲染空壳标题;
  • 当最新请求的generationDurationMs为 0 时,TPS 显示为formatDuration之外的另一处防除零处理);
  • timedRequests为 0 时,Average TTFT 显示为
  • 当累计生成耗时为 0 时,Session TPS 显示为
  • 数字使用Intl.NumberFormat按当前语言本地化格式化。

这与回归检查“Opening/statsbefore any streamed response does not show an empty Generation Metrics section”以及“A zero generation duration displays TPS as unavailable instead of Infinity”直接对应。此外,/stats export输出的文本末尾带有明确提示:Note: generation timing (TTFT/TPS) belongs to generation metrics.,用于避免与 token 用量统计混淆。


七、回归检查清单:六条不可回归的边界

验证文档将以下场景列为回归红线,每条都有对应的实现或测试佐证:

#回归检查项实现保证(源码/测试依据)
1打开/stats但尚无任何流式响应时,不显示空的 Generation Metrics 节formatGenerationMetrics对空 metrics 返回空数组;StatsSessionTab仅在有lastGeneration时渲染该区域
2非流式响应不编造 TTFT 或 TPSTTFT 仅在流式响应出现用户可见内容时记录(loggingContentGenerator);无ttft_ms的事件直接跳过采样
3无用户可见内容的流不产生计时样本hasUserVisibleContent(response)为假时ttftMs保持undefined,事件被采样过滤
4零生成耗时显示 TPS 为不可用而非 InfinitygenerationDurationMs > 0才参与 TPS/吞吐累计;展示层分母为零时输出
5内部 prompt 不覆盖最新用户可见生成样本isInternalPromptId(event.prompt_id)直接 return,不更新generation.last
6/stats daily/stats monthly/stats export行为不变子命令走独立的queryTokenUsage路径,Generation Metrics 不介入 token 用量聚合

对应测试集中在 packages/core/src/telemetry/uiTelemetry.test.ts,例如:

  • it('does not create samples for missing TTFT or internal prompts')同时覆盖检查 2、3、5;
  • duration_ms: 100, ttft_ms: 150的事件断言generationDurationMs: 0,对应检查 4;
  • 按 session 隔离与 service reset 的用例保证会话切换不会串数据。

八、基线状态:变更前的可验证前提

验证文档记录了一个重要的环境约束:当前验证环境中没有发布版全局qwen可执行文件,因此无法运行“变更前”的手动场景对比。其基线结论为:

  • TTFT 已通过 tracing(链路追踪)输出——即时序数据此前就存在于观测侧;
  • /stats在变更前没有生成时序区块——即该功能属于对/stats的增量扩展,而非重构。

这意味着本功能的行为验证完全依赖源码与新增测试来确立基线:uiTelemetry.test.tsloggingContentGenerator.test.ts中的断言即代表了“变更后”的期望行为,手动场景仅作为 TUI 层面的最终验收补充。


九、相关文件速查

围绕本功能,仓库中的关键文件与角色如下:

文件角色
.qwen/e2e-tests/2026-07-24-generation-stats.md本功能的验证与回归检查规范(本文依据)
packages/core/src/telemetry/uiTelemetry.tsGenerationMetrics/GenerationTimingSample定义与采样累加逻辑
packages/core/src/telemetry/uiTelemetry.test.tscore 侧采样与边界场景测试
packages/core/src/core/loggingContentGenerator/loggingContentGenerator.tsTTFT 测量点(首个用户可见内容)
packages/cli/src/ui/components/StatsSessionTab.tsxTUI Session 标签页的 Generation Metrics 渲染
packages/cli/src/ui/commands/statsCommand.ts/stats命令、文本输出与daily/monthly/export子命令
packages/cli/src/ui/contexts/SessionContext.tsx会话统计上下文数据源
.qwen/specs/2025-06-03-stats-dashboard-redesign.md/stats仪表盘整体设计(Session 标签页保持不变的背景)

结语

Generation Metrics 为 qwen-code 的/stats补齐了“生成过程性能”这一观测维度,其设计有三个显著特点:增量累加模型(用last快照 + 四个累计值同时支撑单请求与会话级指标)、防御式采样(对缺失 TTFT、内部 prompt、零耗时、无可见内容等边界一律显式处理)、双出口一致性(TUI 渲染与非交互文本输出共享同一数据源与计算口径)。配合.qwen/e2e-tests/2026-07-24-generation-stats.md中给出的自动化与手动验证流程,任何开发者都可以在几分钟内独立验证该功能的正确性。

【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 1:08:07

NocoBase表单与详情页一体化设计实践

1. 项目概述&#xff1a;表单与详情页的一体化设计表单录入与详情展示是后台管理系统中最基础也最频繁出现的功能模块。传统开发中&#xff0c;这两个功能往往被割裂处理——前端需要为同一数据实体分别开发录入表单和展示页面&#xff0c;后端也要提供两套不同的接口。这种模式…

作者头像 李华
网站建设 2026/9/11 0:56:51

系统部署与软件安装作业标准化实践指南

1. 作业安装的基本概念与场景"安装的作业"这个表述在技术领域通常指代系统部署、软件安装或环境配置相关的任务流程。不同于简单的双击安装包操作&#xff0c;这类作业往往涉及多个环节的串联执行&#xff0c;需要处理依赖关系、权限配置、环境变量设置等复杂问题。在…

作者头像 李华
网站建设 2026/9/11 0:47:37

怀化烘焙AI短视频:甜品行业种草营销

来源&#xff1a;唐sirAI&#xff08;www.tangsir.cc&#xff09; | 电话&#xff1a;18874530691━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━在怀化烘焙行业竞争日益激烈的今天&#xff0c;如何低成本、高效率地进行品牌推广&#xff…

作者头像 李华
网站建设 2026/9/11 0:38:21

基于51单片机的烟雾检测报警系统:从传感器选型到仿真标定

简介&#xff1a;基于51单片机的烟雾检测报警系统完整设计资源&#xff0c;适合电子类课程设计、毕业设计及单片机爱好者。系统以51单片机为核心&#xff0c;通过ADC0833采集烟雾浓度&#xff0c;LCD1602显示浓度与阈值&#xff0c;支持按键调节阈值。浓度超标时&#xff0c;蜂…

作者头像 李华
网站建设 2026/9/11 0:35:16

Enlightenment 0.27桌面环境:Wayland支持与性能优化

1. Enlightenment 0.27桌面环境深度解析Enlightenment作为Linux系统上历史最悠久的窗口管理器之一&#xff0c;最新发布的0.27版本带来了多项突破性改进。我在实际使用这个轻量级桌面环境两周后&#xff0c;发现其模块化架构和可定制性确实令人印象深刻。这个版本最显著的特点是…

作者头像 李华