forked from microsoft/semantic-kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChatMessageExtensions.cs
More file actions
96 lines (86 loc) · 4.74 KB
/
ChatMessageExtensions.cs
File metadata and controls
96 lines (86 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
namespace Microsoft.Extensions.AI;
[ExcludeFromCodeCoverage]
internal static class ChatMessageExtensions
{
/// <summary>Converts a <see cref="ChatMessage"/> to a <see cref="ChatMessageContent"/>.</summary>
internal static ChatMessageContent ToChatMessageContent(this ChatMessage message, Microsoft.Extensions.AI.ChatResponse? response = null)
{
ChatMessageContent result = new()
{
ModelId = response?.ModelId,
AuthorName = message.AuthorName,
InnerContent = response?.RawRepresentation ?? message.RawRepresentation,
Metadata = new AdditionalPropertiesDictionary(message.AdditionalProperties ?? []) { ["Usage"] = response?.Usage },
Role = new AuthorRole(message.Role.Value),
};
if (response?.RawRepresentation is not null)
{
var raw = response.RawRepresentation;
var messageProp = raw.GetType().GetProperty("Message");
var messageObj = messageProp?.GetValue(raw);
var thinkingProp = messageObj?.GetType().GetProperty("Thinking");
var thinking = thinkingProp?.GetValue(messageObj) as string;
if (!string.IsNullOrWhiteSpace(thinking))
{
result.Items.Add(new Microsoft.SemanticKernel.TextContent($"[THINKING]\n{thinking}")
{
ModelId = response?.ModelId,
InnerContent = raw
});
}
}
foreach (AIContent content in message.Contents)
{
#pragma warning disable SKEXP0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
KernelContent? resultContent = content switch
{
Microsoft.Extensions.AI.TextContent tc => new Microsoft.SemanticKernel.TextContent(tc.Text),
Microsoft.Extensions.AI.DataContent dc when dc.HasTopLevelMediaType("image") => new Microsoft.SemanticKernel.ImageContent(dc.Uri),
Microsoft.Extensions.AI.UriContent uc when uc.HasTopLevelMediaType("image") => new Microsoft.SemanticKernel.ImageContent(uc.Uri),
Microsoft.Extensions.AI.DataContent dc when dc.HasTopLevelMediaType("audio") => new Microsoft.SemanticKernel.AudioContent(dc.Uri),
Microsoft.Extensions.AI.UriContent uc when uc.HasTopLevelMediaType("audio") => new Microsoft.SemanticKernel.AudioContent(uc.Uri),
Microsoft.Extensions.AI.DataContent dc => new Microsoft.SemanticKernel.BinaryContent(dc.Uri),
Microsoft.Extensions.AI.UriContent uc => new Microsoft.SemanticKernel.BinaryContent(uc.Uri),
Microsoft.Extensions.AI.FunctionCallContent fcc => new Microsoft.SemanticKernel.FunctionCallContent(
functionName: fcc.Name,
id: fcc.CallId,
arguments: fcc.Arguments is not null ? new(fcc.Arguments) : null),
Microsoft.Extensions.AI.FunctionResultContent frc => new Microsoft.SemanticKernel.FunctionResultContent(
functionName: GetFunctionCallContent(frc.CallId)?.Name,
callId: frc.CallId,
result: frc.Result),
_ => null
};
#pragma warning restore SKEXP0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
if (resultContent is not null)
{
resultContent.Metadata = content.AdditionalProperties;
resultContent.InnerContent = content.RawRepresentation;
resultContent.ModelId = response?.ModelId;
result.Items.Add(resultContent);
}
}
return result;
Microsoft.Extensions.AI.FunctionCallContent? GetFunctionCallContent(string callId)
=> response?.Messages
.Select(m => m.Contents
.FirstOrDefault(c => c is Microsoft.Extensions.AI.FunctionCallContent fcc && fcc.CallId == callId) as Microsoft.Extensions.AI.FunctionCallContent)
.FirstOrDefault(fcc => fcc is not null);
}
/// <summary>Converts a list of <see cref="ChatMessage"/> to a <see cref="ChatHistory"/>.</summary>
internal static ChatHistory ToChatHistory(this IEnumerable<ChatMessage> chatMessages)
{
ChatHistory chatHistory = [];
foreach (var message in chatMessages)
{
chatHistory.Add(message.ToChatMessageContent());
}
return chatHistory;
}
}