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:
Luis Castillo 2026-09-05 15:26:47 +02:00
parent c52b53706e
commit 43fe6afcac
No known key found for this signature in database
5 changed files with 371 additions and 0 deletions

View file

@ -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"]
}
}

View file

@ -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",

View file

@ -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
}
}

View file

@ -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": {

View 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