From bdffa5c81bbf13bc671ed56c6bffe90cdab85c2c Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 22 Jul 2026 18:01:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A8=A1=E5=9E=8B=E5=BB=B6=E8=BF=9F?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=94=A8COALESCE(ttft,ttot)=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E5=BC=82=E6=AD=A5=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sage_datamart/init.py | 24 +++++++++--------------- wwwroot/sect_model_perf.ui | 28 ++++++++-------------------- 2 files changed, 17 insertions(+), 35 deletions(-) diff --git a/sage_datamart/init.py b/sage_datamart/init.py index 2486b0d..b4f3152 100644 --- a/sage_datamart/init.py +++ b/sage_datamart/init.py @@ -55,26 +55,20 @@ async def _resolve_view(request): async def api_model_perf(sor, params_kw=None): try: - model = params_kw.get('model') if params_kw else None stat_date = params_kw.get('date') if params_kw else None - sql = """SELECT model, catelogid, providerid, - SUM(total_calls) as total_calls, - SUM(success_calls) as success_calls, - SUM(fail_calls) as fail_calls, - CASE WHEN SUM(total_calls)>0 THEN ROUND(SUM(success_calls)*100.0/SUM(total_calls),1) ELSE 0 END as success_rate, - CASE WHEN SUM(total_calls)>0 THEN ROUND(SUM(total_calls*avg_ttft_ms)/SUM(total_calls),1) ELSE NULL END as avg_ttft_ms, + sql = """SELECT COALESCE(l.name, f.model) as model, + CASE WHEN SUM(total_calls)>0 THEN ROUND(SUM(total_calls*COALESCE(avg_ttft_ms,avg_ttot_ms))/SUM(total_calls),1) ELSE NULL END as avg_latency_ms, CASE WHEN SUM(total_calls)>0 THEN ROUND(SUM(total_calls*avg_ttot_ms)/SUM(total_calls),1) ELSE NULL END as avg_ttot_ms, - COALESCE(SUM(total_amount_cny),0) as total_amount_cny - FROM dm_model_perf_daily WHERE 1=1""" + ROUND(SUM(success_calls)*100.0/GREATEST(SUM(total_calls),1),1) as success_rate + FROM dm_model_perf_daily f + LEFT JOIN llm l ON l.id = f.llmid + WHERE 1=1""" ns = {} if stat_date: - sql += " AND stat_date=${stat_date}$" + sql += " AND f.stat_date=${stat_date}$" ns['stat_date'] = stat_date - if model: - sql += " AND model=${model}$" - ns['model'] = model - sql += " GROUP BY model, catelogid, providerid" - sql += " ORDER BY total_calls DESC LIMIT 50" + sql += " GROUP BY f.model, f.catelogid, f.providerid" + sql += " ORDER BY avg_latency_ms ASC LIMIT 5" rows = await sor.sqlExe(sql, ns) return [dict(r) for r in rows] except Exception as e: diff --git a/wwwroot/sect_model_perf.ui b/wwwroot/sect_model_perf.ui index 5c257af..9316ffb 100644 --- a/wwwroot/sect_model_perf.ui +++ b/wwwroot/sect_model_perf.ui @@ -1,23 +1,11 @@ {% set data = j2_model_perf_data(request) %} +{% set names = [] %}{% set vals = [] %}{% for r in data %}{% set _ = names.append(r.get("model","")) %}{% set _ = vals.append(r.get("avg_latency_ms",0)|float) %}{% endfor %} +{% set script %}(function(){var c=echarts.init(document.getElementById('chart_model_perf'));c.setOption({tooltip:{trigger:'axis',formatter:function(p){return p[0].name+'
延迟: '+p[0].value+'ms'}},grid:{left:10,right:40,top:5,bottom:5,containLabel:true},xAxis:{type:'value',name:'ms',axisLabel:{fontSize:10}},yAxis:{type:'category',data:{{json.dumps(names,ensure_ascii=False)}},inverse:true,axisLabel:{fontSize:11}},series:[{type:'bar',data:{{json.dumps(vals,ensure_ascii=False)}},barMaxWidth:18,label:{show:true,position:'right',formatter:'{c}ms',fontSize:10},itemStyle:{borderRadius:[0,4,4,0]}}]});window.addEventListener('resize',function(){c.resize()});})();{% endset %} { - "widgettype": "VBox", - "options": {"width": "100%"}, - "subwidgets": [ - {"widgettype": "HBox","options":{"cheight":2,"width":"100%","bgcolor":"var(--sage-bg-secondary)","borderRadius":"4px 4px 0 0","padding":"4px 8px"},"subwidgets":[ - {"widgettype":"Text","options":{"text":"模型","width":"30%","fontSize":"11px","color":"var(--sage-text-secondary)"}}, - {"widgettype":"Text","options":{"text":"延迟","width":"15%","fontSize":"11px","color":"var(--sage-text-secondary)"}}, - {"widgettype":"Text","options":{"text":"成功率","width":"15%","fontSize":"11px","color":"var(--sage-text-secondary)"}}, - {"widgettype":"Text","options":{"text":"调用","width":"20%","fontSize":"11px","color":"var(--sage-text-secondary)"}}, - {"widgettype":"Text","options":{"text":"金额","width":"20%","fontSize":"11px","color":"var(--sage-text-secondary)"}} - ]} - {% for r in data %} - ,{"widgettype":"HBox","options":{"cheight":2,"width":"100%","padding":"2px 8px"},"subwidgets":[ - {"widgettype":"Text","options":{"text":{{json.dumps(r.get("model",""),ensure_ascii=False)}},"width":"30%","fontSize":"12px"}}, - {"widgettype":"Text","options":{"text":{{json.dumps(r.get("avg_ttft_ms",""),ensure_ascii=False)}},"width":"15%","fontSize":"12px"}}, - {"widgettype":"Text","options":{"text":{{json.dumps(r.get("success_rate",""),ensure_ascii=False)}},"width":"15%","fontSize":"12px"}}, - {"widgettype":"Text","options":{"text":{{json.dumps(r.get("total_calls",""),ensure_ascii=False)}},"width":"20%","fontSize":"12px"}}, - {"widgettype":"Text","options":{"text":{{json.dumps(r.get("total_amount_cny",""),ensure_ascii=False)}},"width":"20%","fontSize":"12px"}} - ]} - {% endfor %} - ] + "widgettype": "WebWidget", + "options": { + "height": "180px", + "html": "
", + "script": {{json.dumps(script, ensure_ascii=False)}} + } }