diff --git a/src/Libraries/Microsoft.Extensions.AI.Ollama/OllamaChatClient.cs b/src/Libraries/Microsoft.Extensions.AI.Ollama/OllamaChatClient.cs index 408fa36d876..608573e05f6 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Ollama/OllamaChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Ollama/OllamaChatClient.cs @@ -142,6 +142,7 @@ public async IAsyncEnumerable CompleteStreamingAs StreamingChatCompletionUpdate update = new() { + CompletionId = chunk.CreatedAt, Role = chunk.Message?.Role is not null ? new ChatRole(chunk.Message.Role) : null, CreatedAt = DateTimeOffset.TryParse(chunk.CreatedAt, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTimeOffset createdAt) ? createdAt : null, FinishReason = ToFinishReason(chunk), diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMapper.ChatCompletion.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMapper.ChatCompletion.cs index 9f35727cf80..6ef871fcbbe 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMapper.ChatCompletion.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMapper.ChatCompletion.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; @@ -54,7 +55,7 @@ public static OpenAI.Chat.ChatCompletion ToOpenAIChatCompletion(ChatCompletion c } return OpenAIChatModelFactory.ChatCompletion( - id: chatCompletion.CompletionId, + id: chatCompletion.CompletionId ?? CreateCompletionId(), model: chatCompletion.ModelId, createdAt: chatCompletion.CreatedAt ?? default, role: ToOpenAIChatRole(chatCompletion.Message.Role).Value, @@ -584,6 +585,8 @@ private static FunctionCallContent ParseCallContentFromBinaryData(BinaryData ut8 private static T? GetValueOrDefault(this AdditionalPropertiesDictionary? dict, string key) => dict?.TryGetValue(key, out T? value) is true ? value : default; + private static string CreateCompletionId() => $"chatcmpl-{Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)}"; + /// Used to create the JSON payload for an OpenAI chat tool description. public sealed class OpenAIChatToolJson { diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMappers.StreamingChatCompletion.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMappers.StreamingChatCompletion.cs index 9fe6fa3fada..a4d8551461f 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMappers.StreamingChatCompletion.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIModelMappers.StreamingChatCompletion.cs @@ -46,7 +46,7 @@ internal static partial class OpenAIModelMappers } yield return OpenAIChatModelFactory.StreamingChatCompletionUpdate( - completionId: chatCompletionUpdate.CompletionId, + completionId: chatCompletionUpdate.CompletionId ?? CreateCompletionId(), model: chatCompletionUpdate.ModelId, createdAt: chatCompletionUpdate.CreatedAt ?? default, role: ToOpenAIChatRole(chatCompletionUpdate.Role), diff --git a/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaChatClientTests.cs index 6c2fcebb154..507666e52fc 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaChatClientTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaChatClientTests.cs @@ -185,6 +185,7 @@ public async Task BasicRequestResponse_Streaming() for (int i = 0; i < updates.Count; i++) { + Assert.NotNull(updates[i].CompletionId); Assert.Equal(i < updates.Count - 1 ? 1 : 2, updates[i].Contents.Count); Assert.Equal(ChatRole.Assistant, updates[i].Role); Assert.Equal("llama3.1", updates[i].ModelId);