feat(llmage): model pricing query page — select model, display pricing table
This commit is contained in:
parent
6ab53eca2b
commit
233b5db481
@ -69,6 +69,8 @@ PATHS_LOGINED = [
|
|||||||
f"/{MOD}/show_llms.ui",
|
f"/{MOD}/show_llms.ui",
|
||||||
f"/{MOD}/show_llms_by_providers.ui",
|
f"/{MOD}/show_llms_by_providers.ui",
|
||||||
f"/{MOD}/model_plaza.ui",
|
f"/{MOD}/model_plaza.ui",
|
||||||
|
f"/{MOD}/model_pricing.dspy",
|
||||||
|
f"/{MOD}/model_pricing.ui",
|
||||||
f"/{MOD}/failed_accounting.ui",
|
f"/{MOD}/failed_accounting.ui",
|
||||||
f"/{MOD}/llmcatelog_list.ui",
|
f"/{MOD}/llmcatelog_list.ui",
|
||||||
|
|
||||||
@ -101,6 +103,7 @@ PATHS_LOGINED = [
|
|||||||
f"/{MOD}/api/get_search_apiname.dspy",
|
f"/{MOD}/api/get_search_apiname.dspy",
|
||||||
f"/{MOD}/api/get_search_providerid.dspy",
|
f"/{MOD}/api/get_search_providerid.dspy",
|
||||||
f"/{MOD}/api/get_search_upappid.dspy",
|
f"/{MOD}/api/get_search_upappid.dspy",
|
||||||
|
f"/{MOD}/api/get_search_model.dspy",
|
||||||
f"/{MOD}/api/get_upapps.dspy",
|
f"/{MOD}/api/get_upapps.dspy",
|
||||||
f"/{MOD}/api/llm_launch_check_api.dspy",
|
f"/{MOD}/api/llm_launch_check_api.dspy",
|
||||||
f"/{MOD}/api/llm_api_map_create.dspy",
|
f"/{MOD}/api/llm_api_map_create.dspy",
|
||||||
|
|||||||
7
wwwroot/api/get_search_model.dspy
Normal file
7
wwwroot/api/get_search_model.dspy
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
||||||
|
recs = await sor.sqlExe(
|
||||||
|
"SELECT id, name FROM llm ORDER BY name", {})
|
||||||
|
result = [{'value': '', 'text': '全部'}]
|
||||||
|
for r in recs:
|
||||||
|
result.append({'value': r.id, 'text': r.name})
|
||||||
|
return result
|
||||||
17
wwwroot/model_pricing.dspy
Normal file
17
wwwroot/model_pricing.dspy
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
llmid = params_kw.get('llmid', '')
|
||||||
|
if not llmid:
|
||||||
|
return json.dumps({'status': 'error', 'data': {'message': '请选择模型'}}, ensure_ascii=False)
|
||||||
|
|
||||||
|
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
||||||
|
maps = await sor.sqlExe(
|
||||||
|
"select ppid from llm_api_map where llmid=${llmid}$", {'llmid': llmid})
|
||||||
|
ppids = [m.ppid for m in maps if m.ppid] if maps else []
|
||||||
|
|
||||||
|
if not ppids:
|
||||||
|
return json.dumps({'status': 'error', 'data': {'message': '该模型未配置定价'}}, ensure_ascii=False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = await get_pricing_display(ppids[0])
|
||||||
|
return json.dumps({'status': 'ok', 'data': data}, ensure_ascii=False, default=str)
|
||||||
|
except Exception as e:
|
||||||
|
return json.dumps({'status': 'error', 'data': {'message': str(e)}}, ensure_ascii=False)
|
||||||
52
wwwroot/model_pricing.ui
Normal file
52
wwwroot/model_pricing.ui
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"id": "model_pricing_page",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%",
|
||||||
|
"padding": "20px",
|
||||||
|
"gap": "16px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Title3",
|
||||||
|
"options": {
|
||||||
|
"text": "模型定价查询"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "InlineForm",
|
||||||
|
"id": "pricing_form",
|
||||||
|
"options": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "llmid",
|
||||||
|
"label": "选择模型",
|
||||||
|
"uitype": "code",
|
||||||
|
"required": true,
|
||||||
|
"dataurl": "{{entire_url('/llmage/api/get_search_model.dspy')}}",
|
||||||
|
"valueField": "value",
|
||||||
|
"textField": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"submit_label": "查询"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "submit",
|
||||||
|
"actiontype": "script",
|
||||||
|
"script": "var v=this.values||{};if(!v.llmid)return;var url='{{entire_url('/llmage/model_pricing.dspy')}}?llmid='+encodeURIComponent(v.llmid);fetch(url,{credentials:'include'}).then(function(r){return r.json()}).then(function(d){var box=bricks.getWidgetById('pricing_result');if(!box)return;if(d.status!=='ok'){box.clear();box.add({widgettype:'Text',options:{text:d.data.message,color:'#ef4444',fontSize:'14px'}});return;}var items=d.data.items||[];var rows=[];for(var i=0;i<items.length;i++){var it=items[i];var fl=it.filter_labels||{};var label=[];for(var k in fl)label.push(fl[k]);var pfs=it.price_factors||[];for(var j=0;j<pfs.length;j++){var pf=pfs[j];rows.push({model:label.join(' '),factor:pf.label||pf.factor,unit:pf.unit_label||(pf.unit_price+'/'+pf.unit),price:pf.unit_price});}}var tbl=bricks.getWidgetById('pricing_table');if(tbl){tbl.setData({total:rows.length,rows:rows})}else{box.clear();box.add({widgettype:'Tabular',id:'pricing_table',options:{width:'100%',editable:false,row_options:{fields:[{name:'model',title:'模型/规格',cwidth:20},{name:'factor',title:'计费因子',cwidth:14},{name:'unit',title:'单价',cwidth:18},{name:'price',title:'价格',cwidth:10,type:'float'}]}},data:{total:rows.length,rows:rows}});}}).catch(function(e){var box=bricks.getWidgetById('pricing_result');if(box){box.clear();box.add({widgettype:'Text',options:{text:'查询失败: '+e.toString(),color:'#ef4444'}})}})"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"id": "pricing_result",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"flex": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user