-
Notifications
You must be signed in to change notification settings - Fork 841
Description
Description
In Microsoft.Extensions.AI.ChatResponseExtensions.ToChatResponse(), a ChatMessage is built from a series of ChatResponseUpdate items. Each ChatResponseUpdate may have a CreatedAt timestamp and the last non-null timestamp of the updates becomes the timestamp for the resulting ChatMessage.
However, it appears that some LLM calls stream updates with timestamps set to the Unix epoch (i.e. 1/1/1970 12AM) as an equivalent for a "null" value. In those cases, because the deserialized value is a real DateTimeOffset, the resulting ChatMessage will end up with CreatedAt timestamp set to that "null" value.
It may be better to update the ChatMessage timestamp upon the next update only if that update's timestamp is later than the current timestamp. (Or, alternatively, treat a timestamp set to the UNIX epoch as equivalent to null.)
Reproduction Steps
Adding this test to the ChatResponseUpdateExtensionsTests.cs in the Microsoft.Extensions.AI.Abstractions.Tests exposes the issue.
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task ToChatResponse_AlternativeTimestamps(bool useAsync)
{
DateTimeOffset now = DateTimeOffset.UtcNow;
ChatResponseUpdate[] updates =
[
new(ChatRole.Tool, "f") { MessageId = "4", CreatedAt = now },
new(null, "g") { CreatedAt = DateTimeOffset.UnixEpoch },
];
ChatResponse response = useAsync ?
updates.ToChatResponse() :
await YieldAsync(updates).ToChatResponseAsync();
Assert.Single(response.Messages);
Assert.Equal("fg", response.Messages[0].Text);
Assert.Equal(ChatRole.Tool, response.Messages[0].Role);
Assert.Equal(now, response.Messages[0].CreatedAt);
}Expected behavior
The first update's timestamp becomes the timestamp (i.e. CreatedAt) for the ChatMessage.
Actual behavior
The CreatedAt property of the ChatMessage is set to DateTimeOffset.UnixEpoc.
Regression?
Unknown.
Known Workarounds
None.
Configuration
.NET 9 with Microsoft.Extensions.AI.Abstractions version 9.9.0
Other information
No response