From e66883e72a1c05a545705bf3427d0b4077ec489d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:31:12 -0500 Subject: [PATCH 1/3] .Net: Bump Microsoft.Data.Sqlite from 8.0.10 to 9.0.0 in /dotnet (#9915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [Microsoft.Data.Sqlite](https://github.com/dotnet/efcore) from 8.0.10 to 9.0.0.
Release notes

Sourced from Microsoft.Data.Sqlite's releases.

.NET 9.0.0

Release

What's Changed

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.Data.Sqlite&package-manager=nuget&previous-version=8.0.10&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dotnet/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 2e07233500c9..a032edea6116 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -97,7 +97,7 @@ - + From e8838437e93b68d665ee8acf84c1abcd4f5410e8 Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:56:31 +0000 Subject: [PATCH 2/3] .Net: Fix OpenApiDocumentParser fail when X-API-version is provide in the content key (#9959) ### Motivation and Context 1. Closes #9952 2. Also includes an OpenAI text embedding sample ### Description ### Contribution Checklist - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone :smile: --------- Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> --- .../Memory/OpenAI_EmbeddingGeneration.cs | 34 +++++++++++ dotnet/samples/Concepts/README.md | 1 + .../OpenApi/OpenApiDocumentParser.cs | 33 ++++++++++- .../OpenApiDocumentParserExtensionsTests.cs | 19 +++++++ .../OpenApi/OpenApiDocumentParserV30Tests.cs | 2 +- .../OpenApi/OpenApiDocumentParserV31Tests.cs | 2 +- .../OpenApiKernelPluginFactoryTests.cs | 4 +- .../OpenApi/TestPlugins/documentV3_0.json | 57 +++++++++++++++++++ .../OpenApi/TestPlugins/documentV3_1.yaml | 32 +++++++++++ 9 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 dotnet/samples/Concepts/Memory/OpenAI_EmbeddingGeneration.cs diff --git a/dotnet/samples/Concepts/Memory/OpenAI_EmbeddingGeneration.cs b/dotnet/samples/Concepts/Memory/OpenAI_EmbeddingGeneration.cs new file mode 100644 index 000000000000..93ddda59d614 --- /dev/null +++ b/dotnet/samples/Concepts/Memory/OpenAI_EmbeddingGeneration.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Embeddings; +using xRetry; + +#pragma warning disable format // Format item can be simplified +#pragma warning disable CA1861 // Avoid constant arrays as arguments + +namespace Memory; + +// The following example shows how to use Semantic Kernel with OpenAI. +public class OpenAI_EmbeddingGeneration(ITestOutputHelper output) : BaseTest(output) +{ + [RetryFact(typeof(HttpOperationException))] + public async Task RunEmbeddingAsync() + { + Assert.NotNull(TestConfiguration.OpenAI.EmbeddingModelId); + Assert.NotNull(TestConfiguration.OpenAI.ApiKey); + + IKernelBuilder kernelBuilder = Kernel.CreateBuilder(); + kernelBuilder.AddOpenAITextEmbeddingGeneration( + modelId: TestConfiguration.OpenAI.EmbeddingModelId!, + apiKey: TestConfiguration.OpenAI.ApiKey!); + Kernel kernel = kernelBuilder.Build(); + + var embeddingGenerator = kernel.GetRequiredService(); + + // Generate embeddings for the specified text. + var embeddings = await embeddingGenerator.GenerateEmbeddingsAsync(["Semantic Kernel is a lightweight, open-source development kit that lets you easily build AI agents and integrate the latest AI models into your C#, Python, or Java codebase."]); + + Console.WriteLine($"Generated {embeddings.Count} embeddings for the provided text"); + } +} diff --git a/dotnet/samples/Concepts/README.md b/dotnet/samples/Concepts/README.md index d53367f532d0..6b0f28b329ca 100644 --- a/dotnet/samples/Concepts/README.md +++ b/dotnet/samples/Concepts/README.md @@ -123,6 +123,7 @@ dotnet test -l "console;verbosity=detailed" --filter "FullyQualifiedName=ChatCom ### Memory - Using AI [`Memory`](https://github.com/microsoft/semantic-kernel/tree/main/dotnet/src/SemanticKernel.Abstractions/Memory) concepts +- [OpenAI_EmbeddingGeneration](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/OpenAI_EmbeddingGeneration.cs) - [Ollama_EmbeddingGeneration](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/Ollama_EmbeddingGeneration.cs) - [Onnx_EmbeddingGeneration](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/Onnx_EmbeddingGeneration.cs) - [HuggingFace_EmbeddingGeneration](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/HuggingFace_EmbeddingGeneration.cs) diff --git a/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs b/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs index 964c55828337..67ba2d34e79a 100644 --- a/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs +++ b/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs @@ -430,7 +430,7 @@ private static List CreateRestApiOperationParameters(string op return null; } - var mediaType = s_supportedMediaTypes.FirstOrDefault(requestBody.Content.ContainsKey) ?? throw new KernelException($"Neither of the media types of {operationId} is supported."); + var mediaType = GetMediaType(requestBody.Content) ?? throw new KernelException($"Neither of the media types of {operationId} is supported."); var mediaTypeMetadata = requestBody.Content[mediaType]; var payloadProperties = GetPayloadProperties(operationId, mediaTypeMetadata.Schema); @@ -438,11 +438,40 @@ private static List CreateRestApiOperationParameters(string op return new RestApiPayload(mediaType, payloadProperties, requestBody.Description, mediaTypeMetadata?.Schema?.ToJsonSchema()); } + /// + /// Returns the first supported media type. If none of the media types are supported, an exception is thrown. + /// + /// + /// Handles the case when the media type contains additional parameters e.g. application/json; x-api-version=2.0. + /// + /// The OpenAPI request body content. + /// The first support ed media type. + /// + private static string? GetMediaType(IDictionary content) + { + foreach (var mediaType in s_supportedMediaTypes) + { + foreach (var key in content.Keys) + { + var keyParts = key.Split(';'); + if (keyParts[0].Equals(mediaType, StringComparison.OrdinalIgnoreCase)) + { + return key; + } + } + } + return null; + } + + /// + /// Create collection of expected responses for the REST API operation for the supported media types. + /// + /// Responses from the OpenAPI endpoint. private static IEnumerable<(string, RestApiExpectedResponse)> CreateRestApiOperationExpectedResponses(OpenApiResponses responses) { foreach (var response in responses) { - var mediaType = s_supportedMediaTypes.FirstOrDefault(response.Value.Content.ContainsKey); + var mediaType = GetMediaType(response.Value.Content); if (mediaType is not null) { var matchingSchema = response.Value.Content[mediaType].Schema; diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserExtensionsTests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserExtensionsTests.cs index 0dde27b47306..88cb52d183e6 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserExtensionsTests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserExtensionsTests.cs @@ -77,4 +77,23 @@ public async Task ItCanExtractExtensionsOfAllTypesAsync(string documentName) Assert.True(operation.Extensions.TryGetValue("x-object-extension", out var objectValue)); Assert.Equal("{\"key1\":\"value1\",\"key2\":\"value2\"}", objectValue); } + + [Theory] + [InlineData("documentV3_0.json")] + [InlineData("documentV3_1.yaml")] + public async Task ItCanParseMediaTypeAsync(string documentName) + { + // Arrange. + using var openApiDocument = ResourcePluginsProvider.LoadFromResource(documentName); + + // Act. + var restApi = await this._sut.ParseAsync(openApiDocument); + + // Assert. + Assert.NotNull(restApi.Operations); + Assert.Equal(7, restApi.Operations.Count); + var operation = restApi.Operations.Single(o => o.Id == "Joke"); + Assert.NotNull(operation); + Assert.Equal("application/json; x-api-version=2.0", operation.Payload?.MediaType); + } } diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV30Tests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV30Tests.cs index 6a00410e24e6..8728771ac54a 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV30Tests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV30Tests.cs @@ -236,7 +236,7 @@ public async Task ItCanExtractAllPathsAsOperationsAsync() var restApi = await this._sut.ParseAsync(this._openApiDocument); // Assert - Assert.Equal(6, restApi.Operations.Count); + Assert.Equal(7, restApi.Operations.Count); } [Fact] diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV31Tests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV31Tests.cs index 79f3d8330694..6455b95dd34b 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV31Tests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiDocumentParserV31Tests.cs @@ -236,7 +236,7 @@ public async Task ItCanExtractAllPathsAsOperationsAsync() var restApi = await this._sut.ParseAsync(this._openApiDocument); // Assert - Assert.Equal(6, restApi.Operations.Count); + Assert.Equal(7, restApi.Operations.Count); } [Fact] diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs index f05eab224b5e..2242f5032610 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/OpenApiKernelPluginFactoryTests.cs @@ -353,7 +353,7 @@ public async Task ItShouldHandleEmptyOperationNameAsync() var plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync("fakePlugin", content, this._executionParameters); // Assert - Assert.Equal(6, plugin.Count()); + Assert.Equal(7, plugin.Count()); Assert.True(plugin.TryGetFunction("GetSecretsSecretname", out var _)); } @@ -372,7 +372,7 @@ public async Task ItShouldHandleNullOperationNameAsync() var plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync("fakePlugin", content, this._executionParameters); // Assert - Assert.Equal(6, plugin.Count()); + Assert.Equal(7, plugin.Count()); Assert.True(plugin.TryGetFunction("GetSecretsSecretname", out var _)); } diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_0.json b/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_0.json index d92e8b50dde3..a2990fb86f90 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_0.json +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_0.json @@ -212,6 +212,63 @@ } } }, + "/FunPlugin/Joke": { + "post": { + "summary": "Generate a funny joke", + "operationId": "Joke", + "requestBody": { + "description": "Joke subject", + "content": { + "text/plain; x-api-version=2.0": { + "schema": { + "type": "string" + } + }, + "application/json; x-api-version=2.0": { + "schema": { + "required": [ + "scenario" + ], + "type": "object", + "properties": { + "scenario": { + "type": "string", + "description": "Joke subject" + } + } + } + } + }, + "x-bodyName": "body" + }, + "responses": { + "200": { + "description": "The OK response", + "content": { + "text/plain; x-api-version=2.0": { + "schema": { + "type": "string" + } + }, + "application/json; x-api-version=2.0": { + "schema": { + "required": [ + "scenario" + ], + "type": "object", + "properties": { + "scenario": { + "type": "string", + "description": "Joke subject" + } + } + } + } + } + } + } + } + }, "/test-default-values/{string-parameter}": { "put": { "summary": "Operation to test default parameter values.", diff --git a/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_1.yaml b/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_1.yaml index 54005930d0d0..8c250db741cb 100644 --- a/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_1.yaml +++ b/dotnet/src/Functions/Functions.UnitTests/OpenApi/TestPlugins/documentV3_1.yaml @@ -138,6 +138,38 @@ paths: text/plain: schema: type: string + /FunPlugin/Joke: + post: + summary: Gneerate a funny joke + operationId: Joke + requestBody: + description: Joke subject + content: + application/json; x-api-version=2.0: + schema: + type: object + properties: + scenario: + type: string + description: Joke subject + text/plain; x-api-version=2.0: + schema: + type: string + x-bodyName: body + responses: + '200': + description: The OK response + content: + text/plain; x-api-version=2.0: + schema: + type: string + application/json; x-api-version=2.0: + schema: + type: object + properties: + scenario: + type: string + description: Joke subject '/test-default-values/{string-parameter}': put: summary: Operation to test default parameter values. From fbbd444992df9b045749abc6774e0088d80923cc Mon Sep 17 00:00:00 2001 From: Tao Chen Date: Fri, 13 Dec 2024 11:15:04 -0800 Subject: [PATCH 3/3] Python: Add PR number to test coverage workflow (#9964) ### Motivation and Context The test coverage workflow needs the PR number to post comments to PRs. However, the `workflow_run` context doesn't contain the PR number thus we need to save it. ### Description Save the PR number in a file and upload it as artifact for the second workflow to use. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: --- .github/workflows/python-test-coverage-report.yml | 9 +++++++++ .github/workflows/python-test-coverage.yml | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/.github/workflows/python-test-coverage-report.yml b/.github/workflows/python-test-coverage-report.yml index 7f0d323bb710..67c848609f6b 100644 --- a/.github/workflows/python-test-coverage-report.yml +++ b/.github/workflows/python-test-coverage-report.yml @@ -25,10 +25,19 @@ jobs: merge-multiple: true - name: Display structure of downloaded files run: ls + - name: Read and set PR number + # Need to read the PR number from the file saved in the previous workflow + # because the workflow_run event does not have access to the PR number + # The PR number is needed to post the comment on the PR + run: | + PR_NUMBER=$(cat pr_number) + echo "PR number: $PR_NUMBER" + echo "::set-env name=PR_NUMBER::$PR_NUMBER" - name: Pytest coverage comment id: coverageComment uses: MishaKav/pytest-coverage-comment@main with: + issue-number: ${{ env.PR_NUMBER }} pytest-coverage-path: python/python-coverage.txt title: "Python Test Coverage Report" badge-title: "Python Test Coverage" diff --git a/.github/workflows/python-test-coverage.yml b/.github/workflows/python-test-coverage.yml index 7ffc9925fb34..5d67b29b6b12 100644 --- a/.github/workflows/python-test-coverage.yml +++ b/.github/workflows/python-test-coverage.yml @@ -21,6 +21,11 @@ jobs: UV_PYTHON: "3.10" steps: - uses: actions/checkout@v4 + # Save the PR number to a file since the workflow_run event + # in the coverage report workflow does not have access to it + - name: Save PR number + run: | + echo ${{ github.event.number }} > ./pr_number - name: Set up uv uses: astral-sh/setup-uv@v4 with: @@ -37,6 +42,7 @@ jobs: path: | python/python-coverage.txt python/pytest.xml + python/pr_number overwrite: true retention-days: 1 if-no-files-found: error