mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
feat(zai): fall back to BIGMODEL/ZHIPUAI api keys and add GLM-5.3 aliases and glm-5v-turbo
Resolve the zai api key from ZAI_API_KEY, BIGMODEL_API_KEY or ZHIPUAI_API_KEY so deployments predating the zai rename keep working. Accept response_format and max_completion_tokens as supported openai params. Register zai/GLM-5.3 and zai/GLM-5.3-Flash aliases plus the glm-5v-turbo vision model in both the main and backup cost maps
This commit is contained in:
parent
dddbaa803d
commit
215a60fa1d
4 changed files with 217 additions and 1 deletions
|
|
@ -17,7 +17,12 @@ class ZAIChatConfig(OpenAIGPTConfig):
|
|||
self, api_base: str | None, api_key: str | None
|
||||
) -> tuple[str | None, str | None]:
|
||||
api_base = api_base or get_secret_str("ZAI_API_BASE") or ZAI_API_BASE
|
||||
dynamic_api_key: Final = api_key or get_secret_str("ZAI_API_KEY")
|
||||
dynamic_api_key: Final = (
|
||||
api_key
|
||||
or get_secret_str("ZAI_API_KEY")
|
||||
or get_secret_str("BIGMODEL_API_KEY")
|
||||
or get_secret_str("ZHIPUAI_API_KEY")
|
||||
)
|
||||
return api_base, dynamic_api_key
|
||||
|
||||
def get_openai_compatible_provider_info(
|
||||
|
|
@ -43,6 +48,8 @@ class ZAIChatConfig(OpenAIGPTConfig):
|
|||
def get_supported_openai_params(self, model: str) -> list:
|
||||
base_params: Final = [
|
||||
"max_tokens",
|
||||
"max_completion_tokens",
|
||||
"response_format",
|
||||
"stream",
|
||||
"stream_options",
|
||||
"temperature",
|
||||
|
|
|
|||
|
|
@ -54934,6 +54934,21 @@
|
|||
"supports_reasoning": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"zai/GLM-5.3": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"zai/glm-5.3-flash": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
|
|
@ -54950,6 +54965,46 @@
|
|||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/GLM-5.3-Flash": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"output_cost_per_token": 5e-07,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_tool_choice": true,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/glm-5v-turbo": {
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/GLM-5V-Turbo": {
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/glm-5.1": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
|
|
|
|||
|
|
@ -54934,6 +54934,21 @@
|
|||
"supports_reasoning": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"zai/GLM-5.3": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"zai/glm-5.3-flash": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
|
|
@ -54950,6 +54965,46 @@
|
|||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/GLM-5.3-Flash": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"output_cost_per_token": 5e-07,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_tool_choice": true,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/glm-5v-turbo": {
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/GLM-5V-Turbo": {
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "zai",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"source": "https://docs.z.ai/guides/overview/pricing",
|
||||
"supports_function_calling": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"zai/glm-5.1": {
|
||||
"cache_creation_input_token_cost": 0,
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
|
|
|
|||
99
tests/unit/test_zai_glm_5_3_metadata.py
Normal file
99
tests/unit/test_zai_glm_5_3_metadata.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import json
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
import pytest
|
||||
|
||||
import litellm
|
||||
from litellm.llms.zai.chat.transformation import ZAIChatConfig
|
||||
|
||||
REPO_ROOT: Final = Path(__file__).parents[2]
|
||||
MAIN_PATH: Final = REPO_ROOT / "model_prices_and_context_window.json"
|
||||
BACKUP_PATH: Final = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json"
|
||||
|
||||
ZAI_API_KEY_ENV_VARS: Final = ("ZAI_API_KEY", "BIGMODEL_API_KEY", "ZHIPUAI_API_KEY")
|
||||
LEGACY_API_KEY_ENV_VARS: Final = ("BIGMODEL_API_KEY", "ZHIPUAI_API_KEY")
|
||||
NEW_ZAI_MODEL_KEYS: Final = ("zai/GLM-5.3", "zai/GLM-5.3-Flash", "zai/glm-5v-turbo", "zai/GLM-5V-Turbo")
|
||||
|
||||
|
||||
def _load(path: Path) -> Mapping[str, object]:
|
||||
with open(path) as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_model_cost_map(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""Resolve get_model_info against the in-repo cost map instead of the remote one
|
||||
fetched at import time."""
|
||||
monkeypatch.setenv("LITELLM_LOCAL_MODEL_COST_MAP", "True")
|
||||
monkeypatch.setattr(litellm, "model_cost", litellm.get_model_cost_map(url=""))
|
||||
litellm.get_model_info.cache_clear()
|
||||
yield
|
||||
litellm.get_model_info.cache_clear()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("legacy_env_var", LEGACY_API_KEY_ENV_VARS)
|
||||
def test_provider_info_resolves_legacy_api_key(monkeypatch: pytest.MonkeyPatch, legacy_env_var: str) -> None:
|
||||
for env_var in ZAI_API_KEY_ENV_VARS:
|
||||
monkeypatch.delenv(env_var, raising=False)
|
||||
monkeypatch.setenv(legacy_env_var, "legacy-secret")
|
||||
|
||||
api_base, api_key = ZAIChatConfig()._get_openai_compatible_provider_info(api_base=None, api_key=None)
|
||||
|
||||
assert api_key == "legacy-secret"
|
||||
assert api_base == "https://api.z.ai/api/paas/v4"
|
||||
|
||||
|
||||
def test_provider_info_prefers_zai_api_key_over_legacy(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
for env_var in ZAI_API_KEY_ENV_VARS:
|
||||
monkeypatch.setenv(env_var, f"{env_var}-secret")
|
||||
|
||||
_, api_key = ZAIChatConfig()._get_openai_compatible_provider_info(api_base=None, api_key=None)
|
||||
|
||||
assert api_key == "ZAI_API_KEY-secret"
|
||||
|
||||
|
||||
def test_supported_openai_params_include_new_params() -> None:
|
||||
params: Final = ZAIChatConfig().get_supported_openai_params(model="zai/glm-5.3")
|
||||
|
||||
assert "response_format" in params
|
||||
assert "max_completion_tokens" in params
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("alias", "canonical"),
|
||||
[
|
||||
("zai/GLM-5.3", "zai/glm-5.3"),
|
||||
("zai/GLM-5.3-Flash", "zai/glm-5.3-flash"),
|
||||
("zai/GLM-5V-Turbo", "zai/glm-5v-turbo"),
|
||||
],
|
||||
)
|
||||
def test_uppercase_alias_model_info_matches_canonical(local_model_cost_map: None, alias: str, canonical: str) -> None:
|
||||
alias_info: Final = litellm.get_model_info(alias)
|
||||
canonical_info: Final = litellm.get_model_info(canonical)
|
||||
|
||||
assert alias_info["key"] == alias
|
||||
assert {k: v for k, v in alias_info.items() if k != "key"} == {
|
||||
k: v for k, v in canonical_info.items() if k != "key"
|
||||
}
|
||||
|
||||
|
||||
def test_glm_5v_turbo_model_info(local_model_cost_map: None) -> None:
|
||||
info: Final = litellm.get_model_info("zai/glm-5v-turbo")
|
||||
|
||||
assert info["litellm_provider"] == "zai"
|
||||
assert info["mode"] == "chat"
|
||||
assert info["supports_vision"] is True
|
||||
assert info["supports_function_calling"] is True
|
||||
assert info["supports_tool_choice"] is True
|
||||
|
||||
|
||||
def test_new_zai_entries_match_between_main_and_backup() -> None:
|
||||
main_cost: Final = _load(MAIN_PATH)
|
||||
backup_cost: Final = _load(BACKUP_PATH)
|
||||
|
||||
for model in NEW_ZAI_MODEL_KEYS:
|
||||
assert backup_cost.get(model) == main_cost.get(model), (
|
||||
f"{model} differs between main and backup model cost maps"
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue