mslxdff 0.1.148 → 0.1.149

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.148",
3
+ "version": "0.1.149",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,20 +34,39 @@ function fmtTps(v) {
34
34
  return v == null || !Number.isFinite(v) ? "—" : `${v} tok/s`;
35
35
  }
36
36
 
37
- // 中文字符按 2 列宽算,否则表格错位
38
- function width(s) {
37
+ // 中文字符按 2 列宽算,否则表格错位。
38
+ function width(value) {
39
39
  let w = 0;
40
- for (const ch of String(s)) w += /[\u1100-\u115F\u2E80-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFF60\uFFE0-\uFFE6]/.test(ch) ? 2 : 1;
40
+ for (const ch of String(value ?? "")) w += /[\u1100-\u115F\u2E80-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFF60\uFFE0-\uFFE6]/.test(ch) ? 2 : 1;
41
41
  return w;
42
42
  }
43
43
 
44
- function padW(s, w) {
45
- const t = String(s);
46
- return t + " ".repeat(Math.max(0, w - width(t)));
44
+ function padCell(value, w, align = "left") {
45
+ const text = String(value ?? "");
46
+ const padding = " ".repeat(Math.max(0, w - width(text)));
47
+ return align === "right" ? padding + text : text + padding;
47
48
  }
48
49
 
49
- function rowText(id, r) {
50
- return ` ${padW(id, 30)} ${padW(r.requests, 6)} ${padW(fmtTok(r.promptTokens), 8)} ${padW(fmtTok(r.completionTokens), 10)} ${padW(fmtTok(r.totalTokens), 8)} ${padW(fmtMs(r.avgTtfbMs), 7)} ${padW(fmtMs(r.avgTotalMs), 8)} ${fmtTps(r.avgTps)}`;
50
+ function renderTable(headers, rows, aligns = []) {
51
+ const matrix = [headers, ...rows];
52
+ const widths = headers.map((_, col) => Math.max(...matrix.map((row) => width(row[col]))));
53
+ const rule = (left, middle, right) => left + widths.map((w) => "─".repeat(w + 2)).join(middle) + right;
54
+ const line = (row) => `│${row.map((cell, col) => ` ${padCell(cell, widths[col], aligns[col])} `).join("│")}│`;
55
+ return [
56
+ rule("┌", "┬", "┐"),
57
+ line(headers),
58
+ rule("├", "┼", "┤"),
59
+ ...rows.map(line),
60
+ rule("└", "┴", "┘"),
61
+ ].join("\n");
62
+ }
63
+
64
+ function tokenRow(id, r) {
65
+ return [id, r.requests, fmtTok(r.promptTokens), fmtTok(r.completionTokens), fmtTok(r.reasoningTokens), fmtTok(r.totalTokens)];
66
+ }
67
+
68
+ function performanceRow(id, r) {
69
+ return [id, fmtMs(r.avgTtfbMs), fmtMs(r.avgTotalMs), fmtTps(r.avgTps)];
51
70
  }
52
71
 
53
72
  export function renderStats(report, { hours = 24, model = null } = {}) {
@@ -59,15 +78,30 @@ export function renderStats(report, { hours = 24, model = null } = {}) {
59
78
  lines.push("说明:-chat 直连 mimo/big-pickle 不经网关,不计入本表");
60
79
  return lines.join("\n");
61
80
  }
62
- lines.push(`模型用量(近 ${hours}h · 成功请求 ${totals.requests} 次 · ${models.length} 个模型)`);
63
- lines.push(` ${padW("模型", 30)} ${padW("请求", 6)} ${padW("prompt", 8)} ${padW("输出", 10)} ${padW("合计", 8)} ${padW("首字", 7)} ${padW("总耗时", 8)} 速度`);
64
- for (const m of models) lines.push(rowText(m.id, m));
65
- lines.push(` ${"-".repeat(76)}`);
66
- lines.push(rowText("合计", totals));
67
- if (totals.reasoningTokens > 0) lines.push(` 其中思考 tokens:${fmtTok(totals.reasoningTokens)}`);
81
+
82
+ const right = "right";
83
+ const tokenRows = [...models.map((m) => tokenRow(m.id, m)), tokenRow("合计", totals)];
84
+ const performanceRows = [...models.map((m) => performanceRow(m.id, m)), performanceRow("合计", totals)];
85
+ lines.push(`模型用量报告(近 ${hours}h${model ? ` · 筛选 ${model}` : ""})`);
86
+ lines.push(`成功请求:${totals.requests} 次 · 模型:${models.length} 个`);
87
+ lines.push("");
88
+ lines.push("Token 用量");
89
+ lines.push(renderTable(["模型", "请求", "输入", "输出", "思考", "合计"], tokenRows, ["left", right, right, right, right, right]));
90
+ lines.push("");
91
+ lines.push("响应性能");
92
+ lines.push(renderTable(["模型", "首字", "总耗时", "速度"], performanceRows, ["left", right, right, right]));
68
93
  lines.push("");
69
94
  lines.push("说明:速度 = 输出 tokens ÷ 生成耗时(总耗时−首字),按窗口加权;只统计成功请求。");
70
- lines.push(` -chat 直连 mimo/big-pickle 不经 8989 网关,不计入。数据保留 ${usageKeepDays()} 天,mslxdff -stats --hours 1|--json|--model <id> 可调。`);
95
+ lines.push("范围:只含经 8989 网关的成功请求;不含失败请求和 -chat 直连。");
96
+ const keepDays = usageKeepDays();
97
+ if (hours > keepDays * 24) {
98
+ lines.push(`警告:查询 ${hours}h 超过数据保留 ${keepDays} 天,历史可能不完整。`);
99
+ } else {
100
+ lines.push(`数据保留 ${keepDays} 天;更早的历史已删除。`);
101
+ }
102
+ lines.push("明细口径:本表按模型聚合,不展开 via、interrupted 和单次 tps。");
103
+ lines.push("数值使用 k/M 缩写;需要精确值或机器处理请加 --json。");
104
+ lines.push("可调:mslxdff -stats --hours 1 | --model <id> | --json");
71
105
  return lines.join("\n");
72
106
  }
73
107
 
@@ -85,4 +119,4 @@ export async function handleStats(args) {
85
119
  }
86
120
  console.log(renderStats(report, { hours, model }));
87
121
  return true;
88
- }
122
+ }