diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index 164100d4194..acb5f7d12bd 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -168,6 +168,15 @@ }, "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] }, + "greenpt": { + "base_url": "https://api.greenpt.ai/v1", + "api_key_env": "GREENPT_API_KEY", + "api_base_env": "GREENPT_API_BASE", + "param_mappings": { + "max_completion_tokens": "max_tokens" + }, + "supported_endpoints": ["/v1/chat/completions", "/v1/embeddings"] + }, "meta": { "base_url": "https://api.meta.ai/v1", "api_key_env": "META_API_KEY", diff --git a/litellm/types/utils.py b/litellm/types/utils.py index e4dfac48141..2470c6b600b 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3467,6 +3467,7 @@ class LlmProviders(str, Enum): TOPAZ = "topaz" SAP_GENERATIVE_AI_HUB = "sap" ASSEMBLYAI = "assemblyai" + GREENPT = "greenpt" CHARITY_ENGINE = "charity_engine" GITHUB_COPILOT = "github_copilot" SNOWFLAKE = "snowflake" diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index db28118d52b..2ac7b06c43d 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -46260,6 +46260,129 @@ "supports_system_messages": true, "supports_tool_choice": true }, + "greenpt/gemma4": { + "input_cost_per_token": 5.6885e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 262144, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 1.70655e-06, + "source": "https://docs.greenpt.ai/pricing", + "supports_reasoning": true, + "supports_vision": true + }, + "greenpt/glm-5.2": { + "input_cost_per_token": 1.501764e-06, + "litellm_provider": "greenpt", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 5.256174e-06, + "source": "https://docs.greenpt.ai/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "greenpt/green-embedding": { + "input_cost_per_token": 2.2754e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 32768, + "max_output_tokens": 2560, + "max_tokens": 32768, + "mode": "embedding", + "output_cost_per_token": 0, + "source": "https://docs.greenpt.ai/pricing" + }, + "greenpt/green-l": { + "input_cost_per_token": 2.84425e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 128000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "output_cost_per_token": 9.1016e-07, + "source": "https://docs.greenpt.ai/pricing", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "greenpt/green-l-raw": { + "input_cost_per_token": 2.84425e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 128000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "output_cost_per_token": 9.1016e-07, + "source": "https://docs.greenpt.ai/pricing", + "supports_function_calling": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "greenpt/green-r": { + "input_cost_per_token": 3.98195e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 131072, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 1.080815e-06, + "source": "https://docs.greenpt.ai/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "greenpt/green-r-raw": { + "input_cost_per_token": 3.98195e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 131072, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 1.080815e-06, + "source": "https://docs.greenpt.ai/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "greenpt/kimi-k2.6": { + "input_cost_per_token": 8.30521e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4.380145e-06, + "source": "https://docs.greenpt.ai/pricing", + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text" + ], + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "greenpt/minimax-m2.5": { + "input_cost_per_token": 1.93409e-07, + "litellm_provider": "greenpt", + "max_input_tokens": 200000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "output_cost_per_token": 1.126323e-06, + "source": "https://docs.greenpt.ai/pricing", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, "fallback_generalizations": { "rules": [ { diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index 65db63dc045..ec1baed2292 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -2941,6 +2941,23 @@ "rerank": false, "a2a": false } + }, + "greenpt": { + "display_name": "GreenPT (`greenpt`)", + "url": "https://docs.greenpt.ai", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": false, + "embeddings": true, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false + } } }, "endpoints": { diff --git a/tests/litellm/llms/openai_like/test_greenpt_provider.py b/tests/litellm/llms/openai_like/test_greenpt_provider.py new file mode 100644 index 00000000000..648f6f2d90b --- /dev/null +++ b/tests/litellm/llms/openai_like/test_greenpt_provider.py @@ -0,0 +1,71 @@ +import os +import sys + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../.."))) + +from litellm.llms.openai_like.dynamic_config import create_config_class +from litellm.llms.openai_like.json_loader import JSONProviderRegistry + +GREENPT_BASE_URL = "https://api.greenpt.ai/v1" + + +def _get_config(): + provider = JSONProviderRegistry.get("greenpt") + assert provider is not None + config_class = create_config_class(provider) + return config_class() + + +def test_greenpt_provider_registered(): + provider = JSONProviderRegistry.get("greenpt") + assert provider is not None + assert provider.base_url == GREENPT_BASE_URL + assert provider.api_key_env == "GREENPT_API_KEY" + assert provider.api_base_env == "GREENPT_API_BASE" + + +def test_greenpt_resolves_env_api_key(monkeypatch): + config = _get_config() + monkeypatch.setenv("GREENPT_API_KEY", "test-key") + api_base, api_key = config._get_openai_compatible_provider_info(None, None) + assert api_base == GREENPT_BASE_URL + assert api_key == "test-key" + + +def test_greenpt_maps_max_completion_tokens(): + config = _get_config() + params = config.map_openai_params( + non_default_params={"max_completion_tokens": 256}, + optional_params={}, + model="greenpt/gemma4", + drop_params=False, + ) + assert params == {"max_tokens": 256} + + +def test_greenpt_complete_url_appends_endpoint(): + config = _get_config() + url = config.get_complete_url( + api_base=GREENPT_BASE_URL, + api_key="test-key", + model="greenpt/gemma4", + optional_params={}, + litellm_params={}, + stream=False, + ) + assert url == f"{GREENPT_BASE_URL}/chat/completions" + + +def test_greenpt_provider_resolution(): + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, _, api_base = get_llm_provider( + model="greenpt/gemma4", + custom_llm_provider=None, + api_base=None, + api_key=None, + ) + + assert model == "gemma4" + assert provider == "greenpt" + assert api_base == GREENPT_BASE_URL