From ae92404d05b8e224b6632edfe5a5ef335061ea42 Mon Sep 17 00:00:00 2001 From: Eddie Richter Date: Thu, 18 Sep 2025 13:06:09 -0600 Subject: [PATCH] Initial addition of Lemonade provider. --- litellm/__init__.py | 7 +++++ litellm/constants.py | 1 + .../get_llm_provider_logic.py | 11 +++++++ litellm/main.py | 31 +++++++++++++++++++ ...odel_prices_and_context_window_backup.json | 10 ++++++ litellm/types/utils.py | 1 + model_prices_and_context_window.json | 10 ++++++ 7 files changed, 71 insertions(+) diff --git a/litellm/__init__.py b/litellm/__init__.py index 02bb773d268..078c4348206 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -250,6 +250,7 @@ wandb_key: Optional[str] = None heroku_key: Optional[str] = None cometapi_key: Optional[str] = None ovhcloud_key: Optional[str] = None +lemonade_key: Optional[str] = None common_cloud_provider_auth_params: dict = { "params": ["project", "region_name", "token"], "providers": ["vertex_ai", "bedrock", "watsonx", "azure", "vertex_ai_beta"], @@ -536,6 +537,7 @@ volcengine_models: Set = set() wandb_models: Set = set(WANDB_MODELS) ovhcloud_models: Set = set() ovhcloud_embedding_models: Set = set() +lemonade_models: Set = set() def is_bedrock_pricing_only_model(key: str) -> bool: @@ -756,6 +758,8 @@ def add_known_models(): ovhcloud_models.add(key) elif value.get("litellm_provider") == "ovhcloud-embedding-models": ovhcloud_embedding_models.add(key) + elif value.get("litellm_provider") == "lemonade": + lemonade_models.add(key) add_known_models() @@ -852,6 +856,7 @@ model_list = list( | volcengine_models | wandb_models | ovhcloud_models + | lemonade_models ) model_list_set = set(model_list) @@ -935,6 +940,7 @@ models_by_provider: dict = { "volcengine": volcengine_models, "wandb": wandb_models, "ovhcloud": ovhcloud_models | ovhcloud_embedding_models, + "lemonade": lemonade_models, } # mapping for those models which have larger equivalents @@ -1284,6 +1290,7 @@ from .llms.hyperbolic.chat.transformation import HyperbolicChatConfig from .llms.vercel_ai_gateway.chat.transformation import VercelAIGatewayConfig from .llms.ovhcloud.chat.transformation import OVHCloudChatConfig from .llms.ovhcloud.embedding.transformation import OVHCloudEmbeddingConfig +from .llms.lemonade.chat.transformation import LemonadeChatConfig from .main import * # type: ignore from .integrations import * from .llms.custom_httpx.async_client_cleanup import close_litellm_async_clients diff --git a/litellm/constants.py b/litellm/constants.py index b839256b78e..3ff9a4b6fb0 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -315,6 +315,7 @@ LITELLM_CHAT_PROVIDERS = [ "vercel_ai_gateway", "wandb", "ovhcloud", + "lemonade" ] LITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENS = [ diff --git a/litellm/litellm_core_utils/get_llm_provider_logic.py b/litellm/litellm_core_utils/get_llm_provider_logic.py index 69c996d8139..f209aed483c 100644 --- a/litellm/litellm_core_utils/get_llm_provider_logic.py +++ b/litellm/litellm_core_utils/get_llm_provider_logic.py @@ -368,6 +368,8 @@ def get_llm_provider( # noqa: PLR0915 # bytez models elif model.startswith("bytez/"): custom_llm_provider = "bytez" + elif model.startswith("lemonade/"): + custom_llm_provider = "lemonade" elif model.startswith("heroku/"): custom_llm_provider = "heroku" # cometapi models @@ -379,6 +381,8 @@ def get_llm_provider( # noqa: PLR0915 custom_llm_provider = "compactifai" elif model.startswith("ovhcloud/"): custom_llm_provider = "ovhcloud" + elif model.startswith("lemonade/"): + custom_llm_provider = "lemonade" if not custom_llm_provider: if litellm.suppress_debug_info is False: print() # noqa @@ -783,6 +787,13 @@ def _get_openai_compatible_provider_info( # noqa: PLR0915 or "https://api.inference.wandb.ai/v1" ) # type: ignore dynamic_api_key = api_key or get_secret_str("WANDB_API_KEY") + elif custom_llm_provider == "lemonade": + ( + api_base, + dynamic_api_key, + ) = litellm.LemonadeChatConfig()._get_openai_compatible_provider_info( + api_base, api_key + ) if api_base is not None and not isinstance(api_base, str): raise Exception("api base needs to be a string. api_base={}".format(api_base)) diff --git a/litellm/main.py b/litellm/main.py index 351d3d69eb7..76b39329866 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -149,6 +149,7 @@ from .llms.bedrock.chat import BedrockConverseLLM, BedrockLLM from .llms.bedrock.embed.embedding import BedrockEmbedding from .llms.bedrock.image.image_handler import BedrockImageGeneration from .llms.bytez.chat.transformation import BytezChatConfig +from .llms.lemonade.chat.transformation import LemonadeChatConfig from .llms.codestral.completion.handler import CodestralTextCompletion from .llms.cohere.embed import handler as cohere_embed from .llms.custom_httpx.aiohttp_handler import BaseLLMAIOHTTPHandler @@ -267,6 +268,7 @@ bytez_transformation = BytezChatConfig() heroku_transformation = HerokuChatConfig() oci_transformation = OCIChatConfig() ovhcloud_transformation = OVHCloudChatConfig() +lemonade_transformation = LemonadeChatConfig() ####### COMPLETION ENDPOINTS ################ @@ -3545,6 +3547,35 @@ def completion( # type: ignore # noqa: PLR0915 ) pass + elif custom_llm_provider == "lemonade": + api_key = ( + api_key + or litellm.bytez_key + or get_secret_str("LEMONADE_API_KEY") + or litellm.api_key + ) + + response = base_llm_http_handler.completion( + model=model, + messages=messages, + headers=headers, + model_response=model_response, + api_key=api_key, + api_base=api_base, + acompletion=acompletion, + logging_obj=logging, + optional_params=optional_params, + litellm_params=litellm_params, + timeout=timeout, # type: ignore + client=client, + custom_llm_provider=custom_llm_provider, + encoding=encoding, + stream=stream, + provider_config=lemonade_transformation, + ) + + pass + elif custom_llm_provider == "ovhcloud" or model in litellm.ovhcloud_models: api_key = ( diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index f855547a530..e9404f885b5 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -13256,6 +13256,16 @@ ], "supports_tool_choice": false }, + "lemonade/Qwen3-Coder-30B-A3B-Instruct-GGUF": { + "input_cost_per_token": 0, + "litellm_provider": "lemonade", + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 0, + "supports_function_calling": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, "groq/deepseek-r1-distill-llama-70b": { "input_cost_per_token": 7.5e-07, "litellm_provider": "groq", diff --git a/litellm/types/utils.py b/litellm/types/utils.py index b0183249ba2..e5786e50a5d 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -2428,6 +2428,7 @@ class LlmProviders(str, Enum): DOTPROMPT = "dotprompt" WANDB = "wandb" OVHCLOUD = "ovhcloud" + LEMONADE = "lemonade" # Create a set of all provider values for quick lookup diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index f855547a530..e9404f885b5 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -13256,6 +13256,16 @@ ], "supports_tool_choice": false }, + "lemonade/Qwen3-Coder-30B-A3B-Instruct-GGUF": { + "input_cost_per_token": 0, + "litellm_provider": "lemonade", + "max_tokens": 32768, + "mode": "chat", + "output_cost_per_token": 0, + "supports_function_calling": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, "groq/deepseek-r1-distill-llama-70b": { "input_cost_per_token": 7.5e-07, "litellm_provider": "groq",