mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-13 03:59:12 +00:00
feat(provider): add The Grid as a JSON-configured OpenAI-compatible provider
The Grid is a spot market for inference. Instrument ids such as text-standard, code-prime or agent-max name a task type and a quality tier rather than a fixed model, and each request is filled by whichever supplier is competitive at the time, so the model reported in a response differs from the instrument requested. Chat completions and responses are both served, and max_completion_tokens is accepted natively, so the entry carries no param_mappings for it.
This commit is contained in:
parent
c52b53706e
commit
43fe6afcac
5 changed files with 371 additions and 0 deletions
|
|
@ -200,5 +200,11 @@
|
|||
"temperature_max": 1.99
|
||||
},
|
||||
"supported_endpoints": ["/v1/chat/completions"]
|
||||
},
|
||||
"thegrid": {
|
||||
"base_url": "https://api.thegrid.ai/v1",
|
||||
"api_key_env": "THEGRID_API_KEY",
|
||||
"api_base_env": "THEGRID_API_BASE",
|
||||
"supported_endpoints": ["/v1/chat/completions", "/v1/responses"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1097,6 +1097,23 @@
|
|||
"interactions": true
|
||||
}
|
||||
},
|
||||
"thegrid": {
|
||||
"display_name": "The Grid (`thegrid`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/thegrid",
|
||||
"endpoints": {
|
||||
"chat_completions": true,
|
||||
"messages": false,
|
||||
"responses": true,
|
||||
"embeddings": false,
|
||||
"image_generations": false,
|
||||
"audio_transcriptions": false,
|
||||
"audio_speech": false,
|
||||
"moderations": false,
|
||||
"batches": false,
|
||||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
},
|
||||
"vertex_ai": {
|
||||
"display_name": "Google - Vertex AI (`vertex_ai`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/vertex",
|
||||
|
|
|
|||
|
|
@ -63091,5 +63091,243 @@
|
|||
"supports_tool_choice": false,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/agent-max": {
|
||||
"max_tokens": 128000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 128000,
|
||||
"input_cost_per_token": 1.5532e-06,
|
||||
"output_cost_per_token": 1.5532e-06,
|
||||
"cache_read_input_token_cost": 1.5532e-06,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/agent-prime": {
|
||||
"max_tokens": 131072,
|
||||
"max_input_tokens": 120000,
|
||||
"max_output_tokens": 131072,
|
||||
"input_cost_per_token": 1.335e-07,
|
||||
"output_cost_per_token": 1.335e-07,
|
||||
"cache_read_input_token_cost": 1.335e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/agent-standard": {
|
||||
"max_tokens": 65536,
|
||||
"max_input_tokens": 120000,
|
||||
"max_output_tokens": 65536,
|
||||
"input_cost_per_token": 4.02e-08,
|
||||
"output_cost_per_token": 4.02e-08,
|
||||
"cache_read_input_token_cost": 4.02e-08,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/bytedance-pro-latest": {
|
||||
"max_tokens": 131072,
|
||||
"max_input_tokens": 256000,
|
||||
"max_output_tokens": 131072,
|
||||
"input_cost_per_token": 1.91e-07,
|
||||
"output_cost_per_token": 1.91e-07,
|
||||
"cache_read_input_token_cost": 1.91e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/claude-opus-latest": {
|
||||
"max_tokens": 128000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 128000,
|
||||
"input_cost_per_token": 1.5176e-06,
|
||||
"output_cost_per_token": 1.5176e-06,
|
||||
"cache_read_input_token_cost": 1.5176e-06,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/code-max": {
|
||||
"max_tokens": 128000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 128000,
|
||||
"input_cost_per_token": 1.5874999999999998e-06,
|
||||
"output_cost_per_token": 1.5874999999999998e-06,
|
||||
"cache_read_input_token_cost": 1.5874999999999998e-06,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/code-prime": {
|
||||
"max_tokens": 131072,
|
||||
"max_input_tokens": 120000,
|
||||
"max_output_tokens": 131072,
|
||||
"input_cost_per_token": 1.3719999999999998e-07,
|
||||
"output_cost_per_token": 1.3719999999999998e-07,
|
||||
"cache_read_input_token_cost": 1.3719999999999998e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/code-standard": {
|
||||
"max_tokens": 65536,
|
||||
"max_input_tokens": 120000,
|
||||
"max_output_tokens": 65536,
|
||||
"input_cost_per_token": 2e-08,
|
||||
"output_cost_per_token": 2e-08,
|
||||
"cache_read_input_token_cost": 2e-08,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/deepseek-pro-latest": {
|
||||
"max_tokens": 384000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 384000,
|
||||
"input_cost_per_token": 3.1809999999999997e-07,
|
||||
"output_cost_per_token": 3.1809999999999997e-07,
|
||||
"cache_read_input_token_cost": 3.1809999999999997e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/gemini-pro-latest": {
|
||||
"max_tokens": 65536,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 65536,
|
||||
"input_cost_per_token": 5.887e-07,
|
||||
"output_cost_per_token": 5.887e-07,
|
||||
"cache_read_input_token_cost": 5.887e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/glm-latest": {
|
||||
"max_tokens": 128000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 128000,
|
||||
"input_cost_per_token": 3.383e-07,
|
||||
"output_cost_per_token": 3.383e-07,
|
||||
"cache_read_input_token_cost": 3.383e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/gpt-sol-latest": {
|
||||
"max_tokens": 128000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 128000,
|
||||
"input_cost_per_token": 1.4545e-06,
|
||||
"output_cost_per_token": 1.4545e-06,
|
||||
"cache_read_input_token_cost": 1.4545e-06,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/kimi-latest": {
|
||||
"max_tokens": 1048576,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 1048576,
|
||||
"input_cost_per_token": 7.163e-07,
|
||||
"output_cost_per_token": 7.163e-07,
|
||||
"cache_read_input_token_cost": 7.163e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/minimax-latest": {
|
||||
"max_tokens": 512000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 512000,
|
||||
"input_cost_per_token": 1.063e-07,
|
||||
"output_cost_per_token": 1.063e-07,
|
||||
"cache_read_input_token_cost": 1.063e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/text-max": {
|
||||
"max_tokens": 128000,
|
||||
"max_input_tokens": 922000,
|
||||
"max_output_tokens": 128000,
|
||||
"input_cost_per_token": 1.6147e-06,
|
||||
"output_cost_per_token": 1.6147e-06,
|
||||
"cache_read_input_token_cost": 1.6147e-06,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"thegrid/text-prime": {
|
||||
"max_tokens": 131072,
|
||||
"max_input_tokens": 120000,
|
||||
"max_output_tokens": 131072,
|
||||
"input_cost_per_token": 1.0090000000000001e-07,
|
||||
"output_cost_per_token": 1.0090000000000001e-07,
|
||||
"cache_read_input_token_cost": 1.0090000000000001e-07,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
},
|
||||
"thegrid/text-standard": {
|
||||
"max_tokens": 65536,
|
||||
"max_input_tokens": 120000,
|
||||
"max_output_tokens": 65536,
|
||||
"input_cost_per_token": 3.02e-08,
|
||||
"output_cost_per_token": 3.02e-08,
|
||||
"cache_read_input_token_cost": 3.02e-08,
|
||||
"litellm_provider": "thegrid",
|
||||
"mode": "chat",
|
||||
"supports_function_calling": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_vision": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3033,6 +3033,23 @@
|
|||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
},
|
||||
"thegrid": {
|
||||
"display_name": "The Grid (`thegrid`)",
|
||||
"url": "https://docs.litellm.ai/docs/providers/thegrid",
|
||||
"endpoints": {
|
||||
"chat_completions": true,
|
||||
"messages": false,
|
||||
"responses": true,
|
||||
"embeddings": false,
|
||||
"image_generations": false,
|
||||
"audio_transcriptions": false,
|
||||
"audio_speech": false,
|
||||
"moderations": false,
|
||||
"batches": false,
|
||||
"rerank": false,
|
||||
"a2a": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"endpoints": {
|
||||
|
|
|
|||
93
tests/test_litellm/llms/openai_like/test_thegrid_provider.py
Normal file
93
tests/test_litellm/llms/openai_like/test_thegrid_provider.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
"""
|
||||
Unit tests for The Grid OpenAI-like provider.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import litellm
|
||||
from litellm.llms.openai_like.dynamic_config import create_config_class
|
||||
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
|
||||
|
||||
THEGRID_BASE_URL = "https://api.thegrid.ai/v1"
|
||||
|
||||
|
||||
def _get_config():
|
||||
provider = JSONProviderRegistry.get("thegrid")
|
||||
assert provider is not None
|
||||
config_class = create_config_class(provider)
|
||||
return config_class()
|
||||
|
||||
|
||||
def test_thegrid_provider_registered():
|
||||
provider = JSONProviderRegistry.get("thegrid")
|
||||
assert provider is not None
|
||||
assert provider.base_url == THEGRID_BASE_URL
|
||||
assert provider.api_key_env == "THEGRID_API_KEY"
|
||||
assert provider.api_base_env == "THEGRID_API_BASE"
|
||||
|
||||
|
||||
def test_thegrid_resolves_env_api_key(monkeypatch):
|
||||
config = _get_config()
|
||||
monkeypatch.setenv("THEGRID_API_KEY", "test-key")
|
||||
api_base, api_key = config._get_openai_compatible_provider_info(None, None)
|
||||
assert api_base == THEGRID_BASE_URL
|
||||
assert api_key == "test-key"
|
||||
|
||||
|
||||
def test_thegrid_env_api_base_overrides_default(monkeypatch):
|
||||
config = _get_config()
|
||||
monkeypatch.setenv("THEGRID_API_KEY", "test-key")
|
||||
monkeypatch.setenv("THEGRID_API_BASE", "https://proxy.internal/v1")
|
||||
api_base, _ = config._get_openai_compatible_provider_info(None, None)
|
||||
assert api_base == "https://proxy.internal/v1"
|
||||
|
||||
|
||||
def test_thegrid_keeps_max_completion_tokens():
|
||||
"""The Grid accepts max_completion_tokens natively, so it is not remapped.
|
||||
|
||||
Unlike providers that only understand the legacy max_tokens field, sending
|
||||
max_completion_tokens to /v1/chat/completions caps the response, so the
|
||||
provider entry deliberately carries no param_mappings for it.
|
||||
"""
|
||||
config = _get_config()
|
||||
params = config.map_openai_params(
|
||||
non_default_params={"max_completion_tokens": 256},
|
||||
optional_params={},
|
||||
model="thegrid/text-standard",
|
||||
drop_params=False,
|
||||
)
|
||||
assert params.get("max_completion_tokens") == 256
|
||||
|
||||
|
||||
def test_thegrid_complete_url_appends_endpoint():
|
||||
config = _get_config()
|
||||
url = config.get_complete_url(
|
||||
api_base=THEGRID_BASE_URL,
|
||||
api_key="test-key",
|
||||
model="thegrid/text-standard",
|
||||
optional_params={},
|
||||
litellm_params={},
|
||||
stream=False,
|
||||
)
|
||||
assert url == f"{THEGRID_BASE_URL}/chat/completions"
|
||||
|
||||
|
||||
def test_thegrid_supports_responses_endpoint():
|
||||
provider = JSONProviderRegistry.get("thegrid")
|
||||
assert provider is not None
|
||||
assert "/v1/chat/completions" in provider.supported_endpoints
|
||||
assert "/v1/responses" in provider.supported_endpoints
|
||||
|
||||
|
||||
def test_supported_endpoints_matrix():
|
||||
"""The Grid must appear in the packaged backup that /public/endpoints serves."""
|
||||
matrix = json.loads(
|
||||
(Path(litellm.__file__).parent / "provider_endpoints_support_backup.json").read_text()
|
||||
)
|
||||
|
||||
endpoints = matrix["providers"]["thegrid"]["endpoints"]
|
||||
assert endpoints["chat_completions"] is True
|
||||
assert endpoints["responses"] is True
|
||||
assert endpoints["embeddings"] is False
|
||||
assert endpoints["messages"] is False
|
||||
Loading…
Add table
Reference in a new issue