Skip to content

Commit cd4448c

Browse files
author
Ritiz Tambi
committed
Fix Choice object deserialization in Trajectory validator
When trajectories are serialized and sent to the backend, Choice objects become dicts with structure {'message': {...}, 'logprobs': {...}, ...}. After deserialization, Pydantic doesn't reconstruct them back to Choice objects, causing KeyError: 'role' in tokenize.py. This adds a field_validator that detects serialized Choice dicts (by checking for 'message' and 'finish_reason' keys) and reconstructs them back into proper Choice objects using Choice.model_validate().
1 parent f2415e5 commit cd4448c

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

src/art/trajectories.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,28 @@ class Trajectory(pydantic.BaseModel):
4646
logs: list[str] = []
4747
start_time: datetime = pydantic.Field(default_factory=datetime.now, exclude=True)
4848

49+
@pydantic.field_validator('messages_and_choices', mode='before')
50+
@classmethod
51+
def reconstruct_choice_objects(cls, v: Any) -> Any:
52+
"""Reconstruct Choice objects from serialized dicts after deserialization."""
53+
if not isinstance(v, list):
54+
return v
55+
56+
result = []
57+
for item in v:
58+
# Check if this is a serialized Choice (has "message" key instead of "role")
59+
if isinstance(item, dict) and "message" in item and "finish_reason" in item:
60+
# Reconstruct as Choice object
61+
try:
62+
result.append(Choice.model_validate(item))
63+
except Exception:
64+
# If reconstruction fails, keep as dict
65+
result.append(item)
66+
else:
67+
# Regular message dict or already a Choice object
68+
result.append(item)
69+
return result
70+
4971
def __init__(self, **data: Any):
5072
super().__init__(**data)
5173
self.start_time = datetime.now()

0 commit comments

Comments
 (0)