mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-31 06:56:59 +00:00
Merge 0d8f8bba1d into 2590f641f5
This commit is contained in:
commit
e5d7c52d4e
10 changed files with 451 additions and 0 deletions
|
|
@ -681,6 +681,7 @@ publicai_models: Set = set()
|
|||
darkbloom_models: Set = set()
|
||||
openinfer_models: Final[Set[str]] = set()
|
||||
v0_models: Set = set()
|
||||
vispark_models: Set[str] = set()
|
||||
morph_models: Set = set()
|
||||
lambda_ai_models: Set = set()
|
||||
inception_models: Set = set()
|
||||
|
|
@ -968,6 +969,8 @@ def _populate_provider_model_sets(model_cost_map: Mapping[str, Mapping[str, obje
|
|||
openinfer_models.add(key)
|
||||
elif value.get("litellm_provider") == "v0":
|
||||
v0_models.add(key)
|
||||
elif value.get("litellm_provider") == "vispark":
|
||||
vispark_models.add(key)
|
||||
elif value.get("litellm_provider") == "morph":
|
||||
morph_models.add(key)
|
||||
elif value.get("litellm_provider") == "lambda_ai":
|
||||
|
|
@ -1136,6 +1139,7 @@ model_list = list(
|
|||
| darkbloom_models
|
||||
| openinfer_models
|
||||
| v0_models
|
||||
| vispark_models
|
||||
| morph_models
|
||||
| lambda_ai_models
|
||||
| inception_models
|
||||
|
|
@ -1253,6 +1257,7 @@ def _build_models_by_provider() -> dict:
|
|||
"darkbloom": darkbloom_models,
|
||||
"openinfer": openinfer_models,
|
||||
"v0": v0_models,
|
||||
"vispark": vispark_models,
|
||||
"morph": morph_models,
|
||||
"lambda_ai": lambda_ai_models,
|
||||
"inception": inception_models,
|
||||
|
|
|
|||
|
|
@ -1056,6 +1056,7 @@ openai_compatible_endpoints: Final[list[str]] = [
|
|||
"https://inference.coralbricks.ai/v1",
|
||||
"https://api.cortecs.ai/v1",
|
||||
"https://api.scx.ai/v1",
|
||||
"https://api.lab.vispark.in/v1",
|
||||
"https://api.prisminference.com/v1",
|
||||
"https://api.reka.ai/v1",
|
||||
"https://gigachat.devices.sberbank.ru/api/v1",
|
||||
|
|
@ -1130,6 +1131,7 @@ openai_compatible_providers: Final[list[str]] = [
|
|||
"pinstripes", # Pinstripes - JSON-configured provider
|
||||
"openinfer",
|
||||
"darkbloom",
|
||||
"vispark", # Vispark Lab - JSON-configured provider
|
||||
"meta", # Meta Model API (Muse Spark) - JSON-configured provider
|
||||
"cognition",
|
||||
"coralbricks",
|
||||
|
|
@ -1163,6 +1165,7 @@ openai_text_completion_compatible_providers: Final[list] = [ # providers that s
|
|||
"poe",
|
||||
"chutes",
|
||||
"v0",
|
||||
"vispark",
|
||||
"lambda_ai",
|
||||
"hyperbolic",
|
||||
"wandb",
|
||||
|
|
|
|||
|
|
@ -249,5 +249,14 @@
|
|||
"/v1/responses",
|
||||
"/v1/messages"
|
||||
]
|
||||
},
|
||||
"vispark": {
|
||||
"base_url": "https://api.lab.vispark.in/v1",
|
||||
"api_key_env": "VISPARK_LAB_API_KEY",
|
||||
"api_base_env": "VISPARK_LAB_API_BASE",
|
||||
"param_mappings": {
|
||||
"max_completion_tokens": "max_tokens"
|
||||
},
|
||||
"supported_endpoints": ["/v1/chat/completions", "/v1/completions"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49883,6 +49883,102 @@
|
|||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vispark/vision-small": {
|
||||
"input_cost_per_token": 1.05e-06,
|
||||
"litellm_provider": "vispark",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 65536,
|
||||
"max_tokens": 65536,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.16e-06,
|
||||
"source": "https://api.lab.vispark.in/v1/models",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/completions"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vispark/vision-medium": {
|
||||
"input_cost_per_token": 4.21e-06,
|
||||
"litellm_provider": "vispark",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 65536,
|
||||
"max_tokens": 65536,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.263e-05,
|
||||
"source": "https://api.lab.vispark.in/v1/models",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/completions"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vispark/vision-large": {
|
||||
"input_cost_per_token": 7.37e-06,
|
||||
"litellm_provider": "vispark",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 65536,
|
||||
"max_tokens": 65536,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.211e-05,
|
||||
"source": "https://api.lab.vispark.in/v1/models",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/completions"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vercel_ai_gateway/alibaba/qwen-3-14b": {
|
||||
"input_cost_per_token": 8e-08,
|
||||
"litellm_provider": "vercel_ai_gateway",
|
||||
|
|
|
|||
|
|
@ -2352,6 +2352,24 @@
|
|||
"interactions": true
|
||||
}
|
||||
},
|
||||
"vispark": {
|
||||
"display_name": "Vispark (`vispark`)",
|
||||
"url": "https://lab.vispark.in/#vision",
|
||||
"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,
|
||||
"interactions": false
|
||||
}
|
||||
},
|
||||
"vercel_ai_gateway": {
|
||||
"display_name": "Vercel AI Gateway (`vercel_ai_gateway`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/vercel_ai_gateway",
|
||||
|
|
|
|||
|
|
@ -4070,5 +4070,33 @@
|
|||
}
|
||||
],
|
||||
"default_model_placeholder": "cursor/claude-4-sonnet"
|
||||
},
|
||||
{
|
||||
"provider": "VISPARK",
|
||||
"provider_display_name": "Vispark",
|
||||
"litellm_provider": "vispark",
|
||||
"credential_fields": [
|
||||
{
|
||||
"key": "api_base",
|
||||
"label": "API Base",
|
||||
"placeholder": "https://api.lab.vispark.in/v1",
|
||||
"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": "vispark/vision-medium"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4453,6 +4453,7 @@ class LlmProviders(str, Enum):
|
|||
MOONSHOT = "moonshot"
|
||||
PUBLICAI = "publicai"
|
||||
V0 = "v0"
|
||||
VISPARK = "vispark"
|
||||
MORPH = "morph"
|
||||
LAMBDA_AI = "lambda_ai"
|
||||
INCEPTION = "inception"
|
||||
|
|
|
|||
|
|
@ -49883,6 +49883,102 @@
|
|||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vispark/vision-small": {
|
||||
"input_cost_per_token": 1.05e-06,
|
||||
"litellm_provider": "vispark",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 65536,
|
||||
"max_tokens": 65536,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 3.16e-06,
|
||||
"source": "https://api.lab.vispark.in/v1/models",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/completions"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vispark/vision-medium": {
|
||||
"input_cost_per_token": 4.21e-06,
|
||||
"litellm_provider": "vispark",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 65536,
|
||||
"max_tokens": 65536,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1.263e-05,
|
||||
"source": "https://api.lab.vispark.in/v1/models",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/completions"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vispark/vision-large": {
|
||||
"input_cost_per_token": 7.37e-06,
|
||||
"litellm_provider": "vispark",
|
||||
"max_input_tokens": 1000000,
|
||||
"max_output_tokens": 65536,
|
||||
"max_tokens": 65536,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 2.211e-05,
|
||||
"source": "https://api.lab.vispark.in/v1/models",
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/completions"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image",
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_pdf_input": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"vercel_ai_gateway/alibaba/qwen-3-14b": {
|
||||
"input_cost_per_token": 8e-08,
|
||||
"litellm_provider": "vercel_ai_gateway",
|
||||
|
|
|
|||
|
|
@ -2722,6 +2722,24 @@
|
|||
"interactions": true
|
||||
}
|
||||
},
|
||||
"vispark": {
|
||||
"display_name": "Vispark (`vispark`)",
|
||||
"url": "https://lab.vispark.in/#vision",
|
||||
"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,
|
||||
"interactions": false
|
||||
}
|
||||
},
|
||||
"vercel_ai_gateway": {
|
||||
"display_name": "Vercel AI Gateway (`vercel_ai_gateway`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/vercel_ai_gateway",
|
||||
|
|
|
|||
177
tests/unit/llms/openai_like/test_vispark_provider.py
Normal file
177
tests/unit/llms/openai_like/test_vispark_provider.py
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
import pytest
|
||||
import respx
|
||||
|
||||
import litellm
|
||||
|
||||
_CHAT_COMPLETION: Final = {
|
||||
"id": "chatcmpl_vispark",
|
||||
"object": "chat.completion",
|
||||
"created": 1_790_000_000,
|
||||
"model": "vision-medium",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"message": {"role": "assistant", "content": "Hello from Vispark"},
|
||||
"finish_reason": "stop",
|
||||
}
|
||||
],
|
||||
"usage": {"prompt_tokens": 4, "completion_tokens": 3, "total_tokens": 7},
|
||||
}
|
||||
|
||||
_TEXT_COMPLETION: Final = {
|
||||
"id": "cmpl_vispark",
|
||||
"object": "text_completion",
|
||||
"created": 1_790_000_000,
|
||||
"model": "vision-small",
|
||||
"choices": [{"index": 0, "text": "Hello from Vispark", "finish_reason": "stop", "logprobs": None}],
|
||||
"usage": {"prompt_tokens": 4, "completion_tokens": 3, "total_tokens": 7},
|
||||
}
|
||||
|
||||
|
||||
def test_vispark_provider_resolution(monkeypatch: pytest.MonkeyPatch):
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
||||
monkeypatch.setenv("VISPARK_LAB_API_KEY", "vispark-env-key")
|
||||
monkeypatch.delenv("VISPARK_LAB_API_BASE", raising=False)
|
||||
|
||||
model, provider, api_key, api_base = get_llm_provider(
|
||||
model="vispark/vision-medium",
|
||||
custom_llm_provider=None,
|
||||
api_base=None,
|
||||
api_key=None,
|
||||
)
|
||||
|
||||
assert model == "vision-medium"
|
||||
assert provider == "vispark"
|
||||
assert api_key == "vispark-env-key"
|
||||
assert api_base == "https://api.lab.vispark.in/v1"
|
||||
|
||||
|
||||
def test_vispark_provider_keeps_explicit_credentials(monkeypatch: pytest.MonkeyPatch):
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
||||
monkeypatch.setenv("VISPARK_LAB_API_KEY", "vispark-env-key")
|
||||
monkeypatch.setenv("VISPARK_LAB_API_BASE", "https://vispark.env.example/v1")
|
||||
|
||||
_, provider, api_key, api_base = get_llm_provider(
|
||||
model="vispark/vision-medium",
|
||||
custom_llm_provider=None,
|
||||
api_base="https://vispark.internal.example/v1",
|
||||
api_key="vispark-explicit-key",
|
||||
)
|
||||
|
||||
assert provider == "vispark"
|
||||
assert api_key == "vispark-explicit-key"
|
||||
assert api_base == "https://vispark.internal.example/v1"
|
||||
|
||||
|
||||
def test_vispark_api_base_env_overrides_default(monkeypatch: pytest.MonkeyPatch):
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
||||
monkeypatch.setenv("VISPARK_LAB_API_KEY", "vispark-env-key")
|
||||
monkeypatch.setenv("VISPARK_LAB_API_BASE", "https://vispark.env.example/v1")
|
||||
|
||||
_, provider, _, api_base = get_llm_provider(
|
||||
model="vispark/vision-medium",
|
||||
custom_llm_provider=None,
|
||||
api_base=None,
|
||||
api_key=None,
|
||||
)
|
||||
|
||||
assert provider == "vispark"
|
||||
assert api_base == "https://vispark.env.example/v1"
|
||||
|
||||
|
||||
def test_vispark_api_base_autodetects_provider(monkeypatch: pytest.MonkeyPatch):
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
||||
monkeypatch.setenv("VISPARK_LAB_API_KEY", "vispark-env-key")
|
||||
|
||||
model, provider, api_key, api_base = get_llm_provider(
|
||||
model="vision-medium",
|
||||
custom_llm_provider=None,
|
||||
api_base="https://api.lab.vispark.in/v1",
|
||||
api_key=None,
|
||||
)
|
||||
|
||||
assert model == "vision-medium"
|
||||
assert provider == "vispark"
|
||||
assert api_key == "vispark-env-key"
|
||||
assert api_base == "https://api.lab.vispark.in/v1"
|
||||
|
||||
|
||||
def test_vispark_chat_completion_request_maps_max_completion_tokens():
|
||||
with respx.mock() as upstream:
|
||||
route: Final = upstream.post("https://api.lab.vispark.in/v1/chat/completions").respond(
|
||||
200, json=_CHAT_COMPLETION
|
||||
)
|
||||
response: Final = litellm.completion(
|
||||
model="vispark/vision-medium",
|
||||
messages=[{"role": "user", "content": "Say hello"}],
|
||||
max_completion_tokens=64,
|
||||
api_key="vispark-test-key",
|
||||
)
|
||||
|
||||
request: Final = route.calls.last.request
|
||||
body: Final = json.loads(request.content)
|
||||
assert route.call_count == 1
|
||||
assert request.headers["authorization"] == "Bearer vispark-test-key"
|
||||
assert body["model"] == "vision-medium"
|
||||
assert body["max_tokens"] == 64
|
||||
assert "max_completion_tokens" not in body
|
||||
assert response.choices[0].message.content == "Hello from Vispark"
|
||||
|
||||
|
||||
def test_vispark_text_completion_request():
|
||||
with respx.mock() as upstream:
|
||||
route: Final = upstream.post("https://api.lab.vispark.in/v1/completions").respond(200, json=_TEXT_COMPLETION)
|
||||
response: Final = litellm.text_completion(
|
||||
model="vispark/vision-small",
|
||||
prompt="Say hello",
|
||||
api_key="vispark-test-key",
|
||||
)
|
||||
|
||||
body: Final = json.loads(route.calls.last.request.content)
|
||||
assert route.call_count == 1
|
||||
assert body["model"] == "vision-small"
|
||||
assert body["prompt"] == "Say hello"
|
||||
assert response.choices[0].text == "Hello from Vispark"
|
||||
|
||||
|
||||
def test_vispark_cost_follows_the_cost_map():
|
||||
cost_entry: Final = litellm.model_cost["vispark/vision-large"]
|
||||
|
||||
prompt_cost, completion_cost = litellm.cost_per_token(
|
||||
model="vision-large",
|
||||
custom_llm_provider="vispark",
|
||||
prompt_tokens=1_000,
|
||||
completion_tokens=500,
|
||||
)
|
||||
|
||||
assert prompt_cost == pytest.approx(1_000 * cost_entry["input_cost_per_token"])
|
||||
assert completion_cost == pytest.approx(500 * cost_entry["output_cost_per_token"])
|
||||
|
||||
|
||||
def test_vispark_models_are_listed_for_the_provider():
|
||||
from litellm.utils import get_valid_models
|
||||
|
||||
expected: Final = {name for name, entry in litellm.model_cost.items() if entry.get("litellm_provider") == "vispark"}
|
||||
|
||||
assert expected
|
||||
assert set(litellm.models_by_provider["vispark"]) == expected
|
||||
assert expected <= set(get_valid_models(custom_llm_provider="vispark"))
|
||||
|
||||
|
||||
def test_vispark_endpoint_matrix_matches_between_root_and_backup():
|
||||
backup_path: Final = Path(litellm.__file__).parent / "provider_endpoints_support_backup.json"
|
||||
root_path: Final = Path(litellm.__file__).parent.parent / "provider_endpoints_support.json"
|
||||
|
||||
backup_entry: Final = json.loads(backup_path.read_text())["providers"]["vispark"]
|
||||
root_entry: Final = json.loads(root_path.read_text())["providers"]["vispark"]
|
||||
|
||||
assert backup_entry == root_entry
|
||||
assert root_entry["endpoints"]["chat_completions"] is True
|
||||
Loading…
Add table
Reference in a new issue