diff --git a/README.md b/README.md index 31a93bf8c67..6fd7aa77fec 100644 --- a/README.md +++ b/README.md @@ -404,6 +404,7 @@ Set `LITELLM_PROXY_API_BASE` and `LITELLM_PROXY_API_KEY` and every model call th | [Fal AI (`fal_ai`)](https://docs.litellm.ai/docs/providers/fal_ai) | ✅ | ✅ | ✅ | | ✅ | | | | | | | [Featherless AI (`featherless_ai`)](https://docs.litellm.ai/docs/providers/featherless_ai) | ✅ | ✅ | ✅ | | | | | | | | | [Fireworks AI (`fireworks_ai`)](https://docs.litellm.ai/docs/providers/fireworks_ai) | ✅ | ✅ | ✅ | | | | | | | | +| [FlexAI (`flexai`)](https://docs.litellm.ai/docs/providers/flexai) | ✅ | ✅ | ✅ | | | | | | | | | [FriendliAI (`friendliai`)](https://docs.litellm.ai/docs/providers/friendliai) | ✅ | ✅ | ✅ | | | | | | | | | [Galadriel (`galadriel`)](https://docs.litellm.ai/docs/providers/galadriel) | ✅ | ✅ | ✅ | | | | | | | | | [GitHub Copilot (`github_copilot`)](https://docs.litellm.ai/docs/providers/github_copilot) | ✅ | ✅ | ✅ | ✅ | | | | | | | diff --git a/litellm-rust/crates/core-utils/src/exception_mapping_utils/original.rs b/litellm-rust/crates/core-utils/src/exception_mapping_utils/original.rs index 615d530af19..9ae8de32699 100644 --- a/litellm-rust/crates/core-utils/src/exception_mapping_utils/original.rs +++ b/litellm-rust/crates/core-utils/src/exception_mapping_utils/original.rs @@ -114,6 +114,7 @@ const OPENAI_COMPATIBLE_PROVIDERS: &[&str] = &[ "cognition", "scx-ai", "zerogpu", + "flexai", ]; impl ExceptionFamily { diff --git a/litellm/__init__.py b/litellm/__init__.py index 8e5dd68a186..a7f570742e3 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -690,6 +690,7 @@ kyma_models: Final[set[str]] = set() # mutable-ok: populated when the shared mo streamlake_models: Final[Set[str]] = set() wally_models: Final[Set[str]] = set() zerogpu_models: Final[Set[str]] = set() +flexai_models: Final[Set[str]] = set() v0_models: Set = set() morph_models: Set = set() opencode_go_models: Final[set[str]] = set() # mutable-ok: populated when the shared model catalog loads @@ -989,6 +990,8 @@ def _populate_provider_model_sets(model_cost_map: Mapping[str, Mapping[str, obje wally_models.add(key) elif value.get("litellm_provider") == "zerogpu": zerogpu_models.add(key) + elif value.get("litellm_provider") == "flexai": + flexai_models.add(key) elif value.get("litellm_provider") == "v0": v0_models.add(key) elif value.get("litellm_provider") == "morph": @@ -1170,6 +1173,7 @@ model_list = list( | streamlake_models | wally_models | zerogpu_models + | flexai_models | v0_models | morph_models | opencode_go_models @@ -1304,6 +1308,7 @@ def _build_models_by_provider() -> dict: "streamlake": streamlake_models, "wally": wally_models, "zerogpu": zerogpu_models, + "flexai": flexai_models, "v0": v0_models, "morph": morph_models, "opencode_go": opencode_go_models, diff --git a/litellm/constants.py b/litellm/constants.py index 8d05115e76e..30052f5ea7f 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -1097,6 +1097,7 @@ openai_compatible_endpoints: Final[list[str]] = [ "https://gigachat.devices.sberbank.ru/api/v1", "https://api.openinfer.ai/v1", "https://vanchin.streamlake.ai/api/gateway/v1/endpoints", + "https://api.flex.ai/v1", ] @@ -1182,6 +1183,7 @@ openai_compatible_providers: Final[list[str]] = [ "reka", "streamlake", "wally", + "flexai", # FlexAI Token Service - JSON-configured provider ] OPENAI_AUDIO_TRANSCRIPTION_PROVIDERS: Final = frozenset({"openai"} | frozenset(openai_compatible_providers)) diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index f937e4d2f75..a3949ec41ad 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -314,5 +314,12 @@ "supports_function_calling": true, "supports_reasoning": true } + }, + "flexai": { + "base_url": "https://api.flex.ai/v1", + "api_key_env": "FLEXAI_API_KEY", + "api_base_env": "FLEXAI_API_BASE", + "base_class": "openai_gpt", + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] } } diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index a5b9a5cb457..486a9490510 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -64728,6 +64728,366 @@ ], "supports_audio_output": true }, + "flexai/bge-m3": { + "input_cost_per_token": 1e-08, + "litellm_provider": "flexai", + "max_input_tokens": 8192, + "mode": "embedding", + "output_cost_per_token": 0.0, + "output_vector_size": 1024, + "source": "https://platform.flex.ai/models" + }, + "flexai/DeepSeek-V4-Flash-0731": { + "cache_read_input_token_cost": 1.78e-08, + "input_cost_per_token": 1.19e-07, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 2.38e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/DeepSeek-V4.1-Flash-1017": { + "cache_read_input_token_cost": 2.25e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 6e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/FLUX.1-schnell": { + "input_cost_per_image": 0.0005, + "litellm_provider": "flexai", + "mode": "image_generation", + "source": "https://platform.flex.ai/models" + }, + "flexai/gemma-4-26B-A4B-it": { + "cache_read_input_token_cost": 1.05e-08, + "input_cost_per_token": 7e-08, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.4e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/gemma-4-31b-it": { + "cache_read_input_token_cost": 2.1e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/GLM-4.5-Air-FP8": { + "cache_read_input_token_cost": 2.1e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 8.6e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/GLM-5.2": { + "cache_read_input_token_cost": 1.05e-07, + "input_cost_per_token": 7e-07, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 2.2e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/GLM-5.3-Flash": { + "cache_read_input_token_cost": 1.2e-08, + "input_cost_per_token": 8e-08, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/gpt-oss-120b": { + "cache_read_input_token_cost": 7.5e-09, + "input_cost_per_token": 5e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 2.5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/gpt-oss-20b": { + "cache_read_input_token_cost": 3e-09, + "input_cost_per_token": 2e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 1e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/Kokoro-82M": { + "input_cost_per_character": 9.9e-07, + "litellm_provider": "flexai", + "mode": "audio_speech", + "source": "https://platform.flex.ai/models", + "supported_endpoints": [ + "/v1/audio/speech" + ] + }, + "flexai/Llama-3.3-70B-Instruct-FP8": { + "cache_read_input_token_cost": 3.3e-08, + "input_cost_per_token": 2.2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/Meta-Llama-3.1-8B-Instruct-FP8": { + "cache_read_input_token_cost": 3e-09, + "input_cost_per_token": 2e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 5e-08, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/MiniMax-M2.7": { + "cache_read_input_token_cost": 4.5e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "flexai", + "max_input_tokens": 204800, + "max_output_tokens": 204800, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/Mistral-Nemo-Instruct-2407-FP8": { + "cache_read_input_token_cost": 3.4e-09, + "input_cost_per_token": 2.3e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 3e-08, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/Muse-Glimmer-30B": { + "cache_read_input_token_cost": 4.5e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/NVIDIA-Nemotron-3.5-Lightning-30B-A3B": { + "cache_read_input_token_cost": 9e-09, + "input_cost_per_token": 6e-08, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 1.6e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/PaddleOCR-VL": { + "input_cost_per_token": 1.4e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 8e-07, + "source": "https://platform.flex.ai/models", + "supports_vision": true + }, + "flexai/parakeet-tdt-0.6b-v3": { + "input_cost_per_second": 2.5e-05, + "litellm_provider": "flexai", + "mode": "audio_transcription", + "output_cost_per_second": 0.0, + "source": "https://platform.flex.ai/models", + "supported_endpoints": [ + "/v1/audio/transcriptions" + ] + }, + "flexai/Qwen3-30B-A3B-Thinking-2507-FP8": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.4e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/Qwen3-Coder-30B-A3B-Instruct-FP8": { + "cache_read_input_token_cost": 1.05e-08, + "input_cost_per_token": 7e-08, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/Qwen3.5-9B": { + "cache_read_input_token_cost": 1.8e-08, + "input_cost_per_token": 1.2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 1.8e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.6-27B-FP8": { + "cache_read_input_token_cost": 4.5e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 3e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.6-35B-A3B-FP8": { + "cache_read_input_token_cost": 1.5e-08, + "input_cost_per_token": 1e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 9.5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.8-27B": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.5e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.8-Flash-Next": { + "cache_read_input_token_cost": 2.25e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4.7e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Step-3.7-Flash": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 1.15e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/whisper-large-v3-turbo": { + "input_cost_per_second": 3.333333333e-06, + "litellm_provider": "flexai", + "mode": "audio_transcription", + "output_cost_per_second": 0.0, + "source": "https://platform.flex.ai/models", + "supported_endpoints": [ + "/v1/audio/transcriptions" + ] + }, "fallback_generalizations": { "rules": [ { diff --git a/litellm/provider_endpoints_support_backup.json b/litellm/provider_endpoints_support_backup.json index 00fee0a0d5a..e15a124634d 100644 --- a/litellm/provider_endpoints_support_backup.json +++ b/litellm/provider_endpoints_support_backup.json @@ -1686,6 +1686,32 @@ "generateContent": true } }, + "flexai": { + "display_name": "FlexAI (`flexai`)", + "url": "https://docs.litellm.ai/docs/providers/flexai", + "endpoints": { + "chat_completions": true, + "responses": true, + "text_completion": true, + "embeddings": false, + "image_generations": false, + "image_edits": false, + "audio_transcriptions": false, + "audio_speech": false, + "rerank": false, + "ocr": false, + "search": false, + "moderations": false, + "realtime": false, + "video_generations": false, + "batches": false, + "messages": true, + "interactions": true, + "systemone": false, + "a2a": true, + "generateContent": true + } + }, "firecrawl": { "display_name": "Firecrawl (`firecrawl`)", "url": "https://docs.litellm.ai/docs/search/firecrawl", diff --git a/litellm/proxy/public_endpoints/provider_create_fields.json b/litellm/proxy/public_endpoints/provider_create_fields.json index 5ded2fa5f5e..15d36711896 100644 --- a/litellm/proxy/public_endpoints/provider_create_fields.json +++ b/litellm/proxy/public_endpoints/provider_create_fields.json @@ -1701,6 +1701,34 @@ ], "default_model_placeholder": "gpt-3.5-turbo" }, + { + "provider": "FLEXAI", + "provider_display_name": "FlexAI", + "litellm_provider": "flexai", + "credential_fields": [ + { + "key": "api_key", + "label": "API Key", + "placeholder": null, + "tooltip": "Your FlexAI API key from platform.flex.ai", + "required": true, + "field_type": "password", + "options": null, + "default_value": null + }, + { + "key": "api_base", + "label": "API Base", + "placeholder": "https://api.flex.ai/v1", + "tooltip": "Defaults to https://api.flex.ai/v1", + "required": false, + "field_type": "text", + "options": null, + "default_value": null + } + ], + "default_model_placeholder": "flexai/gpt-oss-120b" + }, { "provider": "FRIENDLIAI", "provider_display_name": "Friendliai", diff --git a/litellm/types/utils.py b/litellm/types/utils.py index ba29a67a36c..adc97295c87 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -4781,6 +4781,7 @@ class LlmProviders(str, Enum): REKA = "reka" STREAMLAKE = "streamlake" WALLY = "wally" + FLEXAI = "flexai" LITELLM_AGENT = "litellm_agent" CURSOR = "cursor" BEDROCK_MANTLE = "bedrock_mantle" diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index a5b9a5cb457..486a9490510 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -64728,6 +64728,366 @@ ], "supports_audio_output": true }, + "flexai/bge-m3": { + "input_cost_per_token": 1e-08, + "litellm_provider": "flexai", + "max_input_tokens": 8192, + "mode": "embedding", + "output_cost_per_token": 0.0, + "output_vector_size": 1024, + "source": "https://platform.flex.ai/models" + }, + "flexai/DeepSeek-V4-Flash-0731": { + "cache_read_input_token_cost": 1.78e-08, + "input_cost_per_token": 1.19e-07, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 2.38e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/DeepSeek-V4.1-Flash-1017": { + "cache_read_input_token_cost": 2.25e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 6e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/FLUX.1-schnell": { + "input_cost_per_image": 0.0005, + "litellm_provider": "flexai", + "mode": "image_generation", + "source": "https://platform.flex.ai/models" + }, + "flexai/gemma-4-26B-A4B-it": { + "cache_read_input_token_cost": 1.05e-08, + "input_cost_per_token": 7e-08, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.4e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/gemma-4-31b-it": { + "cache_read_input_token_cost": 2.1e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/GLM-4.5-Air-FP8": { + "cache_read_input_token_cost": 2.1e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 8.6e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/GLM-5.2": { + "cache_read_input_token_cost": 1.05e-07, + "input_cost_per_token": 7e-07, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 2.2e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/GLM-5.3-Flash": { + "cache_read_input_token_cost": 1.2e-08, + "input_cost_per_token": 8e-08, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/gpt-oss-120b": { + "cache_read_input_token_cost": 7.5e-09, + "input_cost_per_token": 5e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 2.5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/gpt-oss-20b": { + "cache_read_input_token_cost": 3e-09, + "input_cost_per_token": 2e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 1e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/Kokoro-82M": { + "input_cost_per_character": 9.9e-07, + "litellm_provider": "flexai", + "mode": "audio_speech", + "source": "https://platform.flex.ai/models", + "supported_endpoints": [ + "/v1/audio/speech" + ] + }, + "flexai/Llama-3.3-70B-Instruct-FP8": { + "cache_read_input_token_cost": 3.3e-08, + "input_cost_per_token": 2.2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/Meta-Llama-3.1-8B-Instruct-FP8": { + "cache_read_input_token_cost": 3e-09, + "input_cost_per_token": 2e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 5e-08, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/MiniMax-M2.7": { + "cache_read_input_token_cost": 4.5e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "flexai", + "max_input_tokens": 204800, + "max_output_tokens": 204800, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/Mistral-Nemo-Instruct-2407-FP8": { + "cache_read_input_token_cost": 3.4e-09, + "input_cost_per_token": 2.3e-08, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 3e-08, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/Muse-Glimmer-30B": { + "cache_read_input_token_cost": 4.5e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 1.2e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/NVIDIA-Nemotron-3.5-Lightning-30B-A3B": { + "cache_read_input_token_cost": 9e-09, + "input_cost_per_token": 6e-08, + "litellm_provider": "flexai", + "max_input_tokens": 1048576, + "max_output_tokens": 1048576, + "mode": "chat", + "output_cost_per_token": 1.6e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/PaddleOCR-VL": { + "input_cost_per_token": 1.4e-07, + "litellm_provider": "flexai", + "max_input_tokens": 131072, + "max_output_tokens": 131072, + "mode": "chat", + "output_cost_per_token": 8e-07, + "source": "https://platform.flex.ai/models", + "supports_vision": true + }, + "flexai/parakeet-tdt-0.6b-v3": { + "input_cost_per_second": 2.5e-05, + "litellm_provider": "flexai", + "mode": "audio_transcription", + "output_cost_per_second": 0.0, + "source": "https://platform.flex.ai/models", + "supported_endpoints": [ + "/v1/audio/transcriptions" + ] + }, + "flexai/Qwen3-30B-A3B-Thinking-2507-FP8": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.4e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "flexai/Qwen3-Coder-30B-A3B-Instruct-FP8": { + "cache_read_input_token_cost": 1.05e-08, + "input_cost_per_token": 7e-08, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "flexai/Qwen3.5-9B": { + "cache_read_input_token_cost": 1.8e-08, + "input_cost_per_token": 1.2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 1.8e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.6-27B-FP8": { + "cache_read_input_token_cost": 4.5e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 3e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.6-35B-A3B-FP8": { + "cache_read_input_token_cost": 1.5e-08, + "input_cost_per_token": 1e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 9.5e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.8-27B": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 2.5e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Qwen3.8-Flash-Next": { + "cache_read_input_token_cost": 2.25e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 4.7e-07, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/Step-3.7-Flash": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 2e-07, + "litellm_provider": "flexai", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 1.15e-06, + "source": "https://platform.flex.ai/models", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "flexai/whisper-large-v3-turbo": { + "input_cost_per_second": 3.333333333e-06, + "litellm_provider": "flexai", + "mode": "audio_transcription", + "output_cost_per_second": 0.0, + "source": "https://platform.flex.ai/models", + "supported_endpoints": [ + "/v1/audio/transcriptions" + ] + }, "fallback_generalizations": { "rules": [ { diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index 00fee0a0d5a..1645860c1a5 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -5509,6 +5509,32 @@ "a2a": true, "generateContent": true } + }, + "flexai": { + "display_name": "FlexAI (`flexai`)", + "url": "https://docs.litellm.ai/docs/providers/flexai", + "endpoints": { + "chat_completions": true, + "responses": true, + "text_completion": true, + "embeddings": false, + "image_generations": false, + "image_edits": false, + "audio_transcriptions": false, + "audio_speech": false, + "rerank": false, + "ocr": false, + "search": false, + "moderations": false, + "realtime": false, + "video_generations": false, + "batches": false, + "messages": true, + "interactions": true, + "systemone": false, + "a2a": true, + "generateContent": true + } } }, "endpoints": { diff --git a/tests/unit/llms/openai_like/test_flexai_provider.py b/tests/unit/llms/openai_like/test_flexai_provider.py new file mode 100644 index 00000000000..dc4c65b3ab1 --- /dev/null +++ b/tests/unit/llms/openai_like/test_flexai_provider.py @@ -0,0 +1,332 @@ +""" +Tests for FlexAI provider configuration and integration. +""" + +import json +import os + +import litellm + +# a flagship model FlexAI pins always-on; used only for provider-resolution +# assertions, which do not require the model to be reachable +FLEXAI_MODEL = "gpt-oss-120b" +FLEXAI_BASE_URL = "https://api.flex.ai/v1" + + +class TestFlexAIProviderConfig: + """Test FlexAI provider configuration""" + + def test_flexai_in_provider_list(self): + """Test that flexai is in the provider list""" + from litellm import LlmProviders + + assert hasattr(LlmProviders, "FLEXAI") + assert LlmProviders.FLEXAI.value == "flexai" + assert "flexai" in litellm.provider_list + + def test_flexai_json_config_exists(self): + """Test that flexai is configured in providers.json""" + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + assert JSONProviderRegistry.exists("flexai") + + flexai = JSONProviderRegistry.get("flexai") + assert flexai is not None + assert flexai.base_url == FLEXAI_BASE_URL + assert flexai.api_key_env == "FLEXAI_API_KEY" + assert flexai.api_base_env == "FLEXAI_API_BASE" + + def test_flexai_supports_responses_api(self): + """Test that flexai declares Responses API support""" + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + assert JSONProviderRegistry.supports_responses_api("flexai") + + def test_flexai_in_openai_compatible_providers(self): + """Test that flexai is in the openai_compatible_providers list""" + from litellm.constants import ( + openai_compatible_endpoints, + openai_compatible_providers, + ) + + assert "flexai" in openai_compatible_providers + assert FLEXAI_BASE_URL in openai_compatible_endpoints + + def test_flexai_provider_resolution(self): + """Test that provider resolution finds flexai and returns the default base URL""" + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, api_key, api_base = get_llm_provider( + model=f"flexai/{FLEXAI_MODEL}", + custom_llm_provider=None, + api_base=None, + api_key=None, + ) + + assert model == FLEXAI_MODEL + assert provider == "flexai" + assert api_base == FLEXAI_BASE_URL + + def test_flexai_api_base_override(self): + """Test that an explicit api_base / api_key overrides the default""" + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, api_key, api_base = get_llm_provider( + model=f"flexai/{FLEXAI_MODEL}", + custom_llm_provider=None, + api_base="https://tokens.staging.flex.ai/v1", + api_key="sk-test", + ) + + assert provider == "flexai" + assert api_base == "https://tokens.staging.flex.ai/v1" + assert api_key == "sk-test" + + def test_flexai_env_key_resolution(self, monkeypatch): + """Test that the key is read from FLEXAI_API_KEY when not passed explicitly""" + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + monkeypatch.setenv("FLEXAI_API_KEY", "sk-flexai-env") + + config = create_config_class(JSONProviderRegistry.get("flexai"))() + api_base, api_key = config._get_openai_compatible_provider_info(None, None) + + assert api_base == FLEXAI_BASE_URL + assert api_key == "sk-flexai-env" + + def test_flexai_url_autodetection(self): + """Test that api_base=api.flex.ai/v1 auto-sets custom_llm_provider=flexai""" + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, api_key, api_base = get_llm_provider( + model=FLEXAI_MODEL, + custom_llm_provider=None, + api_base=FLEXAI_BASE_URL, + api_key=None, + ) + + assert provider == "flexai" + assert api_base == FLEXAI_BASE_URL + + def test_flexai_url_autodetection_prefers_caller_key(self, monkeypatch): + """An explicit api_key must win over the server's FLEXAI_API_KEY. + + `completion()` overwrites api_key with dynamic_api_key whenever it is + set, so reading the environment unconditionally here would spend the + server's credential on a caller-supplied api_base. + """ + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + monkeypatch.setenv("FLEXAI_API_KEY", "sk-server-env") + + _, provider, api_key, _ = get_llm_provider( + model=FLEXAI_MODEL, + custom_llm_provider=None, + api_base=FLEXAI_BASE_URL, + api_key="sk-caller", + ) + + assert provider == "flexai" + assert api_key == "sk-caller" + + def test_flexai_url_autodetection_falls_back_to_env_key(self, monkeypatch): + """With no explicit key, the server environment is still used""" + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + monkeypatch.setenv("FLEXAI_API_KEY", "sk-server-env") + + _, provider, api_key, _ = get_llm_provider( + model=FLEXAI_MODEL, + custom_llm_provider=None, + api_base=FLEXAI_BASE_URL, + api_key=None, + ) + + assert provider == "flexai" + assert api_key == "sk-server-env" + + def test_flexai_router_config(self): + """Test that flexai can be used in Router configuration""" + from litellm import Router + + router = Router( + model_list=[ + { + "model_name": "flexai-chat", + "litellm_params": { + "model": f"flexai/{FLEXAI_MODEL}", + "api_key": "test-key", + }, + } + ] + ) + + assert len(router.model_list) == 1 + assert router.model_list[0]["model_name"] == "flexai-chat" + + +class TestFlexAICostMap: + """Test the FlexAI entries in the model cost map""" + + @staticmethod + def _cost_map(): + repo_root = os.path.abspath( + os.path.join(os.path.dirname(__file__), "../../../..") + ) + with open(os.path.join(repo_root, "model_prices_and_context_window.json")) as f: + return json.load(f) + + @staticmethod + def _backup_cost_map(): + repo_root = os.path.abspath( + os.path.join(os.path.dirname(__file__), "../../../..") + ) + path = os.path.join( + repo_root, "litellm", "model_prices_and_context_window_backup.json" + ) + with open(path) as f: + return json.load(f) + + def test_flexai_entries_present(self): + """Test that flexai models are priced in the cost map""" + entries = { + k: v for k, v in self._cost_map().items() if k.startswith("flexai/") + } + + assert entries, "no flexai/* entries in the cost map" + for key, entry in entries.items(): + assert entry["litellm_provider"] == "flexai", key + assert entry.get("mode"), key + + def test_flexai_chat_entries_are_priced(self): + """Test that every flexai chat model carries per-token pricing + context""" + entries = { + k: v + for k, v in self._cost_map().items() + if k.startswith("flexai/") and v.get("mode") == "chat" + } + + assert entries, "no flexai/* chat entries in the cost map" + for key, entry in entries.items(): + assert entry["input_cost_per_token"] > 0, key + assert entry["output_cost_per_token"] > 0, key + assert entry["max_input_tokens"] > 0, key + assert entry["max_output_tokens"] > 0, key + + def test_flexai_entries_match_packaged_backup(self): + """Test that the packaged backup carries the same flexai entries. + + litellm loads the packaged backup when the remote cost map is + unavailable (or when LITELLM_LOCAL_MODEL_COST_MAP=True), so the two + files must not drift. + """ + root = {k: v for k, v in self._cost_map().items() if k.startswith("flexai/")} + backup = { + k: v for k, v in self._backup_cost_map().items() if k.startswith("flexai/") + } + + assert root == backup + + def test_flexai_non_chat_entries_use_calculator_readable_fields(self): + """Non-chat entries must carry the cost fields the generic calculators read. + + `default_image_cost_calculator` reads `input_cost_per_image` / + `input_cost_per_pixel`, and `select_cost_metric_for_model` requires + `input_cost_per_character` (or `input_cost_per_token`) for speech. Using + the `output_*` variants instead makes cost calculation raise rather than + return the configured cost. + """ + readable_fields = { + "image_generation": ("input_cost_per_image", "input_cost_per_pixel"), + "audio_speech": ("input_cost_per_character", "input_cost_per_token"), + "audio_transcription": ("input_cost_per_second", "input_cost_per_token"), + "embedding": ("input_cost_per_token",), + } + + entries = { + k: v + for k, v in self._cost_map().items() + if k.startswith("flexai/") and v.get("mode") != "chat" + } + assert entries, "no non-chat flexai/* entries in the cost map" + + for key, entry in entries.items(): + options = readable_fields.get(entry["mode"]) + assert options, f"{key}: unhandled mode {entry['mode']}" + assert any(field in entry for field in options), ( + f"{key} (mode={entry['mode']}) has none of {options}" + ) + + def test_flexai_image_cost_calculation(self): + """Test that image cost resolves through the generic image calculator""" + from litellm.cost_calculator import default_image_cost_calculator + + cost_map = self._cost_map() + key = next( + k + for k, v in cost_map.items() + if k.startswith("flexai/") and v.get("mode") == "image_generation" + ) + per_image = cost_map[key]["input_cost_per_image"] + + for n in (1, 3): + cost = default_image_cost_calculator( + model=key, custom_llm_provider="flexai", n=n, quality=None, size=None + ) + assert cost == per_image * n + + def test_flexai_speech_cost_calculation(self): + """Test that TTS cost resolves per input character""" + from litellm.cost_calculator import cost_per_token + from litellm.litellm_core_utils.llm_cost_calc.utils import ( + select_cost_metric_for_model, + ) + + cost_map = self._cost_map() + key = next( + k + for k, v in cost_map.items() + if k.startswith("flexai/") and v.get("mode") == "audio_speech" + ) + model = key.split("/", 1)[1] + per_character = cost_map[key]["input_cost_per_character"] + + model_info = litellm.get_model_info(model=model, custom_llm_provider="flexai") + assert select_cost_metric_for_model(model_info) == "cost_per_character" + + prompt_cost, completion_cost = cost_per_token( + model=model, + custom_llm_provider="flexai", + call_type="speech", + prompt_characters=1000, + ) + assert prompt_cost + completion_cost == per_character * 1000 + + def test_flexai_cost_calculation(self): + """Test that completion_cost resolves for a flexai chat model""" + from litellm.types.utils import Choices, Message, ModelResponse, Usage + + cost_map = self._cost_map() + key = next( + k + for k, v in cost_map.items() + if k.startswith("flexai/") and v.get("mode") == "chat" + ) + entry = cost_map[key] + + response = ModelResponse( + model=key.split("/", 1)[1], + choices=[Choices(message=Message(role="assistant", content="ok"))], + usage=Usage(prompt_tokens=1000, completion_tokens=500, total_tokens=1500), + ) + response._hidden_params = {"custom_llm_provider": "flexai"} + + cost = litellm.completion_cost( + completion_response=response, custom_llm_provider="flexai", model=key + ) + + expected = ( + 1000 * entry["input_cost_per_token"] + 500 * entry["output_cost_per_token"] + ) + assert cost == expected diff --git a/tests/unit/proxy/public_endpoints/test_public_endpoints.py b/tests/unit/proxy/public_endpoints/test_public_endpoints.py index dd3ffad4727..56a72576093 100644 --- a/tests/unit/proxy/public_endpoints/test_public_endpoints.py +++ b/tests/unit/proxy/public_endpoints/test_public_endpoints.py @@ -447,6 +447,25 @@ def test_zerogpu_add_model_form_defaults_resolve_to_a_priced_zerogpu_model(): assert fields_by_key["api_key"]["field_type"] == "password" +def test_flexai_add_model_form_defaults_resolve_to_a_priced_flexai_model(): + import litellm + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + app_instance: Final = FastAPI() + app_instance.include_router(router) + providers: Final = TestClient(app_instance).get("/public/providers/fields").json() + + flexai: Final = next(p for p in providers if p["litellm_provider"] == "flexai") + fields_by_key: Final = {f["key"]: f for f in flexai["credential_fields"]} + placeholder: Final = flexai["default_model_placeholder"] + _, provider, _, api_base = get_llm_provider(model=placeholder) + + assert provider == "flexai" + assert api_base == fields_by_key["api_base"]["placeholder"] + assert litellm.model_cost[placeholder]["litellm_provider"] == "flexai" + assert fields_by_key["api_key"]["required"] is True + assert fields_by_key["api_key"]["field_type"] == "password" + def test_qwen_mainland_provider_fields_carry_the_qianwen_brand(): app_instance = FastAPI() app_instance.include_router(router) diff --git a/tests/unit/test_model_prices_and_context_window.py b/tests/unit/test_model_prices_and_context_window.py index e195b970fd5..0b439b1e0b5 100644 --- a/tests/unit/test_model_prices_and_context_window.py +++ b/tests/unit/test_model_prices_and_context_window.py @@ -132,6 +132,16 @@ def test_zerogpu_rows_have_an_output_limit_that_fits_the_context_window(path: Pa assert tuple(key for key, row in rows.items() if row.max_output_tokens > row.max_input_tokens) == () +@pytest.mark.parametrize("path", (PRICES_PATH, BACKUP_PRICES_PATH), ids=("main", "backup")) +def test_flexai_chat_rows_have_an_output_limit_that_fits_the_context_window(path: Path) -> None: + prices: Final[dict[str, JsonValue]] = TypeAdapter(dict[str, JsonValue]).validate_json(path.read_bytes()) + rows: Final = MappingProxyType( + {key: _TokenLimits.model_validate(value) for key, value in prices.items() if key.startswith("flexai/") and isinstance(value, dict) and value.get("mode") == "chat"} + ) + assert rows, f"No FlexAI chat rows found in {path}" + assert tuple(key for key, row in rows.items() if row.max_output_tokens > row.max_input_tokens) == () + + def test_github_copilot_rows_resolve_through_get_model_info() -> None: rows: Final[Mapping[str, _CopilotEndpointRow]] = _copilot_endpoint_rows(PRICES_PATH) assert { diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx index 604d5923caa..c389480c3e5 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx @@ -273,6 +273,7 @@ describe("provider_info_helpers", () => { Providers.WANDB, Providers.ZAI, Providers.ZeroGPU, + Providers.FlexAI, ]; const logolessProviders = Object.values(Providers).filter((provider) => !providerLogoMap[provider]); expect([...logolessProviders].sort()).toEqual([...knownLogolessProviders].sort()); @@ -410,6 +411,10 @@ describe("provider_info_helpers", () => { expect(getPlaceholder("ZeroGPU")).toBe("zerogpu/gpt-oss-120b"); }); + it("should return flexai/gpt-oss-120b placeholder for FlexAI provider", () => { + expect(getPlaceholder("FlexAI")).toBe("flexai/gpt-oss-120b"); + }); + it("should return a chatgpt/ placeholder for the CHATGPT dropdown key", () => { expect(getPlaceholder("CHATGPT")).toBe("chatgpt/gpt-5.4"); }); diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index 167343fc05e..59b6f4b9ae7 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -209,6 +209,7 @@ export enum Providers { ZAI = "Z.AI (Zhipu AI)", BIGMODEL = "BigModel (Zhipu AI)", ZeroGPU = "ZeroGPU", + FlexAI = "FlexAI", } export const provider_map: Record = { @@ -345,6 +346,7 @@ export const provider_map: Record = { ZAI: "zai", BIGMODEL: "bigmodel", ZeroGPU: "zerogpu", + FlexAI: "flexai", }; const standaloneSubproviderSlugs = new Set(["bedrock_mantle", "meta_llama"]); @@ -530,6 +532,7 @@ const providerPlaceholderMap: Partial> = { [Providers.ZAI]: "zai/glm-4.5", [Providers.BIGMODEL]: "bigmodel/glm-5.3", [Providers.ZeroGPU]: "zerogpu/gpt-oss-120b", + [Providers.FlexAI]: "flexai/gpt-oss-120b", }; export const getPlaceholder = (selectedProvider: string): string => {