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_by_providers.ui",
|
||||
f"/{MOD}/model_plaza.ui",
|
||||
f"/{MOD}/model_pricing.dspy",
|
||||
f"/{MOD}/model_pricing.ui",
|
||||
f"/{MOD}/failed_accounting.ui",
|
||||
f"/{MOD}/llmcatelog_list.ui",
|
||||
|
||||
@ -101,6 +103,7 @@ PATHS_LOGINED = [
|
||||
f"/{MOD}/api/get_search_apiname.dspy",
|
||||
f"/{MOD}/api/get_search_providerid.dspy",
|
||||
f"/{MOD}/api/get_search_upappid.dspy",
|
||||
f"/{MOD}/api/get_search_model.dspy",
|
||||
f"/{MOD}/api/get_upapps.dspy",
|
||||
f"/{MOD}/api/llm_launch_check_api.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