This commit is contained in:
hedging8563 2026-09-16 03:46:38 +00:00 committed by GitHub
commit 8b40af7c6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 6650 additions and 0 deletions

View file

@ -366,6 +366,7 @@ For MCP OAuth, an upstream may advertise dynamic client registration but refuse
| [Text Completion Codestral (`text-completion-codestral`)](https://docs.litellm.ai/docs/providers/codestral) | ✅ | ✅ | ✅ | | | | | | | |
| [Text Completion OpenAI (`text-completion-openai`)](https://docs.litellm.ai/docs/providers/text_completion_openai) | ✅ | ✅ | ✅ | | | ✅ | ✅ | ✅ | ✅ | |
| [Together AI (`together_ai`)](https://docs.litellm.ai/docs/providers/togetherai) | ✅ | ✅ | ✅ | | | | | | | |
| [TokenLab (`tokenlab`)](https://docs.tokenlab.sh/integrations/litellm) | ✅ | ✅ | ✅ | ✅ | | | | | | |
| [Topaz (`topaz`)](https://docs.litellm.ai/docs/providers/topaz) | ✅ | ✅ | ✅ | | | | | | | |
| [Triton (`triton`)](https://docs.litellm.ai/docs/providers/triton-inference-server) | ✅ | ✅ | ✅ | | | | | | | |
| [V0 (`v0`)](https://docs.litellm.ai/docs/providers/v0) | ✅ | ✅ | ✅ | | | | | | | |

View file

@ -680,6 +680,7 @@ qwen_ai_platform_models: Set = set()
moonshot_models: Set = set()
publicai_models: Set = set()
darkbloom_models: Set = set()
tokenlab_models: Set = set() # mutable-ok: populated while loading the static model registry
v0_models: Set = set()
morph_models: Set = set()
lambda_ai_models: Set = set()
@ -939,6 +940,8 @@ def _populate_provider_model_sets(model_cost_map: Dict) -> None:
publicai_models.add(key)
elif value.get("litellm_provider") == "darkbloom":
darkbloom_models.add(key)
elif value.get("litellm_provider") == "tokenlab":
tokenlab_models.add(key)
elif value.get("litellm_provider") == "v0":
v0_models.add(key)
elif value.get("litellm_provider") == "morph":
@ -1099,6 +1102,7 @@ model_list = list(
| moonshot_models
| publicai_models
| darkbloom_models
| tokenlab_models
| v0_models
| morph_models
| lambda_ai_models
@ -1208,6 +1212,7 @@ def _build_models_by_provider() -> dict:
"moonshot": moonshot_models,
"publicai": publicai_models,
"darkbloom": darkbloom_models,
"tokenlab": tokenlab_models,
"v0": v0_models,
"morph": morph_models,
"lambda_ai": lambda_ai_models,

View file

@ -893,6 +893,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://api.tokenlab.sh/v1",
"https://pinstripes.io/v1",
"https://api.meta.ai/v1",
"https://api.cognition.ai/v1",
@ -965,6 +966,7 @@ openai_compatible_providers: Final[list] = [
"docker_model_runner",
"ragflow",
"pinstripes", # Pinstripes - JSON-configured provider
"tokenlab", # TokenLab - JSON-configured provider
"darkbloom",
"meta", # Meta Model API (Muse Spark) - JSON-configured provider
"cognition",

View file

@ -363,6 +363,10 @@ def get_llm_provider(
elif endpoint == "https://api.inference.wandb.ai/v1":
custom_llm_provider = "wandb"
dynamic_api_key = get_secret_str("WANDB_API_KEY")
elif endpoint == "https://api.tokenlab.sh/v1":
custom_llm_provider = "tokenlab"
tokenlab_config: Final = JSONProviderRegistry.get("tokenlab")
dynamic_api_key = get_secret_str(tokenlab_config.api_key_env) if tokenlab_config else None
elif endpoint == "https://pinstripes.io/v1":
custom_llm_provider = "pinstripes"
dynamic_api_key = get_secret_str("PINSTRIPES_API_KEY")

View file

@ -78,6 +78,14 @@ class JSONProviderRegistry:
return False
return "/v1/responses" in provider.supported_endpoints
@classmethod
def supports_anthropic_messages_api(cls, slug: str) -> bool:
"""Check if a JSON provider supports the Anthropic Messages API"""
provider = cls._providers.get(slug)
if provider is None:
return False
return "/v1/messages" in provider.supported_endpoints
@classmethod
def list_providers(cls) -> list:
"""List all registered provider slugs"""

View file

@ -180,6 +180,15 @@
"api_key_env": "COGNITION_API_KEY",
"api_base_env": "COGNITION_API_BASE"
},
"tokenlab": {
"base_url": "https://api.tokenlab.sh/v1",
"api_key_env": "TOKENLAB_API_KEY",
"api_base_env": "TOKENLAB_API_BASE",
"param_mappings": {
"max_completion_tokens": "max_tokens"
},
"supported_endpoints": ["/v1/chat/completions", "/v1/messages", "/v1/responses", "/v1/embeddings"]
},
"pinstripes": {
"base_url": "https://pinstripes.io/v1",
"api_key_env": "PINSTRIPES_API_KEY",

File diff suppressed because it is too large Load diff

View file

@ -1628,6 +1628,23 @@
"a2a": false
}
},
"tokenlab": {
"display_name": "TokenLab (`tokenlab`)",
"url": "https://docs.tokenlab.sh/integrations/litellm",
"endpoints": {
"chat_completions": true,
"messages": true,
"responses": true,
"embeddings": true,
"image_generations": false,
"audio_transcriptions": false,
"audio_speech": false,
"moderations": false,
"batches": false,
"rerank": false,
"a2a": false
}
},
"nvidia_nim": {
"display_name": "Nvidia NIM (`nvidia_nim`)",
"url": "https://docs.litellm.ai/docs/providers/nvidia_nim",

View file

@ -4042,6 +4042,7 @@ class LlmProviders(str, Enum):
PARASAIL = "parasail"
XIAOMI_MIMO = "xiaomi_mimo"
TENSORMESH = "tensormesh"
TOKENLAB = "tokenlab"
LIBERTAI = "libertai"
PINSTRIPES = "pinstripes"
COGNITION = "cognition"

File diff suppressed because it is too large Load diff

View file

@ -2366,6 +2366,23 @@
"a2a": false
}
},
"tokenlab": {
"display_name": "TokenLab (`tokenlab`)",
"url": "https://docs.tokenlab.sh/integrations/litellm",
"endpoints": {
"chat_completions": true,
"messages": true,
"responses": true,
"embeddings": true,
"image_generations": false,
"audio_transcriptions": false,
"audio_speech": false,
"moderations": false,
"batches": false,
"rerank": false,
"a2a": false
}
},
"tensormesh": {
"display_name": "Tensormesh (`tensormesh`)",
"url": "https://docs.litellm.ai/docs/providers/tensormesh",

View file

@ -0,0 +1,176 @@
import pytest
import litellm
TOKENLAB_API_BASE = "https://api.tokenlab.sh/v1"
TOKENLAB_SAMPLE_MODELS = [
"tokenlab/gpt-5.5",
"tokenlab/claude-opus-4-8",
"tokenlab/gemini-3.5-flash",
"tokenlab/deepseek-v4-pro",
"tokenlab/qwen3.7-max",
"tokenlab/text-embedding-3-small",
]
def test_tokenlab_json_registry():
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
assert litellm.LlmProviders.TOKENLAB.value == "tokenlab"
assert litellm.LlmProviders("tokenlab") == litellm.LlmProviders.TOKENLAB
assert JSONProviderRegistry.exists("tokenlab")
config = JSONProviderRegistry.get("tokenlab")
assert config is not None
assert config.base_url == TOKENLAB_API_BASE
assert config.api_key_env == "TOKENLAB_API_KEY"
assert config.api_base_env == "TOKENLAB_API_BASE"
assert config.param_mappings["max_completion_tokens"] == "max_tokens"
assert config.supported_endpoints == [
"/v1/chat/completions",
"/v1/messages",
"/v1/responses",
"/v1/embeddings",
]
assert JSONProviderRegistry.supports_responses_api("tokenlab") is True
assert JSONProviderRegistry.supports_anthropic_messages_api("tokenlab") is True
def test_tokenlab_provider_detection_by_prefix():
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
model, provider, _, api_base = get_llm_provider("tokenlab/gpt-5.5")
assert model == "gpt-5.5"
assert provider == "tokenlab"
assert api_base == TOKENLAB_API_BASE
def test_tokenlab_api_base_override():
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
_, provider, api_key, api_base = get_llm_provider(
model="tokenlab/gpt-5.5",
api_base="https://custom.tokenlab.example/v1",
api_key="sk-test",
)
assert provider == "tokenlab"
assert api_base == "https://custom.tokenlab.example/v1"
assert api_key == "sk-test"
def test_tokenlab_url_autodetection():
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
_, provider, _, api_base = get_llm_provider(
model="gpt-5.5",
api_base=TOKENLAB_API_BASE,
)
assert provider == "tokenlab"
assert api_base == TOKENLAB_API_BASE
def test_tokenlab_chat_complete_url():
from litellm.llms.openai_like.dynamic_config import create_config_class
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
config = create_config_class(JSONProviderRegistry.get("tokenlab"))()
assert (
config.get_complete_url(
api_base=None,
api_key=None,
model="gpt-5.5",
optional_params={},
litellm_params={},
)
== "https://api.tokenlab.sh/v1/chat/completions"
)
def test_tokenlab_responses_api_config():
from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig
from litellm.utils import ProviderConfigManager
config = ProviderConfigManager.get_provider_responses_api_config(
provider="tokenlab",
model="tokenlab/gpt-5.5",
)
assert isinstance(config, OpenAIResponsesAPIConfig)
assert config.custom_llm_provider == "tokenlab"
assert config.get_complete_url(api_base=None, litellm_params={}) == "https://api.tokenlab.sh/v1/responses"
def test_tokenlab_anthropic_messages_config():
from litellm.llms.openai_like.messages.transformation import (
OpenAILikeAnthropicMessagesConfig,
)
from litellm.utils import ProviderConfigManager
config = ProviderConfigManager.get_provider_anthropic_messages_config(
provider=litellm.LlmProviders.TOKENLAB,
model="claude-opus-4-8",
)
assert isinstance(config, OpenAILikeAnthropicMessagesConfig)
assert (
config.get_complete_url(
api_base=TOKENLAB_API_BASE,
api_key="sk-test",
model="claude-opus-4-8",
optional_params={},
litellm_params={},
)
== "https://api.tokenlab.sh/v1/messages"
)
class TestTokenLabCostMap:
@pytest.fixture(autouse=True)
def _use_local_model_cost_map(self, monkeypatch):
original_model_cost = litellm.model_cost
monkeypatch.setenv("LITELLM_LOCAL_MODEL_COST_MAP", "True")
litellm.model_cost = litellm.get_model_cost_map(url="")
litellm.get_model_info.cache_clear()
try:
yield
finally:
litellm.model_cost = original_model_cost
litellm.get_model_info.cache_clear()
def test_sample_models_registered(self):
for model in TOKENLAB_SAMPLE_MODELS:
info = litellm.get_model_info(model)
assert info["litellm_provider"] == "tokenlab"
assert info["mode"] in {"chat", "embedding"}
def test_claude_model_cost_map_keeps_schema_supported_endpoints(self):
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
endpoints = litellm.model_cost["tokenlab/claude-opus-4-8"]["supported_endpoints"]
assert endpoints == ["/v1/chat/completions", "/v1/responses"]
provider_config = JSONProviderRegistry.get("tokenlab")
assert provider_config is not None
assert "/v1/messages" in provider_config.supported_endpoints
def test_chat_cost_is_wired(self):
prompt_cost, completion_cost = litellm.cost_per_token(
model="tokenlab/gpt-5.5",
prompt_tokens=1_000_000,
completion_tokens=1_000_000,
)
assert prompt_cost == pytest.approx(1.5)
assert completion_cost == pytest.approx(9.0)
def test_embedding_cost_is_wired(self):
prompt_cost, completion_cost = litellm.cost_per_token(
model="tokenlab/text-embedding-3-small",
prompt_tokens=1_000_000,
completion_tokens=0,
)
assert prompt_cost == pytest.approx(0.02)
assert completion_cost == 0