Skip to content

Commit d42d3e5

Browse files
authored
Tweak ChatMessage/StreamingChatCompletionUpdate.ToString (#5617)
* Tweak ChatMessage/StreamingChatCompletionUpdate.ToString Include all text rather than just the first text content. * Address PR feedback and fix / add tests
1 parent 81847a8 commit d42d3e5

File tree

6 files changed

+65
-9
lines changed

6 files changed

+65
-9
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Text;
67
using System.Text.Json.Serialization;
78
using Microsoft.Shared.Diagnostics;
89

@@ -85,8 +86,26 @@ public ChatMessage Message
8586
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
8687

8788
/// <inheritdoc />
88-
public override string ToString() =>
89-
Choices is { Count: > 0 } choices ? string.Join(Environment.NewLine, choices) : string.Empty;
89+
public override string ToString()
90+
{
91+
if (Choices.Count == 1)
92+
{
93+
return Choices[0].ToString();
94+
}
95+
96+
StringBuilder sb = new();
97+
for (int i = 0; i < Choices.Count; i++)
98+
{
99+
if (i > 0)
100+
{
101+
_ = sb.AppendLine().AppendLine();
102+
}
103+
104+
_ = sb.Append("Choice ").Append(i).AppendLine(":").Append(Choices[i]);
105+
}
106+
107+
return sb.ToString();
108+
}
90109

91110
/// <summary>Creates an array of <see cref="StreamingChatCompletionUpdate" /> instances that represent this <see cref="ChatCompletion" />.</summary>
92111
/// <returns>An array of <see cref="StreamingChatCompletionUpdate" /> instances that may be used to represent this <see cref="ChatCompletion" />.</returns>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,6 @@ public IList<AIContent> Contents
9595
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
9696

9797
/// <inheritdoc/>
98-
public override string ToString() => Text ?? string.Empty;
98+
public override string ToString() =>
99+
string.Concat(Contents.OfType<TextContent>());
99100
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,6 @@ public IList<AIContent> Contents
116116
public string? ModelId { get; set; }
117117

118118
/// <inheritdoc/>
119-
public override string ToString() => Text ?? string.Empty;
119+
public override string ToString() =>
120+
string.Concat(Contents.OfType<TextContent>());
120121
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,40 @@ public void JsonSerialization_Roundtrips()
168168
Assert.Equal("value", ((JsonElement)value!).GetString());
169169
}
170170

171+
[Fact]
172+
public void ToString_OneChoice_OutputsChatMessageToString()
173+
{
174+
ChatCompletion completion = new(
175+
[
176+
new ChatMessage(ChatRole.Assistant, "This is a test." + Environment.NewLine + "It's multiple lines.")
177+
]);
178+
179+
Assert.Equal(completion.Choices[0].Text, completion.ToString());
180+
}
181+
182+
[Fact]
183+
public void ToString_MultipleChoices_OutputsAllChoicesWithPrefix()
184+
{
185+
ChatCompletion completion = new(
186+
[
187+
new ChatMessage(ChatRole.Assistant, "This is a test." + Environment.NewLine + "It's multiple lines."),
188+
new ChatMessage(ChatRole.Assistant, "So is" + Environment.NewLine + " this."),
189+
new ChatMessage(ChatRole.Assistant, "And this."),
190+
]);
191+
192+
Assert.Equal(
193+
"Choice 0:" + Environment.NewLine +
194+
completion.Choices[0] + Environment.NewLine + Environment.NewLine +
195+
196+
"Choice 1:" + Environment.NewLine +
197+
completion.Choices[1] + Environment.NewLine + Environment.NewLine +
198+
199+
"Choice 2:" + Environment.NewLine +
200+
completion.Choices[2],
201+
202+
completion.ToString());
203+
}
204+
171205
[Fact]
172206
public void ToStreamingChatCompletionUpdates_SingleChoice()
173207
{

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Text.Json;
78
using Xunit;
89

@@ -91,7 +92,7 @@ public void Constructor_RoleList_PropsRoundtrip(int messageCount)
9192
}
9293

9394
Assert.Equal("text-0", message.Text);
94-
Assert.Equal("text-0", message.ToString());
95+
Assert.Equal(string.Concat(Enumerable.Range(0, messageCount).Select(i => $"text-{i}")), message.ToString());
9596
}
9697

9798
Assert.Null(message.AuthorName);
@@ -134,13 +135,13 @@ public void Text_GetSet_UsesFirstTextContent()
134135
TextContent textContent = Assert.IsType<TextContent>(message.Contents[3]);
135136
Assert.Equal("text-1", textContent.Text);
136137
Assert.Equal("text-1", message.Text);
137-
Assert.Equal("text-1", message.ToString());
138+
Assert.Equal("text-1text-2", message.ToString());
138139

139140
message.Text = "text-3";
140141
Assert.Equal("text-3", message.Text);
141142
Assert.Equal("text-3", message.Text);
142143
Assert.Same(textContent, message.Contents[3]);
143-
Assert.Equal("text-3", message.ToString());
144+
Assert.Equal("text-3text-2", message.ToString());
144145
}
145146

146147
[Fact]

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ public void Text_GetSet_UsesFirstTextContent()
103103
TextContent textContent = Assert.IsType<TextContent>(update.Contents[3]);
104104
Assert.Equal("text-1", textContent.Text);
105105
Assert.Equal("text-1", update.Text);
106-
Assert.Equal("text-1", update.ToString());
106+
Assert.Equal("text-1text-2", update.ToString());
107107

108108
update.Text = "text-3";
109109
Assert.Equal("text-3", update.Text);
110110
Assert.Equal("text-3", update.Text);
111111
Assert.Same(textContent, update.Contents[3]);
112-
Assert.Equal("text-3", update.ToString());
112+
Assert.Equal("text-3text-2", update.ToString());
113113
}
114114

115115
[Fact]

0 commit comments

Comments
 (0)