@@ -165,6 +165,28 @@ def delete_cache_metadata(
165165 logger .warning (f"Failed to delete cache metadata: { str (e )} " )
166166
167167
168+ def _make_json_serializable (obj : object ) -> object :
169+ """Recursively convert objects to JSON-serializable types.
170+
171+ Handles Pydantic models, dicts, lists, and other common types.
172+ """
173+ if hasattr (obj , "model_dump" ):
174+ # Pydantic v2 model
175+ return obj .model_dump (mode = "json" )
176+ elif hasattr (obj , "dict" ):
177+ # Pydantic v1 model or similar
178+ return _make_json_serializable (obj .dict ())
179+ elif isinstance (obj , dict ):
180+ return {k : _make_json_serializable (v ) for k , v in obj .items ()}
181+ elif isinstance (obj , (list , tuple )):
182+ return [_make_json_serializable (item ) for item in obj ]
183+ elif isinstance (obj , (str , int , float , bool , type (None ))):
184+ return obj
185+ else :
186+ # Fallback: convert to string representation
187+ return str (obj )
188+
189+
168190def generate_cache_key_hash (
169191 cacheable_prefix : LanguageModelInput ,
170192 provider : str ,
@@ -184,8 +206,8 @@ def generate_cache_key_hash(
184206 """
185207 # Normalize to Sequence[ChatCompletionMessage] for consistent hashing
186208 messages = normalize_language_model_input (cacheable_prefix )
187- # Convert to list of dicts for serialization
188- messages_dict = [dict (msg ) for msg in messages ]
209+ # Convert to list of dicts for serialization, handling nested Pydantic models
210+ messages_dict = [_make_json_serializable ( dict (msg ) ) for msg in messages ]
189211
190212 # Serialize messages in a deterministic way
191213 # Include only content, roles, and order - exclude timestamps or dynamic fields
0 commit comments