diff --git a/scripts/load_path.py b/scripts/load_path.py index 01a739a..5724276 100644 --- a/scripts/load_path.py +++ b/scripts/load_path.py @@ -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", diff --git a/wwwroot/api/get_search_model.dspy b/wwwroot/api/get_search_model.dspy new file mode 100644 index 0000000..c00b7cb --- /dev/null +++ b/wwwroot/api/get_search_model.dspy @@ -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 diff --git a/wwwroot/model_pricing.dspy b/wwwroot/model_pricing.dspy new file mode 100644 index 0000000..f8dfb5e --- /dev/null +++ b/wwwroot/model_pricing.dspy @@ -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) diff --git a/wwwroot/model_pricing.ui b/wwwroot/model_pricing.ui new file mode 100644 index 0000000..6b6a945 --- /dev/null +++ b/wwwroot/model_pricing.ui @@ -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