diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a3f6d583cda5..b4708221f544 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -6,9 +6,9 @@ name: "CodeQL" on: push: - branches: [ "main", "experimental*", "feature*" ] + branches: ["main", "experimental*", "feature*"] schedule: - - cron: '17 11 * * 2' + - cron: "17 11 * * 2" jobs: analyze: @@ -22,45 +22,44 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'csharp', 'python' ] + language: ["csharp", "python", "java"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Use only 'java' to analyze code written in Java, Kotlin or both # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/docs/decisions/0005-open-api-dynamic-payload-and-namespaces.md b/docs/decisions/0006-open-api-dynamic-payload-and-namespaces.md similarity index 100% rename from docs/decisions/0005-open-api-dynamic-payload-and-namespaces.md rename to docs/decisions/0006-open-api-dynamic-payload-and-namespaces.md diff --git a/docs/decisions/0006-prompt-extract-template-engine.md b/docs/decisions/0007-prompt-extract-template-engine.md similarity index 100% rename from docs/decisions/0006-prompt-extract-template-engine.md rename to docs/decisions/0007-prompt-extract-template-engine.md diff --git a/docs/decisions/0007-support-multiple-named-args-in-template-function-calls.md b/docs/decisions/0009-support-multiple-named-args-in-template-function-calls.md similarity index 100% rename from docs/decisions/0007-support-multiple-named-args-in-template-function-calls.md rename to docs/decisions/0009-support-multiple-named-args-in-template-function-calls.md diff --git a/docs/decisions/0009-dotnet-project-structure.md b/docs/decisions/0010-dotnet-project-structure.md similarity index 100% rename from docs/decisions/0009-dotnet-project-structure.md rename to docs/decisions/0010-dotnet-project-structure.md diff --git a/docs/decisions/0009-function-and-kernel-result-types.md b/docs/decisions/0011-function-and-kernel-result-types.md similarity index 100% rename from docs/decisions/0009-function-and-kernel-result-types.md rename to docs/decisions/0011-function-and-kernel-result-types.md diff --git a/docs/decisions/0011-memory-as-plugin.md b/docs/decisions/0013-memory-as-plugin.md similarity index 100% rename from docs/decisions/0011-memory-as-plugin.md rename to docs/decisions/0013-memory-as-plugin.md diff --git a/dotnet/nuget/nuget-package.props b/dotnet/nuget/nuget-package.props index 69f17536329e..62e7e6cfc718 100644 --- a/dotnet/nuget/nuget-package.props +++ b/dotnet/nuget/nuget-package.props @@ -1,7 +1,7 @@ - 1.0.0-beta2 + 1.0.0-beta3 Debug;Release;Publish true diff --git a/dotnet/samples/KernelSyntaxExamples/Example60_AdvancedNativeFunctions.cs b/dotnet/samples/KernelSyntaxExamples/Example60_AdvancedNativeFunctions.cs new file mode 100644 index 000000000000..64609aa95df7 --- /dev/null +++ b/dotnet/samples/KernelSyntaxExamples/Example60_AdvancedNativeFunctions.cs @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Orchestration; + +/** + * This example shows different ways how to define and execute native functions using custom and primitive types. + */ +// ReSharper disable once InconsistentNaming +public static class Example60_AdvancedNativeFunctions +{ + public static async Task RunAsync() + { + await NativeFunctionsChainingAsync(); + + await NativeFunctionsPipelineAsync(); + + await PrimitiveTypesAutoConversionAsync(); + } + + #region Native Functions Chaining + + /// + /// This example executes Function1, which in turn executes Function2. + /// + private static async Task NativeFunctionsChainingAsync() + { + Console.WriteLine("Running Native Function Chaining example..."); + + var kernel = new KernelBuilder().Build(); + + var functions = kernel.ImportFunctions(new FunctionsChainingPlugin(), FunctionsChainingPlugin.PluginName); + + var result = await kernel.RunAsync(functions["Function1"]); + var customType = result.GetValue()!; + + Console.WriteLine(customType.Number); // 2 + Console.WriteLine(customType.Text); // From Function1 + From Function2 + } + + /// + /// Plugin example with two native functions, where one function is called from another. + /// + private sealed class FunctionsChainingPlugin + { + public const string PluginName = nameof(FunctionsChainingPlugin); + + [SKFunction, SKName("Function1")] + public async Task Function1Async(SKContext context) + { + // Execute another function + var result = await context.Runner.RunAsync(PluginName, "Function2"); + var value = result.GetValue()!; + + return new MyCustomType + { + Number = 2 * value.Number, + Text = "From Function1 + " + value.Text + }; + } + + [SKFunction, SKName("Function2")] + public static MyCustomType Function2() + { + return new MyCustomType + { + Number = 1, + Text = "From Function2" + }; + } + } + + #endregion + + #region Native Functions Pipeline + + /// + /// This example executes Function1 and Function2 sequentially. + /// Kernel will pass required parameters to second function as result from first function. + /// + private static async Task NativeFunctionsPipelineAsync() + { + Console.WriteLine("Running Native Function Pipeline example..."); + + var kernel = new KernelBuilder().Build(); + + var functions = kernel.ImportFunctions(new FunctionsPipelinePlugin(), FunctionsPipelinePlugin.PluginName); + + var result = await kernel.RunAsync(functions["Function1"], functions["Function2"]); + var customType = result.GetValue()!; + + Console.WriteLine(customType.Number); // 2 + Console.WriteLine(customType.Text); // From Function1 + From Function2 + } + + /// + /// Plugin example with two native functions, which will be called sequentially by Kernel. + /// + private sealed class FunctionsPipelinePlugin + { + public const string PluginName = nameof(FunctionsPipelinePlugin); + + [SKFunction, SKName("Function1")] + public MyCustomType Function1() + { + return new MyCustomType + { + Number = 1, + Text = "From Function1" + }; + } + + [SKFunction, SKName("Function2")] + public static MyCustomType Function2(MyCustomType customType) + { + return new MyCustomType + { + Number = customType.Number * 2, + Text = customType.Text + " + From Function2" + }; + } + } + + #endregion + + #region Primitive Types Auto Conversion + + /// + /// This example shows how to initialize variables, which will be auto-converted to primitive types + /// in parameters of native function. + /// + private static async Task PrimitiveTypesAutoConversionAsync() + { + Console.WriteLine("Running Primitive Types Auto Conversion example..."); + + var kernel = new KernelBuilder().Build(); + + var functions = kernel.ImportFunctions(new PrimitiveTypesPlugin(), PrimitiveTypesPlugin.PluginName); + + var contextVariables = new ContextVariables(); + + contextVariables["number"] = "2"; + contextVariables["text"] = "From Context Variables"; + + var result = await kernel.RunAsync(contextVariables, functions["Function1"]); + var customType = result.GetValue()!; + + Console.WriteLine(customType.Number); // 2 + Console.WriteLine(customType.Text); // From Context Variables + } + + /// + /// Plugin example with native function, which contains two parameters with primitive types. + /// + private sealed class PrimitiveTypesPlugin + { + public const string PluginName = nameof(PrimitiveTypesPlugin); + + [SKFunction, SKName("Function1")] + public MyCustomType Function1(int number, string text) + { + return new MyCustomType + { + Number = number, + Text = text + }; + } + } + + #endregion + + #region Custom Type + + /// + /// In order to use custom types, should be specified, + /// that will convert object instance to string representation. + /// + /// + /// is used to represent complex object as meaningful string, so + /// it can be passed to AI for further processing using semantic functions. + /// It's possible to choose any format (e.g. XML, JSON, YAML) to represent your object. + /// + [TypeConverter(typeof(MyCustomTypeConverter))] + private sealed class MyCustomType + { + public int Number { get; set; } + + public string? Text { get; set; } + } + + /// + /// Implementation of for . + /// In this example, object instance is serialized with from System.Text.Json, + /// but it's possible to convert object to string using any other serialization logic. + /// +#pragma warning disable CA1812 // instantiated by Kernel + private sealed class MyCustomTypeConverter : TypeConverter +#pragma warning restore CA1812 + { + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) => true; + + /// + /// This method is used to convert object from string to actual type. This will allow to pass object to + /// native function which requires it. + /// + public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + return JsonSerializer.Deserialize((string)value); + } + + /// + /// This method is used to convert actual type to string representation, so it can be passed to AI + /// for further processing. + /// + public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) + { + return JsonSerializer.Serialize(value); + } + } + + #endregion +}