diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ac0208aebcd..427a514700a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,196 +1,196 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - e36e4d1a8f8dfb08d7e3a6041459c9791d732c01 + 3875b54e7b10b10606b105340199946d0b877754 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - ed74665e773dd1ebea3289c5662d71c590305932 + 379bfc7b2559e7cc9f42f997a497b2f2dd8e12d2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 6765359588e8b38bab2a7974db9398432703828f + 8751e6d519fda94d5154187358765311ed4a4e84 diff --git a/eng/Versions.props b/eng/Versions.props index 483b6366af6..690e6d32f2d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,14 +11,14 @@ - false + true - + release true @@ -34,55 +34,55 @@ --> - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 - 9.0.5 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 + 9.0.6 - 9.0.5 + 9.0.6 9.0.0-beta.25271.1 @@ -108,8 +108,8 @@ 8.0.1 8.0.0 8.0.2 - 8.0.16 - 8.0.16 + 8.0.17 + 8.0.17 8.0.0 8.0.1 8.0.1 @@ -126,17 +126,17 @@ 8.0.5 8.0.0 - 8.0.16 - 8.0.16 - 8.0.16 - 8.0.16 - 8.0.16 - 8.0.16 - 8.0.16 - 8.0.16 - 8.0.16 + 8.0.17 + 8.0.17 + 8.0.17 + 8.0.17 + 8.0.17 + 8.0.17 + 8.0.17 + 8.0.17 + 8.0.17 - 8.0.16 + 8.0.17 - $(Version) - $(Version) - $(Version) + 9.6.0 + 9.6.0-preview.1.25310.2 + 9.6.0 diff --git a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs index 994fef47517..f34f930f3ea 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs @@ -342,8 +342,8 @@ private static void AssertUsageAgainstActivities(ChatResponse response, List (int?)a.GetTagItem("gen_ai.response.input_tokens")!); - var totalOutputTokens = activities.Sum(a => (int?)a.GetTagItem("gen_ai.response.output_tokens")!); + var totalInputTokens = activities.Sum(a => (int?)a.GetTagItem("gen_ai.usage.input_tokens")!); + var totalOutputTokens = activities.Sum(a => (int?)a.GetTagItem("gen_ai.usage.output_tokens")!); Assert.Equal(totalInputTokens, finalUsage.InputTokenCount * 2); Assert.Equal(totalOutputTokens, finalUsage.OutputTokenCount * 2); } @@ -618,9 +618,9 @@ public virtual async Task Caching_AfterFunctionInvocation_FunctionOutputUnchange // Second time, the calls to the LLM don't happen, but the function is called again var secondResponse = await chatClient.GetResponseAsync([message]); - Assert.Equal(response.Text, secondResponse.Text); Assert.Equal(2, functionCallCount); Assert.Equal(FunctionInvokingChatClientSetsConversationId ? 3 : 2, llmCallCount!.CallCount); + Assert.Equal(response.Text, secondResponse.Text); } public virtual bool FunctionInvokingChatClientSetsConversationId => false; @@ -785,8 +785,8 @@ public virtual async Task OpenTelemetry_CanEmitTracesAndMetrics() Assert.Equal(chatClient.GetService()?.ProviderUri?.Port, (int)activity.GetTagItem("server.port")!); Assert.NotNull(activity.Id); Assert.NotEmpty(activity.Id); - Assert.NotEqual(0, (int)activity.GetTagItem("gen_ai.response.input_tokens")!); - Assert.NotEqual(0, (int)activity.GetTagItem("gen_ai.response.output_tokens")!); + Assert.NotEqual(0, (int)activity.GetTagItem("gen_ai.usage.input_tokens")!); + Assert.NotEqual(0, (int)activity.GetTagItem("gen_ai.usage.output_tokens")!); Assert.True(activity.Duration.TotalMilliseconds > 0); } diff --git a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs index 1504d0d2488..0f422d950b8 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs @@ -128,7 +128,7 @@ public virtual async Task OpenTelemetry_CanEmitTracesAndMetrics() Assert.Equal(embeddingGenerator.GetService()?.ProviderUri?.Port, (int)activity.GetTagItem("server.port")!); Assert.NotNull(activity.Id); Assert.NotEmpty(activity.Id); - Assert.NotEqual(0, (int)activity.GetTagItem("gen_ai.response.input_tokens")!); + Assert.NotEqual(0, (int)activity.GetTagItem("gen_ai.usage.input_tokens")!); Assert.True(activity.Duration.TotalMilliseconds > 0); } diff --git a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/QuantizationEmbeddingGenerator.cs b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/QuantizationEmbeddingGenerator.cs index ea87408da38..5a7bf0b246e 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/QuantizationEmbeddingGenerator.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/QuantizationEmbeddingGenerator.cs @@ -52,7 +52,7 @@ private static BinaryEmbedding QuantizeToBinary(Embedding embedding) { if (vector[i] > 0) { - result[i / 8] = true; + result[i] = true; } } diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIAssistantChatClientIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIAssistantChatClientIntegrationTests.cs new file mode 100644 index 00000000000..e616d5fb87b --- /dev/null +++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIAssistantChatClientIntegrationTests.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. +#pragma warning disable CA1822 // Mark members as static +#pragma warning disable CA2000 // Dispose objects before losing scope +#pragma warning disable S1135 // Track uses of "TODO" tags +#pragma warning disable xUnit1013 // Public method should be marked as test + +using System; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using OpenAI.Assistants; +using Xunit; + +namespace Microsoft.Extensions.AI; + +public class OpenAIAssistantChatClientIntegrationTests : ChatClientIntegrationTests +{ + protected override IChatClient? CreateChatClient() + { + var openAIClient = IntegrationTestHelpers.GetOpenAIClient(); + if (openAIClient is null) + { + return null; + } + + AssistantClient ac = openAIClient.GetAssistantClient(); + var assistant = + ac.GetAssistants().FirstOrDefault() ?? + ac.CreateAssistant("gpt-4o-mini"); + + return ac.AsIChatClient(assistant.Id); + } + + public override bool FunctionInvokingChatClientSetsConversationId => true; + + // These tests aren't written in a way that works well with threads. + public override Task Caching_AfterFunctionInvocation_FunctionOutputChangedAsync() => Task.CompletedTask; + public override Task Caching_AfterFunctionInvocation_FunctionOutputUnchangedAsync() => Task.CompletedTask; + + // Assistants doesn't support data URIs. + public override Task MultiModal_DescribeImage() => Task.CompletedTask; + public override Task MultiModal_DescribePdf() => Task.CompletedTask; + + // [Fact] // uncomment and run to clear out _all_ threads in your OpenAI account + public async Task DeleteAllThreads() + { + using HttpClient client = new(new HttpClientHandler + { + AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, + }); + + // These values need to be filled in. The bearer token needs to be sniffed from a browser + // session interacting with the dashboard (e.g. use F12 networking tools to look at request headers + // made to "https://api.openai.com/v1/threads?limit=10" after clicking on Assistants | Threads in the + // OpenAI portal dashboard). + client.DefaultRequestHeaders.Add("authorization", $"Bearer sess-ENTERYOURSESSIONTOKEN"); + client.DefaultRequestHeaders.Add("openai-organization", "org-ENTERYOURORGID"); + client.DefaultRequestHeaders.Add("openai-project", "proj_ENTERYOURPROJECTID"); + + AssistantClient ac = new AssistantClient(Environment.GetEnvironmentVariable("AI:OpenAI:ApiKey")!); + while (true) + { + string listing = await client.GetStringAsync("https://api.openai.com/v1/threads?limit=100"); + + var matches = Regex.Matches(listing, @"thread_\w+"); + if (matches.Count == 0) + { + break; + } + + foreach (Match m in matches) + { + var dr = await ac.DeleteThreadAsync(m.Value); + Assert.True(dr.Value.Deleted); + } + } + } +} diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIAssistantChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIAssistantChatClientTests.cs new file mode 100644 index 00000000000..6d3a02a08ec --- /dev/null +++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIAssistantChatClientTests.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ClientModel; +using Azure.AI.OpenAI; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.Memory; +using OpenAI; +using OpenAI.Assistants; +using Xunit; + +#pragma warning disable S103 // Lines should not be too long +#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. + +namespace Microsoft.Extensions.AI; + +public class OpenAIAssistantChatClientTests +{ + [Fact] + public void AsIChatClient_InvalidArgs_Throws() + { + Assert.Throws("assistantClient", () => ((AssistantClient)null!).AsIChatClient("assistantId")); + Assert.Throws("assistantId", () => new AssistantClient("ignored").AsIChatClient(null!)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AsIChatClient_OpenAIClient_ProducesExpectedMetadata(bool useAzureOpenAI) + { + Uri endpoint = new("http://localhost/some/endpoint"); + + var client = useAzureOpenAI ? + new AzureOpenAIClient(endpoint, new ApiKeyCredential("key")) : + new OpenAIClient(new ApiKeyCredential("key"), new OpenAIClientOptions { Endpoint = endpoint }); + + IChatClient[] clients = + [ + client.GetAssistantClient().AsIChatClient("assistantId"), + client.GetAssistantClient().AsIChatClient("assistantId", "threadId"), + ]; + + foreach (var chatClient in clients) + { + var metadata = chatClient.GetService(); + Assert.Equal("openai", metadata?.ProviderName); + Assert.Equal(endpoint, metadata?.ProviderUri); + } + } + + [Fact] + public void GetService_AssistantClient_SuccessfullyReturnsUnderlyingClient() + { + AssistantClient assistantClient = new OpenAIClient("key").GetAssistantClient(); + IChatClient chatClient = assistantClient.AsIChatClient("assistantId"); + + Assert.Same(assistantClient, chatClient.GetService()); + + Assert.Null(chatClient.GetService()); + + using IChatClient pipeline = chatClient + .AsBuilder() + .UseFunctionInvocation() + .UseOpenTelemetry() + .UseDistributedCache(new MemoryDistributedCache(Options.Options.Create(new MemoryDistributedCacheOptions()))) + .Build(); + + Assert.NotNull(pipeline.GetService()); + Assert.NotNull(pipeline.GetService()); + Assert.NotNull(pipeline.GetService()); + Assert.NotNull(pipeline.GetService()); + + Assert.Same(assistantClient, pipeline.GetService()); + Assert.IsType(pipeline.GetService()); + } +} diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs index 2c1d6cdc80e..f8e835bdb81 100644 --- a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Threading.Tasks; + namespace Microsoft.Extensions.AI; public class OpenAIResponseClientIntegrationTests : ChatClientIntegrationTests @@ -11,4 +13,7 @@ public class OpenAIResponseClientIntegrationTests : ChatClientIntegrationTests .AsIChatClient(); public override bool FunctionInvokingChatClientSetsConversationId => true; + + // Test structure doesn't make sense with Respones. + public override Task Caching_AfterFunctionInvocation_FunctionOutputUnchangedAsync() => Task.CompletedTask; } diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs index 3747b79dc88..8b27cd918a7 100644 --- a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs @@ -264,19 +264,24 @@ public async Task BasicRequestResponse_Streaming() Assert.Equal("Hello! How can I assist you today?", string.Concat(updates.Select(u => u.Text))); var createdAt = DateTimeOffset.FromUnixTimeSeconds(1_741_892_091); - Assert.Equal(10, updates.Count); + Assert.Equal(17, updates.Count); + for (int i = 0; i < updates.Count; i++) { Assert.Equal("resp_67d329fbc87c81919f8952fe71dafc96029dabe3ee19bb77", updates[i].ResponseId); Assert.Equal("resp_67d329fbc87c81919f8952fe71dafc96029dabe3ee19bb77", updates[i].ConversationId); Assert.Equal(createdAt, updates[i].CreatedAt); Assert.Equal("gpt-4o-mini-2024-07-18", updates[i].ModelId); - Assert.Equal(ChatRole.Assistant, updates[i].Role); Assert.Null(updates[i].AdditionalProperties); - Assert.Equal(i == 10 ? 0 : 1, updates[i].Contents.Count); + Assert.Equal((i >= 4 && i <= 12) || i == 16 ? 1 : 0, updates[i].Contents.Count); Assert.Equal(i < updates.Count - 1 ? null : ChatFinishReason.Stop, updates[i].FinishReason); } + for (int i = 4; i < updates.Count; i++) + { + Assert.Equal(ChatRole.Assistant, updates[i].Role); + } + UsageContent usage = updates.SelectMany(u => u.Contents).OfType().Single(); Assert.Equal(26, usage.Details.InputTokenCount); Assert.Equal(10, usage.Details.OutputTokenCount); diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs index 4d0122c7c92..b81a480e207 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs @@ -171,8 +171,8 @@ async static IAsyncEnumerable CallbackAsync( Assert.Equal("id123", activity.GetTagItem("gen_ai.response.id")); Assert.Equal("""["stop"]""", activity.GetTagItem("gen_ai.response.finish_reasons")); - Assert.Equal(10, activity.GetTagItem("gen_ai.response.input_tokens")); - Assert.Equal(20, activity.GetTagItem("gen_ai.response.output_tokens")); + Assert.Equal(10, activity.GetTagItem("gen_ai.usage.input_tokens")); + Assert.Equal(20, activity.GetTagItem("gen_ai.usage.output_tokens")); Assert.Equal(enableSensitiveData ? "abcdefgh" : null, activity.GetTagItem("gen_ai.testservice.response.system_fingerprint")); Assert.Equal(enableSensitiveData ? "value2" : null, activity.GetTagItem("gen_ai.testservice.response.and_something_else")); diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/OpenTelemetryEmbeddingGeneratorTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/OpenTelemetryEmbeddingGeneratorTests.cs index 25e01afb1df..418d11544a3 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/OpenTelemetryEmbeddingGeneratorTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/OpenTelemetryEmbeddingGeneratorTests.cs @@ -89,7 +89,7 @@ public async Task ExpectedInformationLogged_Async(string? perRequestModelId, boo Assert.Equal(enableSensitiveData ? "value1" : null, activity.GetTagItem("gen_ai.testservice.request.service_tier")); Assert.Equal(enableSensitiveData ? "value2" : null, activity.GetTagItem("gen_ai.testservice.request.something_else")); - Assert.Equal(10, activity.GetTagItem("gen_ai.response.input_tokens")); + Assert.Equal(10, activity.GetTagItem("gen_ai.usage.input_tokens")); Assert.Equal(enableSensitiveData ? "abcdefgh" : null, activity.GetTagItem("gen_ai.testservice.response.system_fingerprint")); Assert.Equal(enableSensitiveData ? "value3" : null, activity.GetTagItem("gen_ai.testservice.response.and_something_else"));