diff --git a/scripts/load_path.py b/scripts/load_path.py index ea625b6..a9a7f66 100644 --- a/scripts/load_path.py +++ b/scripts/load_path.py @@ -57,7 +57,14 @@ PATHS_LOGINED = [ f"/{MOD}/api_doc.md", f"/{MOD}/llm_dialog.ui", f"/{MOD}/llm_launch_check.ui", - f"/{MOD}/llm_launch_check_page.dspy", + f"/{MOD}/check_model_record.dspy", + f"/{MOD}/check_date_status.dspy", + f"/{MOD}/check_upapp.dspy", + f"/{MOD}/check_uapi.dspy", + f"/{MOD}/check_uapiio.dspy", + f"/{MOD}/check_llm_api_map.dspy", + f"/{MOD}/check_pricing_program.dspy", + f"/{MOD}/check_pricing_data.dspy", f"/{MOD}/show_same_catelog_llm.ui", f"/{MOD}/show_llms.ui", f"/{MOD}/show_llms_by_providers.ui", diff --git a/wwwroot/check_date_status.dspy b/wwwroot/check_date_status.dspy new file mode 100644 index 0000000..0215732 --- /dev/null +++ b/wwwroot/check_date_status.dspy @@ -0,0 +1,31 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 日期与状态: 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + recs = await sor.sqlExe( + "select * from llm where id=${llmid}$", {'llmid': llmid}) + +if not recs: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 日期与状态: 模型不存在", "i18n": false} + }, ensure_ascii=False) + +llm = recs[0] +date_ok = bool(llm.enabled_date and llm.expired_date) +status_ok = llm.status == 'published' + +if date_ok and status_ok: + text = f"✅ 日期与状态: 启用:{llm.enabled_date} 失效:{llm.expired_date} 状态:{llm.status}" +else: + text = f"❌ 日期与状态: 启用:{llm.enabled_date} 失效:{llm.expired_date} 状态:{llm.status}" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_llm_api_map.dspy b/wwwroot/check_llm_api_map.dspy new file mode 100644 index 0000000..fa7c6c9 --- /dev/null +++ b/wwwroot/check_llm_api_map.dspy @@ -0,0 +1,22 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 能力映射(llm_api_map): 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + maps = await sor.sqlExe( + "select * from llm_api_map where llmid=${llmid}$", {'llmid': llmid}) + +if maps: + ppids = [m.ppid for m in maps if m.ppid] + text = f"✅ 能力映射(llm_api_map): {len(maps)}条记录, {len(ppids)}个有定价" +else: + text = "❌ 能力映射(llm_api_map): 无映射记录" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_model_record.dspy b/wwwroot/check_model_record.dspy new file mode 100644 index 0000000..984d5c9 --- /dev/null +++ b/wwwroot/check_model_record.dspy @@ -0,0 +1,22 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 模型记录: 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + recs = await sor.sqlExe( + "select * from llm where id=${llmid}$", {'llmid': llmid}) + +if recs: + llm = recs[0] + text = f"✅ 模型记录: {llm.name} ({llm.model})" +else: + text = f"❌ 模型记录: llm id={llmid} 不存在" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_pricing_data.dspy b/wwwroot/check_pricing_data.dspy new file mode 100644 index 0000000..93d5e7c --- /dev/null +++ b/wwwroot/check_pricing_data.dspy @@ -0,0 +1,36 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 定价数据(pricingdata): 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + maps = await sor.sqlExe( + "select * 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: + text = "❌ 定价数据(pricingdata): 无定价项目" +else: + ppid = ppids[0] + async with get_sor_context(request._run_ns, 'pricing') as psor: + # First check if pricing_program exists + pregs = await psor.sqlExe( + "select * from pricing_program where id=${ppid}$", {'ppid': ppid}) + if not pregs: + text = "❌ 定价数据(pricingdata): 依赖定价项目未通过" + else: + datas = await psor.sqlExe( + "select count(*) as cnt from pricingdata where ppid=${ppid}$", {'ppid': ppid}) + cnt = datas[0].cnt if datas else 0 + if cnt > 0: + text = f"✅ 定价数据(pricingdata): {cnt}条记录" + else: + text = "❌ 定价数据(pricingdata): 无定价数据" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_pricing_program.dspy b/wwwroot/check_pricing_program.dspy new file mode 100644 index 0000000..aab1c5f --- /dev/null +++ b/wwwroot/check_pricing_program.dspy @@ -0,0 +1,29 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 定价项目(pricing_program): 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + maps = await sor.sqlExe( + "select * 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: + text = "❌ 定价项目(pricing_program): llm_api_map中无ppid" +else: + ppid = ppids[0] + async with get_sor_context(request._run_ns, 'pricing') as psor: + pregs = await psor.sqlExe( + "select * from pricing_program where id=${ppid}$", {'ppid': ppid}) + if pregs: + text = f"✅ 定价项目(pricing_program): {pregs[0].name} (id={ppid})" + else: + text = f"❌ 定价项目(pricing_program): ppid={ppid} 未找到" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_uapi.dspy b/wwwroot/check_uapi.dspy new file mode 100644 index 0000000..43b0511 --- /dev/null +++ b/wwwroot/check_uapi.dspy @@ -0,0 +1,30 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ API映射(uapi): 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + recs = await sor.sqlExe(""" + select a.*, e.ioid, e.stream + from llm a + join llm_api_map m on a.id = m.llmid + join upapp c on a.upappid = c.id + join uapi e on c.id = e.upappid and m.apiname = e.name + where a.id=${llmid}$""", {'llmid': llmid}) + +if recs: + text = f"✅ API映射(uapi): ioid={recs[0].ioid}, stream={recs[0].stream}" +else: + # Get apiname from llm + async with get_sor_context(request._run_ns, 'llmage') as sor: + llm_recs = await sor.sqlExe("select apiname from llm where id=${llmid}$", {'llmid': llmid}) + apiname = llm_recs[0].apiname if llm_recs else 'N/A' + text = f"❌ API映射(uapi): apiname={apiname} 在upapp中未找到" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_uapiio.dspy b/wwwroot/check_uapiio.dspy new file mode 100644 index 0000000..8d89f40 --- /dev/null +++ b/wwwroot/check_uapiio.dspy @@ -0,0 +1,33 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ IO定义(uapiio): 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + # First get ioid from uapi + recs = await sor.sqlExe(""" + select e.ioid + from llm a + join llm_api_map m on a.id = m.llmid + join upapp c on a.upappid = c.id + join uapi e on c.id = e.upappid and m.apiname = e.name + where a.id=${llmid}$""", {'llmid': llmid}) + + if not recs: + text = "❌ IO定义(uapiio): 依赖 uapi 未通过" + else: + ioid = recs[0].ioid + recs2 = await sor.sqlExe( + "select * from uapiio where id=${ioid}$", {'ioid': ioid}) + if recs2: + text = f"✅ IO定义(uapiio): uapiio id={ioid}" + else: + text = f"❌ IO定义(uapiio): ioid={ioid} 未找到" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/check_upapp.dspy b/wwwroot/check_upapp.dspy new file mode 100644 index 0000000..16a4680 --- /dev/null +++ b/wwwroot/check_upapp.dspy @@ -0,0 +1,27 @@ +llmid = params_kw.get('llmid', '') + +if not llmid: + return json.dumps({ + "widgettype": "Text", + "options": {"text": "❌ 上位系统(upapp): 缺少llmid参数", "i18n": false} + }, ensure_ascii=False) + +async with get_sor_context(request._run_ns, 'llmage') as sor: + recs = await sor.sqlExe( + "select a.* from llm a, upapp b where a.id=${llmid}$ and a.upappid=b.id", + {'llmid': llmid}) + + if recs: + llm = recs[0] + text = f"✅ 上位系统(upapp): upappid={llm.upappid}" + else: + # Get llm info to show upappid + llm_recs = await sor.sqlExe( + "select upappid from llm where id=${llmid}$", {'llmid': llmid}) + upappid = llm_recs[0].upappid if llm_recs else '未知' + text = f"❌ 上位系统(upapp): upappid={upappid} 未找到关联" + +return json.dumps({ + "widgettype": "Text", + "options": {"text": text, "i18n": false} +}, ensure_ascii=False) diff --git a/wwwroot/llm_launch_check.ui b/wwwroot/llm_launch_check.ui index 7ded590..ecd2116 100644 --- a/wwwroot/llm_launch_check.ui +++ b/wwwroot/llm_launch_check.ui @@ -28,15 +28,64 @@ "options": { "name": "checks_list", "spacing": 5 - } + }, + "subwidgets": [ + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_model_record.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_date_status.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_upapp.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_uapi.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_uapiio.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_llm_api_map.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_pricing_program.dspy')}}?llmid={{llmid}}" + } + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./check_pricing_data.dspy')}}?llmid={{llmid}}" + } + } + ] }, { "widgettype": "Button", "options": { "name": "test_btn", - "text": "体验一次", - "i18n": false, - "disabled": true + "label": "体验一次", + "i18n": false } }, { @@ -50,16 +99,15 @@ { "widgettype": "Button", "options": { - "name": "check_charging_btn", - "text": "检查计费", - "i18n": false, - "disabled": true + "name": "charge_btn", + "label": "检查计费", + "i18n": false } }, { "widgettype": "Text", "options": { - "name": "charging_result", + "name": "charge_result", "text": "", "i18n": false } @@ -67,11 +115,22 @@ ], "binds": [ { - "wid": "self", - "event": "load", - "actiontype": "script", - "target": "self", - "script": "var resp = await fetch('{{entire_url('./api/llm_launch_check_api.dspy')}}?llmid={{llmid}}&action=check'); var data = await resp.json(); var statusEl = this.getWidgetByName('check_status'); var listEl = this.getWidgetByName('checks_list'); if(data.error) { statusEl.set_text('错误: ' + data.error); return; } var html = ''; var allOk = true; (data.checks||[]).forEach(function(c){ var icon = c.passed ? '✅' : '❌'; if(!c.passed) allOk = false; html += '