mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-30 06:43:27 +00:00
Merge b250ff66eb into bc18e10f6b
This commit is contained in:
commit
a9859ee1d3
14 changed files with 1049 additions and 0 deletions
|
|
@ -680,6 +680,7 @@ moonshot_models: Set = set()
|
|||
publicai_models: Set = set()
|
||||
darkbloom_models: Set = set()
|
||||
openinfer_models: Final[Set[str]] = set()
|
||||
streamlake_models: Final[Set[str]] = set()
|
||||
v0_models: Set = set()
|
||||
morph_models: Set = set()
|
||||
lambda_ai_models: Set = set()
|
||||
|
|
@ -966,6 +967,8 @@ def _populate_provider_model_sets(model_cost_map: Mapping[str, Mapping[str, obje
|
|||
darkbloom_models.add(key)
|
||||
elif value.get("litellm_provider") == "openinfer":
|
||||
openinfer_models.add(key)
|
||||
elif value.get("litellm_provider") == "streamlake":
|
||||
streamlake_models.add(key)
|
||||
elif value.get("litellm_provider") == "v0":
|
||||
v0_models.add(key)
|
||||
elif value.get("litellm_provider") == "morph":
|
||||
|
|
@ -1135,6 +1138,7 @@ model_list = list(
|
|||
| publicai_models
|
||||
| darkbloom_models
|
||||
| openinfer_models
|
||||
| streamlake_models
|
||||
| v0_models
|
||||
| morph_models
|
||||
| lambda_ai_models
|
||||
|
|
@ -1252,6 +1256,7 @@ def _build_models_by_provider() -> dict:
|
|||
"publicai": publicai_models,
|
||||
"darkbloom": darkbloom_models,
|
||||
"openinfer": openinfer_models,
|
||||
"streamlake": streamlake_models,
|
||||
"v0": v0_models,
|
||||
"morph": morph_models,
|
||||
"lambda_ai": lambda_ai_models,
|
||||
|
|
|
|||
|
|
@ -1060,6 +1060,7 @@ openai_compatible_endpoints: Final[list[str]] = [
|
|||
"https://api.reka.ai/v1",
|
||||
"https://gigachat.devices.sberbank.ru/api/v1",
|
||||
"https://api.openinfer.ai/v1",
|
||||
"https://vanchin.streamlake.ai/api/gateway/v1/endpoints",
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -1138,6 +1139,7 @@ openai_compatible_providers: Final[list[str]] = [
|
|||
"prism",
|
||||
"sail",
|
||||
"reka",
|
||||
"streamlake",
|
||||
]
|
||||
|
||||
OPENAI_AUDIO_TRANSCRIPTION_PROVIDERS: Final = frozenset({"openai"} | frozenset(openai_compatible_providers))
|
||||
|
|
|
|||
|
|
@ -249,5 +249,18 @@
|
|||
"/v1/responses",
|
||||
"/v1/messages"
|
||||
]
|
||||
},
|
||||
"streamlake": {
|
||||
"base_url": "https://vanchin.streamlake.ai/api/gateway/v1/endpoints",
|
||||
"api_key_env": "STREAMLAKE_API_KEY",
|
||||
"api_base_env": "STREAMLAKE_API_BASE",
|
||||
"param_mappings": {
|
||||
"max_completion_tokens": "max_tokens"
|
||||
},
|
||||
"provider_info": {
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true
|
||||
},
|
||||
"supported_endpoints": ["/v1/chat/completions"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62175,6 +62175,297 @@
|
|||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"streamlake/deepseek-v4-flash-0731": {
|
||||
"cache_read_input_token_cost": 1.4e-08,
|
||||
"input_cost_per_token": 4.4e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.32e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/DeepSeek-V4-Pro-0813": {
|
||||
"cache_read_input_token_cost": 4.4e-08,
|
||||
"input_cost_per_token": 1.32e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.96e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/DeepSeek-V3": {
|
||||
"cache_read_input_token_cost": 1.14e-07,
|
||||
"input_cost_per_token": 2.86e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 56000,
|
||||
"max_output_tokens": 8000,
|
||||
"max_tokens": 8000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.143e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": false,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/GLM-5.3": {
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_assistant_prefill": true,
|
||||
"supports_prompt_caching": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/GLM-5.3-Flash": {
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 5e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true,
|
||||
"supports_assistant_prefill": true,
|
||||
"supports_prompt_caching": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/Kimi-K2-Instruct-0905": {
|
||||
"cache_read_input_token_cost": 1.43e-07,
|
||||
"input_cost_per_token": 5.71e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 224000,
|
||||
"max_output_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.286e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": false,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-r1": {
|
||||
"cache_read_input_token_cost": 2.29e-07,
|
||||
"input_cost_per_token": 5.71e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 112000,
|
||||
"max_output_tokens": 16000,
|
||||
"max_tokens": 16000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.286e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v3.1": {
|
||||
"cache_read_input_token_cost": 2.29e-07,
|
||||
"input_cost_per_token": 5.71e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 96000,
|
||||
"max_output_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.714e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4-flash": {
|
||||
"cache_read_input_token_cost": 2.8e-08,
|
||||
"input_cost_per_token": 1.4e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.8e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4-pro": {
|
||||
"cache_read_input_token_cost": 1.45e-07,
|
||||
"input_cost_per_token": 1.74e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.48e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4.1-flash-1017": {
|
||||
"cache_read_input_token_cost": 6e-09,
|
||||
"input_cost_per_token": 3e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4.1-flash-260910": {
|
||||
"cache_read_input_token_cost": 6e-09,
|
||||
"input_cost_per_token": 3e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/glm-5": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
"input_cost_per_token": 1e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/glm-5.1": {
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/glm-5.2": {
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/kimi-k2.6": {
|
||||
"cache_read_input_token_cost": 1.6e-07,
|
||||
"input_cost_per_token": 9.5e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 256000,
|
||||
"max_output_tokens": 256000,
|
||||
"max_tokens": 256000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4e-06,
|
||||
"supports_function_calling": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/kimi-k2.7-code": {
|
||||
"cache_read_input_token_cost": 1.9e-07,
|
||||
"input_cost_per_token": 9.5e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 256000,
|
||||
"max_output_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/minimax-m2.5": {
|
||||
"cache_creation_input_token_cost": 3.75e-07,
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
"input_cost_per_token": 3e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.5-397b-a17b": {
|
||||
"cache_read_input_token_cost": 1.2e-07,
|
||||
"input_cost_per_token": 6e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 252000,
|
||||
"max_output_tokens": 64000,
|
||||
"max_tokens": 64000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.6e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.6-27b": {
|
||||
"input_cost_per_token": 6e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 254000,
|
||||
"max_output_tokens": 64000,
|
||||
"max_tokens": 64000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.6e-06,
|
||||
"supports_function_calling": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.6-35b-a3b": {
|
||||
"input_cost_per_token": 3.75e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 254000,
|
||||
"max_output_tokens": 64000,
|
||||
"max_tokens": 64000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.25e-06,
|
||||
"supports_function_calling": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.8-2.4t-a95b": {
|
||||
"input_cost_per_token": 2e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 991000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 6e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"deepseek-v4-flash": {
|
||||
"cache_creation_input_token_cost": 0.0,
|
||||
"cache_read_input_token_cost": 6e-09,
|
||||
|
|
|
|||
|
|
@ -2748,6 +2748,23 @@
|
|||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
},
|
||||
"streamlake": {
|
||||
"display_name": "StreamLake (`streamlake`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/openai_compatible",
|
||||
"endpoints": {
|
||||
"chat_completions": true,
|
||||
"messages": false,
|
||||
"responses": false,
|
||||
"embeddings": false,
|
||||
"image_generations": false,
|
||||
"audio_transcriptions": false,
|
||||
"audio_speech": false,
|
||||
"moderations": false,
|
||||
"batches": false,
|
||||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"endpoints": {
|
||||
|
|
|
|||
|
|
@ -3417,6 +3417,34 @@
|
|||
],
|
||||
"default_model_placeholder": "inferenceapis/deepseek-ai/DeepSeek-V4-Flash"
|
||||
},
|
||||
{
|
||||
"provider": "StreamLake",
|
||||
"provider_display_name": "StreamLake",
|
||||
"litellm_provider": "streamlake",
|
||||
"credential_fields": [
|
||||
{
|
||||
"key": "api_base",
|
||||
"label": "API Base",
|
||||
"placeholder": "https://vanchin.streamlake.ai/api/gateway/v1/endpoints",
|
||||
"tooltip": null,
|
||||
"required": false,
|
||||
"field_type": "text",
|
||||
"options": null,
|
||||
"default_value": null
|
||||
},
|
||||
{
|
||||
"key": "api_key",
|
||||
"label": "API Key",
|
||||
"placeholder": null,
|
||||
"tooltip": null,
|
||||
"required": true,
|
||||
"field_type": "password",
|
||||
"options": null,
|
||||
"default_value": null
|
||||
}
|
||||
],
|
||||
"default_model_placeholder": "streamlake/GLM-5.3-Flash"
|
||||
},
|
||||
{
|
||||
"provider": "Snowflake",
|
||||
"provider_display_name": "Snowflake",
|
||||
|
|
|
|||
|
|
@ -4553,6 +4553,7 @@ class LlmProviders(str, Enum):
|
|||
META = "meta"
|
||||
SAIL = "sail"
|
||||
REKA = "reka"
|
||||
STREAMLAKE = "streamlake"
|
||||
LITELLM_AGENT = "litellm_agent"
|
||||
CURSOR = "cursor"
|
||||
BEDROCK_MANTLE = "bedrock_mantle"
|
||||
|
|
|
|||
|
|
@ -62175,6 +62175,297 @@
|
|||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"streamlake/deepseek-v4-flash-0731": {
|
||||
"cache_read_input_token_cost": 1.4e-08,
|
||||
"input_cost_per_token": 4.4e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.32e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/DeepSeek-V4-Pro-0813": {
|
||||
"cache_read_input_token_cost": 4.4e-08,
|
||||
"input_cost_per_token": 1.32e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.96e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/DeepSeek-V3": {
|
||||
"cache_read_input_token_cost": 1.14e-07,
|
||||
"input_cost_per_token": 2.86e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 56000,
|
||||
"max_output_tokens": 8000,
|
||||
"max_tokens": 8000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.143e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": false,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/GLM-5.3": {
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_assistant_prefill": true,
|
||||
"supports_prompt_caching": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/GLM-5.3-Flash": {
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 5e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true,
|
||||
"supports_assistant_prefill": true,
|
||||
"supports_prompt_caching": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/Kimi-K2-Instruct-0905": {
|
||||
"cache_read_input_token_cost": 1.43e-07,
|
||||
"input_cost_per_token": 5.71e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 224000,
|
||||
"max_output_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.286e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": false,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-r1": {
|
||||
"cache_read_input_token_cost": 2.29e-07,
|
||||
"input_cost_per_token": 5.71e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 112000,
|
||||
"max_output_tokens": 16000,
|
||||
"max_tokens": 16000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.286e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v3.1": {
|
||||
"cache_read_input_token_cost": 2.29e-07,
|
||||
"input_cost_per_token": 5.71e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 96000,
|
||||
"max_output_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.714e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4-flash": {
|
||||
"cache_read_input_token_cost": 2.8e-08,
|
||||
"input_cost_per_token": 1.4e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.8e-07,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4-pro": {
|
||||
"cache_read_input_token_cost": 1.45e-07,
|
||||
"input_cost_per_token": 1.74e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.48e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4.1-flash-1017": {
|
||||
"cache_read_input_token_cost": 6e-09,
|
||||
"input_cost_per_token": 3e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/deepseek-v4.1-flash-260910": {
|
||||
"cache_read_input_token_cost": 6e-09,
|
||||
"input_cost_per_token": 3e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 384000,
|
||||
"max_tokens": 384000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/glm-5": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
"input_cost_per_token": 1e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/glm-5.1": {
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/glm-5.2": {
|
||||
"cache_read_input_token_cost": 2.6e-07,
|
||||
"input_cost_per_token": 1.4e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4.4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/kimi-k2.6": {
|
||||
"cache_read_input_token_cost": 1.6e-07,
|
||||
"input_cost_per_token": 9.5e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 256000,
|
||||
"max_output_tokens": 256000,
|
||||
"max_tokens": 256000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4e-06,
|
||||
"supports_function_calling": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/kimi-k2.7-code": {
|
||||
"cache_read_input_token_cost": 1.9e-07,
|
||||
"input_cost_per_token": 9.5e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 256000,
|
||||
"max_output_tokens": 32000,
|
||||
"max_tokens": 32000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 4e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/minimax-m2.5": {
|
||||
"cache_creation_input_token_cost": 3.75e-07,
|
||||
"cache_read_input_token_cost": 3e-08,
|
||||
"input_cost_per_token": 3e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 200000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.2e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.5-397b-a17b": {
|
||||
"cache_read_input_token_cost": 1.2e-07,
|
||||
"input_cost_per_token": 6e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 252000,
|
||||
"max_output_tokens": 64000,
|
||||
"max_tokens": 64000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.6e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.6-27b": {
|
||||
"input_cost_per_token": 6e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 254000,
|
||||
"max_output_tokens": 64000,
|
||||
"max_tokens": 64000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.6e-06,
|
||||
"supports_function_calling": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.6-35b-a3b": {
|
||||
"input_cost_per_token": 3.75e-07,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 254000,
|
||||
"max_output_tokens": 64000,
|
||||
"max_tokens": 64000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.25e-06,
|
||||
"supports_function_calling": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"streamlake/qwen3.8-2.4t-a95b": {
|
||||
"input_cost_per_token": 2e-06,
|
||||
"litellm_provider": "streamlake",
|
||||
"max_input_tokens": 991000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 6e-06,
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"source": "https://www.streamlake.ai/document/DOC/mgrnm4xm362hvp5wyce"
|
||||
},
|
||||
"deepseek-v4-flash": {
|
||||
"cache_creation_input_token_cost": 0.0,
|
||||
"cache_read_input_token_cost": 6e-09,
|
||||
|
|
|
|||
|
|
@ -2547,6 +2547,23 @@
|
|||
"text_completion": true
|
||||
}
|
||||
},
|
||||
"streamlake": {
|
||||
"display_name": "StreamLake (`streamlake`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/openai_compatible",
|
||||
"endpoints": {
|
||||
"chat_completions": true,
|
||||
"messages": true,
|
||||
"responses": true,
|
||||
"embeddings": false,
|
||||
"image_generations": false,
|
||||
"audio_transcriptions": false,
|
||||
"audio_speech": false,
|
||||
"moderations": false,
|
||||
"batches": false,
|
||||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
},
|
||||
"tencent": {
|
||||
"display_name": "Tencent TokenHub (`tencent`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/tencent",
|
||||
|
|
|
|||
315
tests/unit/llms/openai_like/test_streamlake_provider.py
Normal file
315
tests/unit/llms/openai_like/test_streamlake_provider.py
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
import respx
|
||||
|
||||
import litellm
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
from litellm.llms.openai_like.dynamic_config import create_config_class
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
from litellm.types.utils import ModelResponse, Usage
|
||||
|
||||
STREAMLAKE_BASE_URL = "https://vanchin.streamlake.ai/api/gateway/v1/endpoints"
|
||||
STREAMLAKE_CHAT_URL = f"{STREAMLAKE_BASE_URL}/chat/completions"
|
||||
|
||||
REPO_ROOT: Final = Path(__file__).parents[4]
|
||||
|
||||
|
||||
class TestStreamlakeProviderConfig:
|
||||
def test_streamlake_provider_resolution(self):
|
||||
model, provider, api_key, api_base = get_llm_provider(
|
||||
model="streamlake/ep-test-endpoint",
|
||||
custom_llm_provider=None,
|
||||
api_base=None,
|
||||
api_key="sk-test",
|
||||
)
|
||||
|
||||
assert model == "ep-test-endpoint"
|
||||
assert provider == "streamlake"
|
||||
assert api_base == STREAMLAKE_BASE_URL
|
||||
assert api_key == "sk-test"
|
||||
|
||||
def test_streamlake_api_base_override(self):
|
||||
model, provider, api_key, api_base = get_llm_provider(
|
||||
model="streamlake/ep-test-endpoint",
|
||||
custom_llm_provider=None,
|
||||
api_base="https://custom.streamlake.example/v1",
|
||||
api_key="sk-test",
|
||||
)
|
||||
|
||||
assert model == "ep-test-endpoint"
|
||||
assert provider == "streamlake"
|
||||
assert api_base == "https://custom.streamlake.example/v1"
|
||||
assert api_key == "sk-test"
|
||||
|
||||
def test_streamlake_url_autodetection(self):
|
||||
model, provider, api_key, api_base = get_llm_provider(
|
||||
model="some-public-model",
|
||||
custom_llm_provider=None,
|
||||
api_base=STREAMLAKE_BASE_URL,
|
||||
api_key=None,
|
||||
)
|
||||
assert provider == "streamlake"
|
||||
assert api_base == STREAMLAKE_BASE_URL
|
||||
|
||||
def test_streamlake_api_key_resolved_from_env(self, monkeypatch):
|
||||
monkeypatch.setenv("STREAMLAKE_API_KEY", "sk-env-key")
|
||||
|
||||
_, provider, api_key, _ = get_llm_provider(
|
||||
model="streamlake/ep-test-endpoint",
|
||||
custom_llm_provider=None,
|
||||
api_base=None,
|
||||
api_key=None,
|
||||
)
|
||||
assert provider == "streamlake"
|
||||
assert api_key == "sk-env-key"
|
||||
|
||||
def test_streamlake_validate_environment_sets_bearer(self):
|
||||
from litellm.llms.openai_like.dynamic_config import create_config_class
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
|
||||
provider = JSONProviderRegistry.get("streamlake")
|
||||
assert provider is not None
|
||||
config = create_config_class(provider)()
|
||||
|
||||
headers = config.validate_environment(
|
||||
headers={},
|
||||
model="ep-test-endpoint",
|
||||
messages=[{"role": "user", "content": "hi"}],
|
||||
optional_params={},
|
||||
litellm_params={},
|
||||
api_key="sk-resolved-key",
|
||||
api_base=None,
|
||||
)
|
||||
assert headers["Authorization"] == "Bearer sk-resolved-key"
|
||||
|
||||
def test_streamlake_complete_url_appends_chat_completions(self):
|
||||
from litellm.llms.openai_like.dynamic_config import create_config_class
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
|
||||
provider = JSONProviderRegistry.get("streamlake")
|
||||
assert provider is not None
|
||||
config = create_config_class(provider)()
|
||||
|
||||
url = config.get_complete_url(
|
||||
api_base=None,
|
||||
api_key="sk-test",
|
||||
model="ep-test-endpoint",
|
||||
optional_params={},
|
||||
litellm_params={},
|
||||
)
|
||||
assert url == STREAMLAKE_CHAT_URL
|
||||
|
||||
def test_streamlake_max_completion_tokens_mapped_to_max_tokens(self):
|
||||
from litellm.llms.openai_like.dynamic_config import create_config_class
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
|
||||
provider = JSONProviderRegistry.get("streamlake")
|
||||
assert provider is not None
|
||||
config = create_config_class(provider)()
|
||||
|
||||
optional_params = config.map_openai_params(
|
||||
non_default_params={"max_completion_tokens": 1024},
|
||||
optional_params={},
|
||||
model="ep-test-endpoint",
|
||||
drop_params=False,
|
||||
)
|
||||
assert optional_params == {"max_tokens": 1024}
|
||||
assert "max_completion_tokens" not in optional_params
|
||||
|
||||
def test_streamlake_chat_params_pass_through(self):
|
||||
from litellm.llms.openai_like.dynamic_config import create_config_class
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
|
||||
provider = JSONProviderRegistry.get("streamlake")
|
||||
assert provider is not None
|
||||
config = create_config_class(provider)()
|
||||
|
||||
optional_params = config.map_openai_params(
|
||||
non_default_params={"temperature": 0.2, "top_p": 0.9, "stream": True},
|
||||
optional_params={},
|
||||
model="ep-test-endpoint",
|
||||
drop_params=False,
|
||||
)
|
||||
assert optional_params == {"temperature": 0.2, "top_p": 0.9, "stream": True}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"is_async, api_base",
|
||||
(
|
||||
(False, None),
|
||||
(False, "https://custom.streamlake.example/v1"),
|
||||
(False, "https://custom.streamlake.example/v1/"),
|
||||
(True, None),
|
||||
(True, "https://custom.streamlake.example/v1"),
|
||||
(True, "https://custom.streamlake.example/v1/"),
|
||||
),
|
||||
ids=(
|
||||
"sync-default",
|
||||
"sync-override",
|
||||
"sync-override-trailing-slash",
|
||||
"async-default",
|
||||
"async-override",
|
||||
"async-override-trailing-slash",
|
||||
),
|
||||
)
|
||||
async def test_streamlake_completion_uses_openai_compatible_http(
|
||||
is_async: bool, api_base: str | None, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
response_body: Final[dict[str, object]] = {
|
||||
"id": "chatcmpl-streamlake-test",
|
||||
"object": "chat.completion",
|
||||
"created": 1710000000,
|
||||
"model": "ep-test-endpoint",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {"role": "assistant", "content": "StreamLake response"},
|
||||
"finish_reason": "stop",
|
||||
}
|
||||
],
|
||||
"usage": {"prompt_tokens": 3, "completion_tokens": 2, "total_tokens": 5},
|
||||
}
|
||||
expected_url: Final[str] = f"{(api_base or STREAMLAKE_BASE_URL).rstrip('/')}/chat/completions"
|
||||
expected_request_body: Final[dict[str, object]] = {
|
||||
"messages": [{"role": "user", "content": "hello"}],
|
||||
"model": "ep-test-endpoint",
|
||||
"max_tokens": 512,
|
||||
}
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
assert request.method == "POST"
|
||||
assert str(request.url) == expected_url
|
||||
assert request.headers["authorization"] == "Bearer sk-streamlake-test"
|
||||
assert request.headers["content-type"] == "application/json"
|
||||
assert json.loads(request.content) == expected_request_body
|
||||
return httpx.Response(200, json=response_body, request=request)
|
||||
|
||||
monkeypatch.setattr(litellm, "disable_aiohttp_transport", True)
|
||||
litellm.in_memory_llm_clients_cache.flush_cache()
|
||||
with respx.mock(assert_all_called=True) as respx_mock:
|
||||
route: Final = respx_mock.post(expected_url).mock(side_effect=handler)
|
||||
if is_async:
|
||||
response: Final = await litellm.acompletion(
|
||||
model="streamlake/ep-test-endpoint",
|
||||
messages=[{"role": "user", "content": "hello"}],
|
||||
api_key="sk-streamlake-test",
|
||||
api_base=api_base,
|
||||
max_completion_tokens=512,
|
||||
)
|
||||
else:
|
||||
response: Final = litellm.completion(
|
||||
model="streamlake/ep-test-endpoint",
|
||||
messages=[{"role": "user", "content": "hello"}],
|
||||
api_key="sk-streamlake-test",
|
||||
api_base=api_base,
|
||||
max_completion_tokens=512,
|
||||
)
|
||||
|
||||
assert route.call_count == 1
|
||||
assert len(response.choices) == 1
|
||||
assert response.choices[0].message.role == "assistant"
|
||||
assert response.choices[0].message.content == "StreamLake response"
|
||||
assert response.usage is not None
|
||||
assert response.usage.prompt_tokens == 3
|
||||
assert response.usage.completion_tokens == 2
|
||||
assert response.usage.total_tokens == 5
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("local_model_cost_map")
|
||||
def test_endpoint_id_call_forwards_tools_and_reasoning_effort_to_streamlake(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
tools: Final = [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}},
|
||||
},
|
||||
}
|
||||
]
|
||||
response_body: Final[dict[str, object]] = {
|
||||
"id": "chatcmpl-streamlake-tools",
|
||||
"object": "chat.completion",
|
||||
"created": 1710000000,
|
||||
"model": "glm-5.3",
|
||||
"choices": [{"index": 0, "message": {"role": "assistant", "content": "ok"}, "finish_reason": "stop"}],
|
||||
"usage": {"prompt_tokens": 3, "completion_tokens": 1, "total_tokens": 4},
|
||||
}
|
||||
monkeypatch.setattr(litellm, "disable_aiohttp_transport", True)
|
||||
litellm.in_memory_llm_clients_cache.flush_cache()
|
||||
with respx.mock(assert_all_called=True) as respx_mock:
|
||||
route: Final = respx_mock.post(STREAMLAKE_CHAT_URL).mock(
|
||||
return_value=httpx.Response(200, json=response_body)
|
||||
)
|
||||
litellm.completion(
|
||||
model="streamlake/ep-test-endpoint",
|
||||
messages=[{"role": "user", "content": "weather in Paris?"}],
|
||||
api_key="sk-streamlake-test",
|
||||
tools=tools,
|
||||
tool_choice="auto",
|
||||
reasoning_effort="low",
|
||||
)
|
||||
|
||||
sent: Final = json.loads(route.calls.last.request.content)
|
||||
assert sent["tools"] == tools
|
||||
assert sent["tool_choice"] == "auto"
|
||||
assert sent["reasoning_effort"] == "low"
|
||||
|
||||
|
||||
def _streamlake_keys(cost_map: dict[str, object]) -> tuple[str, ...]:
|
||||
return tuple(key for key in cost_map if key.startswith("streamlake/"))
|
||||
|
||||
|
||||
def test_root_and_backup_cost_maps_carry_the_same_streamlake_rows() -> None:
|
||||
root: Final = json.loads((REPO_ROOT / "model_prices_and_context_window.json").read_text())
|
||||
backup: Final = json.loads((REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json").read_text())
|
||||
|
||||
assert _streamlake_keys(root)
|
||||
assert {key: root[key] for key in _streamlake_keys(root)} == {key: backup[key] for key in _streamlake_keys(backup)}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("local_model_cost_map")
|
||||
def test_endpoint_id_call_is_priced_from_the_lowercase_model_streamlake_returns() -> None:
|
||||
keys: Final = _streamlake_keys(litellm.model_cost)
|
||||
assert keys
|
||||
|
||||
for key in keys:
|
||||
info = litellm.get_model_info(model=key)
|
||||
response = ModelResponse(
|
||||
model=key.split("/", 1)[1].lower(),
|
||||
usage=Usage(prompt_tokens=1000, completion_tokens=500, total_tokens=1500),
|
||||
)
|
||||
cost = litellm.completion_cost(
|
||||
completion_response=response,
|
||||
model="streamlake/ep-test-endpoint",
|
||||
custom_llm_provider="streamlake",
|
||||
)
|
||||
expected = 1000 * info["input_cost_per_token"] + 500 * info["output_cost_per_token"]
|
||||
assert cost == pytest.approx(expected), key
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("local_model_cost_map")
|
||||
def test_named_model_params_follow_the_row_and_fall_back_to_the_provider_default() -> None:
|
||||
provider: Final = JSONProviderRegistry.get("streamlake")
|
||||
assert provider is not None
|
||||
config: Final = create_config_class(provider)()
|
||||
keys: Final = _streamlake_keys(litellm.model_cost)
|
||||
assert keys
|
||||
|
||||
for key in keys:
|
||||
row = litellm.model_cost[key]
|
||||
supported = config.get_supported_openai_params(model=key.split("/", 1)[1].lower())
|
||||
assert ("tools" in supported) is (row.get("supports_function_calling") is not False), key
|
||||
assert ("reasoning_effort" in supported) is (row.get("supports_reasoning") is not False), key
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("local_model_cost_map")
|
||||
def test_streamlake_wildcard_expands_to_every_streamlake_row() -> None:
|
||||
from litellm.proxy.auth.model_checks import get_known_models_from_wildcard
|
||||
|
||||
expanded: Final = get_known_models_from_wildcard("streamlake/*")
|
||||
assert set(expanded) == set(_streamlake_keys(litellm.model_cost))
|
||||
|
|
@ -1121,6 +1121,29 @@ def test_get_supported_endpoints_chat_completions_present(reset_endpoints_cache)
|
|||
assert len(chat["providers"]) > 0
|
||||
|
||||
|
||||
def test_get_supported_endpoints_streamlake_only_advertises_chat_completions(
|
||||
reset_endpoints_cache: None,
|
||||
) -> None:
|
||||
app: Final[FastAPI] = FastAPI()
|
||||
app.include_router(router)
|
||||
client: Final[TestClient] = TestClient(app)
|
||||
with client:
|
||||
response: Final = client.get("/public/endpoints")
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
endpoints: Final = response.json()["endpoints"]
|
||||
streamlake_endpoints: Final = {
|
||||
endpoint["key"]
|
||||
for endpoint in endpoints
|
||||
if any(provider["slug"] == "streamlake" for provider in endpoint["providers"])
|
||||
}
|
||||
assert streamlake_endpoints == {"chat_completions"}
|
||||
|
||||
chat_completions: Final = next(endpoint for endpoint in endpoints if endpoint["key"] == "chat_completions")
|
||||
assert chat_completions["endpoint"] == "/chat/completions"
|
||||
assert "streamlake" in {provider["slug"] for provider in chat_completions["providers"]}
|
||||
|
||||
|
||||
def test_get_supported_endpoints_display_names_have_no_slug_suffix(
|
||||
reset_endpoints_cache,
|
||||
):
|
||||
|
|
|
|||
|
|
@ -80,6 +80,13 @@ vi.mock("@/app/(dashboard)/hooks/providers/useProviderFields", () => ({
|
|||
default_model_placeholder: "jev-latest",
|
||||
credential_fields: [{ key: "api_key", label: "API Key", field_type: "password", required: false }],
|
||||
},
|
||||
{
|
||||
provider: "StreamLake",
|
||||
provider_display_name: "StreamLake",
|
||||
litellm_provider: "streamlake",
|
||||
default_model_placeholder: "streamlake/<model-or-endpoint>",
|
||||
credential_fields: [{ key: "api_key", label: "API Key", field_type: "password", required: false }],
|
||||
},
|
||||
],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
|
|
@ -278,6 +285,28 @@ describe("AddModelPanel submit payload contract", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("creates a StreamLake model from a public model selection and API key", async () => {
|
||||
mockUseModelCostMap.mockReturnValue({ data: { "streamlake/GLM-5.3": { litellm_provider: "streamlake" } } });
|
||||
const { user, submit } = await setup();
|
||||
|
||||
await user.click(screen.getByRole("combobox", { name: /provider/i }));
|
||||
await user.click(await screen.findByText("StreamLake"));
|
||||
await user.click(screen.getByRole("combobox", { name: "Select models" }));
|
||||
await user.click(await screen.findByText("streamlake/GLM-5.3"));
|
||||
await user.type(screen.getByLabelText("API Key"), "sk-streamlake-test");
|
||||
await submit();
|
||||
|
||||
expect(lastCreatedModel()).toStrictEqual({
|
||||
model_name: "streamlake/GLM-5.3",
|
||||
litellm_params: {
|
||||
model: "streamlake/GLM-5.3",
|
||||
custom_llm_provider: "streamlake",
|
||||
api_key: "sk-streamlake-test",
|
||||
},
|
||||
model_info: { ...baseModelInfo },
|
||||
});
|
||||
});
|
||||
|
||||
it("registers four more keys as undefined once Advanced Settings opens", async () => {
|
||||
const { openAdvanced, fillRequired, submit } = await setup();
|
||||
await fillRequired();
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ describe("provider_info_helpers", () => {
|
|||
Providers.PG_VECTOR,
|
||||
Providers.PREDIBASE,
|
||||
Providers.Sail,
|
||||
Providers.StreamLake,
|
||||
Providers.WANDB,
|
||||
Providers.ZAI,
|
||||
];
|
||||
|
|
@ -457,6 +458,19 @@ describe("provider_info_helpers", () => {
|
|||
expect(result).toEqual(["gpt-3.5-turbo", "gpt-4"]);
|
||||
});
|
||||
|
||||
it("should return StreamLake models and exclude models from other providers", () => {
|
||||
const modelMap = {
|
||||
"streamlake/GLM-5.3": { litellm_provider: "streamlake" },
|
||||
"streamlake/DeepSeek-V3": { litellm_provider: "streamlake" },
|
||||
"gpt-4o": { litellm_provider: "openai" },
|
||||
};
|
||||
const result = getProviderModels(Providers.StreamLake, modelMap);
|
||||
|
||||
expect(provider_map.StreamLake).toBe("streamlake");
|
||||
expect(result).toEqual(["streamlake/GLM-5.3", "streamlake/DeepSeek-V3"]);
|
||||
expect(result).not.toContain("gpt-4o");
|
||||
});
|
||||
|
||||
it("should return models whose litellm_provider is a prefix-anchored variant of the provider", () => {
|
||||
const modelMap = {
|
||||
"anthropic-text-model": { litellm_provider: "anthropic_text" },
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ export enum Providers {
|
|||
Snowflake = "Snowflake",
|
||||
Soniox = "Soniox",
|
||||
StrandsDecider = "Strands Decider",
|
||||
StreamLake = "StreamLake",
|
||||
TEXT_COMPLETION_CODESTRAL = "Text-Completion-Codestral",
|
||||
Tencent = "Tencent",
|
||||
TogetherAI = "TogetherAI",
|
||||
|
|
@ -302,6 +303,7 @@ export const provider_map: Record<string, string> = {
|
|||
Snowflake: "snowflake",
|
||||
Soniox: "soniox",
|
||||
StrandsDecider: "strands_decider",
|
||||
StreamLake: "streamlake",
|
||||
TEXT_COMPLETION_CODESTRAL: "text-completion-codestral",
|
||||
Tencent: "tencent",
|
||||
TogetherAI: "together_ai",
|
||||
|
|
@ -488,6 +490,7 @@ const providerPlaceholderMap: Partial<Record<Providers, string>> = {
|
|||
[Providers.Tencent]: "tencent/deepseek-v4-pro",
|
||||
[Providers.TypeSafe]: "typesafe/jev-latest",
|
||||
[Providers.Nace]: "nace/drex-latest",
|
||||
[Providers.StreamLake]: "streamlake/<model-or-endpoint>",
|
||||
[Providers.Vertex_AI]: "gemini-pro",
|
||||
[Providers.VolcEngine]: "volcengine/<any-model-on-volcengine>",
|
||||
[Providers.Voyage]: "voyage/",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue