From b8131aec352d490620e30412402723035037f644 Mon Sep 17 00:00:00 2001 From: Pine Date: Tue, 25 Aug 2026 17:03:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(compute):=20compute=5Fcatalog=20=E9=80=8F?= =?UTF-8?q?=E4=BC=A0=E6=A8=A1=E5=9E=8B=E5=AF=8C=E5=AD=97=E6=AE=B5(?= =?UTF-8?q?=E6=A8=A1=E6=80=81/=E4=BD=9C=E8=80=85/=E4=BE=9B=E5=BA=94?= =?UTF-8?q?=E5=95=86/=E5=8C=BA=E9=97=B4=E4=BB=B7/=E7=AA=97=E5=8F=A3/?= =?UTF-8?q?=E8=BE=93=E5=87=BA/=E5=85=8D=E8=B4=B9=E8=AF=95=E7=94=A8)?= =?UTF-8?q?=E7=BB=99=20OPC=20=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/compute_catalog.py | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/app/services/compute_catalog.py b/app/services/compute_catalog.py index 92df571..3ffde34 100644 --- a/app/services/compute_catalog.py +++ b/app/services/compute_catalog.py @@ -5,9 +5,24 @@ """ from __future__ import annotations +import json + from . import compute_client +def _parse_list(v): + """JSON 数组字符串 → list;已 list 原样。""" + if isinstance(v, list): + return v + if isinstance(v, str): + try: + a = json.loads(v) + return a if isinstance(a, list) else [] + except Exception: # noqa: BLE001 + return [] + return [] + + def _map(row: dict) -> dict: """Model 行 → 桌面端模型形状。""" name = row.get("name") or row.get("model_name") or "" @@ -28,6 +43,30 @@ def _map(row: dict) -> dict: "video_support": bool(row.get("video_support", False)), "tags": (row.get("tags") or "").split(",") if row.get("tags") else [], "vendor_id": row.get("vendor_id", 0), + # 富字段(models.json 语义) + "icon": row.get("icon", ""), + "icon_file": row.get("icon_file", ""), + "modality": row.get("modality", ""), + "input_forms": _parse_list(row.get("input_forms")), + "output_forms": _parse_list(row.get("output_forms")), + "function_icons": _parse_list(row.get("function_icons")), + "url": row.get("url", ""), + "author": row.get("author", ""), + "author_icon": row.get("author_icon", ""), + "supplier": row.get("supplier", ""), + "supplier_icon": row.get("supplier_icon", ""), + "price_is_range": bool(row.get("price_is_range", False)), + "input_price_min": row.get("input_price_min", 0) or 0, + "input_price_max": row.get("input_price_max", 0) or 0, + "output_price_min": row.get("output_price_min", 0) or 0, + "output_price_max": row.get("output_price_max", 0) or 0, + "context_window": row.get("context_window", 0) or 0, + "context_window_unit": row.get("context_window_unit", "M"), + "context_window_display": row.get("context_window_display", ""), + "max_output": row.get("max_output", 0) or 0, + "max_output_unit": row.get("max_output_unit", "K"), + "max_output_display": row.get("max_output_display", ""), + "free_trial": bool(row.get("free_trial", False)), }