v2.2.0:data-chart-tool 双Y轴折线图(预填充左轴虚线/解码右轴实线)+画图CSV一键复制+下载PNG+默认上下文长度增加4096/16384/65536

This commit is contained in:
2026-08-31 00:17:26 +08:00
parent 577fbf69e3
commit 2d889c80e0
7 changed files with 216 additions and 15 deletions
+83
View File
@@ -3,6 +3,7 @@
import io
import json
import requests
from flask import Flask, jsonify, request, send_file, send_from_directory
import config
@@ -160,6 +161,88 @@ def del_test(tid):
return jsonify({"ok": True})
# ───────────────────────── 图表(data-chart-tool 折线图:预填充左轴虚线 / 解码右轴实线) ─────────────────────────
def _build_chart_csv(t):
"""由测试汇总 by_length 构建画图 CSV:上下文长度, 预填充速度(tok/s), 解码速度(tok/s)"""
s = t.get("summary") or {}
by = s.get("by_length") or {}
lens = sorted(int(k) for k in by)
rows = []
for L in lens:
bl = by.get(str(L)) if str(L) in by else by.get(L) or {}
pre = bl.get("avg_prefill_speed")
dec = bl.get("avg_decode_speed")
if pre is None or dec is None:
continue
rows.append([L, round(pre, 2), round(dec, 2)])
if not rows:
return None
csv_lines = ["上下文长度, 预填充速度(tok/s), 解码速度(tok/s)"]
for L, pre, dec in rows:
csv_lines.append("%d, %.2f, %.2f" % (L, pre, dec))
return {"csv": "\n".join(csv_lines), "rows": rows}
def _chart_payload(t, csv_text):
"""组装 data-chart-tool /api/chart 请求体(双Y轴折线图)"""
title = ("%s %s" % (t.get("model") or "", t.get("name") or "速度对比")).strip()
return {
"data": csv_text,
"chartType": "line",
"title": title,
"theme": "default",
"showLegend": True,
"showGrid": True,
"showLabel": False,
"smoothLine": True,
"dualYAxis": True,
"leftAxisName": "预填充速度(tok/s)",
"rightAxisName": "解码速度(tok/s)",
"seriesTypes": ["line", "line"],
"seriesAxis": [0, 1],
"seriesStyles": ["dashed", "solid"], # 预填充=左轴虚线,解码=右轴实线
"width": 1000,
"height": 560,
"pixelRatio": 2,
}
@app.route("/api/tests/<int:tid>/chart-data")
def test_chart_data(tid):
t = db.get_test(tid)
if not t:
return jsonify({"ok": False, "error": "测试不存在"}), 404
built = _build_chart_csv(t)
if not built:
return jsonify({"ok": False, "error": "无成功采样数据,无法画图"}), 400
return jsonify({
"ok": True,
"csv": built["csv"],
"rows": built["rows"],
"payload": _chart_payload(t, built["csv"]),
})
@app.route("/api/tests/<int:tid>/chart")
def test_chart(tid):
"""用 data-chart-tool 生成折线图 PNG(预填充左轴虚线 / 解码右轴实线)"""
t = db.get_test(tid)
if not t:
return jsonify({"ok": False, "error": "测试不存在"}), 404
built = _build_chart_csv(t)
if not built:
return jsonify({"ok": False, "error": "无成功采样数据,无法画图"}), 400
try:
resp = requests.post(config.CHART_API_BASE + "/api/chart",
json=_chart_payload(t, built["csv"]), timeout=60)
except requests.RequestException as e:
return jsonify({"ok": False, "error": "图表服务不可用: %s" % e}), 502
if resp.status_code != 200:
return jsonify({"ok": False, "error": "图表生成失败(%d): %s" % (resp.status_code, resp.text[:300])}), 502
return send_file(io.BytesIO(resp.content), mimetype="image/png")
@app.route("/api/tests/<int:tid>/export.json")
def export_json(tid):
t = db.get_test(tid)