Skip to content

Commit 44fbcce

Browse files
authored
Factor ChatMessage.Role into ChatResponseUpdate coalescing logic (#6778)
If the role changes, consider it a new message.
1 parent a5200db commit 44fbcce

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseExtensions.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ private static void FinalizeResponse(ChatResponse response)
303303
private static void ProcessUpdate(ChatResponseUpdate update, ChatResponse response)
304304
{
305305
// If there is no message created yet, or if the last update we saw had a different
306-
// message ID than the newest update, create a new message.
306+
// message ID or role than the newest update, create a new message.
307307
ChatMessage message;
308308
var isNewMessage = false;
309309
if (response.Messages.Count == 0)
@@ -316,6 +316,12 @@ private static void ProcessUpdate(ChatResponseUpdate update, ChatResponse respon
316316
{
317317
isNewMessage = true;
318318
}
319+
else if (update.Role is { } updateRole
320+
&& response.Messages[response.Messages.Count - 1].Role is { } lastRole
321+
&& updateRole != lastRole)
322+
{
323+
isNewMessage = true;
324+
}
319325

320326
if (isNewMessage)
321327
{

test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/ChatCompletion/ChatResponseUpdateExtensionsTests.cs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public async Task ToChatResponse_SuccessfullyCreatesResponse(bool useAsync)
2929
ChatResponseUpdate[] updates =
3030
[
3131
new(ChatRole.Assistant, "Hello") { ResponseId = "someResponse", MessageId = "12345", CreatedAt = new DateTimeOffset(1, 2, 3, 4, 5, 6, TimeSpan.Zero), ModelId = "model123" },
32-
new(new("human"), ", ") { AuthorName = "Someone", AdditionalProperties = new() { ["a"] = "b" } },
32+
new(ChatRole.Assistant, ", ") { AuthorName = "Someone", AdditionalProperties = new() { ["a"] = "b" } },
3333
new(null, "world!") { CreatedAt = new DateTimeOffset(2, 2, 3, 4, 5, 6, TimeSpan.Zero), ConversationId = "123", AdditionalProperties = new() { ["c"] = "d" } },
3434

3535
new() { Contents = [new UsageContent(new() { InputTokenCount = 1, OutputTokenCount = 2 })] },
@@ -53,7 +53,7 @@ public async Task ToChatResponse_SuccessfullyCreatesResponse(bool useAsync)
5353

5454
ChatMessage message = response.Messages.Single();
5555
Assert.Equal("12345", message.MessageId);
56-
Assert.Equal(new ChatRole("human"), message.Role);
56+
Assert.Equal(ChatRole.Assistant, message.Role);
5757
Assert.Equal("Someone", message.AuthorName);
5858
Assert.Null(message.AdditionalProperties);
5959

@@ -65,6 +65,62 @@ public async Task ToChatResponse_SuccessfullyCreatesResponse(bool useAsync)
6565
Assert.Equal("Hello, world!", response.Text);
6666
}
6767

68+
[Theory]
69+
[InlineData(false)]
70+
[InlineData(true)]
71+
public async Task ToChatResponse_RoleOrIdChangeDictatesMessageChange(bool useAsync)
72+
{
73+
ChatResponseUpdate[] updates =
74+
[
75+
new(null, "!") { MessageId = "1" },
76+
new(ChatRole.Assistant, "a") { MessageId = "1" },
77+
new(ChatRole.Assistant, "b") { MessageId = "2" },
78+
new(ChatRole.User, "c") { MessageId = "2" },
79+
new(ChatRole.User, "d") { MessageId = "2" },
80+
new(ChatRole.Assistant, "e") { MessageId = "3" },
81+
new(ChatRole.Tool, "f") { MessageId = "4" },
82+
new(ChatRole.Tool, "g") { MessageId = "4" },
83+
new(ChatRole.Tool, "h") { MessageId = "5" },
84+
new(new("human"), "i") { MessageId = "6" },
85+
new(new("human"), "j") { MessageId = "7" },
86+
new(new("human"), "k") { MessageId = "7" },
87+
new(null, "l") { MessageId = "7" },
88+
new(null, "m") { MessageId = "8" },
89+
];
90+
91+
ChatResponse response = useAsync ?
92+
updates.ToChatResponse() :
93+
await YieldAsync(updates).ToChatResponseAsync();
94+
Assert.Equal(9, response.Messages.Count);
95+
96+
Assert.Equal("!a", response.Messages[0].Text);
97+
Assert.Equal(ChatRole.Assistant, response.Messages[0].Role);
98+
99+
Assert.Equal("b", response.Messages[1].Text);
100+
Assert.Equal(ChatRole.Assistant, response.Messages[1].Role);
101+
102+
Assert.Equal("cd", response.Messages[2].Text);
103+
Assert.Equal(ChatRole.User, response.Messages[2].Role);
104+
105+
Assert.Equal("e", response.Messages[3].Text);
106+
Assert.Equal(ChatRole.Assistant, response.Messages[3].Role);
107+
108+
Assert.Equal("fg", response.Messages[4].Text);
109+
Assert.Equal(ChatRole.Tool, response.Messages[4].Role);
110+
111+
Assert.Equal("h", response.Messages[5].Text);
112+
Assert.Equal(ChatRole.Tool, response.Messages[5].Role);
113+
114+
Assert.Equal("i", response.Messages[6].Text);
115+
Assert.Equal(new ChatRole("human"), response.Messages[6].Role);
116+
117+
Assert.Equal("jkl", response.Messages[7].Text);
118+
Assert.Equal(new ChatRole("human"), response.Messages[7].Role);
119+
120+
Assert.Equal("m", response.Messages[8].Text);
121+
Assert.Equal(ChatRole.Assistant, response.Messages[8].Role);
122+
}
123+
68124
[Theory]
69125
[InlineData(false)]
70126
[InlineData(true)]

0 commit comments

Comments
 (0)