mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix: support Cursor IDE tool_choice format {"type": "auto"} (#12168)
* fix: support Cursor IDE tool_choice format {"type": "auto"}
- Update validate_chat_completion_tool_choice to normalize {"type": "auto"} to "auto"
- Handles Cursor IDE sending non-standard tool_choice format
- Add comprehensive tests for tool choice validation
Fixes #12098
* fix: return full tool_choice object for Cursor IDE format
Based on PR feedback, updated validate_chat_completion_tool_choice to return
the full tool_choice dictionary instead of just extracting the type string.
This maintains consistency with downstream code that expects the full object
structure.
- Changed behavior: {"type": "auto"} now returns {"type": "auto"} instead of "auto"
- Updated tests to reflect the new expected behavior
- Ensures compatibility with code that passes tool_choice to optional_params
Addresses feedback from PR #12168
This commit is contained in:
parent
4bb732d30f
commit
a7594196cd
2 changed files with 71 additions and 0 deletions
|
|
@ -6571,6 +6571,14 @@ def validate_chat_completion_tool_choice(
|
|||
elif isinstance(tool_choice, str):
|
||||
return tool_choice
|
||||
elif isinstance(tool_choice, dict):
|
||||
# Handle Cursor IDE format: {"type": "auto"} -> return as-is
|
||||
if (
|
||||
tool_choice.get("type") in ["auto", "none", "required"]
|
||||
and "function" not in tool_choice
|
||||
):
|
||||
return tool_choice
|
||||
|
||||
# Standard OpenAI format: {"type": "function", "function": {...}}
|
||||
if tool_choice.get("type") is None or tool_choice.get("function") is None:
|
||||
raise Exception(
|
||||
f"Invalid tool choice, tool_choice={tool_choice}. Please ensure tool_choice follows the OpenAI spec"
|
||||
|
|
|
|||
63
tests/litellm_utils_tests/test_validate_tool_choice.py
Normal file
63
tests/litellm_utils_tests/test_validate_tool_choice.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import pytest
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../.."))
|
||||
|
||||
from litellm.utils import validate_chat_completion_tool_choice
|
||||
|
||||
|
||||
def test_validate_tool_choice_none():
|
||||
"""Test that None is returned as-is."""
|
||||
result = validate_chat_completion_tool_choice(None)
|
||||
assert result is None
|
||||
|
||||
|
||||
def test_validate_tool_choice_string():
|
||||
"""Test that string values are returned as-is."""
|
||||
assert validate_chat_completion_tool_choice("auto") == "auto"
|
||||
assert validate_chat_completion_tool_choice("none") == "none"
|
||||
assert validate_chat_completion_tool_choice("required") == "required"
|
||||
|
||||
|
||||
def test_validate_tool_choice_standard_dict():
|
||||
"""Test standard OpenAI format with function."""
|
||||
tool_choice = {"type": "function", "function": {"name": "my_function"}}
|
||||
result = validate_chat_completion_tool_choice(tool_choice)
|
||||
assert result == tool_choice
|
||||
|
||||
|
||||
def test_validate_tool_choice_cursor_format():
|
||||
"""Test Cursor IDE format: {"type": "auto"} -> {"type": "auto"}."""
|
||||
assert validate_chat_completion_tool_choice({"type": "auto"}) == {"type": "auto"}
|
||||
assert validate_chat_completion_tool_choice({"type": "none"}) == {"type": "none"}
|
||||
assert validate_chat_completion_tool_choice({"type": "required"}) == {"type": "required"}
|
||||
|
||||
|
||||
def test_validate_tool_choice_invalid_dict():
|
||||
"""Test that invalid dict formats raise exceptions."""
|
||||
# Missing both type and function
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
validate_chat_completion_tool_choice({})
|
||||
assert "Invalid tool choice" in str(exc_info.value)
|
||||
|
||||
# Invalid type value
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
validate_chat_completion_tool_choice({"type": "invalid"})
|
||||
assert "Invalid tool choice" in str(exc_info.value)
|
||||
|
||||
# Has type but missing function when type is "function"
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
validate_chat_completion_tool_choice({"type": "function"})
|
||||
assert "Invalid tool choice" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_validate_tool_choice_invalid_type():
|
||||
"""Test that invalid types raise exceptions."""
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
validate_chat_completion_tool_choice(123)
|
||||
assert "Got=<class 'int'>" in str(exc_info.value)
|
||||
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
validate_chat_completion_tool_choice([])
|
||||
assert "Got=<class 'list'>" in str(exc_info.value)
|
||||
Loading…
Add table
Reference in a new issue