diff --git a/litellm/llms/vertex_ai/common_utils.py b/litellm/llms/vertex_ai/common_utils.py index 970759479fe..1e068e8ff8f 100644 --- a/litellm/llms/vertex_ai/common_utils.py +++ b/litellm/llms/vertex_ai/common_utils.py @@ -511,6 +511,9 @@ def _fix_enum_empty_strings(schema, depth=0): if depth > DEFAULT_MAX_RECURSE_DEPTH: raise ValueError(f"Max depth of {DEFAULT_MAX_RECURSE_DEPTH} exceeded while processing schema.") + if not isinstance(schema, dict): + return + if "enum" in schema and isinstance(schema["enum"], list): schema["enum"] = [None if value == "" else value for value in schema["enum"]] @@ -524,6 +527,12 @@ def _fix_enum_empty_strings(schema, depth=0): if items is not None: _fix_enum_empty_strings(items, depth=depth + 1) + anyof = schema.get("anyOf", None) + if anyof is not None and isinstance(anyof, list): + for item in anyof: + if isinstance(item, dict): + _fix_enum_empty_strings(item, depth=depth + 1) + def _fix_enum_types(schema, depth=0): """Remove `enum` fields when the schema type is not string. diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py b/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py index dddc95bf54a..e86a1a27100 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py @@ -885,6 +885,46 @@ def test_fix_enum_empty_strings(): assert "tablet" in enum_values +def test_fix_enum_empty_strings_anyof(): + """Test _fix_enum_empty_strings handles anyOf structures including nullable enums.""" + from litellm.llms.vertex_ai.common_utils import _fix_enum_empty_strings + + schema = { + "type": "object", + "properties": { + "mode": { + "anyOf": [ + {"enum": ["", "fast", "slow"], "type": "string"}, + {"type": "null"}, + ] + }, + "complex_choice": { + "anyOf": [ + {"enum": ["", "option1"], "type": "string"}, + {"type": "integer"}, + ] + }, + }, + } + + _fix_enum_empty_strings(schema) + + mode_enum = schema["properties"]["mode"]["anyOf"][0]["enum"] + assert "" not in mode_enum + assert None in mode_enum + assert mode_enum == [None, "fast", "slow"] + + choice_enum = schema["properties"]["complex_choice"]["anyOf"][0]["enum"] + assert "" not in choice_enum + assert None in choice_enum + assert choice_enum == [None, "option1"] + + # Non-dict input should not raise AttributeError + _fix_enum_empty_strings("string_input") + _fix_enum_empty_strings(None) + + + def test_get_vertex_model_id_from_url(): """Test get_vertex_model_id_from_url with various URLs""" from litellm.llms.vertex_ai.common_utils import get_vertex_model_id_from_url