Files

287 lines
6.7 KiB
Python

"""模型服务商预设目录。
预设只保存公开的协议与端点,不保存用户凭据。需要云 IAM、部署名称或
业务空间域名的服务商仍展示在目录中,但不会误导用户只靠 API Key 即可连接。
"""
from dataclasses import dataclass
@dataclass(frozen=True)
class ModelProvider:
"""描述一个可展示、可验证的模型服务商预设。"""
code: str
name: str
vendor: str
category: str
protocol: str
base_url: str = ""
models_path: str = "models"
default_model: str = ""
key_only: bool = True
note: str = ""
mark: str = "AI"
@property
def protocol_label(self) -> str:
labels = {
"openai_responses": "Responses API",
"openai_compatible": "OpenAI 兼容",
"anthropic_messages": "Messages API",
"gemini": "Gemini API",
"cloud": "云平台接口",
}
return labels.get(self.protocol, self.protocol)
PROVIDERS = (
ModelProvider(
"openai",
"OpenAI",
"OpenAI",
"official",
"openai_responses",
"https://api.openai.com/v1",
default_model="gpt-5.6-terra",
mark="OA",
),
ModelProvider(
"anthropic",
"Anthropic Claude",
"Anthropic",
"official",
"anthropic_messages",
"https://api.anthropic.com/v1",
default_model="claude-sonnet-4-6",
mark="CL",
),
ModelProvider(
"deepseek",
"DeepSeek",
"深度求索",
"domestic",
"openai_compatible",
"https://api.deepseek.com",
default_model="deepseek-chat",
mark="DS",
),
ModelProvider(
"gemini",
"Google Gemini",
"Google",
"official",
"gemini",
"https://generativelanguage.googleapis.com/v1beta",
models_path="models",
default_model="gemini-2.5-flash",
mark="GE",
),
ModelProvider(
"aliyun",
"阿里云百炼 / Qwen",
"阿里云",
"domestic",
"openai_compatible",
"https://dashscope.aliyuncs.com/compatible-mode/v1",
default_model="qwen-plus",
mark="QW",
),
ModelProvider(
"zhipu",
"智谱 AI / Z.AI",
"智谱",
"domestic",
"openai_compatible",
"https://open.bigmodel.cn/api/paas/v4",
default_model="glm-4.5",
mark="GL",
),
ModelProvider(
"xiaomi_mimo",
"小米 MiMo",
"小米",
"domestic",
"openai_compatible",
key_only=False,
note="官方端点及账户区域确认后开放",
mark="MI",
),
ModelProvider(
"siliconflow",
"硅基流动",
"SiliconFlow",
"domestic",
"openai_compatible",
"https://api.siliconflow.cn/v1",
default_model="deepseek-ai/DeepSeek-V3",
mark="SF",
),
ModelProvider(
"moonshot",
"月之暗面 Kimi",
"Moonshot AI",
"domestic",
"openai_compatible",
"https://api.moonshot.cn/v1",
default_model="moonshot-v1-8k",
mark="KM",
),
ModelProvider(
"minimax",
"MiniMax",
"MiniMax",
"domestic",
"openai_compatible",
key_only=False,
note="部分账户还需要 Group ID",
mark="MM",
),
ModelProvider(
"volcengine",
"火山引擎方舟 / 豆包",
"火山引擎",
"domestic",
"cloud",
key_only=False,
note="需要接入点或推理端点配置",
mark="DB",
),
ModelProvider(
"baidu",
"百度智能云千帆 / 文心",
"百度智能云",
"domestic",
"cloud",
key_only=False,
note="需要应用或云鉴权配置",
mark="BD",
),
ModelProvider(
"tencent",
"腾讯混元",
"腾讯云",
"domestic",
"cloud",
key_only=False,
note="需要腾讯云鉴权配置",
mark="HY",
),
ModelProvider(
"huawei",
"华为云 ModelArts / 盘古",
"华为云",
"domestic",
"cloud",
key_only=False,
note="需要项目、区域及云鉴权配置",
mark="HW",
),
ModelProvider(
"openrouter",
"OpenRouter",
"OpenRouter",
"gateway",
"openai_compatible",
"https://openrouter.ai/api/v1",
default_model="openai/gpt-4o-mini",
mark="OR",
),
ModelProvider(
"groq",
"Groq",
"Groq",
"gateway",
"openai_compatible",
"https://api.groq.com/openai/v1",
default_model="llama-3.3-70b-versatile",
mark="GQ",
),
ModelProvider(
"together",
"Together AI",
"Together AI",
"gateway",
"openai_compatible",
"https://api.together.xyz/v1",
mark="TO",
),
ModelProvider(
"mistral",
"Mistral AI",
"Mistral",
"official",
"openai_compatible",
"https://api.mistral.ai/v1",
default_model="mistral-large-latest",
mark="MS",
),
ModelProvider(
"cohere",
"Cohere",
"Cohere",
"official",
"openai_compatible",
key_only=False,
note="原生协议适配待接入",
mark="CO",
),
ModelProvider(
"xai",
"xAI Grok",
"xAI",
"official",
"openai_compatible",
"https://api.x.ai/v1",
default_model="grok-4",
mark="XA",
),
ModelProvider(
"azure_openai",
"Azure OpenAI",
"Microsoft Azure",
"cloud",
"cloud",
key_only=False,
note="需要资源端点和部署名称",
mark="AZ",
),
ModelProvider(
"aws_bedrock",
"AWS Bedrock",
"Amazon Web Services",
"cloud",
"cloud",
key_only=False,
note="需要区域和 AWS IAM 凭据",
mark="AW",
),
ModelProvider(
"custom",
"自定义 OpenAI 兼容服务",
"自定义",
"gateway",
"openai_compatible",
key_only=False,
note="需要 Base URL 和模型 ID",
mark="+",
),
)
PROVIDER_BY_CODE = {provider.code: provider for provider in PROVIDERS}
CATEGORY_LABELS = {
"all": "全部",
"official": "官方直连",
"domestic": "国内平台",
"gateway": "云与聚合",
"cloud": "云平台",
"connected": "已连接",
}
def get_provider(code: str) -> ModelProvider | None:
"""按稳定编码读取预设,未知编码返回空值。"""
return PROVIDER_BY_CODE.get(code)