dsh-recent-usage-metrics 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.en.md +1 -0
- package/README.md +1 -0
- package/client/client.js +94 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 0.3.5
|
|
2
|
+
|
|
3
|
+
- 修复:模型切换或缓存偏低时,高亮只染了数字列,时间与速度列仍是灰色——那三列各自设置了
|
|
4
|
+
颜色,把行级颜色挡掉了。现在高亮会覆盖所有单元格,整行才真的变色。
|
|
5
|
+
- 总用时列新增悬浮提示,说明工具调用的用时:`工具调用 3 次 · 串行 12.4 s · 并行合并 5.1 s`。
|
|
6
|
+
两个口径都报,因为差值正是并行省下的时间。无工具时写「无工具调用」,
|
|
7
|
+
压缩行写明「压缩上下文不计工具时间」。
|
|
8
|
+
- 总用时的表头提示补上一句「不含工具调用时间」,把口径歧义说清。
|
|
9
|
+
|
|
1
10
|
## 0.3.4
|
|
2
11
|
|
|
3
12
|
- 实时行也能显示模型名了:形态与编号行相同——本步窗口内有 `request/header` 判为切换、
|
package/README.en.md
CHANGED
|
@@ -152,6 +152,7 @@ Every drawer column and every header carries a hint:
|
|
|
152
152
|
| Clock column | the full timestamp `11-06 10:47:41.828` |
|
|
153
153
|
| Speed column | the model that served that row |
|
|
154
154
|
| Tokens column | input tokens (with thousands separators, e.g. `370,683 tok`) and cache hit rate |
|
|
155
|
+
| Time column | how much of the request was tool time, both summed and parallel-merged |
|
|
155
156
|
| Headers | what the column measures (the `#` header draws the four state glyphs) |
|
|
156
157
|
|
|
157
158
|
**Row highlights:**
|
package/README.md
CHANGED
|
@@ -136,6 +136,7 @@ DSH 的极客级请求指标。它在 **设置 → 通用 → 性能与用量**
|
|
|
136
136
|
| 时间列 | 完整时间戳 `11-06 10:47:41.828` |
|
|
137
137
|
| 速度列 | 该行使用的模型 |
|
|
138
138
|
| 输出 Token 列 | 输入 token(带千分位,如 `370,683 tok`)与缓存命中率 |
|
|
139
|
+
| 总用时列 | 工具调用的用时(串行累加与并行合并两个口径);无工具时说明没有调用 |
|
|
139
140
|
| 表头 | 该列的含义(`#` 一列用图标展示四种状态) |
|
|
140
141
|
|
|
141
142
|
**行高亮:**
|
package/client/client.js
CHANGED
|
@@ -119,9 +119,13 @@ window.__ModuleLoader__.load({
|
|
|
119
119
|
hintTtft: '从发出到收到第一个 token 的耗时',
|
|
120
120
|
hintSpeed: '模型生成速度 = 输出 token ÷ 解码时长',
|
|
121
121
|
hintTokens: '模型本次生成的 token 数',
|
|
122
|
-
hintTotal: '
|
|
122
|
+
hintTotal: '请求耗时:从发出请求一直到模型输出结束,不含工具调用时间',
|
|
123
123
|
hintAmortized: '输出 token ÷ 总用时,包含请求时间和响应时间,更加能表明本地到模型输出完整链路的速度',
|
|
124
124
|
tokensHint: '输入 {input} · 缓存命中 {hit}',
|
|
125
|
+
toolHintOne: '工具调用 {count} 次 · {total}',
|
|
126
|
+
toolHintTwo: '工具调用 {count} 次 · 串行 {total} · 并行合并 {wall}',
|
|
127
|
+
toolHintNone: '无工具调用',
|
|
128
|
+
toolHintCompaction: '压缩上下文不计工具时间',
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
const en = {
|
|
@@ -177,9 +181,13 @@ window.__ModuleLoader__.load({
|
|
|
177
181
|
hintTtft: 'Time from issuing the request to receiving its first token',
|
|
178
182
|
hintSpeed: 'Generation speed = output tokens ÷ decode time',
|
|
179
183
|
hintTokens: 'Tokens this reply generated',
|
|
180
|
-
hintTotal: 'Request time: from issuing the request until the model finished replying',
|
|
184
|
+
hintTotal: 'Request time: from issuing the request until the model finished replying, not counting tool calls',
|
|
181
185
|
hintAmortized: 'Output tokens ÷ total time, including both queueing and response — the throughput of the whole local-to-model path',
|
|
182
186
|
tokensHint: 'Input {input} · cache hit {hit}',
|
|
187
|
+
toolHintOne: 'Tool calls: {count} · {total}',
|
|
188
|
+
toolHintTwo: 'Tool calls: {count} · serial {total} · parallel-merged {wall}',
|
|
189
|
+
toolHintNone: 'No tool calls',
|
|
190
|
+
toolHintCompaction: 'A compaction spends no time on tools',
|
|
183
191
|
}
|
|
184
192
|
|
|
185
193
|
const STYLE_TEXT = `
|
|
@@ -450,6 +458,26 @@ window.__ModuleLoader__.load({
|
|
|
450
458
|
color: var(--dsw-alias-label-tertiary);
|
|
451
459
|
text-align: left;
|
|
452
460
|
}
|
|
461
|
+
/*
|
|
462
|
+
* A highlighted row colours EVERY cell, not just the ones that inherit.
|
|
463
|
+
*
|
|
464
|
+
* The index, clock and primary cells each set their own colour, so without this they stay
|
|
465
|
+
* grey inside a blue or yellow row and the highlight reads as a stray word rather than as a
|
|
466
|
+
* whole row. Their own rules stay in place for every unhighlighted row.
|
|
467
|
+
*
|
|
468
|
+
* The specificity is deliberately higher than each of those cell rules: one class plus two
|
|
469
|
+
* attribute selectors beats a plain class selector.
|
|
470
|
+
*/
|
|
471
|
+
.dsh-rum-item[data-switched="true"] .dsh-rum-col,
|
|
472
|
+
.dsh-rum-item[data-switched="true"] .dsh-rum-index,
|
|
473
|
+
.dsh-rum-item[data-switched="true"] .dsh-rum-clock {
|
|
474
|
+
color: inherit;
|
|
475
|
+
}
|
|
476
|
+
.dsh-rum-item[data-lowcache="true"] .dsh-rum-col,
|
|
477
|
+
.dsh-rum-item[data-lowcache="true"] .dsh-rum-index,
|
|
478
|
+
.dsh-rum-item[data-lowcache="true"] .dsh-rum-clock {
|
|
479
|
+
color: inherit;
|
|
480
|
+
}
|
|
453
481
|
/*
|
|
454
482
|
* The index cells are flex boxes so a row number and the streaming dot share one alignment
|
|
455
483
|
* rule. With inline content, a 6px dot aligned on the text baseline sits visibly lower than
|
|
@@ -1084,6 +1112,16 @@ window.__ModuleLoader__.load({
|
|
|
1084
1112
|
provider: null,
|
|
1085
1113
|
context: numberOrNull(stats.context),
|
|
1086
1114
|
cacheRead: numberOrNull(stats.cacheRead),
|
|
1115
|
+
/*
|
|
1116
|
+
* Tool time, for the total column hint. `tool` sums each call from its dispatch to its
|
|
1117
|
+
* result, so three parallel 10 s tools report 30 s; `toolWall` unions the intervals, so
|
|
1118
|
+
* the same three report 10 s. Both are reported because the gap between them is exactly
|
|
1119
|
+
* how much the parallelism bought.
|
|
1120
|
+
*/
|
|
1121
|
+
toolMs: numberOrNull(stats.tool),
|
|
1122
|
+
toolWallMs: numberOrNull(stats.toolWall),
|
|
1123
|
+
/** How many calls the step made, from the fold's own call list. */
|
|
1124
|
+
toolCalls: Array.isArray(stats.calls) ? stats.calls.length : null,
|
|
1087
1125
|
cacheHit: numberOrNull(stats.cacheHit),
|
|
1088
1126
|
}
|
|
1089
1127
|
}
|
|
@@ -1824,6 +1862,42 @@ window.__ModuleLoader__.load({
|
|
|
1824
1862
|
return provider === null ? model : `${provider} / ${model}`
|
|
1825
1863
|
}
|
|
1826
1864
|
|
|
1865
|
+
/**
|
|
1866
|
+
* The total column's hint: how much of the request was tool time.
|
|
1867
|
+
*
|
|
1868
|
+
* Two figures, because they answer different questions. `tool` adds up each call, so it
|
|
1869
|
+
* says how much tool work there was; `toolWall` unions the intervals, so it says how much
|
|
1870
|
+
* wall time the tools occupied. Three parallel 10 s calls are 30 s of work in 10 s of
|
|
1871
|
+
* elapsed time, and the gap is what parallelism bought.
|
|
1872
|
+
*
|
|
1873
|
+
* Neither is part of the total above, which is model time only — the header says so.
|
|
1874
|
+
*/
|
|
1875
|
+
function toolHintText(row, t) {
|
|
1876
|
+
if (row.compaction === true) return t('toolHintCompaction')
|
|
1877
|
+
const calls = numberOrNull(row.toolCalls)
|
|
1878
|
+
const serial = numberOrNull(row.toolMs)
|
|
1879
|
+
if (serial === null && calls === null) return t('toolHintNone')
|
|
1880
|
+
if (serial === null) return t('toolHintNone')
|
|
1881
|
+
const wall = numberOrNull(row.toolWallMs)
|
|
1882
|
+
const count = calls === null ? 0 : calls
|
|
1883
|
+
if (wall === null || wall === serial) {
|
|
1884
|
+
return t('toolHintOne', { count, total: secondsValue(serial, t) })
|
|
1885
|
+
}
|
|
1886
|
+
return t('toolHintTwo', {
|
|
1887
|
+
count,
|
|
1888
|
+
total: secondsValue(serial, t),
|
|
1889
|
+
wall: secondsValue(wall, t),
|
|
1890
|
+
})
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
/** A duration as the hint spells it: seconds, one decimal, no unit label of its own. */
|
|
1894
|
+
function secondsValue(ms, t) {
|
|
1895
|
+
if (ms === null || ms === undefined || !Number.isFinite(ms)) return t('none')
|
|
1896
|
+
const seconds = ms / 1000
|
|
1897
|
+
const text = seconds < 100 ? seconds.toFixed(1) : String(Math.round(seconds))
|
|
1898
|
+
return `${text} s`
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1827
1901
|
/** The tokens column's hint: the input side, which the cell itself does not show. */
|
|
1828
1902
|
function tokensHintText(row, t) {
|
|
1829
1903
|
const none = t('none')
|
|
@@ -3787,7 +3861,13 @@ window.__ModuleLoader__.load({
|
|
|
3787
3861
|
h('span', { className: 'dsh-rum-col', role: 'cell' }, tokensText(live.tokens, live.estimated === true, t)),
|
|
3788
3862
|
h(
|
|
3789
3863
|
'span',
|
|
3790
|
-
{
|
|
3864
|
+
{
|
|
3865
|
+
className: 'dsh-rum-col',
|
|
3866
|
+
role: 'cell',
|
|
3867
|
+
/* Same hint as the numbered rows, so the meaning never changes. */
|
|
3868
|
+
onMouseEnter: (event) => hint.show(toolHintText(live, t), event),
|
|
3869
|
+
onMouseLeave: hint.hide,
|
|
3870
|
+
},
|
|
3791
3871
|
secondsText(
|
|
3792
3872
|
live.compaction !== null && live.compaction !== undefined
|
|
3793
3873
|
? compactionSpan(live.compaction, now)
|
|
@@ -3902,7 +3982,17 @@ window.__ModuleLoader__.load({
|
|
|
3902
3982
|
),
|
|
3903
3983
|
h(
|
|
3904
3984
|
'span',
|
|
3905
|
-
{
|
|
3985
|
+
{
|
|
3986
|
+
className: 'dsh-rum-col',
|
|
3987
|
+
role: 'cell',
|
|
3988
|
+
/*
|
|
3989
|
+
* The hint explains how much of the request was tool time. The figure
|
|
3990
|
+
* in the cell deliberately excludes it, which is exactly why the two
|
|
3991
|
+
* need to be shown together.
|
|
3992
|
+
*/
|
|
3993
|
+
onMouseEnter: (event) => hint.show(toolHintText(entry.row, t), event),
|
|
3994
|
+
onMouseLeave: hint.hide,
|
|
3995
|
+
},
|
|
3906
3996
|
secondsText(
|
|
3907
3997
|
/*
|
|
3908
3998
|
* A running compaction counts up from its own start, exactly as the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-recent-usage-metrics",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Geek level for the Performance & usage setting: a live reading of the newest request (first-token latency, speed, tokens, total, amortised) plus a drawer listing the last ten, all derived from the shipped Statistics view data",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|