feat(refuseless): add provider and model pricing (#48497)

* feat(refuseless): add provider and model pricing

* feat(refuseless): expose provider in Add Model catalog

* test(refuseless): verify model input trimming after upstream fix

* fix(refuseless): exclude unavailable free model from catalogs
This commit is contained in:
moe-berri 2026-10-26 18:08:42 -07:00 • committed by GitHub
parent b1f40b042b
commit c905cd065d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 392 additions and 0 deletions

View file

@ -249,5 +249,13 @@
"/v1/responses",
"/v1/messages"
]
},
"refuseless": {
"base_url": "https://api.refuseless.com/v1",
"api_key_env": "REFUSELESS_API_KEY",
"supported_endpoints": [
"/v1/chat/completions",
"/v1/responses"
]
}
}

View file

@ -75900,5 +75900,110 @@
"supports_reasoning": true,
"supports_response_schema": true,
"supports_vision": true
},
"refuseless/glm-5.3-abliterated": {
"cache_read_input_token_cost": 2.5e-07,
"input_cost_per_token": 1.25e-06,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.25e-06,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/glm-5.3-flash-abliterated": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 2.5e-07,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 8e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/deepseek-v4.1-flash-abliterated": {
"cache_read_input_token_cost": 4.5e-08,
"input_cost_per_token": 2.2e-07,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 130000,
"mode": "chat",
"output_cost_per_token": 7.5e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/deepseek-v4.1-flash-fast": {
"cache_read_input_token_cost": 3e-09,
"input_cost_per_token": 5e-08,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 262144,
"mode": "chat",
"output_cost_per_token": 1.5e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/minimax-m3.1-flash": {
"cache_read_input_token_cost": 2e-09,
"input_cost_per_token": 5e-08,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 512000,
"mode": "chat",
"output_cost_per_token": 2.5e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
}
}

View file

@ -32,6 +32,23 @@
}
},
"providers": {
"refuseless": {
"display_name": "Refuseless (`refuseless`)",
"url": "https://docs.litellm.ai/docs/providers/refuseless",
"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
}
},
"a2a": {
"display_name": "A2A (Agent-to-Agent) (`a2a`)",
"url": "https://docs.litellm.ai/docs/providers/a2a",

View file

@ -3231,6 +3231,34 @@
],
"default_model_placeholder": "gpt-3.5-turbo"
},
{
"provider": "REFUSELESS",
"provider_display_name": "Refuseless",
"litellm_provider": "refuseless",
"credential_fields": [
{
"key": "api_key",
"label": "API Key",
"placeholder": null,
"tooltip": null,
"required": true,
"field_type": "password",
"options": null,
"default_value": null
},
{
"key": "api_base",
"label": "API Base",
"placeholder": "https://api.refuseless.com/v1",
"tooltip": "Optional. Leave blank to use the provider's default endpoint.",
"required": false,
"field_type": "text",
"options": null,
"default_value": null
}
],
"default_model_placeholder": "refuseless/glm-5.3-abliterated"
},
{
"provider": "REPLICATE",
"provider_display_name": "Replicate",

View file

@ -4415,6 +4415,7 @@ GenericBudgetConfigType = dict[str, BudgetConfig]
class LlmProviders(str, Enum):
REFUSELESS = "refuseless"
OPENAI = "openai"
CHATGPT = "chatgpt"
OPENAI_LIKE = "openai_like" # embedding only

View file

@ -75900,5 +75900,110 @@
"supports_reasoning": true,
"supports_response_schema": true,
"supports_vision": true
},
"refuseless/glm-5.3-abliterated": {
"cache_read_input_token_cost": 2.5e-07,
"input_cost_per_token": 1.25e-06,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.25e-06,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/glm-5.3-flash-abliterated": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 2.5e-07,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 8e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/deepseek-v4.1-flash-abliterated": {
"cache_read_input_token_cost": 4.5e-08,
"input_cost_per_token": 2.2e-07,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 130000,
"mode": "chat",
"output_cost_per_token": 7.5e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/deepseek-v4.1-flash-fast": {
"cache_read_input_token_cost": 3e-09,
"input_cost_per_token": 5e-08,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 262144,
"mode": "chat",
"output_cost_per_token": 1.5e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
},
"refuseless/minimax-m3.1-flash": {
"cache_read_input_token_cost": 2e-09,
"input_cost_per_token": 5e-08,
"litellm_provider": "refuseless",
"max_input_tokens": 1048576,
"max_output_tokens": 512000,
"mode": "chat",
"output_cost_per_token": 2.5e-07,
"source": "https://refuseless.com/pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": false,
"reasoning_effort_levels": [
"low",
"high",
"max"
]
}
}

