diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 481e23b8083f..17db80f3b7bc 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -39,7 +39,7 @@ - + @@ -150,8 +150,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + \ No newline at end of file diff --git a/dotnet/src/IntegrationTests/Connectors/Onnx/BertOnnxTextEmbeddingGenerationServiceTests.cs b/dotnet/src/IntegrationTests/Connectors/Onnx/BertOnnxTextEmbeddingGenerationServiceTests.cs index e2f7f006202c..be32d4cda549 100644 --- a/dotnet/src/IntegrationTests/Connectors/Onnx/BertOnnxTextEmbeddingGenerationServiceTests.cs +++ b/dotnet/src/IntegrationTests/Connectors/Onnx/BertOnnxTextEmbeddingGenerationServiceTests.cs @@ -9,7 +9,9 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.Onnx; using Microsoft.SemanticKernel.Embeddings; using Xunit; diff --git a/dotnet/src/IntegrationTests/Connectors/Onnx/OnnxRuntimeGenAIChatCompletionServiceTests.cs b/dotnet/src/IntegrationTests/Connectors/Onnx/OnnxRuntimeGenAIChatCompletionServiceTests.cs new file mode 100644 index 000000000000..c6359e3b17a5 --- /dev/null +++ b/dotnet/src/IntegrationTests/Connectors/Onnx/OnnxRuntimeGenAIChatCompletionServiceTests.cs @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.Onnx; +using SemanticKernel.IntegrationTests.TestSettings; +using Xunit; + +namespace SemanticKernel.IntegrationTests.Connectors.Onnx; + +public class OnnxRuntimeGenAIChatCompletionServiceTests : BaseIntegrationTest +{ + [Fact(Skip = "For manual verification only")] + public async Task ItCanUseKernelInvokeAsyncAsync() + { + // Arrange + var kernel = this.CreateAndInitializeKernel(); + + var func = kernel.CreateFunctionFromPrompt("List the two planets after '{{$input}}', excluding moons, using bullet points."); + + // Act + var result = await func.InvokeAsync(kernel, new() { ["input"] = "Jupiter" }); + + // Assert + Assert.NotNull(result); + Assert.Contains("Saturn", result.GetValue(), StringComparison.InvariantCultureIgnoreCase); + Assert.Contains("Uranus", result.GetValue(), StringComparison.InvariantCultureIgnoreCase); + } + + [Fact(Skip = "For manual verification only")] + public async Task ItCanUseKernelInvokeStreamingAsyncAsync() + { + // Arrange + var kernel = this.CreateAndInitializeKernel(); + + var plugins = TestHelpers.ImportSamplePlugins(kernel, "ChatPlugin"); + + StringBuilder fullResult = new(); + + var prompt = "Where is the most famous fish market in Seattle, Washington, USA?"; + + // Act + await foreach (var content in kernel.InvokeStreamingAsync(plugins["ChatPlugin"]["Chat"], new() { ["input"] = prompt })) + { + fullResult.Append(content); + } + + // Assert + Assert.Contains("Pike Place", fullResult.ToString(), StringComparison.OrdinalIgnoreCase); + } + + [Fact(Skip = "For manual verification only")] + public async Task ItCanUseServiceGetStreamingChatMessageContentsAsync() + { + using var chat = CreateService(); + + ChatHistory history = []; + history.AddUserMessage("Where is the most famous fish market in Seattle, Washington, USA?"); + + StringBuilder fullResult = new(); + + await foreach (var content in chat.GetStreamingChatMessageContentsAsync(history)) + { + fullResult.Append(content); + } + + // Assert + Assert.Contains("Pike Place", fullResult.ToString(), StringComparison.OrdinalIgnoreCase); + } + + [Fact(Skip = "For manual verification only")] + public async Task ItCanUseServiceGetChatMessageContentsAsync() + { + using var chat = CreateService(); + + ChatHistory history = []; + history.AddUserMessage("Where is the most famous fish market in Seattle, Washington, USA?"); + + var content = await chat.GetChatMessageContentAsync(history); + + Assert.Contains("Pike Place", content.ToString(), StringComparison.OrdinalIgnoreCase); + } + + private static OnnxRuntimeGenAIChatCompletionService CreateService() + { + Assert.NotNull(Configuration.ModelPath); + Assert.NotNull(Configuration.ModelId); + + return new OnnxRuntimeGenAIChatCompletionService(Configuration.ModelId, Configuration.ModelPath); + } + + #region internals + + private Kernel CreateAndInitializeKernel(HttpClient? httpClient = null) + { + Assert.NotNull(Configuration.ModelPath); + Assert.NotNull(Configuration.ModelId); + + var kernelBuilder = base.CreateKernelBuilder(); + + kernelBuilder.AddOnnxRuntimeGenAIChatCompletion( + modelId: Configuration.ModelId, + modelPath: Configuration.ModelPath, + serviceId: Configuration.ServiceId); + + return kernelBuilder.Build(); + } + + private static OnnxConfiguration Configuration => new ConfigurationBuilder() + .AddJsonFile(path: "testsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile(path: "testsettings.development.json", optional: true, reloadOnChange: true) + .AddEnvironmentVariables() + .AddUserSecrets() + .Build() + .GetRequiredSection("Onnx") + .Get()!; + + #endregion +} diff --git a/dotnet/src/IntegrationTests/TestSettings/OnnxConfiguration.cs b/dotnet/src/IntegrationTests/TestSettings/OnnxConfiguration.cs new file mode 100644 index 000000000000..17350b10a701 --- /dev/null +++ b/dotnet/src/IntegrationTests/TestSettings/OnnxConfiguration.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Diagnostics.CodeAnalysis; + +namespace SemanticKernel.IntegrationTests.TestSettings; + +[SuppressMessage("Performance", "CA1812:Internal class that is apparently never instantiated", + Justification = "Configuration classes are instantiated through IConfiguration.")] +internal sealed class OnnxConfiguration +{ + public string? ModelId { get; set; } + public string? ModelPath { get; set; } + public string? ServiceId { get; internal set; } +}