Skip to content

Commit 13e298a

Browse files
fix(llm): expand docstring and add reasoning_effort/response_format fallback coverage tests
Signed-off-by: Hasnaat Hussain <hasnaat.hussain.2@gmail.com>
1 parent b026127 commit 13e298a

2 files changed

Lines changed: 44 additions & 9 deletions

File tree

lib/crewai/src/crewai/llm.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,16 +2380,21 @@ def _get_custom_llm_provider(self) -> str | None:
23802380
return None
23812381

23822382
def _validate_call_params(self) -> None:
2383-
"""
2384-
Validate parameters before making a call. Currently this only checks if
2385-
a response_format is provided and whether the model supports it.
2386-
The custom_llm_provider is dynamically determined from the model:
2387-
- E.g., "openrouter/deepseek/deepseek-chat" yields "openrouter"
2388-
- "gemini/gemini-1.5-pro" yields "gemini"
2389-
- If no slash is present, "openai" is assumed.
2383+
"""Validate call parameters before executing a completion request.
2384+
2385+
Checks whether the requested ``response_format`` is supported by the
2386+
target model/provider via LiteLLM introspection. When introspection
2387+
raises an exception (e.g. an unmapped custom model ID or proxy
2388+
endpoint), the failure is logged at DEBUG level and validation is
2389+
skipped so the request can proceed — this mirrors the permissive
2390+
fallback used in :meth:`supports_function_calling`.
2391+
2392+
When no ``response_format`` is configured (including when only
2393+
``reasoning_effort`` or other parameters are set) this method returns
2394+
immediately without performing any checks.
23902395
23912396
Note: This validation only applies to the litellm fallback path.
2392-
Native providers have their own validation.
2397+
Native providers perform their own parameter validation.
23932398
"""
23942399
if self.response_format is None:
23952400
return

lib/crewai/tests/test_llm.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,7 @@ async def test_non_streaming_async_returns_tool_calls_when_text_also_present():
11991199
response = _build_response_with_text_and_tool_calls()
12001200

12011201
async def _ret(*args, **kwargs):
1202+
"""Return the pre-built mock response."""
12021203
return response
12031204

12041205
with patch("crewai.llm.litellm.acompletion", side_effect=_ret):
@@ -1214,6 +1215,35 @@ def test_validate_call_params_handles_introspection_error():
12141215
llm = LLM(model="custom/unsupported-model", is_litellm=True, response_format={"type": "json_object"})
12151216

12161217
with patch("crewai.llm.supports_response_schema", side_effect=Exception("Introspection error")):
1217-
# Should not raise exception
1218+
# Should not raise exception — permissive fallback applies
12181219
llm._validate_call_params()
12191220

1221+
1222+
def test_validate_call_params_raises_for_confirmed_unsupported_model():
1223+
"""Verify _validate_call_params still raises ValueError when introspection confirms no support.
1224+
1225+
This ensures the validation path is not silently skipped — only introspection
1226+
*errors* are swallowed; a clear ``False`` return still produces a ValueError.
1227+
"""
1228+
llm = LLM(model="my-provider/my-model", is_litellm=True, response_format={"type": "json_object"})
1229+
1230+
with patch("crewai.llm.supports_response_schema", return_value=False):
1231+
with pytest.raises(ValueError, match="does not support response_format"):
1232+
llm._validate_call_params()
1233+
1234+
1235+
def test_validate_call_params_skips_check_when_no_response_format():
1236+
"""Verify _validate_call_params is a no-op when response_format is not set.
1237+
1238+
This covers scenarios where only ``reasoning_effort`` or other parameters
1239+
are configured: the method must return immediately so those parameters are
1240+
forwarded to the provider without interference.
1241+
"""
1242+
llm = LLM(model="gpt-4o", is_litellm=True, reasoning_effort="medium")
1243+
1244+
# If supports_response_schema were called, patching it to raise would surface the bug
1245+
with patch("crewai.llm.supports_response_schema", side_effect=Exception("Should not be called")):
1246+
# No exception — response_format is None so introspection is never invoked
1247+
llm._validate_call_params()
1248+
1249+

0 commit comments

Comments
 (0)