v2.2.0:data-chart-tool 双Y轴折线图(预填充左轴虚线/解码右轴实线)+画图CSV一键复制+下载PNG+默认上下文长度增加4096/16384/65536
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user