Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions litellm/llms/fireworks_ai/chat/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def get_supported_openai_params(self, model: str):
# Only add tool_choice for models that explicitly support it
if supports_tool_choice(model=model, custom_llm_provider="fireworks_ai"):
supported_params.append("tool_choice")
supported_params.append("parallel_tool_calls")

# Only add reasoning_effort for models that support it
if supports_reasoning(model=model, custom_llm_provider="fireworks_ai"):
Expand Down Expand Up @@ -248,34 +249,24 @@ def _transform_messages_helper(

return messages

def get_provider_info(self, model: str) -> ProviderSpecificModelInfo:
# Models that support reasoning_effort
reasoning_supported_models = [
"qwen3-8b",
"qwen3-32b",
"qwen3-coder-480b-a35b-instruct",
"deepseek-v3p1",
"deepseek-v3p2",
"glm-4p5",
"glm-4p5-air",
"glm-4p6",
"gpt-oss-120b",
"gpt-oss-20b",
]
def _get_model_cost_capability(self, model: str, capability: str) -> Optional[bool]:
candidate_keys = [model]
if not model.startswith("fireworks_ai/"):
candidate_keys.append(f"fireworks_ai/{model}")

# Normalize model name - remove prefix if present
normalized_model = model
if model.startswith("fireworks_ai/"):
normalized_model = model.replace("fireworks_ai/", "")
if normalized_model.startswith("accounts/fireworks/models/"):
normalized_model = normalized_model.replace(
"accounts/fireworks/models/", ""
)
for candidate_key in candidate_keys:
model_info = litellm.model_cost.get(candidate_key)
if model_info is not None and model_info.get(capability) is not None:
return cast(Optional[bool], model_info.get(capability))

# Check if model supports reasoning
supports_reasoning_value = any(
reasoning_model in normalized_model
for reasoning_model in reasoning_supported_models
return None

def get_provider_info(self, model: str) -> ProviderSpecificModelInfo:
supports_function_calling_value = self._get_model_cost_capability(
model=model, capability="supports_function_calling"
)
supports_reasoning_value = self._get_model_cost_capability(
model=model, capability="supports_reasoning"
)

provider_specific_model_info: ProviderSpecificModelInfo = {
Expand All @@ -285,9 +276,16 @@ def get_provider_info(self, model: str) -> ProviderSpecificModelInfo:
"supports_vision": True, # via document inlining
}

if supports_function_calling_value is not None:
provider_specific_model_info["supports_function_calling"] = (
supports_function_calling_value
)

# Only include supports_reasoning if True
if supports_reasoning_value:
provider_specific_model_info["supports_reasoning"] = True
if supports_reasoning_value is not None:
provider_specific_model_info["supports_reasoning"] = (
supports_reasoning_value
)

return provider_specific_model_info

Expand Down
30 changes: 30 additions & 0 deletions litellm/model_prices_and_context_window_backup.json
Original file line number Diff line number Diff line change
Expand Up @@ -12979,6 +12979,21 @@
"supports_response_schema": true,
"supports_tool_choice": true
},
"fireworks_ai/accounts/fireworks/models/glm-5p1": {
"cache_read_input_token_cost": 2.6e-07,
"input_cost_per_token": 1.4e-06,
"litellm_provider": "fireworks_ai",
"max_input_tokens": 202800,
"max_output_tokens": 202800,
"max_tokens": 202800,
"mode": "chat",
"output_cost_per_token": 4.4e-06,
"source": "https://fireworks.ai/models/fireworks/glm-5p1",
"supports_function_calling": false,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": false
},
"fireworks_ai/accounts/fireworks/models/gpt-oss-120b": {
"input_cost_per_token": 1.5e-07,
"litellm_provider": "fireworks_ai",
Expand Down Expand Up @@ -13245,6 +13260,21 @@
"supports_response_schema": true,
"supports_tool_choice": true
},
"fireworks_ai/glm-5p1": {
"cache_read_input_token_cost": 2.6e-07,
"input_cost_per_token": 1.4e-06,
"litellm_provider": "fireworks_ai",
"max_input_tokens": 202800,
"max_output_tokens": 202800,
"max_tokens": 202800,
"mode": "chat",
"output_cost_per_token": 4.4e-06,
"source": "https://fireworks.ai/models/fireworks/glm-5p1",
"supports_function_calling": false,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": false
},
"fireworks_ai/kimi-k2p5": {
"cache_read_input_token_cost": 1e-07,
"input_cost_per_token": 6e-07,
Expand Down
30 changes: 30 additions & 0 deletions model_prices_and_context_window.json
Original file line number Diff line number Diff line change
Expand Up @@ -12979,6 +12979,21 @@
"supports_response_schema": true,
"supports_tool_choice": true
},
"fireworks_ai/accounts/fireworks/models/glm-5p1": {
"cache_read_input_token_cost": 2.6e-07,
"input_cost_per_token": 1.4e-06,
"litellm_provider": "fireworks_ai",
"max_input_tokens": 202800,
"max_output_tokens": 202800,
"max_tokens": 202800,
"mode": "chat",
"output_cost_per_token": 4.4e-06,
"source": "https://fireworks.ai/models/fireworks/glm-5p1",
"supports_function_calling": false,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": false
},
"fireworks_ai/accounts/fireworks/models/gpt-oss-120b": {
"input_cost_per_token": 1.5e-07,
"litellm_provider": "fireworks_ai",
Expand Down Expand Up @@ -13245,6 +13260,21 @@
"supports_response_schema": true,
"supports_tool_choice": true
},
"fireworks_ai/glm-5p1": {
"cache_read_input_token_cost": 2.6e-07,
"input_cost_per_token": 1.4e-06,
"litellm_provider": "fireworks_ai",
"max_input_tokens": 202800,
"max_output_tokens": 202800,
"max_tokens": 202800,
"mode": "chat",
"output_cost_per_token": 4.4e-06,
"source": "https://fireworks.ai/models/fireworks/glm-5p1",
"supports_function_calling": false,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": false
},
"fireworks_ai/kimi-k2p5": {
"cache_read_input_token_cost": 1e-07,
"input_cost_per_token": 6e-07,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,23 @@
0, os.path.abspath("../../../../..")
) # Adds the parent directory to the system path

from litellm import supports_reasoning
from litellm import get_model_info, supports_reasoning
from litellm.llms.fireworks_ai.chat.transformation import FireworksAIConfig
from litellm.types.llms.openai import ChatCompletionToolCallFunctionChunk
from litellm.types.utils import ChatCompletionMessageToolCall, Function, Message


@pytest.fixture(autouse=True)
def force_local_model_cost(monkeypatch):
"""Force local model cost map usage for all tests in this file."""
monkeypatch.setenv("LITELLM_LOCAL_MODEL_COST_MAP", "True")
# Refresh model_cost from local map
import litellm
from litellm.litellm_core_utils.get_model_cost_map import get_model_cost_map

litellm.model_cost = get_model_cost_map(url=litellm.model_cost_map_url)


def test_handle_message_content_with_tool_calls():
config = FireworksAIConfig()
message = Message(
Expand Down Expand Up @@ -62,7 +73,6 @@ def test_handle_message_content_with_tool_calls():

def test_supports_reasoning_effort():
"""Test that reasoning_effort is only supported for specific Fireworks AI models."""
# Models that support reasoning_effort
supported_models = [
"fireworks_ai/accounts/fireworks/models/qwen3-8b",
"fireworks_ai/accounts/fireworks/models/qwen3-32b",
Expand All @@ -72,11 +82,13 @@ def test_supports_reasoning_effort():
"fireworks_ai/accounts/fireworks/models/glm-4p5",
"fireworks_ai/accounts/fireworks/models/glm-4p5-air",
"fireworks_ai/accounts/fireworks/models/glm-4p6",
"fireworks_ai/accounts/fireworks/models/glm-4p7",
"fireworks_ai/accounts/fireworks/models/glm-5p1",
"fireworks_ai/accounts/fireworks/models/gpt-oss-120b",
"fireworks_ai/accounts/fireworks/models/gpt-oss-20b",
"fireworks_ai/glm-5p1",
]

# Models that don't support reasoning_effort
unsupported_models = [
"fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct",
"fireworks_ai/accounts/fireworks/models/mixtral-8x7b-instruct",
Expand All @@ -97,19 +109,41 @@ def test_get_supported_openai_params_reasoning_effort():
"""Test that reasoning_effort is only included in supported params for models that support it."""
config = FireworksAIConfig()

# Model that supports reasoning_effort
supported_params = config.get_supported_openai_params(
"fireworks_ai/accounts/fireworks/models/qwen3-8b"
"fireworks_ai/accounts/fireworks/models/glm-5p1"
)
assert "reasoning_effort" in supported_params

# Model that doesn't support reasoning_effort
unsupported_params = config.get_supported_openai_params(
"fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct"
)
assert "reasoning_effort" not in unsupported_params


def test_get_supported_openai_params_parallel_tool_calls():
"""Test that parallel_tool_calls is included for models that support tool_choice."""
config = FireworksAIConfig()

supported_params = config.get_supported_openai_params(
"fireworks_ai/accounts/fireworks/models/glm-4p6"
)
assert "parallel_tool_calls" in supported_params

unsupported_params = config.get_supported_openai_params(
"fireworks_ai/accounts/fireworks/models/glm-5p1"
)
assert "parallel_tool_calls" not in unsupported_params


def test_get_model_info_respects_explicit_fireworks_capabilities():
"""Test that get_model_info preserves explicit capability flags from the model map."""
model_info = get_model_info("fireworks_ai/accounts/fireworks/models/glm-5p1")

assert model_info["supports_function_calling"] is False
assert model_info["supports_reasoning"] is True
assert model_info["supports_tool_choice"] is False


def test_add_transform_inline_image_block_skips_data_urls():
"""
data: URLs must not have #transform=inline appended — doing so corrupts the
Expand Down Expand Up @@ -220,3 +254,11 @@ def test_transform_messages_helper_removes_provider_specific_fields():
out = config._transform_messages_helper(messages, model="fireworks/test", litellm_params={})
for msg in out:
assert "provider_specific_fields" not in msg


def test_unmapped_model_fallback_function_calling():
"""Test that a model not in model_cost still defaults to supporting function calling for Fireworks."""
config = FireworksAIConfig()
model = "fireworks_ai/unmapped-future-model"
info = config.get_provider_info(model)
assert info["supports_function_calling"] is True
Loading