mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
fix(openai_like): resolve 4-state capability matrix for function calling tools
This commit is contained in:
parent
153325492c
commit
703b982b77
2 changed files with 57 additions and 16 deletions
|
|
@ -110,15 +110,24 @@ def create_config_class(provider: SimpleProviderConfig):
|
|||
def _check_supports_fc() -> bool:
|
||||
if is_mocked:
|
||||
return bool(supports_function_calling(model=model, custom_llm_provider=provider.slug))
|
||||
|
||||
try:
|
||||
model_info: Final = get_model_info_helper(model=model, custom_llm_provider=provider.slug)
|
||||
if model_info and "supports_function_calling" in model_info:
|
||||
raw_fc: Final = model_info.get("supports_function_calling")
|
||||
if raw_fc is not None:
|
||||
# State 3: Model row in catalog explicitly declares capability -> takes precedence
|
||||
return bool(raw_fc)
|
||||
except (ModelNotMappedError, KeyError, ValueError):
|
||||
pass
|
||||
|
||||
# State 4: Provider-wide explicit False applies when model has no explicit declaration
|
||||
if provider.provider_info and provider.provider_info.get("supports_function_calling") is False:
|
||||
return False
|
||||
try:
|
||||
# If model is mapped in the catalog, respect its capability declaration
|
||||
get_model_info_helper(model=model, custom_llm_provider=provider.slug)
|
||||
return bool(supports_function_calling(model=model, custom_llm_provider=provider.slug))
|
||||
except (ModelNotMappedError, KeyError, ValueError):
|
||||
# Unmapped models on OpenAI-compatible providers default to supporting tools
|
||||
return True
|
||||
|
||||
# State 1 (unmapped model) & State 2 (mapped model with missing/None declaration):
|
||||
# default to preserving tool parameters for OpenAI-compatible providers
|
||||
return True
|
||||
|
||||
_supports_fc: Final = _check_supports_fc()
|
||||
|
||||
|
|
|
|||
|
|
@ -146,23 +146,30 @@ class TestForceStoreFalse:
|
|||
|
||||
class TestFunctionCallingParams:
|
||||
def test_unmapped_model_preserves_tool_parameters(self) -> None:
|
||||
"""Unmapped or newly added models on OpenAI-compatible providers should default to supporting tools."""
|
||||
"""State 1: Unmapped model on OpenAI-compatible provider defaults to preserving tool parameters."""
|
||||
config = create_config_class(_provider("unmapped_fc"))()
|
||||
params = config.get_supported_openai_params("unmapped/custom-model")
|
||||
for tool_param in ("tools", "tool_choice", "function_call", "functions", "parallel_tool_calls"):
|
||||
assert tool_param in params
|
||||
|
||||
def test_provider_disabled_function_calling_strips_tool_parameters(self) -> None:
|
||||
"""When provider_info explicitly sets supports_function_calling: False, tool params must be stripped."""
|
||||
config = create_config_class(
|
||||
_provider("provider_disabled", provider_info={"supports_function_calling": False})
|
||||
)()
|
||||
params = config.get_supported_openai_params("any-model")
|
||||
def test_known_model_missing_capability_field_preserves_tool_parameters(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""State 2: Known model in catalog without explicit supports_function_calling preserves tool parameters."""
|
||||
import litellm
|
||||
|
||||
monkeypatch.setitem(
|
||||
litellm.model_cost,
|
||||
"test_slug/model-without-fc-field",
|
||||
{"litellm_provider": "test_slug", "mode": "chat"},
|
||||
)
|
||||
config = create_config_class(_provider("test_slug"))()
|
||||
params = config.get_supported_openai_params("model-without-fc-field")
|
||||
for tool_param in ("tools", "tool_choice", "function_call", "functions", "parallel_tool_calls"):
|
||||
assert tool_param not in params
|
||||
assert tool_param in params
|
||||
|
||||
def test_model_explicitly_disabled_strips_tool_parameters(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""When a model is explicitly mapped with supports_function_calling: False, tool params must be stripped."""
|
||||
"""State 3: When a model row explicitly declares supports_function_calling: False, tool params are stripped."""
|
||||
import litellm
|
||||
|
||||
monkeypatch.setitem(
|
||||
|
|
@ -175,3 +182,28 @@ class TestFunctionCallingParams:
|
|||
for tool_param in ("tools", "tool_choice", "function_call", "functions", "parallel_tool_calls"):
|
||||
assert tool_param not in params
|
||||
|
||||
def test_model_explicitly_enabled_overrides_provider_disabled(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""State 3 override: Model explicit True overrides provider-wide supports_function_calling: False."""
|
||||
import litellm
|
||||
|
||||
monkeypatch.setitem(
|
||||
litellm.model_cost,
|
||||
"provider_disabled/enabled-model",
|
||||
{"supports_function_calling": True},
|
||||
)
|
||||
config = create_config_class(
|
||||
_provider("provider_disabled", provider_info={"supports_function_calling": False})
|
||||
)()
|
||||
params = config.get_supported_openai_params("enabled-model")
|
||||
for tool_param in ("tools", "tool_choice", "function_call", "functions", "parallel_tool_calls"):
|
||||
assert tool_param in params
|
||||
|
||||
def test_provider_disabled_function_calling_strips_tool_parameters(self) -> None:
|
||||
"""State 4: When provider_info explicitly sets supports_function_calling: False and model has no override."""
|
||||
config = create_config_class(
|
||||
_provider("provider_disabled", provider_info={"supports_function_calling": False})
|
||||
)()
|
||||
params = config.get_supported_openai_params("any-model")
|
||||
for tool_param in ("tools", "tool_choice", "function_call", "functions", "parallel_tool_calls"):
|
||||
assert tool_param not in params
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue