feat: add china operator llm providers

This commit is contained in:
jxxghp
2026-05-24 09:30:41 +08:00
parent 6430b864b4
commit dc73d61682
4 changed files with 261 additions and 2 deletions

View File

@@ -672,6 +672,88 @@ class LLMProviderManager(metaclass=Singleton):
description="腾讯兼容端点。",
sort_order=170,
),
ProviderSpec(
id="china-unicom",
name="中国联通",
runtime="openai_compatible",
default_base_url="https://aigw-gzgy2.cucloud.cn:8443/v1",
base_url_presets=(
url_preset(
id="china-unicom-coding-openai",
label="Coding Plan / OpenAI",
value="https://aigw-gzgy2.cucloud.cn:8443/v1",
model_list_strategy="manual",
),
url_preset(
id="china-unicom-coding-anthropic",
label="Coding Plan / Anthropic",
value="https://aigw-gzgy2.cucloud.cn:8443",
runtime="anthropic_compatible",
model_list_strategy="manual",
),
),
base_url_editable=True,
api_key_hint="填写联通云 AISP / Coding Plan 专属 API Key模型名称请按控制台可用模型 ID 手动填写。",
supports_model_refresh=False,
model_list_strategy="manual",
description="联通云 AISP Coding Plan 兼容端点,支持 OpenAI 与 Anthropic 协议地址预设。",
sort_order=172,
),
ProviderSpec(
id="china-mobile",
name="中国移动",
runtime="openai_compatible",
default_base_url="https://ecloud.10086.cn/api",
base_url_presets=(
url_preset(
id="china-mobile-moma",
label="MoMA / 移动云",
value="https://ecloud.10086.cn/api",
),
url_preset(
id="china-mobile-coding",
label="Coding Plan / 移动智算包",
value="https://zhenze-huhehaote.cmecloud.cn/api/coding/v1",
),
),
base_url_editable=True,
api_key_hint="填写中国移动 MoMA / 移动云 Token 服务 API Key如控制台下发专属域名请覆盖 Base URL。",
supports_model_refresh=False,
model_list_strategy="manual",
description="中国移动 MoMA / 移动云 OpenAI-compatible Token 服务,支持专属域名覆盖。",
sort_order=174,
),
ProviderSpec(
id="china-telecom",
name="中国电信",
runtime="openai_compatible",
default_base_url="https://wishub-x6.ctyun.cn/v1",
base_url_presets=(
url_preset(
id="china-telecom-token-service",
label="Token 服务 / 息壤",
value="https://wishub-x6.ctyun.cn/v1",
),
url_preset(
id="china-telecom-coding-openai",
label="编码套餐 / OpenAI",
value="https://wishub-x6.ctyun.cn/coding/v1",
model_list_strategy="manual",
),
url_preset(
id="china-telecom-coding-anthropic",
label="编码套餐 / Anthropic",
value="https://wishub-x6.ctyun.cn/coding/v1",
runtime="anthropic_compatible",
model_list_strategy="manual",
),
),
base_url_editable=True,
api_key_label="App Key",
api_key_hint="填写天翼云 Token 服务 / 息壤 App Key编码套餐模型请按控制台展示的模型 ID 手动填写。",
description="天翼云 Token 服务原模型推理服务OpenAI-compatible 端点,支持通用与编码套餐地址预设。",
sort_order=176,
),
ProviderSpec(
id="ollama-cloud",
name="Ollama Cloud",

View File

@@ -90,6 +90,21 @@ LLM_PROVIDER_DEFAULTS = {
"model": "",
"base_url": "https://modelservice.jdcloud.com/v1",
},
"china-unicom": {
"model": "",
"base_url": "https://aigw-gzgy2.cucloud.cn:8443/v1",
"base_url_preset": "china-unicom-coding-openai",
},
"china-mobile": {
"model": "",
"base_url": "https://ecloud.10086.cn/api",
"base_url_preset": "china-mobile-moma",
},
"china-telecom": {
"model": "",
"base_url": "https://wishub-x6.ctyun.cn/v1",
"base_url_preset": "china-telecom-token-service",
},
"kuaishou-wanqing": {
"model": "",
"base_url": "https://wanqing.streamlakeapi.com/api/gateway/v1/endpoints",
@@ -105,6 +120,9 @@ LLM_PROVIDER_FALLBACK_CHOICES = {
"openrouter": "OpenRouter",
"groq": "Groq",
"jdcloud": "京东云",
"china-unicom": "中国联通",
"china-mobile": "中国移动",
"china-telecom": "中国电信",
"kuaishou-wanqing": "快手万擎",
}
RUNTIME_PACKAGE = {

View File

@@ -342,6 +342,127 @@ class LlmProviderRegistryTest(unittest.TestCase):
self.assertEqual(models, [])
def test_builtin_provider_includes_china_operator_token_services(self):
"""三大运营商 Token 服务应作为内置 OpenAI-compatible provider 暴露。"""
manager = LLMProviderManager()
unicom = manager.get_provider("china-unicom")
mobile = manager.get_provider("china-mobile")
telecom = manager.get_provider("china-telecom")
self.assertEqual(unicom.name, "中国联通")
self.assertEqual(unicom.default_base_url, "https://aigw-gzgy2.cucloud.cn:8443/v1")
self.assertEqual(
tuple((preset.id, preset.value, preset.runtime) for preset in unicom.base_url_presets),
(
(
"china-unicom-coding-openai",
"https://aigw-gzgy2.cucloud.cn:8443/v1",
None,
),
(
"china-unicom-coding-anthropic",
"https://aigw-gzgy2.cucloud.cn:8443",
"anthropic_compatible",
),
),
)
self.assertTrue(unicom.base_url_editable)
self.assertFalse(unicom.supports_model_refresh)
self.assertEqual(unicom.model_list_strategy, "manual")
self.assertEqual(mobile.name, "中国移动")
self.assertEqual(mobile.default_base_url, "https://ecloud.10086.cn/api")
self.assertEqual(
tuple((preset.id, preset.value) for preset in mobile.base_url_presets),
(
("china-mobile-moma", "https://ecloud.10086.cn/api"),
(
"china-mobile-coding",
"https://zhenze-huhehaote.cmecloud.cn/api/coding/v1",
),
),
)
self.assertTrue(mobile.base_url_editable)
self.assertFalse(mobile.supports_model_refresh)
self.assertEqual(mobile.model_list_strategy, "manual")
self.assertEqual(telecom.name, "中国电信")
self.assertEqual(telecom.default_base_url, "https://wishub-x6.ctyun.cn/v1")
self.assertEqual(telecom.api_key_label, "App Key")
self.assertEqual(
tuple(
(preset.id, preset.value, preset.runtime, preset.model_list_strategy)
for preset in telecom.base_url_presets
),
(
(
"china-telecom-token-service",
"https://wishub-x6.ctyun.cn/v1",
None,
None,
),
(
"china-telecom-coding-openai",
"https://wishub-x6.ctyun.cn/coding/v1",
None,
"manual",
),
(
"china-telecom-coding-anthropic",
"https://wishub-x6.ctyun.cn/coding/v1",
"anthropic_compatible",
"manual",
),
),
)
self.assertTrue(telecom.base_url_editable)
def test_china_operator_manual_model_presets_return_empty_model_list(self):
"""未提供稳定全局模型目录的运营商套餐应回退为手动填写模型。"""
manager = LLMProviderManager()
unicom_models = asyncio.run(manager.list_models(provider_id="china-unicom"))
mobile_models = asyncio.run(manager.list_models(provider_id="china-mobile"))
telecom_coding_models = asyncio.run(
manager.list_models(
provider_id="china-telecom",
base_url_preset_id="china-telecom-coding-openai",
)
)
self.assertEqual(unicom_models, [])
self.assertEqual(mobile_models, [])
self.assertEqual(telecom_coding_models, [])
def test_china_operator_anthropic_presets_resolve_runtime(self):
"""运营商提供 Anthropic 协议地址时应切换到 anthropic_compatible runtime。"""
manager = LLMProviderManager()
unicom_runtime = asyncio.run(
manager.resolve_runtime(
provider_id="china-unicom",
model=None,
api_key="sk-test",
base_url="https://aigw-gzgy2.cucloud.cn:8443",
base_url_preset_id="china-unicom-coding-anthropic",
)
)
telecom_runtime = asyncio.run(
manager.resolve_runtime(
provider_id="china-telecom",
model=None,
api_key="cp-test",
base_url="https://wishub-x6.ctyun.cn/coding/v1",
base_url_preset_id="china-telecom-coding-anthropic",
)
)
self.assertEqual(unicom_runtime["runtime"], "anthropic_compatible")
self.assertEqual(unicom_runtime["base_url"], "https://aigw-gzgy2.cucloud.cn:8443")
self.assertEqual(telecom_runtime["runtime"], "anthropic_compatible")
self.assertEqual(telecom_runtime["base_url"], "https://wishub-x6.ctyun.cn/coding")
def test_builtin_minimax_provider_merges_general_and_coding_presets(self):
manager = LLMProviderManager()

View File

@@ -185,7 +185,8 @@ class LocalSetupLlmProviderPromptTests(unittest.TestCase):
self.assertEqual(provider, "my-provider_01")
def test_fallback_provider_choices_include_baidu_jdcloud_and_wanqing(self):
def test_fallback_provider_choices_include_builtin_domestic_token_providers(self):
"""本地向导兜底列表应覆盖内置国内 Token 套餐 provider。"""
module = load_local_setup_module()
self.assertEqual(
@@ -197,8 +198,21 @@ class LocalSetupLlmProviderPromptTests(unittest.TestCase):
module.LLM_PROVIDER_FALLBACK_CHOICES["kuaishou-wanqing"],
"快手万擎",
)
self.assertEqual(
module.LLM_PROVIDER_FALLBACK_CHOICES["china-unicom"],
"中国联通",
)
self.assertEqual(
module.LLM_PROVIDER_FALLBACK_CHOICES["china-mobile"],
"中国移动",
)
self.assertEqual(
module.LLM_PROVIDER_FALLBACK_CHOICES["china-telecom"],
"中国电信",
)
def test_local_setup_defaults_include_baidu_jdcloud_and_wanqing_base_urls(self):
def test_local_setup_defaults_include_builtin_domestic_token_base_urls(self):
"""本地向导默认 Base URL 应覆盖内置国内 Token 套餐 provider。"""
module = load_local_setup_module()
self.assertEqual(
@@ -217,6 +231,30 @@ class LocalSetupLlmProviderPromptTests(unittest.TestCase):
module.LLM_PROVIDER_DEFAULTS["kuaishou-wanqing"]["base_url_preset"],
"kuaishou-wanqing-usage",
)
self.assertEqual(
module.LLM_PROVIDER_DEFAULTS["china-unicom"]["base_url"],
"https://aigw-gzgy2.cucloud.cn:8443/v1",
)
self.assertEqual(
module.LLM_PROVIDER_DEFAULTS["china-unicom"]["base_url_preset"],
"china-unicom-coding-openai",
)
self.assertEqual(
module.LLM_PROVIDER_DEFAULTS["china-mobile"]["base_url"],
"https://ecloud.10086.cn/api",
)
self.assertEqual(
module.LLM_PROVIDER_DEFAULTS["china-mobile"]["base_url_preset"],
"china-mobile-moma",
)
self.assertEqual(
module.LLM_PROVIDER_DEFAULTS["china-telecom"]["base_url"],
"https://wishub-x6.ctyun.cn/v1",
)
self.assertEqual(
module.LLM_PROVIDER_DEFAULTS["china-telecom"]["base_url_preset"],
"china-telecom-token-service",
)
def test_collect_agent_config_prompts_for_duplicate_base_url_presets(self):
module = load_local_setup_module()