""" 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 local_model_cost_map(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("LITELLM_LOCAL_MODEL_COST_MAP", "True") monkeypatch.setattr(litellm, "model_cost", litellm.get_model_cost_map(url="")) @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(local_model_cost_map): """Test that ZAI models are in the model cost map""" 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(local_model_cost_map): """Test the cost calculation for glm-4.6""" 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(local_model_cost_map): """Test that glm-4.5-flash has zero cost""" 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(local_model_cost_map): """Test that GLM-4.7 supports reasoning""" 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(local_model_cost_map): """Test cost calculation for GLM-4.7""" 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") monkeypatch.setattr(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") monkeypatch.setattr(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