mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
feat(provider): add Salad AI Gateway
This commit is contained in:
parent
4fcaf7d736
commit
fc3a52c49e
8 changed files with 179 additions and 0 deletions
|
|
@ -736,6 +736,7 @@ openai_compatible_endpoints: Final[list] = [
|
|||
"https://api.inference.wandb.ai/v1",
|
||||
"https://api.clarifai.com/v2/ext/openai/v1",
|
||||
"https://api.libertai.io/v1",
|
||||
"https://ai.salad.cloud/v1",
|
||||
"https://pinstripes.io/v1",
|
||||
"https://api.meta.ai/v1",
|
||||
]
|
||||
|
|
@ -783,6 +784,7 @@ openai_compatible_providers: Final[list] = [
|
|||
"chutes", # Chutes - JSON-configured provider
|
||||
"parasail", # Parasail - JSON-configured provider
|
||||
"libertai", # LibertAI - JSON-configured provider
|
||||
"salad_cloud",
|
||||
"featherless_ai",
|
||||
"nscale",
|
||||
"nebius",
|
||||
|
|
|
|||
|
|
@ -159,6 +159,14 @@
|
|||
"max_completion_tokens": "max_tokens"
|
||||
}
|
||||
},
|
||||
"salad_cloud": {
|
||||
"base_url": "https://ai.salad.cloud/v1",
|
||||
"api_key_env": "SALAD_CLOUD_API_KEY",
|
||||
"api_base_env": "SALAD_CLOUD_API_BASE",
|
||||
"param_mappings": {
|
||||
"max_completion_tokens": "max_tokens"
|
||||
}
|
||||
},
|
||||
"empiriolabs": {
|
||||
"base_url": "https://api.empiriolabs.ai/v1",
|
||||
"api_key_env": "EMPIRIOLABS_API_KEY",
|
||||
|
|
|
|||
|
|
@ -44210,6 +44210,23 @@
|
|||
"supports_reasoning": true,
|
||||
"source": "https://docs.libertai.io/apis/text/"
|
||||
},
|
||||
"salad_cloud/qwen3.6-35b-a3b": {
|
||||
"max_tokens": 262144,
|
||||
"max_input_tokens": 262144,
|
||||
"max_output_tokens": 262144,
|
||||
"input_cost_per_token": 9e-08,
|
||||
"output_cost_per_token": 6e-07,
|
||||
"litellm_provider": "salad_cloud",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_vision": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_native_streaming": true,
|
||||
"source": "https://docs.salad.com/ai-gateway/reference/models"
|
||||
},
|
||||
"libertai/qwen3.5-122b-a10b": {
|
||||
"max_tokens": 262144,
|
||||
"max_input_tokens": 262144,
|
||||
|
|
|
|||
|
|
@ -1305,6 +1305,23 @@
|
|||
"a2a": false
|
||||
}
|
||||
},
|
||||
"salad_cloud": {
|
||||
"display_name": "Salad AI Gateway (`salad_cloud`)",
|
||||
"url": "https://docs.salad.com/ai-gateway/tutorials/getting-started",
|
||||
"endpoints": {
|
||||
"chat_completions": true,
|
||||
"messages": true,
|
||||
"responses": false,
|
||||
"embeddings": false,
|
||||
"image_generations": false,
|
||||
"audio_transcriptions": false,
|
||||
"audio_speech": false,
|
||||
"moderations": false,
|
||||
"batches": false,
|
||||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
},
|
||||
"litellm_proxy": {
|
||||
"display_name": "LiteLLM Proxy (`litellm_proxy`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/litellm_proxy",
|
||||
|
|
|
|||
|
|
@ -3688,6 +3688,7 @@ class LlmProviders(str, Enum):
|
|||
XIAOMI_MIMO = "xiaomi_mimo"
|
||||
TENSORMESH = "tensormesh"
|
||||
LIBERTAI = "libertai"
|
||||
SALAD_CLOUD = "salad_cloud"
|
||||
PINSTRIPES = "pinstripes"
|
||||
DARKBLOOM = "darkbloom"
|
||||
META = "meta"
|
||||
|
|
|
|||
|
|
@ -44331,6 +44331,23 @@
|
|||
"supports_reasoning": true,
|
||||
"source": "https://docs.libertai.io/apis/text/"
|
||||
},
|
||||
"salad_cloud/qwen3.6-35b-a3b": {
|
||||
"max_tokens": 262144,
|
||||
"max_input_tokens": 262144,
|
||||
"max_output_tokens": 262144,
|
||||
"input_cost_per_token": 9e-08,
|
||||
"output_cost_per_token": 6e-07,
|
||||
"litellm_provider": "salad_cloud",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_vision": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_native_streaming": true,
|
||||
"source": "https://docs.salad.com/ai-gateway/reference/models"
|
||||
},
|
||||
"libertai/qwen3.5-122b-a10b": {
|
||||
"max_tokens": 262144,
|
||||
"max_input_tokens": 262144,
|
||||
|
|
|
|||
|
|
@ -1420,6 +1420,23 @@
|
|||
"a2a": false
|
||||
}
|
||||
},
|
||||
"salad_cloud": {
|
||||
"display_name": "Salad AI Gateway (`salad_cloud`)",
|
||||
"url": "https://docs.salad.com/ai-gateway/tutorials/getting-started",
|
||||
"endpoints": {
|
||||
"chat_completions": true,
|
||||
"messages": true,
|
||||
"responses": false,
|
||||
"embeddings": false,
|
||||
"image_generations": false,
|
||||
"audio_transcriptions": false,
|
||||
"audio_speech": false,
|
||||
"moderations": false,
|
||||
"batches": false,
|
||||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
},
|
||||
"litellm_proxy": {
|
||||
"display_name": "LiteLLM Proxy (`litellm_proxy`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/litellm_proxy",
|
||||
|
|
|
|||
100
tests/test_litellm/llms/openai_like/test_salad_cloud_provider.py
Normal file
100
tests/test_litellm/llms/openai_like/test_salad_cloud_provider.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import litellm
|
||||
|
||||
|
||||
class TestSaladCloudProviderConfig:
|
||||
def test_provider_registration(self):
|
||||
from litellm import LlmProviders
|
||||
|
||||
assert LlmProviders.SALAD_CLOUD.value == "salad_cloud"
|
||||
assert "salad_cloud" in litellm.provider_list
|
||||
|
||||
def test_json_config(self):
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
|
||||
assert JSONProviderRegistry.exists("salad_cloud")
|
||||
provider = JSONProviderRegistry.get("salad_cloud")
|
||||
assert provider is not None
|
||||
assert provider.base_url == "https://ai.salad.cloud/v1"
|
||||
assert provider.api_key_env == "SALAD_CLOUD_API_KEY"
|
||||
assert provider.api_base_env == "SALAD_CLOUD_API_BASE"
|
||||
assert provider.param_mappings.get("max_completion_tokens") == "max_tokens"
|
||||
|
||||
def test_provider_resolution(self):
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
||||
model, provider, _, api_base = get_llm_provider(
|
||||
model="salad_cloud/qwen3.6-35b-a3b",
|
||||
custom_llm_provider=None,
|
||||
api_base=None,
|
||||
api_key=None,
|
||||
)
|
||||
|
||||
assert model == "qwen3.6-35b-a3b"
|
||||
assert provider == "salad_cloud"
|
||||
assert api_base == "https://ai.salad.cloud/v1"
|
||||
|
||||
def test_api_base_override(self):
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
||||
_, provider, api_key, api_base = get_llm_provider(
|
||||
model="salad_cloud/qwen3.6-35b-a3b",
|
||||
custom_llm_provider=None,
|
||||
api_base="https://custom.example.com/v1",
|
||||
api_key="test-key",
|
||||
)
|
||||
|
||||
assert provider == "salad_cloud"
|
||||
assert api_base == "https://custom.example.com/v1"
|
||||
assert api_key == "test-key"
|
||||
|
||||
def test_model_metadata(self):
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
cost_map_path = (
|
||||
Path(litellm.__file__).parent
|
||||
/ "model_prices_and_context_window_backup.json"
|
||||
)
|
||||
info = json.loads(cost_map_path.read_text())["salad_cloud/qwen3.6-35b-a3b"]
|
||||
|
||||
assert info["litellm_provider"] == "salad_cloud"
|
||||
assert info["mode"] == "chat"
|
||||
assert info["max_input_tokens"] == 262144
|
||||
assert info["max_output_tokens"] == 262144
|
||||
assert info["input_cost_per_token"] == 0.09e-6
|
||||
assert info["output_cost_per_token"] == 0.60e-6
|
||||
assert info["supports_vision"] is True
|
||||
assert info["supports_reasoning"] is True
|
||||
assert info["supports_response_schema"] is True
|
||||
assert info["supports_native_streaming"] is True
|
||||
|
||||
def test_router_config(self):
|
||||
from litellm import Router
|
||||
|
||||
router = Router(
|
||||
model_list=[
|
||||
{
|
||||
"model_name": "salad-chat",
|
||||
"litellm_params": {
|
||||
"model": "salad_cloud/qwen3.6-35b-a3b",
|
||||
"api_key": "test-key",
|
||||
},
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
assert router.model_list[0]["model_name"] == "salad-chat"
|
||||
|
||||
def test_supported_endpoints_matrix(self):
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
backup_path = (
|
||||
Path(litellm.__file__).parent / "provider_endpoints_support_backup.json"
|
||||
)
|
||||
matrix = json.loads(backup_path.read_text())
|
||||
|
||||
endpoints = matrix["providers"]["salad_cloud"]["endpoints"]
|
||||
assert endpoints["chat_completions"] is True
|
||||
assert endpoints["messages"] is True
|
||||
assert endpoints["responses"] is False
|
||||
Loading…
Add table
Reference in a new issue