View file

@ -33,6 +33,23 @@
}
},
"providers": {
"refuseless": {
"display_name": "Refuseless (`refuseless`)",
"url": "https://docs.litellm.ai/docs/providers/refuseless",
"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
}
},
"a2a": {
"display_name": "A2A (Agent-to-Agent) (`a2a`)",
"url": "https://docs.litellm.ai/docs/providers/a2a",

View file

@ -0,0 +1,111 @@
import json
from typing import Final
import pytest
import respx
import litellm
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
from litellm.utils import trim_messages
def test_refuseless_resolves_environment_and_explicit_credentials(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("REFUSELESS_API_KEY", "fake-environment-key")
assert get_llm_provider(model="refuseless/glm-5.3-abliterated") == (
"glm-5.3-abliterated",
"refuseless",
"fake-environment-key",
"https://api.refuseless.com/v1",
)
assert get_llm_provider(
model="refuseless/glm-5.3-abliterated", api_key="fake-explicit-key", api_base="https://gateway.example/v1"
) == ("glm-5.3-abliterated", "refuseless", "fake-explicit-key", "https://gateway.example/v1")
def test_refuseless_chat_forwards_reasoning_and_accounts_for_cache(local_model_cost_map: None) -> None:
with respx.mock() as upstream:
route: Final = upstream.post("https://api.refuseless.com/v1/chat/completions").respond(
200,
json={
"id": "chatcmpl-test",
"object": "chat.completion",
"created": 1,
"model": "glm-5.3-abliterated",
"choices": [
{"index": 0, "message": {"role": "assistant", "content": "hello"}, "finish_reason": "stop"}
],
"usage": {
"prompt_tokens": 100,
"completion_tokens": 5,
"total_tokens": 105,
"prompt_tokens_details": {"cached_tokens": 80},
},
},
)
response: Final = litellm.completion(
model="refuseless/glm-5.3-abliterated",
api_key="fake-test-key",
messages=[{"role": "user", "content": "Say hello"}],
reasoning_effort="low",
)
request: Final = route.calls.last.request
body: Final = json.loads(request.content)
assert request.headers["authorization"] == "Bearer fake-test-key"
assert body["model"] == "glm-5.3-abliterated"
assert body["reasoning_effort"] == "low"
assert response.choices[0].message.content == "hello"
rates: Final = litellm.model_cost["refuseless/glm-5.3-abliterated"]
expected: Final = (
20 * rates["input_cost_per_token"]
+ 80 * rates["cache_read_input_token_cost"]
+ 5 * rates["output_cost_per_token"]
)
assert litellm.completion_cost(completion_response=response) == pytest.approx(expected)
def test_refuseless_uses_native_responses_endpoint() -> None:
with respx.mock() as upstream:
route: Final = upstream.post("https://api.refuseless.com/v1/responses").respond(
200,
json={
"id": "resp-test",
"object": "response",
"created_at": 1,
"model": "glm-5.3-abliterated",
"status": "completed",
"output": [
{
"id": "msg-test",
"type": "message",
"role": "assistant",
"status": "completed",
"content": [{"type": "output_text", "text": "hello", "annotations": []}],
}
],
"usage": {"input_tokens": 4, "output_tokens": 3, "total_tokens": 7},
},
)
response: Final = litellm.responses(
model="refuseless/glm-5.3-abliterated",
api_key="fake-test-key",
input="Say hello",
store=False,
)
assert route.calls.last.request.headers["authorization"] == "Bearer fake-test-key"
assert json.loads(route.calls.last.request.content)["model"] == "glm-5.3-abliterated"
assert response.output[0].content[0].text == "hello"
def test_refuseless_models_trim_to_their_input_budget(local_model_cost_map: None) -> None:
model_names: Final = tuple(model for model in litellm.model_cost if model.startswith("refuseless/"))
assert model_names
messages: Final = [{"role": "user", "content": "hello " * 500}]
budget: Final = 100
for model in model_names:
trimmed: Final = trim_messages(
messages,
model=model,
trim_ratio=budget / litellm.model_cost[model]["max_input_tokens"],
)
assert litellm.token_counter(model=model, messages=messages) > budget
assert litellm.token_counter(model=model, messages=trimmed) <= budget