"""系统可用模型的判定规则(与「对话可用模型」「生图可用模型」对称)。 ``/api/system/models`` 给出**账号池当前能调用的全部模型**:上游账号池模型 (含生图模型与 ``research`` / ``python`` 这类工具类伪模型)+ 第三方接入模型。 **默认全部启用。** 这里的开关只是**展示层过滤** —— 只决定这些模型是否出现在 管理页「系统可用模型」列表里,不改动上游账号池、第三方配置、计费、路由、 额度,也不影响对外 ``/v1/models``(后者必须保持全量,OpenAI 兼容)。 之所以给系统列表单独一份开关,而不是复用对话 / 生图两边的配置:管理员想把 不关心的模型从列表里收起来时,不应该被迫去改「对话可用模型」或 「生图可用模型」的名单——三份名单的用途完全不同。 """ from __future__ import annotations from typing import Any from services.chat_model_service import ( SOURCE_THIRD_PARTY, SOURCE_UPSTREAM, _clean, _clean_id_set, model_source, ) def resolve_system_models( items: list[Any], overrides: dict[str, Any] | None = None, ) -> list[dict[str, Any]]: """给每个模型标注 ``system_enabled`` / ``system_source``。 不清洗、不过滤任何模型:系统列表就是"能调用到的全部模型", 只是允许管理员把不关心的收起来(``system_enabled`` = False)。 """ source = overrides if isinstance(overrides, dict) else {} include = _clean_id_set(source.get("include")) exclude = _clean_id_set(source.get("exclude")) resolved: list[dict[str, Any]] = [] for item in items or []: if not isinstance(item, dict): continue model_id = _clean(item.get("id")) if not model_id: continue if model_id in include: enabled = True elif model_id in exclude: enabled = False else: enabled = True resolved.append({ **item, "system_enabled": enabled, "system_source": model_source(item), }) # 已启用的排前面;同组内上游模型优先,再按模型名排序。 resolved.sort(key=lambda entry: ( 0 if entry["system_enabled"] else 1, 0 if entry["system_source"] == SOURCE_UPSTREAM else 1, str(entry.get("id") or ""), )) return resolved __all__ = [ "resolve_system_models", "SOURCE_THIRD_PARTY", "SOURCE_UPSTREAM", ]