mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-05 06:22:12 +00:00
fix: address PR review comments for model_dump_with_preserved_fields
- Restore preserve_fields param for backward compatibility (deprecated) - Use zip() instead of index-based iteration to prevent IndexError - Add backward compatibility test
This commit is contained in:
@@ -4565,9 +4565,6 @@ def validate_model_access(
|
||||
)
|
||||
|
||||
|
||||
# Fields within each choice that must be preserved as null (not stripped)
|
||||
# for OpenAI API compatibility. Each tuple is (sub_object, field_name).
|
||||
# To add a new preserved field, just append a tuple here.
|
||||
_PRESERVED_NONE_FIELDS: List[tuple] = [
|
||||
("message", "content"), # null when tool_calls present (issue #6677)
|
||||
("message", "role"), # always required by OpenAI spec
|
||||
@@ -4577,6 +4574,7 @@ _PRESERVED_NONE_FIELDS: List[tuple] = [
|
||||
|
||||
def model_dump_with_preserved_fields(
|
||||
obj: Any,
|
||||
preserve_fields: Optional[List[str]] = None,
|
||||
exclude_unset: bool = True,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
@@ -4588,6 +4586,7 @@ def model_dump_with_preserved_fields(
|
||||
|
||||
Args:
|
||||
obj: The Pydantic BaseModel instance to serialize
|
||||
preserve_fields: Deprecated, kept for backward compatibility.
|
||||
exclude_unset: Whether to exclude fields that were not explicitly set
|
||||
|
||||
Returns:
|
||||
@@ -4600,9 +4599,7 @@ def model_dump_with_preserved_fields(
|
||||
return result
|
||||
|
||||
obj_choices = obj.choices
|
||||
for i, choice_dict in enumerate(choices):
|
||||
choice_obj = obj_choices[i]
|
||||
|
||||
for choice_obj, choice_dict in zip(obj_choices, choices):
|
||||
for sub_object, field_name in _PRESERVED_NONE_FIELDS:
|
||||
sub_dict = choice_dict.get(sub_object)
|
||||
if sub_dict is None:
|
||||
|
||||
@@ -375,3 +375,39 @@ def test_delta_dynamic_attributes_in_model_dump():
|
||||
delta_no_role = Delta(content=None, role=None)
|
||||
dump_no_role = delta_no_role.model_dump(exclude_none=True)
|
||||
assert "role" not in dump_no_role
|
||||
|
||||
|
||||
def test_preserve_fields_param_backward_compat():
|
||||
"""preserve_fields parameter is accepted (deprecated) without error."""
|
||||
response = ModelResponse(
|
||||
choices=[
|
||||
Choices(
|
||||
finish_reason="tool_calls",
|
||||
index=0,
|
||||
message=Message(
|
||||
content=None,
|
||||
role="assistant",
|
||||
tool_calls=[
|
||||
{
|
||||
"id": "call_1",
|
||||
"type": "function",
|
||||
"function": {"name": "f", "arguments": "{}"},
|
||||
}
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
result_default = model_dump_with_preserved_fields(response, exclude_unset=True)
|
||||
result_explicit = model_dump_with_preserved_fields(
|
||||
response,
|
||||
preserve_fields=[
|
||||
"choices.*.message.content",
|
||||
"choices.*.message.role",
|
||||
"choices.*.delta.content",
|
||||
],
|
||||
exclude_unset=True,
|
||||
)
|
||||
assert result_default == result_explicit
|
||||
assert result_default["choices"][0]["message"]["content"] is None
|
||||
assert result_default["choices"][0]["message"]["role"] == "assistant"
|
||||
|
||||
Reference in New Issue
Block a user