v1.2.0 对比车+运行速度对比图+图表可配置:移除前台后台管理链接(网址直达登录);新增🛒对比车(排行榜行加入,浮动条隐藏默认,对比页按加入顺序对比,无车默认前5,默认只对比预填充+解码);首页解码速度对比图改运行速度对比(预填充左轴空心柱+解码右轴实心柱+首字虚线);对比图支持柱状(空心/实心)/折线(实线/虚线)+左右双轴+三色深度+X轴旋转/间隔/字号防拥挤

This commit is contained in:
2026-09-02 13:59:57 +08:00
parent c6eef5e67f
commit 1021a037cf
7 changed files with 275 additions and 91 deletions
+19 -44
View File
@@ -135,34 +135,29 @@ def leaderboard():
keys.add(("", item))
rows = [r for r in rows if (r["provider"], r["model"]) in keys]
# 按排行榜生成柱状图 CSV(解码速度 TOP,默认全部模型,可指定)
chart_rows = rows[: int(request.args.get("chart_top", 20) or 20)]
csv_lines = ["模型, 解码速度(tok/s), 预填充速度(tok/s), 首字延迟(ms)"]
chart_rows = rows[: int(request.args.get("chart_top", 30) or 30)]
chart_csv = _speed_csv(chart_rows)
return jsonify({"ok": True, "rows": rows, "chart_csv": chart_csv})
def _speed_csv(chart_rows):
"""模型 运行速度 CSV:预填充 / 解码 / 首字 三列(前端据此配置柱/折线/双轴/颜色)"""
csv_lines = ["模型, 预填充速度(tok/s), 解码速度(tok/s), 首字延迟(ms)"]
for r in chart_rows:
label = "%s %s" % (r["provider"], r["model"])
csv_lines.append("%s, %s, %s, %s" % (
label.replace(",", " "), _fmt(r["avg_decode_speed"]),
_fmt(r["avg_prefill_speed"]), _fmt(r["avg_ttft_ms"])))
chart_csv = "\n".join(csv_lines)
bar_payload = {
"data": chart_csv, "chartType": "bar",
"title": "模型解码速度对比(%d 个模型)" % len(chart_rows),
"theme": "default", "showLegend": True, "showGrid": True, "showLabel": True,
"seriesTypes": ["bar", "bar", "line"],
"seriesAxis": [0, 0, 1],
"seriesStyles": ["solid", "hollow", "dashed"],
"width": 1100, "height": 560, "pixelRatio": 2,
}
return jsonify({"ok": True, "rows": rows, "chart_csv": chart_csv,
"bar_payload": bar_payload})
label.replace(",", " "), _fmt(r["avg_prefill_speed"]),
_fmt(r["avg_decode_speed"]), _fmt(r["avg_ttft_ms"])))
return "\n".join(csv_lines)
# ───────────────────────── 模型对比(硬件 + 可去留对比项) ─────────────────────────
@app.route("/api/compare")
def compare():
"""返回指定模型(默认全部)的聚合对比行 + 图表数据
models: 逗号分隔 provider|modelchart_metric: 解码/预填充/首字;chart_type: bar/line
"""返回指定模型(默认全部)的聚合对比行 + 运行速度 CSV
models: 逗号分隔 provider|model(保持传入顺序=对比车添加顺序);
不传时默认全部(按解码速度排序,前端默认取前5)。
"""
sel = request.args.get("models", "").strip()
keys = []
@@ -176,35 +171,15 @@ def compare():
keys.append((p.strip(), m.strip()))
else:
keys.append(("", item))
rows = db.compare_models(keys) # 保持传入顺序(对比车顺序)
else:
lb = db.leaderboard(limit=500)
keys = [(r["provider"], r["model"]) for r in lb]
rows = db.compare_models(keys)
# 有硬件优先展示
rows.sort(key=lambda r: (r.get("avg_decode_speed") or 0), reverse=True)
rows = db.compare_models(keys)
rows.sort(key=lambda r: (r.get("avg_decode_speed") or 0), reverse=True)
# 图表数据(按所选指标)
metric = request.args.get("chart_metric", "avg_decode_speed")
ctype = request.args.get("chart_type", "bar")
metric_name = {"avg_decode_speed": "解码速度", "avg_prefill_speed": "预填充速度",
"avg_ttft_ms": "首字延迟", "best_decode": "最佳解码"}.get(metric, "解码速度")
unit = "tok/s" if metric in ("avg_decode_speed", "avg_prefill_speed", "best_decode") else "ms"
chart_rows = rows[: int(request.args.get("chart_top", 50) or 50)]
csv_lines = ["模型, %s(%s)" % (metric_name, unit)]
for r in chart_rows:
label = "%s %s" % (r["provider"], r["model"])
csv_lines.append("%s, %s" % (label.replace(",", " "), _fmt(r.get(metric))))
chart_csv = "\n".join(csv_lines)
chart_payload = {
"data": chart_csv, "chartType": "bar" if ctype != "line" else "line",
"title": "模型%s对比(%d 个模型)" % (metric_name, len(chart_rows)),
"theme": "default", "showLegend": False, "showGrid": True, "showLabel": True,
"smoothLine": True,
"seriesTypes": ["bar"] if ctype != "line" else ["line"],
"width": 1100, "height": 520, "pixelRatio": 2,
}
return jsonify({"ok": True, "rows": rows, "chart_csv": chart_csv,
"chart_payload": chart_payload, "metric": metric})
chart_csv = _speed_csv(rows[: int(request.args.get("chart_top", 60) or 60)])
return jsonify({"ok": True, "rows": rows, "chart_csv": chart_csv})
@app.route("/api/model")