pipeline-llm/wwwroot/api/llm_dashboard_widget.dspy
yumoqing 660ad21365 feat(pipeline-llm): 模型治理模块v1.0.0 — 供应商/端点目录/账号钱包/模型注册/组织容错策略/限额限流/双维度记账
- 8张llm_前缀表(手写幂等DDL): vendor/account/model/api_profile/org_policy/org_quota/user_quota/usage
- gateway.py 门禁链: 限流→限额→策略选模型(主备容错)→账号×端点轮转(偏好过滤+余额加权+冷却避让)→预授权-结算
- api_key AES单层加密(非RC4,盐不对称不可解); 限流Redis分钟窗口(db4) fail-open
- 双维度记账: 一次调用同行记cost(账号侧)+charge(组织池侧); 充值=recharge行
- CRUD+index.ui 8卡片导航+总览; appcodes字典5组; 设计规范+30测试用例
- 策略即开关: 机构无策略→__LEGACY__走旧llm表(向后兼容零改动)
2026-09-01 17:27:17 +08:00

49 lines
2.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# llm_dashboard_widget.dspy — 模型治理总览(顶部统计条,返回 Bricks widget
dbname = get_module_dbname('pipeline_llm')
data = {"vendors": 0, "accounts": 0, "account_balance": 0, "models": 0,
"org_policies": 0, "usage_calls": 0, "usage_charge": 0}
try:
async with get_sor_context(request._run_ns, dbname) as sor:
vendors = await sor.sqlExe("SELECT COUNT(*) AS c FROM llm_vendor WHERE status='active'", {})
accounts = await sor.sqlExe(
"SELECT COUNT(*) AS c, COALESCE(SUM(balance),0) AS b FROM llm_account WHERE status='active'", {})
models = await sor.sqlExe("SELECT COUNT(*) AS c FROM llm_model WHERE status='active'", {})
orgs = await sor.sqlExe("SELECT COUNT(*) AS c FROM llm_org_policy WHERE status='active'", {})
usage = await sor.sqlExe(
"SELECT COUNT(*) AS c, COALESCE(SUM(charge),0) AS ch FROM llm_usage WHERE status='ok'", {})
await sor.sqlExe("COMMIT", {})
data['vendors'] = int(getattr(vendors[0], 'c', 0)) if vendors else 0
data['accounts'] = int(getattr(accounts[0], 'c', 0)) if accounts else 0
data['account_balance'] = round(float(getattr(accounts[0], 'b', 0)), 4) if accounts else 0
data['models'] = int(getattr(models[0], 'c', 0)) if models else 0
data['org_policies'] = int(getattr(orgs[0], 'c', 0)) if orgs else 0
data['usage_calls'] = int(getattr(usage[0], 'c', 0)) if usage else 0
data['usage_charge'] = round(float(getattr(usage[0], 'ch', 0)), 4) if usage else 0
except Exception:
pass
stats = [
('供应商', str(data['vendors'])),
('账号', str(data['accounts'])),
('账号总余额', str(data['account_balance'])),
('模型', str(data['models'])),
('组织策略', str(data['org_policies'])),
('调用次数', str(data['usage_calls'])),
('累计消费', str(data['usage_charge'])),
]
boxes = []
for label, val in stats:
boxes.append({
"widgettype": "VBox",
"options": {"css": "card", "padding": "12px 20px", "minWidth": "110px"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": val, "cfontsize": 1.6, "color": "#1e293b", "halign": "middle"}},
{"widgettype": "Text", "options": {"text": label, "cfontsize": 0.9, "color": "#64748b", "halign": "middle"}},
]
})
return {
"widgettype": "HBox",
"options": {"gap": "12px", "padding": "0 0 16px 0", "wrap": "wrap"},
"subwidgets": boxes
}