diff --git a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/llm.py b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/llm.py index 7300f4a829b..aec8a53b95a 100644 --- a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/llm.py +++ b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/llm.py @@ -39,7 +39,9 @@ class BaiLianLLMModelParams(BaseForm): class BaiLianLLMModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField(_("API URL"), required=True) + api_base = forms.TextInputField( + _("API URL"), required=True, default_value="https://dashscope.aliyuncs.com/compatible-mode/v1" + ) api_key = forms.PasswordInputField(_("API Key"), required=True) def is_valid( diff --git a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/asr_stt.py b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/asr_stt.py index a32c14cf2a0..42255adc9fd 100644 --- a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/asr_stt.py +++ b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/asr_stt.py @@ -10,7 +10,7 @@ class AliyunBaiLianAsrSTTModelCredential(BaseForm, BaseModelCredential): - api_url = forms.TextInputField(_("API URL"), required=True) + api_url = forms.TextInputField(_("API URL"), required=True, default_value="https://dashscope.aliyuncs.com/api/v1") api_key = forms.PasswordInputField(_("API Key"), required=True) def is_valid( diff --git a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/default_stt.py b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/default_stt.py index a9a9bfb7f94..870f7e7cb91 100644 --- a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/default_stt.py +++ b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/default_stt.py @@ -32,7 +32,12 @@ class AliyunBaiLianDefaultSTTModelCredential(BaseForm, BaseModelCredential): {"label": _("Real-time speech recognition - Fun-ASR/Paraformer"), "value": "other"}, ], ) - api_url = forms.TextInputField(_("API URL"), required=True, relation_show_field_dict={"type": ["qwen", "omni"]}) + api_url = forms.TextInputField( + _("API URL"), + required=True, + default_value="https://dashscope.aliyuncs.com/api/v1", + relation_show_field_dict={"type": ["qwen", "omni"]}, + ) api_key = forms.PasswordInputField(_("API Key"), required=True) def is_valid( diff --git a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/omni_stt.py b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/omni_stt.py index 673caa781f1..356213c420a 100644 --- a/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/omni_stt.py +++ b/apps/models_provider/impl/aliyun_bai_lian_model_provider/credential/stt/omni_stt.py @@ -21,7 +21,7 @@ class AliyunBaiLianOmiSTTModelParams(BaseForm): class AliyunBaiLianOmiSTTModelCredential(BaseForm, BaseModelCredential): - api_url = forms.TextInputField(_("API URL"), required=True) + api_url = forms.TextInputField(_("API URL"), required=True, default_value="https://dashscope.aliyuncs.com/api/v1") api_key = forms.PasswordInputField(_("API Key"), required=True) def is_valid( diff --git a/apps/models_provider/impl/anthropic_model_provider/credential/image.py b/apps/models_provider/impl/anthropic_model_provider/credential/image.py index 292d5947ed9..ed06c062637 100644 --- a/apps/models_provider/impl/anthropic_model_provider/credential/image.py +++ b/apps/models_provider/impl/anthropic_model_provider/credential/image.py @@ -39,7 +39,7 @@ class AnthropicImageModelParams(BaseForm): class AnthropicImageModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField(_("API URL"), required=True) + api_base = forms.TextInputField(_("API URL"), required=True, default_value="https://api.anthropic.com/v1") api_key = forms.PasswordInputField(_("API Key"), required=True) def is_valid( diff --git a/apps/models_provider/impl/anthropic_model_provider/credential/llm.py b/apps/models_provider/impl/anthropic_model_provider/credential/llm.py index f736afd613b..692ee7e2703 100644 --- a/apps/models_provider/impl/anthropic_model_provider/credential/llm.py +++ b/apps/models_provider/impl/anthropic_model_provider/credential/llm.py @@ -88,7 +88,7 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField(_("API URL"), required=True) + api_base = forms.TextInputField(_("API URL"), required=True, default_value="https://api.anthropic.com/v1") api_key = forms.PasswordInputField(_("API Key"), required=True) def get_model_params_setting_form(self, model_name): diff --git a/apps/models_provider/impl/kimi_model_provider/credential/llm.py b/apps/models_provider/impl/kimi_model_provider/credential/llm.py index 5d2fbfbe745..8c10b36c029 100644 --- a/apps/models_provider/impl/kimi_model_provider/credential/llm.py +++ b/apps/models_provider/impl/kimi_model_provider/credential/llm.py @@ -88,7 +88,7 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.moonshot.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def get_model_params_setting_form(self, model_name): diff --git a/apps/models_provider/impl/openai_model_provider/credential/embedding.py b/apps/models_provider/impl/openai_model_provider/credential/embedding.py index 93e5322bfb4..30d9940bfc7 100644 --- a/apps/models_provider/impl/openai_model_provider/credential/embedding.py +++ b/apps/models_provider/impl/openai_model_provider/credential/embedding.py @@ -78,5 +78,5 @@ def encryption_dict(self, model: Dict[str, object]): def get_model_params_setting_form(self, model_name): return OpenAIEmbeddingModelParams() - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.openai.com/v1") api_key = forms.PasswordInputField("API Key", required=True) diff --git a/apps/models_provider/impl/openai_model_provider/credential/image.py b/apps/models_provider/impl/openai_model_provider/credential/image.py index d79bfc7dbc0..3d1ed17f462 100644 --- a/apps/models_provider/impl/openai_model_provider/credential/image.py +++ b/apps/models_provider/impl/openai_model_provider/credential/image.py @@ -39,7 +39,7 @@ class OpenAIImageModelParams(BaseForm): class OpenAIImageModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.openai.com/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/openai_model_provider/credential/llm.py b/apps/models_provider/impl/openai_model_provider/credential/llm.py index 0b6a8784287..3cdb65c5ad7 100644 --- a/apps/models_provider/impl/openai_model_provider/credential/llm.py +++ b/apps/models_provider/impl/openai_model_provider/credential/llm.py @@ -89,7 +89,7 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.openai.com/v1") api_key = forms.PasswordInputField("API Key", required=True) def get_model_params_setting_form(self, model_name): diff --git a/apps/models_provider/impl/openai_model_provider/credential/stt.py b/apps/models_provider/impl/openai_model_provider/credential/stt.py index 91419a6bd21..accaa3f82ad 100644 --- a/apps/models_provider/impl/openai_model_provider/credential/stt.py +++ b/apps/models_provider/impl/openai_model_provider/credential/stt.py @@ -19,7 +19,7 @@ class OpenAISTTModelParams(BaseForm): class OpenAISTTModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.openai.com/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/openai_model_provider/credential/tti.py b/apps/models_provider/impl/openai_model_provider/credential/tti.py index a8739067748..0c160e68801 100644 --- a/apps/models_provider/impl/openai_model_provider/credential/tti.py +++ b/apps/models_provider/impl/openai_model_provider/credential/tti.py @@ -63,7 +63,7 @@ class OpenAITTIModelParams(BaseForm): class OpenAITextToImageModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.openai.com/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/openai_model_provider/credential/tts.py b/apps/models_provider/impl/openai_model_provider/credential/tts.py index 73f7fa87db6..ae193b368a1 100644 --- a/apps/models_provider/impl/openai_model_provider/credential/tts.py +++ b/apps/models_provider/impl/openai_model_provider/credential/tts.py @@ -35,7 +35,7 @@ class OpenAITTSModelGeneralParams(BaseForm): class OpenAITTSModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.openai.com/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/qianfan_model_provider/credential/reranker.py b/apps/models_provider/impl/qianfan_model_provider/credential/reranker.py index f1aba200a36..d9df5b3d0f2 100644 --- a/apps/models_provider/impl/qianfan_model_provider/credential/reranker.py +++ b/apps/models_provider/impl/qianfan_model_provider/credential/reranker.py @@ -24,7 +24,7 @@ class QfRerankerModelParams(BaseForm): class QfRerankerCredential(BaseForm, BaseModelCredential): - api_url = forms.TextInputField("API URL", required=True) + api_url = forms.TextInputField("API URL", required=True, default_value="https://qianfan.baidubce.com/v2") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/embedding.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/embedding.py index c24e2d7697a..92193114ed4 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/embedding.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/embedding.py @@ -59,5 +59,5 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/image.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/image.py index 41bbfe50ea7..f6f4e641d1d 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/image.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/image.py @@ -39,7 +39,7 @@ class SiliconCloudImageModelParams(BaseForm): class SiliconCloudImageModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/llm.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/llm.py index 29e146a6cb3..6253e250b4a 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/llm.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/llm.py @@ -88,7 +88,7 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def get_model_params_setting_form(self, model_name): diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/reranker.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/reranker.py index c997c2d5e19..165cad813fc 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/reranker.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/reranker.py @@ -71,7 +71,7 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def get_model_params_setting_form(self, model_name: str) -> SiliconCloudRerankerModelParams: diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/stt.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/stt.py index fd9d18e1920..e8827560c65 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/stt.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/stt.py @@ -11,7 +11,7 @@ class SiliconCloudSTTModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/tti.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/tti.py index 7a884d794b8..8083b847704 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/tti.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/tti.py @@ -63,7 +63,7 @@ class SiliconCloudTTIModelParams(BaseForm): class SiliconCloudTextToImageModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/siliconCloud_model_provider/credential/tts.py b/apps/models_provider/impl/siliconCloud_model_provider/credential/tts.py index 4daa9989aee..2162337e3f1 100644 --- a/apps/models_provider/impl/siliconCloud_model_provider/credential/tts.py +++ b/apps/models_provider/impl/siliconCloud_model_provider/credential/tts.py @@ -37,7 +37,7 @@ class SiliconCloudTTSModelGeneralParams(BaseForm): class SiliconCloudTTSModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://api.siliconflow.cn/v1") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/volcanic_engine_model_provider/credential/embedding.py b/apps/models_provider/impl/volcanic_engine_model_provider/credential/embedding.py index a26a47bfc11..38a6c99208f 100644 --- a/apps/models_provider/impl/volcanic_engine_model_provider/credential/embedding.py +++ b/apps/models_provider/impl/volcanic_engine_model_provider/credential/embedding.py @@ -59,5 +59,5 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "api_key": super().encryption(model.get("api_key", ""))} - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://ark.cn-beijing.volces.com/api/v3") api_key = forms.PasswordInputField("API Key", required=True) diff --git a/apps/models_provider/impl/volcanic_engine_model_provider/credential/image.py b/apps/models_provider/impl/volcanic_engine_model_provider/credential/image.py index 82ddc89bc93..ae3ea8ed6a9 100644 --- a/apps/models_provider/impl/volcanic_engine_model_provider/credential/image.py +++ b/apps/models_provider/impl/volcanic_engine_model_provider/credential/image.py @@ -39,7 +39,7 @@ class VolcanicEngineImageModelParams(BaseForm): class VolcanicEngineImageModelCredential(BaseForm, BaseModelCredential): - api_base = forms.TextInputField("API URL", required=True) + api_base = forms.TextInputField("API URL", required=True, default_value="https://ark.cn-beijing.volces.com/api/v3") api_key = forms.PasswordInputField("API Key", required=True) def is_valid( diff --git a/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py b/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py index f486d4e446e..5edcb9c884c 100644 --- a/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py +++ b/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py @@ -7,6 +7,7 @@ @Date :5/13/24 7:47 AM """ +import copy import os from common.utils.common import get_file_content @@ -146,6 +147,15 @@ class VolcanicEngineModelProvider(IModelProvider): def get_model_info_manage(self): return model_info_manage + def get_model_credential(self, model_type, model_name): + model_credential = super().get_model_credential(model_type, model_name) + # 火山引擎 Ark 统一走 v3 地址;LLM 复用 OpenAI 凭证类,需为实例单独设置, + # 避免覆写共享凭证类的 default_value 影响到其它 provider。 + if model_type == "LLM" and hasattr(model_credential, "api_base"): + model_credential.api_base = copy.copy(model_credential.api_base) + model_credential.api_base.default_value = "https://ark.cn-beijing.volces.com/api/v3" + return model_credential + def get_model_provide_info(self): return ModelProvideInfo( provider="model_volcanic_engine_provider", diff --git a/apps/models_provider/impl/xf_model_provider/credential/llm.py b/apps/models_provider/impl/xf_model_provider/credential/llm.py index afdf2f01e0b..79da1310fb5 100644 --- a/apps/models_provider/impl/xf_model_provider/credential/llm.py +++ b/apps/models_provider/impl/xf_model_provider/credential/llm.py @@ -115,7 +115,7 @@ def is_valid( def encryption_dict(self, model: Dict[str, object]): return {**model, "spark_api_secret": super().encryption(model.get("spark_api_secret", ""))} - spark_api_url = forms.TextInputField("API URL", required=True) + spark_api_url = forms.TextInputField("API URL", required=True, default_value="wss://spark-api.xf-yun.com/v3.5/chat") spark_app_id = forms.TextInputField("APP ID", required=True) spark_api_key = forms.PasswordInputField("API Key", required=True) spark_api_secret = forms.PasswordInputField("API Secret", required=True) diff --git a/apps/models_provider/tests/test_provider_default_urls.py b/apps/models_provider/tests/test_provider_default_urls.py new file mode 100644 index 00000000000..2ad11f5e79d --- /dev/null +++ b/apps/models_provider/tests/test_provider_default_urls.py @@ -0,0 +1,144 @@ +from django.test import SimpleTestCase + +from models_provider.constants.model_provider_constants import ModelProvideConstants + + +class ProviderDefaultUrlTests(SimpleTestCase): + """供应商创建模型表单中的 API 地址应展示官方默认值。""" + + def _url_default(self, provider_key, model_type, model_name, field): + provider = ModelProvideConstants[provider_key] + form_list = provider.get_model_credential(model_type, model_name).to_form_list() + fields = {item["field"]: item for item in form_list} + return fields[field].get("default_value") + + def test_providers_expose_default_url(self): + cases = ( + # OpenAI + ("model_openai_provider", "LLM", "gpt-4o", "api_base", "https://api.openai.com/v1"), + ("model_openai_provider", "STT", "whisper-1", "api_base", "https://api.openai.com/v1"), + ("model_openai_provider", "TTS", "tts-1", "api_base", "https://api.openai.com/v1"), + ("model_openai_provider", "EMBEDDING", "text-embedding-3-small", "api_base", "https://api.openai.com/v1"), + ("model_openai_provider", "IMAGE", "gpt-4o", "api_base", "https://api.openai.com/v1"), + ("model_openai_provider", "TTI", "dall-e-3", "api_base", "https://api.openai.com/v1"), + # Anthropic + ( + "model_anthropic_provider", + "LLM", + "claude-3-5-sonnet-20241022", + "api_base", + "https://api.anthropic.com/v1", + ), + ( + "model_anthropic_provider", + "IMAGE", + "claude-3-5-sonnet-20241022", + "api_base", + "https://api.anthropic.com/v1", + ), + # Kimi + ("model_kimi_provider", "LLM", "moonshot-v1-128k", "api_base", "https://api.moonshot.cn/v1"), + # SiliconCloud + ( + "model_siliconCloud_provider", + "LLM", + "deepseek-ai/DeepSeek-R1-Distill-Llama-8B", + "api_base", + "https://api.siliconflow.cn/v1", + ), + ( + "model_siliconCloud_provider", + "STT", + "FunAudioLLM/SenseVoiceSmall", + "api_base", + "https://api.siliconflow.cn/v1", + ), + ( + "model_siliconCloud_provider", + "EMBEDDING", + "BAAI/bge-large-zh-v1.5", + "api_base", + "https://api.siliconflow.cn/v1", + ), + ( + "model_siliconCloud_provider", + "TTI", + "stabilityai/stable-diffusion-xl-base-1.0", + "api_base", + "https://api.siliconflow.cn/v1", + ), + ( + "model_siliconCloud_provider", + "RERANKER", + "BAAI/bge-reranker-v2-m3", + "api_base", + "https://api.siliconflow.cn/v1", + ), + ( + "model_siliconCloud_provider", + "TTS", + "FunAudioLLM/CosyVoice2-0.5B", + "api_base", + "https://api.siliconflow.cn/v1", + ), + ( + "model_siliconCloud_provider", + "IMAGE", + "Qwen/Qwen3-VL-32B-Instruct", + "api_base", + "https://api.siliconflow.cn/v1", + ), + # Aliyun BaiLian + ( + "aliyun_bai_lian_model_provider", + "LLM", + "qwen3.7-plus", + "api_base", + "https://dashscope.aliyuncs.com/compatible-mode/v1", + ), + ("aliyun_bai_lian_model_provider", "STT", "default", "api_url", "https://dashscope.aliyuncs.com/api/v1"), + ( + "aliyun_bai_lian_model_provider", + "STT", + "qwen-omni-turbo", + "api_url", + "https://dashscope.aliyuncs.com/api/v1", + ), + ( + "aliyun_bai_lian_model_provider", + "STT", + "qwen-audio-asr", + "api_url", + "https://dashscope.aliyuncs.com/api/v1", + ), + # Volcanic engine + ( + "model_volcanic_engine_provider", + "LLM", + "ep-xxxxxxxxxx-yyyy", + "api_base", + "https://ark.cn-beijing.volces.com/api/v3", + ), + ( + "model_volcanic_engine_provider", + "IMAGE", + "ep-xxxxxxxxxx-yyyy", + "api_base", + "https://ark.cn-beijing.volces.com/api/v3", + ), + ( + "model_volcanic_engine_provider", + "EMBEDDING", + "ep-xxxxxxxxxx-yyyy", + "api_base", + "https://ark.cn-beijing.volces.com/api/v3", + ), + # Xunfei + ("model_xf_provider", "LLM", "general", "spark_api_url", "wss://spark-api.xf-yun.com/v3.5/chat"), + # Qianfan reranker + ("model_qianfan_provider", "RERANKER", "bce-reranker-base", "api_url", "https://qianfan.baidubce.com/v2"), + ) + + for provider_key, model_type, model_name, field, expected in cases: + with self.subTest(provider=provider_key, model_type=model_type, model_name=model_name, field=field): + self.assertEqual(expected, self._url_default(provider_key, model_type, model_name, field))