16
16
ANNOTATION_CONTENT_TAG ,
17
17
CHAT_MESSAGE_CONTENT_TAG ,
18
18
DISCRIMINATOR_FIELD ,
19
+ FILE_CONTENT_TAG ,
19
20
FILE_REFERENCE_CONTENT_TAG ,
20
21
FUNCTION_CALL_CONTENT_TAG ,
21
22
FUNCTION_RESULT_CONTENT_TAG ,
26
27
ContentTypes ,
27
28
)
28
29
from semantic_kernel .contents .file_reference_content import FileReferenceContent
30
+ from semantic_kernel .contents .file_content import FileContent
29
31
from semantic_kernel .contents .function_call_content import FunctionCallContent
30
32
from semantic_kernel .contents .function_result_content import FunctionResultContent
31
33
from semantic_kernel .contents .image_content import ImageContent
32
34
from semantic_kernel .contents .kernel_content import KernelContent
33
- from semantic_kernel .contents .streaming_annotation_content import StreamingAnnotationContent
34
- from semantic_kernel .contents .streaming_file_reference_content import StreamingFileReferenceContent
35
+ from semantic_kernel .contents .streaming_annotation_content import (
36
+ StreamingAnnotationContent ,
37
+ )
38
+ from semantic_kernel .contents .streaming_file_reference_content import (
39
+ StreamingFileReferenceContent ,
40
+ )
35
41
from semantic_kernel .contents .text_content import TextContent
36
42
from semantic_kernel .contents .utils .author_role import AuthorRole
37
43
from semantic_kernel .contents .utils .finish_reason import FinishReason
48
54
IMAGE_CONTENT_TAG : ImageContent ,
49
55
STREAMING_FILE_REFERENCE_CONTENT_TAG : StreamingFileReferenceContent ,
50
56
STREAMING_ANNOTATION_CONTENT_TAG : StreamingAnnotationContent ,
57
+ FILE_CONTENT_TAG : FileContent ,
51
58
}
52
59
53
60
CMC_ITEM_TYPES = Annotated [
58
65
| FunctionResultContent
59
66
| FunctionCallContent
60
67
| FileReferenceContent
68
+ | FileContent
61
69
| StreamingAnnotationContent
62
70
| StreamingFileReferenceContent
63
71
| AudioContent ,
@@ -239,7 +247,13 @@ def to_element(self) -> "Element":
239
247
"""
240
248
root = Element (self .tag )
241
249
for field in self .model_fields_set :
242
- if field not in ["role" , "name" , "encoding" , "finish_reason" , "ai_model_id" ]:
250
+ if field not in [
251
+ "role" ,
252
+ "name" ,
253
+ "encoding" ,
254
+ "finish_reason" ,
255
+ "ai_model_id" ,
256
+ ]:
243
257
continue
244
258
value = getattr (self , field )
245
259
if isinstance (value , Enum ):
@@ -260,15 +274,22 @@ def from_element(cls, element: Element) -> "ChatMessageContent":
260
274
ChatMessageContent - The new instance of ChatMessageContent or a subclass.
261
275
"""
262
276
if element .tag != cls .tag :
263
- raise ContentInitializationError (f"Element tag is not { cls .tag } " ) # pragma: no cover
277
+ raise ContentInitializationError (
278
+ f"Element tag is not { cls .tag } "
279
+ ) # pragma: no cover
264
280
kwargs : dict [str , Any ] = {key : value for key , value in element .items ()}
265
281
items : list [KernelContent ] = []
266
282
if element .text :
267
283
items .append (TextContent (text = unescape (element .text )))
268
284
for child in element :
269
285
if child .tag not in TAG_CONTENT_MAP :
270
- logger .warning ('Unknown tag "%s" in ChatMessageContent, treating as text' , child .tag )
271
- text = ElementTree .tostring (child , encoding = "unicode" , short_empty_elements = False )
286
+ logger .warning (
287
+ 'Unknown tag "%s" in ChatMessageContent, treating as text' ,
288
+ child .tag ,
289
+ )
290
+ text = ElementTree .tostring (
291
+ child , encoding = "unicode" , short_empty_elements = False
292
+ )
272
293
items .append (TextContent (text = unescape (text ) or "" ))
273
294
else :
274
295
items .append (TAG_CONTENT_MAP [child .tag ].from_element (child )) # type: ignore
@@ -294,9 +315,13 @@ def to_prompt(self) -> str:
294
315
str - The prompt from the ChatMessageContent.
295
316
"""
296
317
root = self .to_element ()
297
- return ElementTree .tostring (root , encoding = self .encoding or "unicode" , short_empty_elements = False )
318
+ return ElementTree .tostring (
319
+ root , encoding = self .encoding or "unicode" , short_empty_elements = False
320
+ )
298
321
299
- def to_dict (self , role_key : str = "role" , content_key : str = "content" ) -> dict [str , Any ]:
322
+ def to_dict (
323
+ self , role_key : str = "role" , content_key : str = "content"
324
+ ) -> dict [str , Any ]:
300
325
"""Serialize the ChatMessageContent to a dictionary.
301
326
302
327
Returns:
@@ -305,8 +330,14 @@ def to_dict(self, role_key: str = "role", content_key: str = "content") -> dict[
305
330
ret : dict [str , Any ] = {
306
331
role_key : self .role .value ,
307
332
}
308
- if self .role == AuthorRole .ASSISTANT and any (isinstance (item , FunctionCallContent ) for item in self .items ):
309
- ret ["tool_calls" ] = [item .to_dict () for item in self .items if isinstance (item , FunctionCallContent )]
333
+ if self .role == AuthorRole .ASSISTANT and any (
334
+ isinstance (item , FunctionCallContent ) for item in self .items
335
+ ):
336
+ ret ["tool_calls" ] = [
337
+ item .to_dict ()
338
+ for item in self .items
339
+ if isinstance (item , FunctionCallContent )
340
+ ]
310
341
else :
311
342
ret [content_key ] = self ._parse_items ()
312
343
if self .role == AuthorRole .TOOL :
@@ -330,5 +361,16 @@ def _parse_items(self) -> str | list[dict[str, Any]]:
330
361
331
362
def __hash__ (self ) -> int :
332
363
"""Return the hash of the chat message content."""
333
- hashable_items = [make_hashable (item ) for item in self .items ] if self .items else []
334
- return hash ((self .tag , self .role , self .content , self .encoding , self .finish_reason , * hashable_items ))
364
+ hashable_items = (
365
+ [make_hashable (item ) for item in self .items ] if self .items else []
366
+ )
367
+ return hash (
368
+ (
369
+ self .tag ,
370
+ self .role ,
371
+ self .content ,
372
+ self .encoding ,
373
+ self .finish_reason ,
374
+ * hashable_items ,
375
+ )
376
+ )
0 commit comments