@@ -111,8 +111,9 @@ def _generate_response_from_error(error: BaseException) -> list[ChatGeneration]:
111
111
def _format_for_tracing (messages : list [BaseMessage ]) -> list [BaseMessage ]:
112
112
"""Format messages for tracing in on_chat_model_start.
113
113
114
- For backward compatibility, we update image content blocks to OpenAI Chat
115
- Completions format.
114
+ - Update image content blocks to OpenAI Chat Completions format (backward
115
+ compatibility).
116
+ - Add "type" key to content blocks that have a single key.
116
117
117
118
Args:
118
119
messages: List of messages to format.
@@ -125,20 +126,36 @@ def _format_for_tracing(messages: list[BaseMessage]) -> list[BaseMessage]:
125
126
message_to_trace = message
126
127
if isinstance (message .content , list ):
127
128
for idx , block in enumerate (message .content ):
128
- if (
129
- isinstance (block , dict )
130
- and block .get ("type" ) == "image"
131
- and is_data_content_block (block )
132
- and block .get ("source_type" ) != "id"
133
- ):
134
- if message_to_trace is message :
135
- message_to_trace = message .model_copy ()
136
- # Also shallow-copy content
137
- message_to_trace .content = list (message_to_trace .content )
138
-
139
- message_to_trace .content [idx ] = ( # type: ignore[index] # mypy confused by .model_copy
140
- convert_to_openai_image_block (block )
141
- )
129
+ if isinstance (block , dict ):
130
+ # Update image content blocks to OpenAI # Chat Completions format.
131
+ if (
132
+ block .get ("type" ) == "image"
133
+ and is_data_content_block (block )
134
+ and block .get ("source_type" ) != "id"
135
+ ):
136
+ if message_to_trace is message :
137
+ # Shallow copy
138
+ message_to_trace = message .model_copy ()
139
+ message_to_trace .content = list (message_to_trace .content )
140
+
141
+ message_to_trace .content [idx ] = ( # type: ignore[index] # mypy confused by .model_copy
142
+ convert_to_openai_image_block (block )
143
+ )
144
+ elif len (block ) == 1 and "type" not in block :
145
+ # Tracing assumes all content blocks have a "type" key. Here
146
+ # we add this key if it is missing, and there's an obvious
147
+ # choice for the type (e.g., a single key in the block).
148
+ if message_to_trace is message :
149
+ # Shallow copy
150
+ message_to_trace = message .model_copy ()
151
+ message_to_trace .content = list (message_to_trace .content )
152
+ key = next (iter (block ))
153
+ message_to_trace .content [idx ] = { # type: ignore[index]
154
+ "type" : key ,
155
+ key : block [key ],
156
+ }
157
+ else :
158
+ pass
142
159
messages_to_trace .append (message_to_trace )
143
160
144
161
return messages_to_trace
0 commit comments