feat(qianfan): add official OpenAI-compatible provider support

This commit is contained in:
jimmyzhuu 2026-05-06 22:56:33 +08:00
parent bd1ea0252a
commit cb89562541
5 changed files with 142 additions and 0 deletions

View file

@ -778,6 +778,7 @@ openai_compatible_endpoints: List = [
"https://ai-gateway.vercel.sh/v1",
"https://api.inference.wandb.ai/v1",
"https://api.clarifai.com/v2/ext/openai/v1",
"https://qianfan.baidubce.com/v2",
]
@ -814,6 +815,7 @@ openai_compatible_providers: List = [
"novita",
"meta_llama",
"publicai", # PublicAI - JSON-configured provider
"qianfan", # Qianfan - JSON-configured provider
"synthetic", # Synthetic - JSON-configured provider
"apertis", # Apertis - JSON-configured provider
"nano-gpt", # Nano-GPT - JSON-configured provider

View file

@ -362,6 +362,9 @@ def get_llm_provider( # noqa: PLR0915
elif endpoint == "https://api.inference.wandb.ai/v1":
custom_llm_provider = "wandb"
dynamic_api_key = get_secret_str("WANDB_API_KEY")
elif endpoint == "https://qianfan.baidubce.com/v2":
custom_llm_provider = "qianfan"
dynamic_api_key = api_key or get_secret_str("QIANFAN_API_KEY")
if api_base is not None and not isinstance(api_base, str):
raise Exception(

View file

@ -11,6 +11,14 @@
"convert_content_list_to_string": true
}
},
"qianfan": {
"base_url": "https://qianfan.baidubce.com/v2",
"api_key_env": "QIANFAN_API_KEY",
"api_base_env": "QIANFAN_API_BASE",
"param_mappings": {
"max_completion_tokens": "max_tokens"
}
},
"helicone": {
"base_url": "https://ai-gateway.helicone.ai/",
"api_key_env": "HELICONE_API_KEY"

View file

@ -3202,6 +3202,7 @@ class LlmProviders(str, Enum):
OPENAI = "openai"
CHATGPT = "chatgpt"
OPENAI_LIKE = "openai_like" # embedding only
QIANFAN = "qianfan"
JINA_AI = "jina_ai"
XAI = "xai"
ZAI = "zai"

View file

@ -0,0 +1,128 @@
import os
import sys
from unittest.mock import patch
sys.path.insert(0, os.path.abspath("../../../../.."))
import litellm
from litellm import Router
from litellm.llms.openai_like.dynamic_config import create_config_class
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
from litellm.types.utils import LlmProviders
from litellm.utils import ProviderConfigManager
def test_qianfan_in_provider_list():
assert "qianfan" in litellm.provider_list
assert "qianfan" in litellm.openai_compatible_providers
assert LlmProviders.QIANFAN == "qianfan"
def test_qianfan_json_config_exists():
config = JSONProviderRegistry.get("qianfan")
assert config is not None
assert config.base_url == "https://qianfan.baidubce.com/v2"
assert config.api_key_env == "QIANFAN_API_KEY"
assert config.api_base_env == "QIANFAN_API_BASE"
assert config.param_mappings["max_completion_tokens"] == "max_tokens"
def test_qianfan_dynamic_config_defaults():
provider = JSONProviderRegistry.get("qianfan")
assert provider is not None
config = create_config_class(provider)()
api_base, api_key = config._get_openai_compatible_provider_info(
api_base=None, api_key=None
)
assert api_base == "https://qianfan.baidubce.com/v2"
assert api_key is None
assert config.custom_llm_provider == "qianfan"
def test_qianfan_provider_detection_by_prefix():
model, provider, _, api_base = litellm.get_llm_provider(
model="qianfan/ernie-4.5-turbo-128k"
)
assert provider == "qianfan"
assert model == "ernie-4.5-turbo-128k"
assert api_base == "https://qianfan.baidubce.com/v2"
def test_qianfan_provider_detection_by_api_base_preserves_explicit_key():
model, provider, api_key, api_base = litellm.get_llm_provider(
model="ernie-4.5-turbo-128k",
api_base="https://qianfan.baidubce.com/v2",
api_key="test-qianfan-key",
)
assert model == "ernie-4.5-turbo-128k"
assert provider == "qianfan"
assert api_key == "test-qianfan-key"
assert api_base == "https://qianfan.baidubce.com/v2"
def test_qianfan_provider_detection_by_api_base_prefers_explicit_key_over_env():
with patch.dict(os.environ, {"QIANFAN_API_KEY": "env-qianfan-key"}):
model, provider, api_key, api_base = litellm.get_llm_provider(
model="ernie-4.5-turbo-128k",
api_base="https://qianfan.baidubce.com/v2",
api_key="explicit-qianfan-key",
)
assert model == "ernie-4.5-turbo-128k"
assert provider == "qianfan"
assert api_key == "explicit-qianfan-key"
assert api_base == "https://qianfan.baidubce.com/v2"
def test_qianfan_router_config():
router = Router(
model_list=[
{
"model_name": "qianfan-router-model",
"litellm_params": {
"model": "qianfan/ernie-4.5-turbo-128k",
"api_key": "test-key",
},
}
]
)
assert len(router.model_list) == 1
assert router.model_list[0]["model_name"] == "qianfan-router-model"
assert router.deployment_names == ["qianfan/ernie-4.5-turbo-128k"]
def test_qianfan_provider_config_manager():
config = ProviderConfigManager.get_provider_chat_config(
model="ernie-4.5-turbo-128k",
provider=LlmProviders.QIANFAN,
)
assert config is not None
assert config.custom_llm_provider == "qianfan"
def test_qianfan_provider_config_manager_maps_max_completion_tokens():
config = ProviderConfigManager.get_provider_chat_config(
model="ernie-4.5-turbo-128k",
provider=LlmProviders.QIANFAN,
)
mapped_params = config.map_openai_params(
non_default_params={
"max_completion_tokens": 123,
"temperature": 0.7,
},
optional_params={},
model="ernie-4.5-turbo-128k",
drop_params=False,
)
assert mapped_params["max_tokens"] == 123
assert "max_completion_tokens" not in mapped_params
assert mapped_params["temperature"] == 0.7