Files
litellm/tests/test_litellm/llms/zai/test_zai_provider.py
T
cantalupo555andGitHub 9b1c5f7e36 feat(zai): Add GLM-4.7 model with reasoning support (#18476)
Add support for Z.AI GLM-4.7, latest flagship model with enhanced reasoning capabilities.

Changes:
- Add zai/glm-4.7 to model pricing with /bin/bash.60/M input, .20/M output
- Add cached input pricing (/bin/bash.11/M) for GLM-4.7
- Add supports_reasoning flag to enable thinking parameter
- Update ZAIChatConfig to support thinking parameter for models with reasoning
- Update documentation with GLM-4.7 as latest flagship model
- Add cached input column to pricing table (GLM-4.7 only)
- Add tests for GLM-4.7 reasoning support and cost calculation
- Update all examples to use GLM-4.7

Model specifications:
- Context: 200K input, 128K output
- Supports: reasoning, function calling, tool choice, prompt caching
- Pricing: Same as GLM-4.6 with cache support

See: https://docs.z.ai/guides/llm/glm-4.7
2026-01-04 00:44:19 +05:30

182 lines
5.3 KiB
Python

"""
Tests for Z.AI (Zhipu AI) provider - GLM models
"""
import json
import math
import pytest
import respx
import litellm
from litellm import completion
from litellm.cost_calculator import cost_per_token
@pytest.fixture
def zai_response():
"""Mock response from Z.AI API"""
return {
"id": "chatcmpl-zai-123",
"object": "chat.completion",
"created": 1677652288,
"model": "glm-4.6",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "Hello! How can I help you today?"},
"finish_reason": "stop",
}
],
"usage": {"prompt_tokens": 10, "completion_tokens": 15, "total_tokens": 25},
}
def test_get_llm_provider_zai():
"""Test that get_llm_provider correctly identifies zai provider"""
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
model, provider, api_key, api_base = get_llm_provider("zai/glm-4.6")
assert model == "glm-4.6"
assert provider == "zai"
assert api_base == "https://api.z.ai/api/paas/v4"
def test_zai_in_provider_lists():
"""Test that zai is registered in all necessary provider lists"""
assert "zai" in litellm.openai_compatible_providers
assert "zai" in litellm.provider_list
def test_zai_models_in_model_cost():
"""Test that ZAI models are in the model cost map"""
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
litellm.model_cost = litellm.get_model_cost_map(url="")
zai_models = [
"zai/glm-4.7",
"zai/glm-4.6",
"zai/glm-4.5",
"zai/glm-4.5v",
"zai/glm-4.5-x",
"zai/glm-4.5-air",
"zai/glm-4.5-airx",
"zai/glm-4-32b-0414-128k",
"zai/glm-4.5-flash",
]
for model in zai_models:
assert model in litellm.model_cost, f"Model {model} not found in model_cost"
assert litellm.model_cost[model]["litellm_provider"] == "zai"
def test_zai_glm46_cost_calculation():
"""Test the cost calculation for glm-4.6"""
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
litellm.model_cost = litellm.get_model_cost_map(url="")
key = "zai/glm-4.6"
info = litellm.model_cost[key]
prompt_cost, completion_cost = cost_per_token(
model="zai/glm-4.6",
prompt_tokens=1000000, # 1M tokens
completion_tokens=1000000,
)
# GLM-4.6: $0.6/M input, $2.2/M output
assert math.isclose(prompt_cost, 0.6, rel_tol=1e-6)
assert math.isclose(completion_cost, 2.2, rel_tol=1e-6)
def test_zai_flash_model_is_free():
"""Test that glm-4.5-flash has zero cost"""
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
litellm.model_cost = litellm.get_model_cost_map(url="")
key = "zai/glm-4.5-flash"
info = litellm.model_cost[key]
assert info["input_cost_per_token"] == 0
assert info["output_cost_per_token"] == 0
def test_glm47_supports_reasoning():
"""Test that GLM-4.7 supports reasoning"""
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
litellm.model_cost = litellm.get_model_cost_map(url="")
key = "zai/glm-4.7"
assert key in litellm.model_cost, f"Model {key} not found in model_cost"
info = litellm.model_cost[key]
assert info["supports_reasoning"] is True
def test_glm47_cost_calculation():
"""Test cost calculation for GLM-4.7"""
import os
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
litellm.model_cost = litellm.get_model_cost_map(url="")
prompt_cost, completion_cost = cost_per_token(
model="zai/glm-4.7",
prompt_tokens=1000000, # 1M tokens
completion_tokens=1000000,
)
# GLM-4.7: $0.6/M input, $2.2/M output (same as GLM-4.6)
assert math.isclose(prompt_cost, 0.6, rel_tol=1e-6)
assert math.isclose(completion_cost, 2.2, rel_tol=1e-6)
@pytest.mark.asyncio
async def test_zai_completion_call(respx_mock, zai_response, monkeypatch):
"""Test completion call with zai provider using mocked response"""
monkeypatch.setenv("ZAI_API_KEY", "test-api-key")
litellm.disable_aiohttp_transport = True
respx_mock.post("https://api.z.ai/api/paas/v4/chat/completions").respond(json=zai_response)
response = await litellm.acompletion(
model="zai/glm-4.6",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=20,
)
assert response.choices[0].message.content == "Hello! How can I help you today?"
assert response.usage.total_tokens == 25
assert len(respx_mock.calls) == 1
request = respx_mock.calls[0].request
assert request.method == "POST"
assert "api.z.ai" in str(request.url)
assert "Authorization" in request.headers
assert request.headers["Authorization"] == "Bearer test-api-key"
def test_zai_sync_completion(respx_mock, zai_response, monkeypatch):
"""Test synchronous completion call"""
monkeypatch.setenv("ZAI_API_KEY", "test-api-key")
litellm.disable_aiohttp_transport = True
respx_mock.post("https://api.z.ai/api/paas/v4/chat/completions").respond(json=zai_response)
response = completion(
model="zai/glm-4.6",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=20,
)
assert response.choices[0].message.content == "Hello! How can I help you today?"
assert response.usage.total_tokens == 25