chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<!-- Default properties inherited by all projects. Projects can override. -->
|
||||
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<LangVersion>14</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<NoWarn>$(NoWarn);IDE0290;IDE0079</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- In "main" branch this flag should be always "false". -->
|
||||
<IsReleaseCandidate>false</IsReleaseCandidate>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Disable NuGet packaging by default. Projects can override. -->
|
||||
<IsPackable>disable</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Publish'">
|
||||
<Optimize>True</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- .NET Framework/.NET Standard don't property support nullable reference types, suppress any warnings for those TFMs -->
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'net472' ">
|
||||
<NoWarn>$(NoWarn);CS8604;CS8602</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RepoRoot>$([System.IO.Path]::GetDirectoryName($([MSBuild]::GetPathOfFileAbove('.gitignore', '$(MSBuildThisFileDirectory)'))))</RepoRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Add CLSCompliant=false to all projects by default. Projects can override. -->
|
||||
<AssemblyAttribute Include="System.CLSCompliantAttribute">
|
||||
<_Parameter1>false</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<Project>
|
||||
<!-- Direct all packages under 'dotnet' to get versions from Directory.Packages.props -->
|
||||
<!-- using Central Package Management feature -->
|
||||
<!-- https://learn.microsoft.com/en-us/nuget/consume-packages/Central-Package-Management -->
|
||||
<Sdk Name="Microsoft.Build.CentralPackageVersions" Version="2.1.3" />
|
||||
<!-- Only run 'dotnet format' on dev machines, Release builds. Skip on GitHub Actions and Azure DevOps. -->
|
||||
<Target Name="DotnetFormatOnBuild" BeforeTargets="Build"
|
||||
Condition=" '$(Configuration)' == 'Release' AND '$(GITHUB_ACTIONS)' == '' AND '$(TF_BUILD)' != 'true' ">
|
||||
<Message Text="Running dotnet format" Importance="high" />
|
||||
<Exec Command="dotnet format --no-restore -v diag $(ProjectFileName)" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,264 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<!-- Enable central package management -->
|
||||
<!-- https://learn.microsoft.com/en-us/nuget/consume-packages/Central-Package-Management -->
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="9.3.1-preview.1.25305.6" />
|
||||
<PackageVersion Include="Aspire.Azure.Search.Documents" Version="13.3.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.AppHost" Version="13.3.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.Azure.CognitiveServices" Version="13.3.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.NodeJs" Version="9.5.2" />
|
||||
<PackageVersion Include="CommunityToolkit.Aspire.Hosting.Dapr" Version="9.9.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Aspire.Hosting.NodeJS.Extensions" Version="9.9.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.Azure.Search" Version="13.3.0" />
|
||||
<PackageVersion Include="MessagePack" Version="3.1.7" /> <!-- Transitive dependency of Aspire pinned to newer version due to vulnerability in 2.5.192 -->
|
||||
<PackageVersion Include="AWSSDK.BedrockAgent" Version="4.0.7.5" />
|
||||
<PackageVersion Include="AWSSDK.BedrockAgentRuntime" Version="4.0.8.5" />
|
||||
<PackageVersion Include="AWSSDK.BedrockRuntime" Version="4.0.14.5" />
|
||||
<PackageVersion Include="AWSSDK.Core" Version="4.0.3.8" />
|
||||
<PackageVersion Include="AWSSDK.Extensions.Bedrock.MEAI" Version="4.0.5.3" />
|
||||
<PackageVersion Include="AWSSDK.Extensions.NETCore.Setup" Version="4.0.3.19" />
|
||||
<PackageVersion Include="AWSSDK.SecurityToken" Version="4.0.5.6" />
|
||||
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.1.0" />
|
||||
<PackageVersion Include="Azure.AI.ContentSafety" Version="1.0.0" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version="2.9.0-beta.1" />
|
||||
<PackageVersion Include="Azure.AI.Projects" Version="2.0.0-beta.2" />
|
||||
<PackageVersion Include="Azure.Identity" Version="1.21.0" />
|
||||
<PackageVersion Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.7.0" />
|
||||
<PackageVersion Include="Azure.Search.Documents" Version="11.7.0" />
|
||||
<PackageVersion Include="Community.OData.Linq" Version="2.1.0" />
|
||||
<PackageVersion Include="Dapr.Actors" Version="1.16.1" />
|
||||
<PackageVersion Include="Dapr.Actors.AspNetCore" Version="1.16.1" />
|
||||
<PackageVersion Include="Dapr.AspNetCore" Version="1.16.1" />
|
||||
<PackageVersion Include="EntityFramework" Version="6.5.1" />
|
||||
<PackageVersion Include="FastBertTokenizer" Version="1.0.28" />
|
||||
<PackageVersion Include="Google.Apis.Auth" Version="1.73.0" />
|
||||
<PackageVersion Include="Google.Apis.CustomSearchAPI.v1" Version="1.68.0.3520" />
|
||||
<PackageVersion Include="Google.GenAI" Version="0.11.0" />
|
||||
<PackageVersion Include="Google.Protobuf" Version="3.33.4" />
|
||||
<PackageVersion Include="Grpc.AspNetCore" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.AspNetCore.Server" Version="2.70.0" />
|
||||
<PackageVersion Include="Grpc.AspNetCore.Server.Reflection" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.AspNetCore.Web" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.Net.Client" Version="2.76.0" />
|
||||
<PackageVersion Include="Grpc.Tools" Version="2.76.0" />
|
||||
<PackageVersion Include="Handlebars.Net.Helpers" Version="2.5.4" />
|
||||
<PackageVersion Include="Handlebars.Net" Version="2.1.6" />
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.12.4" />
|
||||
<PackageVersion Include="JmesPath.Net" Version="1.0.330" />
|
||||
<PackageVersion Include="JsonSchema.Net" Version="7.3.4" />
|
||||
<PackageVersion Include="JsonSchema.Net.Generation" Version="5.0.2" />
|
||||
<PackageVersion Include="Markdig" Version="0.40.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Abstractions" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Foundry" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Workflows" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.CopilotStudio.Client" Version="1.1.107-beta" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.13" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.14" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.5.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.SDK" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Kusto.Data" Version="12.2.8" />
|
||||
<PackageVersion Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.5.1" />
|
||||
<PackageVersion Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.3.2" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.6" />
|
||||
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
||||
<PackageVersion Include="Microsoft.Bcl.Memory" Version="10.0.4" />
|
||||
<PackageVersion Include="Microsoft.Bcl.Numerics" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.13.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client" Version="4.81.0" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.81.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.16.0" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Abstractions" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Authentication.Azure" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Serialization.Json" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntime" Version="1.23.2" />
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntime.Gpu" Version="1.23.2" />
|
||||
<PackageVersion Include="Microsoft.ML.Tokenizers.Data.Cl100kBase" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Abstractions" Version="1.71.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.71.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Core" Version="1.71.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Planners.OpenAI" Version="1.47.0-preview" />
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Threading" Version="17.14.15" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.2" />
|
||||
<PackageVersion Include="ModelContextProtocol" Version="0.4.0-preview.3" />
|
||||
<PackageVersion Include="MSTest.TestFramework" Version="3.8.0" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageVersion Include="Npgsql" Version="10.0.2" />
|
||||
<PackageVersion Include="OData2Linq" Version="2.2.0" />
|
||||
<PackageVersion Include="OllamaSharp" Version="5.4.25" />
|
||||
<PackageVersion Include="OpenAI" Version="2.10.0" />
|
||||
<PackageVersion Include="OpenTelemetry" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Api" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.2" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.15.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.15.1" />
|
||||
<PackageVersion Include="PdfPig" Version="0.1.13" />
|
||||
<PackageVersion Include="Pinecone.Client" Version="3.1.0" />
|
||||
<PackageVersion Include="Prompty.Core" Version="0.2.3-beta" />
|
||||
<PackageVersion Include="Scriban" Version="7.2.5" />
|
||||
<PackageVersion Include="PuppeteerSharp" Version="20.2.5" />
|
||||
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="10.0.2" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.16.0" />
|
||||
<PackageVersion Include="System.IO.Packaging" Version="10.0.2" />
|
||||
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="10.0.4" />
|
||||
<PackageVersion Include="System.Memory.Data" Version="10.0.2" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Numerics.Tensors" Version="10.0.6" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.6" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.6.2" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
|
||||
<PackageVersion Include="A2A" Version="0.3.1-preview" />
|
||||
<PackageVersion Include="A2A.AspNetCore" Version="0.3.1-preview" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<!-- Tokenizers -->
|
||||
<PackageVersion Include="Microsoft.ML.Tokenizers" Version="2.0.0" />
|
||||
<!-- Microsoft.Extensions.* -->
|
||||
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.5.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.5.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.AzureAIInference" Version="10.0.0-preview.1.25559.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.5.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.FileExtensions" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.VectorData.Abstractions" Version="10.1.0" />
|
||||
<!-- Test -->
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageVersion Include="Moq" Version="[4.18.4]" />
|
||||
<PackageVersion Include="FluentAssertions" Version="8.2.0" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="System.Threading.Channels" Version="10.0.6" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="10.0.2" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="xretry" Version="1.9.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageVersion Include="Docker.DotNet" Version="3.125.15" />
|
||||
<PackageVersion Include="Grpc.Net.ClientFactory" Version="2.76.0" />
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||
<!-- Plugins -->
|
||||
<PackageVersion Include="DocumentFormat.OpenXml" Version="3.3.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.10" />
|
||||
<PackageVersion Include="DuckDB.NET.Data.Full" Version="1.2.0" />
|
||||
<PackageVersion Include="DuckDB.NET.Data" Version="1.1.3" />
|
||||
<PackageVersion Include="MongoDB.Driver" Version="3.5.2" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.48.0" /><!-- Vulnerability fix: GHSA-6c8g-7p36-r338; transitively pinned via MongoDB.Driver -->
|
||||
<PackageVersion Include="Snappier" Version="1.3.1" /><!-- Vulnerability fix: GHSA-pggp-6c3x-2xmx; transitively pinned via MongoDB.Driver -->
|
||||
<PackageVersion Include="Microsoft.Graph" Version="5.105.0" />
|
||||
<PackageVersion Include="Microsoft.Graph.Core" Version="3.2.6" />
|
||||
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
|
||||
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
|
||||
<PackageVersion Include="Microsoft.OpenApi.ApiManifest" Version="0.5.6-preview" />
|
||||
<PackageVersion Include="Microsoft.Plugins.Manifest" Version="1.0.0-rc3" />
|
||||
<PackageVersion Include="protobuf-net" Version="3.2.56" />
|
||||
<PackageVersion Include="protobuf-net.Reflection" Version="3.2.52" />
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="Fluid.Core" Version="2.31.0" />
|
||||
<!-- Memory stores -->
|
||||
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.54.0" />
|
||||
<PackageVersion Include="Pgvector" Version="0.3.2" />
|
||||
<PackageVersion Include="sqlite-vec" Version="0.1.7-alpha.2.1" />
|
||||
<PackageVersion Include="NRedisStack" Version="1.0.0" />
|
||||
<PackageVersion Include="Milvus.Client" Version="2.3.0-preview.1" />
|
||||
<PackageVersion Include="Testcontainers" Version="4.10.0" />
|
||||
<PackageVersion Include="Testcontainers.Milvus" Version="4.8.1" />
|
||||
<PackageVersion Include="Testcontainers.MongoDB" Version="4.6.0" />
|
||||
<PackageVersion Include="Testcontainers.MsSql" Version="4.6.0" />
|
||||
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.6.0" />
|
||||
<PackageVersion Include="Testcontainers.Qdrant" Version="4.10.0" />
|
||||
<PackageVersion Include="Testcontainers.Redis" Version="4.6.0" />
|
||||
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.2" />
|
||||
<PackageVersion Include="Qdrant.Client" Version="1.15.1" />
|
||||
<!-- VectorData Dependencies -->
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAISearch" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.CosmosMongoDB" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.CosmosNoSql" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.InMemory" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.PgVector" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Pinecone" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Qdrant" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Redis" Version="1.74.0-preview" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Weaviate" Version="1.74.0-preview" />
|
||||
<!-- Symbols -->
|
||||
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
|
||||
<!-- Toolset -->
|
||||
<PackageVersion Include="Microsoft.Net.Compilers.Toolset" Version="4.14.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageVersion Include="xunit.analyzers" Version="1.26.0" />
|
||||
<PackageReference Include="xunit.analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageVersion Include="Moq.Analyzers" Version="0.3.1" />
|
||||
<PackageReference Include="Moq.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageVersion Include="Roslynator.Analyzers" Version="[4.13.1]" />
|
||||
<PackageReference Include="Roslynator.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="[4.13.1]" />
|
||||
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="[4.13.1]" />
|
||||
<PackageReference Include="Roslynator.Formatting.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!-- OnnxRuntimeGenAI -->
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI" Version="0.11.4" />
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.Cuda" Version="0.11.4" />
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.DirectML" Version="0.8.1" />
|
||||
<!-- SpectreConsole-->
|
||||
<PackageVersion Include="Spectre.Console" Version="0.49.1" />
|
||||
<PackageVersion Include="Spectre.Console.Cli" Version="0.49.1" />
|
||||
<PackageVersion Include="Spectre.Console.Json" Version="0.49.1" />
|
||||
<PackageVersion Include="NAudio" Version="2.2.1" />
|
||||
<PackageVersion Include="WebRtcVadSharp" Version="1.3.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,66 @@
|
||||
<Solution>
|
||||
<Folder Name="/Solution Items/">
|
||||
<File Path="../.editorconfig" />
|
||||
<File Path="../.github/workflows/dotnet-format.yml" />
|
||||
<File Path="../.gitignore" />
|
||||
<File Path="../nuget.config" />
|
||||
<File Path="../README.md" />
|
||||
<File Path="Directory.Build.props" />
|
||||
<File Path="Directory.Build.targets" />
|
||||
<File Path="Directory.Packages.props" />
|
||||
<File Path="docs/EXPERIMENTS.md" />
|
||||
<File Path="global.json" />
|
||||
</Folder>
|
||||
<Folder Name="/Solution Items/nuget/">
|
||||
<File Path="nuget/icon.png" />
|
||||
<File Path="nuget/nuget-package.props" />
|
||||
<File Path="nuget/NUGET.md" />
|
||||
<File Path="nuget/VECTORDATA-CONNECTORS-NUGET.md" />
|
||||
</Folder>
|
||||
<Folder Name="/src/" />
|
||||
<Folder Name="/src/VectorData/">
|
||||
<File Path="src/VectorData/Directory.Build.props" />
|
||||
<Project Path="src/VectorData/AzureAISearch/AzureAISearch.csproj" />
|
||||
<Project Path="src/VectorData/Chroma/Chroma.csproj" />
|
||||
<Project Path="src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj" />
|
||||
<Project Path="src/VectorData/CosmosNoSql/CosmosNoSql.csproj" />
|
||||
<Project Path="src/VectorData/InMemory/InMemory.csproj" />
|
||||
<Project Path="src/VectorData/Milvus/Milvus.csproj" />
|
||||
<Project Path="src/VectorData/MongoDB/MongoDB.csproj" />
|
||||
<Project Path="src/VectorData/PgVector/PgVector.csproj" />
|
||||
<Project Path="src/VectorData/Pinecone/Pinecone.csproj" />
|
||||
<Project Path="src/VectorData/Qdrant/Qdrant.csproj" />
|
||||
<Project Path="src/VectorData/Redis/Redis.csproj" />
|
||||
<Project Path="src/VectorData/SqliteVec/SqliteVec.csproj" />
|
||||
<Project Path="src/VectorData/SqlServer/SqlServer.csproj" />
|
||||
<Project Path="src/VectorData/Weaviate/Weaviate.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/test/" />
|
||||
<Folder Name="/test/VectorData/">
|
||||
<Project Path="test/VectorData/AzureAISearch.ConformanceTests/AzureAISearch.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/AzureAISearch.UnitTests/AzureAISearch.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Chroma.UnitTests/Chroma.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosMongoDB.ConformanceTests/CosmosMongoDB.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosMongoDB.UnitTests/CosmosMongoDB.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosNoSql.ConformanceTests/CosmosNoSql.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosNoSql.UnitTests/CosmosNoSql.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/InMemory.ConformanceTests/InMemory.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/InMemory.UnitTests/InMemory.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/MongoDB.ConformanceTests/MongoDB.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/MongoDB.UnitTests/MongoDB.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/PgVector.ConformanceTests/PgVector.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/PgVector.UnitTests/PgVector.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Pinecone.ConformanceTests/Pinecone.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Pinecone.UnitTests/Pinecone.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Qdrant.ConformanceTests/Qdrant.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Qdrant.UnitTests/Qdrant.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Redis.ConformanceTests/Redis.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Redis.UnitTests/Redis.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/SqliteVec.ConformanceTests/SqliteVec.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/SqliteVec.UnitTests/SqliteVec.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/SqlServer.ConformanceTests/SqlServer.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Weaviate.ConformanceTests/Weaviate.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Weaviate.UnitTests/Weaviate.UnitTests.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
@@ -0,0 +1,137 @@
|
||||
# Get Started with Semantic Kernel ⚡
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Semantic Kernel is now [Microsoft Agent Framework](https://github.com/microsoft/agent-framework)! Microsoft Agent Framework (MAF) is the enterprise‑ready successor to Semantic Kernel. Microsoft Agent Framework is now available at version 1.0 as a production-ready release: stable APIs, and a commitment to long-term support. Whether you're building a single assistant or orchestrating a fleet of specialized agents, Microsoft Agent Framework 1.0 gives you enterprise-grade multi-agent orchestration, multi-provider model support, and cross-runtime interoperability via A2A and MCP.
|
||||
>
|
||||
> Learn more about Semantic Kernel and Agent Framework here: [Semantic Kernel and Microsoft Agent Framework on the Agent Framework blog](https://devblogs.microsoft.com/agent-framework/semantic-kernel-and-microsoft-agent-framework/), and try out the [Semantic Kernel migration guide](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel).
|
||||
|
||||
## OpenAI / Azure OpenAI API keys
|
||||
|
||||
To run the LLM prompts and semantic functions in the examples below, make sure
|
||||
you have an
|
||||
|
||||
- [Azure OpenAI Service Key](https://learn.microsoft.com/azure/cognitive-services/openai/quickstart?pivots=rest-api) or
|
||||
- [OpenAI API Key](https://platform.openai.com).
|
||||
|
||||
## Nuget package
|
||||
|
||||
Here is a quick example of how to use Semantic Kernel from a C# console app.
|
||||
First, let's create a new project, targeting .NET 6 or newer, and add the
|
||||
`Microsoft.SemanticKernel` nuget package to your project from the command prompt
|
||||
in Visual Studio:
|
||||
|
||||
dotnet add package Microsoft.SemanticKernel
|
||||
|
||||
# Running prompts with input parameters
|
||||
|
||||
Copy and paste the following code into your project, with your Azure OpenAI key in hand:
|
||||
|
||||
```csharp
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
|
||||
builder.AddAzureOpenAIChatCompletion(
|
||||
"gpt-35-turbo", // Azure OpenAI Deployment Name
|
||||
"https://contoso.openai.azure.com/", // Azure OpenAI Endpoint
|
||||
"...your Azure OpenAI Key..."); // Azure OpenAI Key
|
||||
|
||||
// Alternative using OpenAI
|
||||
//builder.AddOpenAIChatCompletion(
|
||||
// "gpt-3.5-turbo", // OpenAI Model name
|
||||
// "...your OpenAI API Key..."); // OpenAI API Key
|
||||
|
||||
var kernel = builder.Build();
|
||||
|
||||
var prompt = @"{{$input}}
|
||||
|
||||
One line TLDR with the fewest words.";
|
||||
|
||||
var summarize = kernel.CreateFunctionFromPrompt(prompt, executionSettings: new OpenAIPromptExecutionSettings { MaxTokens = 100 });
|
||||
|
||||
string text1 = @"
|
||||
1st Law of Thermodynamics - Energy cannot be created or destroyed.
|
||||
2nd Law of Thermodynamics - For a spontaneous process, the entropy of the universe increases.
|
||||
3rd Law of Thermodynamics - A perfect crystal at zero Kelvin has zero entropy.";
|
||||
|
||||
string text2 = @"
|
||||
1. An object at rest remains at rest, and an object in motion remains in motion at constant speed and in a straight line unless acted on by an unbalanced force.
|
||||
2. The acceleration of an object depends on the mass of the object and the amount of force applied.
|
||||
3. Whenever one object exerts a force on another object, the second object exerts an equal and opposite on the first.";
|
||||
|
||||
Console.WriteLine(await kernel.InvokeAsync(summarize, new() { ["input"] = text1 }));
|
||||
|
||||
Console.WriteLine(await kernel.InvokeAsync(summarize, new() { ["input"] = text2 }));
|
||||
|
||||
// Output:
|
||||
// Energy conserved, entropy increases, zero entropy at 0K.
|
||||
// Objects move in response to forces.
|
||||
```
|
||||
|
||||
# Semantic Kernel Notebooks
|
||||
|
||||
The repository contains also a few C# Jupyter notebooks that demonstrates
|
||||
how to get started with the Semantic Kernel.
|
||||
|
||||
See [here](./notebooks/README.md) for the full list, with
|
||||
requirements and setup instructions.
|
||||
|
||||
1. [Getting started](./notebooks/00-getting-started.ipynb)
|
||||
2. [Loading and configuring Semantic Kernel](./notebooks/01-basic-loading-the-kernel.ipynb)
|
||||
3. [Running AI prompts from file](./notebooks/02-running-prompts-from-file.ipynb)
|
||||
4. [Creating Semantic Functions at runtime (i.e. inline functions)](./notebooks/03-semantic-function-inline.ipynb)
|
||||
5. [Using Kernel Arguments to Build a Chat Experience](./notebooks/04-kernel-arguments-chat.ipynb)
|
||||
6. [Introduction to the Function Calling](./notebooks/05-using-function-calling.ipynb)
|
||||
7. [Vector Stores and Embeddings](./notebooks/06-vector-stores-and-embeddings.ipynb)
|
||||
8. [Creating images with DALL-E 3](./notebooks/07-DALL-E-3.ipynb)
|
||||
9. [Chatting with ChatGPT and Images](./notebooks/08-chatGPT-with-DALL-E-3.ipynb)
|
||||
10. [BingSearch using Kernel](./notebooks/09-RAG-with-BingSearch.ipynb)
|
||||
|
||||
# Semantic Kernel Samples
|
||||
|
||||
The repository also contains the following code samples:
|
||||
|
||||
| Type | Description |
|
||||
| -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`GettingStarted`](./samples/GettingStarted/README.md) | Take this step by step tutorial to get started with the Semantic Kernel and get introduced to the key concepts. |
|
||||
| [`GettingStartedWithAgents`](./samples/GettingStartedWithAgents/README.md) | Take this step by step tutorial to get started with the Semantic Kernel Agents and get introduced to the key concepts. |
|
||||
| [`Concepts`](./samples/Concepts/README.md) | This section contains focussed samples which illustrate all of the concepts included in the Semantic Kernel. |
|
||||
| [`Demos`](./samples/Demos/README.md) | Look here to find a sample which demonstrates how to use many of Semantic Kernel features. |
|
||||
| [`LearnResources`](./samples/LearnResources/README.md) | Code snippets that are related to online documentation sources like Microsoft Learn, DevBlogs and others |
|
||||
|
||||
# Nuget packages
|
||||
|
||||
Semantic Kernel provides a set of nuget packages to allow extending the core with
|
||||
more features, such as connectors to services and plugins to perform specific actions.
|
||||
Unless you need to optimize which packages to include in your app, you will usually
|
||||
start by installing this meta-package first:
|
||||
|
||||
- **Microsoft.SemanticKernel**
|
||||
|
||||
This meta package includes core packages and OpenAI connectors, allowing to run
|
||||
most samples and build apps with OpenAI and Azure OpenAI.
|
||||
|
||||
Packages included in **Microsoft.SemanticKernel**:
|
||||
|
||||
1. **Microsoft.SemanticKernel.Abstractions**: contains common interfaces and classes
|
||||
used by the core and other SK components.
|
||||
1. **Microsoft.SemanticKernel.Core**: contains the core logic of SK, such as prompt
|
||||
engineering, semantic memory and semantic functions definition and orchestration.
|
||||
1. **Microsoft.SemanticKernel.Connectors.OpenAI**: connectors to OpenAI and Azure
|
||||
OpenAI, allowing to run semantic functions, chats, text to image with GPT3,
|
||||
GPT3.5, GPT4, DALL-E3.
|
||||
|
||||
Other SK packages available at nuget.org:
|
||||
|
||||
1. **Microsoft.SemanticKernel.Connectors.Qdrant**: Qdrant connector for
|
||||
plugins and semantic memory.
|
||||
2. **Microsoft.SemanticKernel.Connectors.Sqlite**: SQLite connector for
|
||||
plugins and semantic memory
|
||||
3. **Microsoft.SemanticKernel.Plugins.Document**: Document Plugin: Word processing,
|
||||
OpenXML, etc.
|
||||
4. **Microsoft.SemanticKernel.Plugins.MsGraph**: Microsoft Graph Plugin: access your
|
||||
tenant data, schedule meetings, send emails, etc.
|
||||
5. **Microsoft.SemanticKernel.Plugins.OpenApi**: OpenAPI Plugin.
|
||||
6. **Microsoft.SemanticKernel.Plugins.Web**: Web Plugin: search the web, download
|
||||
files, etc.
|
||||
@@ -0,0 +1,277 @@
|
||||
<Solution>
|
||||
<Folder Name="/Solution Items/">
|
||||
<File Path="../.editorconfig" />
|
||||
<File Path="../.github/workflows/dotnet-format.yml" />
|
||||
<File Path="../.gitignore" />
|
||||
<File Path="../nuget.config" />
|
||||
<File Path="../README.md" />
|
||||
<File Path="Directory.Build.props" />
|
||||
<File Path="Directory.Build.targets" />
|
||||
<File Path="Directory.Packages.props" />
|
||||
<File Path="docs/EXPERIMENTS.md" />
|
||||
<File Path="global.json" />
|
||||
</Folder>
|
||||
<Folder Name="/Solution Items/nuget/">
|
||||
<File Path="nuget/icon.png" />
|
||||
<File Path="nuget/nuget-package.props" />
|
||||
<File Path="nuget/NUGET.md" />
|
||||
<File Path="nuget/VECTORDATA-CONNECTORS-NUGET.md" />
|
||||
</Folder>
|
||||
<Folder Name="/samples/">
|
||||
<File Path="samples/README.md" />
|
||||
<Project Path="samples/Concepts/Concepts.csproj" />
|
||||
<Project Path="samples/GettingStarted/GettingStarted.csproj" />
|
||||
<Project Path="samples/GettingStartedWithAgents/GettingStartedWithAgents.csproj" />
|
||||
<Project Path="samples/GettingStartedWithProcesses/GettingStartedWithProcesses.csproj" />
|
||||
<Project Path="samples/GettingStartedWithTextSearch/GettingStartedWithTextSearch.csproj" />
|
||||
<Project Path="samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj" />
|
||||
<Project Path="samples/LearnResources/LearnResources.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/samples/Demos/">
|
||||
<File Path="samples/Demos/README.md" />
|
||||
<Project Path="samples/Demos/AIModelRouter/AIModelRouter.csproj" />
|
||||
<Project Path="samples/Demos/AmazonBedrockModels/AmazonBedrockAIModels.csproj" />
|
||||
<Project Path="samples/Demos/AotCompatibility/AotCompatibility.csproj" />
|
||||
<Project Path="samples/Demos/BookingRestaurant/BookingRestaurant.csproj" />
|
||||
<Project Path="samples/Demos/CodeInterpreterPlugin/CodeInterpreterPlugin.csproj" />
|
||||
<Project Path="samples/Demos/ContentSafety/ContentSafety.csproj" />
|
||||
<Project Path="samples/Demos/FunctionInvocationApproval/FunctionInvocationApproval.csproj" />
|
||||
<Project Path="samples/Demos/HomeAutomation/HomeAutomation.csproj" />
|
||||
<Project Path="samples/Demos/ModelContextProtocolPlugin/ModelContextProtocolPlugin.csproj" />
|
||||
<Project Path="samples/Demos/ModelContextProtocolPluginAuth/ModelContextProtocolPluginAuth.csproj" />
|
||||
<Project Path="samples/Demos/OllamaFunctionCalling/OllamaFunctionCalling.csproj" />
|
||||
<Project Path="samples/Demos/OnnxSimpleChatWithCuda/OnnxSimpleChatWithCuda.csproj" />
|
||||
<Project Path="samples/Demos/OnnxSimpleRAG/OnnxSimpleRAG.csproj" />
|
||||
<Project Path="samples/Demos/OpenAIRealtime/OpenAIRealtime.csproj" />
|
||||
<Project Path="samples/Demos/ProcessWithDapr/ProcessWithDapr.csproj" />
|
||||
<Project Path="samples/Demos/QualityCheck/QualityCheckWithFilters/QualityCheckWithFilters.csproj" />
|
||||
<Project Path="samples/Demos/StepwisePlannerMigration/StepwisePlannerMigration.csproj" />
|
||||
<Project Path="samples/Demos/StructuredDataPlugin/StructuredDataPlugin.csproj" />
|
||||
<Project Path="samples/Demos/TelemetryWithAppInsights/TelemetryWithAppInsights.csproj" />
|
||||
<Project Path="samples/Demos/TimePlugin/TimePlugin.csproj" />
|
||||
<Project Path="samples/Demos/VectorStoreRAG/VectorStoreRAG.csproj" />
|
||||
<Project Path="samples/Demos/VoiceChat/VoiceChat.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/samples/Demos/A2AClientServer/">
|
||||
<Project Path="samples/Demos/A2AClientServer/A2AClient/A2AClient.csproj" />
|
||||
<Project Path="samples/Demos/A2AClientServer/A2AServer/A2AServer.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/samples/Demos/AgentFrameworkWithAspire/">
|
||||
<File Path="samples/Demos/AgentFrameworkWithAspire/README.md" />
|
||||
<Project Path="samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ApiService/ChatWithAgent.ApiService.csproj" />
|
||||
<Project Path="samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.AppHost/ChatWithAgent.AppHost.csproj" />
|
||||
<Project Path="samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.Configuration/ChatWithAgent.Configuration.csproj" />
|
||||
<Project Path="samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.ServiceDefaults/ChatWithAgent.ServiceDefaults.csproj" />
|
||||
<Project Path="samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.Web/ChatWithAgent.Web.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/samples/Demos/ModelContextProtocolClientServer/">
|
||||
<File Path="samples/Demos/ModelContextProtocolClientServer/README.md" />
|
||||
<Project Path="samples/Demos/ModelContextProtocolClientServer/MCPClient/MCPClient.csproj">
|
||||
<BuildDependency Project="samples/Demos/ModelContextProtocolClientServer/MCPServer/MCPServer.csproj" />
|
||||
</Project>
|
||||
<Project Path="samples/Demos/ModelContextProtocolClientServer/MCPServer/MCPServer.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/">
|
||||
<Project Path="src/IntegrationTests/IntegrationTests.csproj" />
|
||||
<Project Path="src/SemanticKernel.Abstractions/SemanticKernel.Abstractions.csproj" />
|
||||
<Project Path="src/SemanticKernel.AotTests/SemanticKernel.AotTests.csproj" />
|
||||
<Project Path="src/SemanticKernel.Core/SemanticKernel.Core.csproj" />
|
||||
<Project Path="src/SemanticKernel.MetaPackage/SemanticKernel.MetaPackage.csproj" />
|
||||
<Project Path="src/SemanticKernel.UnitTests/SemanticKernel.UnitTests.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/agents/">
|
||||
<Project Path="src/Agents/A2A/Agents.A2A.csproj" />
|
||||
<Project Path="src/Agents/Abstractions/Agents.Abstractions.csproj" />
|
||||
<Project Path="src/Agents/AzureAI/Agents.AzureAI.csproj" />
|
||||
<Project Path="src/Agents/Bedrock/Agents.Bedrock.csproj" />
|
||||
<Project Path="src/Agents/Copilot/Agents.CopilotStudio.csproj" />
|
||||
<Project Path="src/Agents/Core/Agents.Core.csproj" />
|
||||
<Project Path="src/Agents/Magentic/Agents.Magentic.csproj" />
|
||||
<Project Path="src/Agents/OpenAI/Agents.OpenAI.csproj" />
|
||||
<Project Path="src/Agents/Orchestration/Agents.Orchestration.csproj" />
|
||||
<Project Path="src/Agents/UnitTests/Agents.UnitTests.csproj" />
|
||||
<Project Path="src/Agents/Yaml/Agents.Yaml.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/agents/Runtime/">
|
||||
<Project Path="src/Agents/Runtime/Abstractions.Tests/Runtime.Abstractions.UnitTests.csproj" />
|
||||
<Project Path="src/Agents/Runtime/Abstractions/Runtime.Abstractions.csproj" />
|
||||
<Project Path="src/Agents/Runtime/Core.Tests/Runtime.Core.UnitTests.csproj" />
|
||||
<Project Path="src/Agents/Runtime/Core/Runtime.Core.csproj" />
|
||||
<Project Path="src/Agents/Runtime/InProcess.Tests/Runtime.InProcess.UnitTests.csproj" />
|
||||
<Project Path="src/Agents/Runtime/InProcess/Runtime.InProcess.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/connectors/" />
|
||||
<Folder Name="/src/connectors/AI/">
|
||||
<Project Path="src/Connectors/Connectors.Amazon.UnitTests/Connectors.Amazon.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Amazon/Connectors.Amazon.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.AzureAIInference.UnitTests/Connectors.AzureAIInference.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.AzureAIInference/Connectors.AzureAIInference.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.AzureOpenAI.UnitTests/Connectors.AzureOpenAI.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.AzureOpenAI/Connectors.AzureOpenAI.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Google.UnitTests/Connectors.Google.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Google/Connectors.Google.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.HuggingFace.UnitTests/Connectors.HuggingFace.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.HuggingFace/Connectors.HuggingFace.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.MistralAI.UnitTests/Connectors.MistralAI.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.MistralAI/Connectors.MistralAI.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Ollama.UnitTests/Connectors.Ollama.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Ollama/Connectors.Ollama.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Onnx.UnitTests/Connectors.Onnx.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.Onnx/Connectors.Onnx.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.OpenAI.UnitTests/Connectors.OpenAI.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.OpenAI/Connectors.OpenAI.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/experimental/">
|
||||
<Project Path="src/Experimental/Orchestration.Flow.IntegrationTests/Experimental.Orchestration.Flow.IntegrationTests.csproj" />
|
||||
<Project Path="src/Experimental/Orchestration.Flow.UnitTests/Experimental.Orchestration.Flow.UnitTests.csproj" />
|
||||
<Project Path="src/Experimental/Orchestration.Flow/Experimental.Orchestration.Flow.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/experimental/process/">
|
||||
<Project Path="src/Experimental/Process.Abstractions/Process.Abstractions.csproj" />
|
||||
<Project Path="src/Experimental/Process.Core/Process.Core.csproj" />
|
||||
<Project Path="src/Experimental/Process.IntegrationTestHost.Dapr/Process.IntegrationTestHost.Dapr.csproj" />
|
||||
<Project Path="src/Experimental/Process.IntegrationTestRunner.Dapr/Process.IntegrationTestRunner.Dapr.csproj" />
|
||||
<Project Path="src/Experimental/Process.IntegrationTestRunner.Local/Process.IntegrationTestRunner.Local.csproj" />
|
||||
<Project Path="src/Experimental/Process.IntegrationTests.Resources/Process.IntegrationTests.Resources.csproj" />
|
||||
<Project Path="src/Experimental/Process.IntegrationTests.Shared/Process.IntegrationTests.Shared.csproj" />
|
||||
<Project Path="src/Experimental/Process.LocalRuntime/Process.LocalRuntime.csproj" />
|
||||
<Project Path="src/Experimental/Process.Runtime.Dapr.UnitTests/Process.Runtime.Dapr.UnitTests.csproj" />
|
||||
<Project Path="src/Experimental/Process.Runtime.Dapr/Process.Runtime.Dapr.csproj" />
|
||||
<Project Path="src/Experimental/Process.UnitTests/Process.UnitTests.csproj" />
|
||||
<Project Path="src/Experimental/Process.Utilities.UnitTests/Process.Utilities.UnitTests.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/functions/">
|
||||
<Project Path="src/Functions/Functions.Grpc/Functions.Grpc.csproj" />
|
||||
<Project Path="src/Functions/Functions.OpenApi.Extensions/Functions.OpenApi.Extensions.csproj" />
|
||||
<Project Path="src/Functions/Functions.OpenApi/Functions.OpenApi.csproj" />
|
||||
<Project Path="src/Functions/Functions.Prompty.UnitTests/Functions.Prompty.UnitTests.csproj" />
|
||||
<Project Path="src/Functions/Functions.Prompty/Functions.Prompty.csproj" />
|
||||
<Project Path="src/Functions/Functions.UnitTests/Functions.UnitTests.csproj" />
|
||||
<Project Path="src/Functions/Functions.Yaml/Functions.Yaml.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/functions/extensions/">
|
||||
<Project Path="src/Extensions/Extensions.UnitTests/Extensions.UnitTests.csproj" />
|
||||
<Project Path="src/Extensions/PromptTemplates.Handlebars/PromptTemplates.Handlebars.csproj" />
|
||||
<Project Path="src/Extensions/PromptTemplates.Liquid.UnitTests/PromptTemplates.Liquid.UnitTests.csproj" />
|
||||
<Project Path="src/Extensions/PromptTemplates.Liquid/PromptTemplates.Liquid.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/" />
|
||||
<Folder Name="/src/InternalUtilities/connectors/" />
|
||||
<Folder Name="/src/InternalUtilities/connectors/AI/" />
|
||||
<Folder Name="/src/InternalUtilities/connectors/AI/FunctionCalling/">
|
||||
<File Path="src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallingUtilities.props" />
|
||||
<File Path="src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/connectors/Memory/" />
|
||||
<Folder Name="/src/InternalUtilities/connectors/Memory/MongoDB/">
|
||||
<File Path="src/InternalUtilities/connectors/Memory/MongoDB/MongoDBConstants.cs" />
|
||||
<File Path="src/InternalUtilities/connectors/Memory/MongoDB/MongoDBGenericDataModelMapper.cs" />
|
||||
<File Path="src/InternalUtilities/connectors/Memory/MongoDB/MongoDBVectorStoreRecordMapper.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/planning/">
|
||||
<File Path="src/InternalUtilities/planning/PlannerInstrumentation.cs" />
|
||||
<File Path="src/InternalUtilities/planning/PlannerOptions.cs" />
|
||||
<File Path="src/InternalUtilities/planning/PlanningUtilities.props" />
|
||||
<File Path="src/InternalUtilities/planning/SemanticMemoryConfig.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/planning/Extensions/">
|
||||
<File Path="src/InternalUtilities/planning/Extensions/ChatHistoryExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/planning/Extensions/KernelFunctionMetadataExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/planning/Extensions/ReadOnlyFunctionCollectionPlannerExtensions.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/planning/Schema/">
|
||||
<File Path="src/InternalUtilities/planning/Schema/JsonSchemaFunctionContent.cs" />
|
||||
<File Path="src/InternalUtilities/planning/Schema/JsonSchemaFunctionParameters.cs" />
|
||||
<File Path="src/InternalUtilities/planning/Schema/JsonSchemaFunctionResponse.cs" />
|
||||
<File Path="src/InternalUtilities/planning/Schema/JsonSchemaFunctionView.cs" />
|
||||
<File Path="src/InternalUtilities/planning/Schema/JsonSchemaResponse.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/samples/">
|
||||
<File Path="src/InternalUtilities/samples/ConfigurationNotFoundException.cs" />
|
||||
<File Path="src/InternalUtilities/samples/EnumerableExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/samples/Env.cs" />
|
||||
<File Path="src/InternalUtilities/samples/ObjectExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/samples/PlanExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/samples/RepoFiles.cs" />
|
||||
<File Path="src/InternalUtilities/samples/SamplesInternalUtilities.props" />
|
||||
<File Path="src/InternalUtilities/samples/TextOutputHelperExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/samples/XunitLogger.cs" />
|
||||
<File Path="src/InternalUtilities/samples/YourAppException.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/">
|
||||
<File Path="src/InternalUtilities/src/InternalUtilities.props" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Diagnostics/">
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/ActivityExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/CompilerServicesAttributes.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/DynamicallyAccessedMembersAttribute.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/ExceptionExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/ExperimentalAttribute.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/IsExternalInit.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/KernelVerify.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/LoggingExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/NullableAttributes.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/RequiresDynamicCodeAttribute.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/RequiresUnreferencedCodeAttribute.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/UnconditionalSuppressMessageAttribute.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/UnreachableException.cs" />
|
||||
<File Path="src/InternalUtilities/src/Diagnostics/Verify.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Functions/">
|
||||
<File Path="src/InternalUtilities/src/Functions/FunctionName.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Http/">
|
||||
<File Path="src/InternalUtilities/src/Http/HttpClientExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/Http/HttpClientProvider.cs" />
|
||||
<File Path="src/InternalUtilities/src/Http/HttpContentExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/Http/HttpHeaderConstant.cs" />
|
||||
<File Path="src/InternalUtilities/src/Http/HttpRequest.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Linq/">
|
||||
<File Path="src/InternalUtilities/src/Linq/AsyncEnumerable.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Model/">
|
||||
<File Path="src/InternalUtilities/src/Model/Freezable.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/System/">
|
||||
<File Path="src/InternalUtilities/src/System/EnvExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/System/IListExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/src/System/IndexRange.cs" />
|
||||
<File Path="src/InternalUtilities/src/System/InternalTypeConverter.cs" />
|
||||
<File Path="src/InternalUtilities/src/System/NonNullCollection.cs" />
|
||||
<File Path="src/InternalUtilities/src/System/TypeConverterFactory.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Text/">
|
||||
<File Path="src/InternalUtilities/src/Text/BoolJsonConverter.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/ExceptionJsonConverter.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/JsonOptionsCache.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/OptionalBoolJsonConverter.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/SseData.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/SseJsonParser.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/SseLine.cs" />
|
||||
<File Path="src/InternalUtilities/src/Text/SseReader.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/src/Type/">
|
||||
<File Path="src/InternalUtilities/src/Type/TypeExtensions.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/test/">
|
||||
<File Path="src/InternalUtilities/test/AssertExtensions.cs" />
|
||||
<File Path="src/InternalUtilities/test/HttpMessageHandlerStub.cs" />
|
||||
<File Path="src/InternalUtilities/test/MultipleHttpMessageHandlerStub.cs" />
|
||||
<File Path="src/InternalUtilities/test/TestInternalUtilities.props" />
|
||||
</Folder>
|
||||
<Folder Name="/src/InternalUtilities/test/Linq/">
|
||||
<File Path="src/InternalUtilities/test/Linq/AsyncEnumerable.cs" />
|
||||
</Folder>
|
||||
<Folder Name="/src/plugins/">
|
||||
<Project Path="src/Plugins/Plugins.AI.UnitTests/Plugins.AI.UnitTests.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.AI/Plugins.AI.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.Core/Plugins.Core.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.Document/Plugins.Document.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.Memory/Plugins.Memory.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.MsGraph/Plugins.MsGraph.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.StructuredData.EntityFramework/Plugins.StructuredData.EntityFramework.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.UnitTests/Plugins.UnitTests.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.Web/Plugins.Web.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
@@ -0,0 +1,248 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/Asp/FormatOnClosingTag/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/Asp/FormatOnEnter/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeEditing/TypingAssist/FormatOnPaste/@EntryValue">FullFormat</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecshtml/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecss/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Eini/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ejs/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Esvg/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">SOLUTION</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/CalculateUnusedTypeMembers/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeAttributes/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeThisQualifier/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadAttributeBracketsSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadBracesSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadChildStatementIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadColonSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadCommaSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadControlBracesIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadControlBracesLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadDeclarationBracesIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadDeclarationBracesLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadEmptyBracesLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadExpressionBracesIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadExpressionBracesLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadGenericBracketsSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadLinqLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadListLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadMemberAccessSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadNamespaceBracesIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadParensLineBreaks/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadParensSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadPreprocessorIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadSemicolonSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadSpacesAfterKeyword/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadSquareBracketsSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadSwitchBracesIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadSymbolSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BuiltInTypeReferenceStyle/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckNamespace/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConditionalTernaryEqualBranch/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CSharpWarnings_003A_003ACS1571/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IncorrectBlankLinesNearBraces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MissingBlankLines/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MissingIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MissingLinebreak/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MissingSpace/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MultipleSpaces/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MultipleStatementsOnOneLine/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MultipleTypeMembersOnOneLine/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=OutdentIsOffPrevLevel/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantBlankLines/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantLinebreak/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantSpace/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TabsAndSpacesMismatch/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TabsOutsideIndent/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedImportClause/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=WrongIndentSize/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=Xunit_002EXunitTestWithConsoleOutput/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/APPLY_ON_COMPLETION/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Field, Property, Event, Method</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_LINQ_QUERY/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_LIST/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FIXED_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOR_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_FOREACH_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_LOCK_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_USINGS_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_WHILE_STMT/@EntryValue">True</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_ATTRIBUTE_ARRANGEMENT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_BLOCK_ARRANGEMENT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_EXPR_METHOD_ON_SINGLE_LINE/@EntryValue">ALWAYS</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_BLOCK_ON_SAME_LINE/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">512</s:Int64>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) Microsoft. All rights reserved.</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ACS/@EntryIndexedValue">ACS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AIGPT/@EntryIndexedValue">AIGPT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AMQP/@EntryIndexedValue">AMQP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CORS/@EntryIndexedValue">CORS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DI/@EntryIndexedValue">DI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GRPC/@EntryIndexedValue">GRPC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HMAC/@EntryIndexedValue">HMAC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HTTP/@EntryIndexedValue">HTTP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IM/@EntryIndexedValue">IM</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IOS/@EntryIndexedValue">IOS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JSON/@EntryIndexedValue">JSON</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JWT/@EntryIndexedValue">JWT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MQTT/@EntryIndexedValue">MQTT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MS/@EntryIndexedValue">MS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MSAL/@EntryIndexedValue">MSAL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OID/@EntryIndexedValue">OID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OK/@EntryIndexedValue">OK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OS/@EntryIndexedValue">OS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PR/@EntryIndexedValue">PR</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QA/@EntryIndexedValue">QA</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SK/@EntryIndexedValue">SK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SKHTTP/@EntryIndexedValue">SKHTTP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TTL/@EntryIndexedValue">TTL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UID/@EntryIndexedValue">UID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">XML</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=YAML/@EntryIndexedValue">YAML</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalFunctions/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Locals/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Method/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Parameters/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Property/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue"><Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=61a991a4_002Dd0a3_002D4d19_002D90a5_002Df8f4d75c30c1/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local variables"><ElementKinds><Kind Name="LOCAL_VARIABLE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=669e5282_002Dfb4b_002D4e90_002D91e7_002D07d269d04b60/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=76f79b1e_002Dece7_002D4df2_002Da322_002D1bd7fea25eb7/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local functions"><ElementKinds><Kind Name="LOCAL_FUNCTION" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8284009d_002De743_002D4d89_002D9402_002Da5bf9a89b657/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Methods"><ElementKinds><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8a85b61a_002D1024_002D4f87_002Db9ef_002D1fdae19930a1/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="Async" Style="aaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a0b4bc4d_002Dd13b_002D4a37_002Db37e_002Dc9c6864e4302/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4f433b8_002Dabcd_002D4e55_002Da08f_002D82e78cef0f0c/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c85a0503_002D4de2_002D40f1_002D9cd6_002Da4054c05d384/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="Async" Style="AaBb" /></Policy></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue"><Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String>
|
||||
<s:Int64 x:Key="/Default/Environment/Hierarchy/Build/BuildTool/MsBuildSolutionLoadingNodeCount/@EntryValue">2</s:Int64>
|
||||
<s:Boolean x:Key="/Default/Environment/Hierarchy/Build/SolutionBuilderNext/LogToFile/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/Hierarchy/Build/SolutionBuilderNext/ShouldRestoreNugetPackages/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECodeCleanup_002EFileHeader_002EFileHeaderSettingsMigrate/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/Environment/Hierarchy/NuGetOptions/IntegratedRestoreEngine/@EntryValue">Console</s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EUnitTestFramework_002ESettings_002EMigrations_002ERemoveBuildPolicyAlwaysMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Housekeeping/Layout/SolBuilderDuoView/ShowBuildProgressInToolWindow/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/Housekeeping/UnitTestingMru/UnitTestSessionDefault/LogSeverity/@EntryValue">TRACE</s:String>
|
||||
<s:Int64 x:Key="/Default/Housekeeping/UnitTestingMru/UnitTestSessionDefault/OutputLineNumberLimit/@EntryValue">8201</s:Int64>
|
||||
<s:String x:Key="/Default/Housekeeping/UnitTestingMru/UnitTestSessionDefault/PlatformType/@EntryValue">Automatic</s:String>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Field/=METHOD/@KeyIndexDefined">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Field/=SOMENAME/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Field/=SOMENAME/Expression/@EntryValue">guid()</s:String>
|
||||
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Field/=SOMENAME/Order/@EntryValue">0</s:Int64>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/IsBlessed/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Reformat/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Scope/=ABDFB0613102DF4DBB59387506ADA616/@KeyIndexDefined">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Scope/=B68999B9D6B43E47A02B22C12A54C3CC/@KeyIndexDefined">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Shortcut/@EntryValue">aaa</s:String>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/ShortenQualifiedReferences/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC90F25BDE5075498DCA20E411C14A16/Text/@EntryValue">[Fact]
|
||||
public void It$SOMENAME$()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
|
||||
}</s:String>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Description/@EntryValue">MSFT copyright</s:String>
|
||||
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Shortcut/@EntryValue">copy</s:String>
|
||||
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DEC4D140B393B04F8A18C0913BDE0592/Text/@EntryValue">// Copyright (c) Microsoft. All rights reserved.
|
||||
</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=APIM/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=daa/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=appsettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=arrivederci/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ask_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=awaiters/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=CHATGPT/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=childrens/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Chunker/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ctors/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=davinci/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dotproduct/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ENDPART/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=fareweller/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=greaterthan/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Joinable/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=keyvault/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kitto/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=langchain/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=lessthan/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mergeresults/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mevd/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Milvus/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mirostat/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=myfile/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Notegen/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=pgvector/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pinecone/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pinecone_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Postgres_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Qdrant/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Roundtrips/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reranker/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=sandboxing/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=SK/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=SKHTTP/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=skillname/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=skprompt/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=Xunit_002EXunitTestWithConsoleOutput/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=testsettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=tldr/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Untrust/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Upsert/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=upserted/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Upserts/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Weaviate/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wellknown/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wordprocessing/@EntryIndexedValue">True</s:Boolean>
|
||||
</wpf:ResourceDictionary>
|
||||
@@ -0,0 +1,5 @@
|
||||
<SolutionConfiguration>
|
||||
<Settings>
|
||||
<SolutionConfigured>True</SolutionConfigured>
|
||||
</Settings>
|
||||
</SolutionConfiguration>
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"solution": {
|
||||
"path": "SK-dotnet.slnx",
|
||||
"projects":
|
||||
[
|
||||
"src\\SemanticKernel.Abstractions\\SemanticKernel.Abstractions.csproj",
|
||||
"src\\SemanticKernel.Core\\SemanticKernel.Core.csproj",
|
||||
"src\\SemanticKernel.MetaPackage\\SemanticKernel.MetaPackage.csproj",
|
||||
|
||||
"src\\Agents\\A2A\\Agents.A2A.csproj",
|
||||
"src\\Agents\\Abstractions\\Agents.Abstractions.csproj",
|
||||
"src\\Agents\\AzureAI\\Agents.AzureAI.csproj",
|
||||
"src\\Agents\\Bedrock\\Agents.Bedrock.csproj",
|
||||
"src\\Agents\\Copilot\\Agents.CopilotStudio.csproj",
|
||||
"src\\Agents\\Core\\Agents.Core.csproj",
|
||||
"src\\Agents\\Magentic\\Agents.Magentic.csproj",
|
||||
"src\\Agents\\OpenAI\\Agents.OpenAI.csproj",
|
||||
"src\\Agents\\Orchestration\\Agents.Orchestration.csproj",
|
||||
"src\\Agents\\Yaml\\Agents.Yaml.csproj",
|
||||
|
||||
"src\\Agents\\Runtime\\Abstractions\\Runtime.Abstractions.csproj",
|
||||
"src\\Agents\\Runtime\\Core\\Runtime.Core.csproj",
|
||||
"src\\Agents\\Runtime\\InProcess\\Runtime.InProcess.csproj",
|
||||
|
||||
"src\\Connectors\\Connectors.Amazon\\Connectors.Amazon.csproj",
|
||||
"src\\Connectors\\Connectors.AzureAIInference\\Connectors.AzureAIInference.csproj",
|
||||
"src\\Connectors\\Connectors.AzureOpenAI\\Connectors.AzureOpenAI.csproj",
|
||||
"src\\Connectors\\Connectors.Google\\Connectors.Google.csproj",
|
||||
"src\\Connectors\\Connectors.HuggingFace\\Connectors.HuggingFace.csproj",
|
||||
"src\\Connectors\\Connectors.MistralAI\\Connectors.MistralAI.csproj",
|
||||
"src\\Connectors\\Connectors.Ollama\\Connectors.Ollama.csproj",
|
||||
"src\\Connectors\\Connectors.Onnx\\Connectors.Onnx.csproj",
|
||||
"src\\Connectors\\Connectors.OpenAI\\Connectors.OpenAI.csproj",
|
||||
|
||||
"src\\Experimental\\Orchestration.Flow\\Experimental.Orchestration.Flow.csproj",
|
||||
|
||||
"src\\Experimental\\Process.Abstractions\\Process.Abstractions.csproj",
|
||||
"src\\Experimental\\Process.Core\\Process.Core.csproj",
|
||||
"src\\Experimental\\Process.LocalRuntime\\Process.LocalRuntime.csproj",
|
||||
"src\\Experimental\\Process.Runtime.Dapr\\Process.Runtime.Dapr.csproj",
|
||||
|
||||
"src\\Functions\\Functions.Grpc\\Functions.Grpc.csproj",
|
||||
"src\\Functions\\Functions.OpenApi.Extensions\\Functions.OpenApi.Extensions.csproj",
|
||||
"src\\Functions\\Functions.OpenApi\\Functions.OpenApi.csproj",
|
||||
"src\\Functions\\Functions.Prompty\\Functions.Prompty.csproj",
|
||||
"src\\Functions\\Functions.Yaml\\Functions.Yaml.csproj",
|
||||
|
||||
"src\\Extensions\\PromptTemplates.Handlebars\\PromptTemplates.Handlebars.csproj",
|
||||
"src\\Extensions\\PromptTemplates.Liquid\\PromptTemplates.Liquid.csproj",
|
||||
|
||||
"src\\Plugins\\Plugins.AI\\Plugins.AI.csproj",
|
||||
"src\\Plugins\\Plugins.Core\\Plugins.Core.csproj",
|
||||
"src\\Plugins\\Plugins.Document\\Plugins.Document.csproj",
|
||||
"src\\Plugins\\Plugins.Memory\\Plugins.Memory.csproj",
|
||||
"src\\Plugins\\Plugins.MsGraph\\Plugins.MsGraph.csproj",
|
||||
"src\\Plugins\\Plugins.StructuredData.EntityFramework\\Plugins.StructuredData.EntityFramework.csproj",
|
||||
"src\\Plugins\\Plugins.Web\\Plugins.Web.csproj"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
setlocal
|
||||
cd "%~dp0"
|
||||
dotnet build --configuration Release --interactive ^
|
||||
&& dotnet test --configuration Release --no-build --no-restore --interactive
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
pushd "$SCRIPT_DIR" > /dev/null
|
||||
|
||||
# Release config triggers also "dotnet format"
|
||||
dotnet build --configuration Release --interactive
|
||||
dotnet test --configuration Release --no-build --no-restore --interactive
|
||||
|
||||
popd > /dev/null
|
||||
@@ -0,0 +1,61 @@
|
||||
# This script is for local use to analyze code coverage in more detail using HTML report.
|
||||
|
||||
Param(
|
||||
[switch]$ProdPackagesOnly = $false
|
||||
)
|
||||
|
||||
# Generate a timestamp for the current date and time
|
||||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
|
||||
# Define paths
|
||||
$scriptPath = Get-Item -Path $PSScriptRoot
|
||||
$coverageOutputPath = Join-Path $scriptPath "TestResults\Coverage\$timestamp"
|
||||
$reportOutputPath = Join-Path $scriptPath "TestResults\Reports\$timestamp"
|
||||
|
||||
# Create output directories
|
||||
New-Item -ItemType Directory -Force -Path $coverageOutputPath
|
||||
New-Item -ItemType Directory -Force -Path $reportOutputPath
|
||||
|
||||
# Find tests for projects ending with 'UnitTests.csproj'
|
||||
$testProjects = Get-ChildItem $scriptPath -Filter "*UnitTests.csproj" -Recurse
|
||||
|
||||
foreach ($project in $testProjects) {
|
||||
$testProjectPath = $project.FullName
|
||||
Write-Host "Running tests for project: $($testProjectPath)"
|
||||
|
||||
# Run tests
|
||||
dotnet test $testProjectPath `
|
||||
--collect:"XPlat Code Coverage" `
|
||||
--results-directory:$coverageOutputPath `
|
||||
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute `
|
||||
|
||||
}
|
||||
|
||||
# Install required tools
|
||||
& dotnet tool install -g coverlet.console
|
||||
& dotnet tool install -g dotnet-reportgenerator-globaltool
|
||||
|
||||
# Generate HTML report
|
||||
if ($ProdPackagesOnly) {
|
||||
$assemblies = @(
|
||||
"+Microsoft.SemanticKernel.Abstractions",
|
||||
"+Microsoft.SemanticKernel.Core",
|
||||
"+Microsoft.SemanticKernel.PromptTemplates.Handlebars",
|
||||
"+Microsoft.SemanticKernel.Connectors.OpenAI",
|
||||
"+Microsoft.SemanticKernel.Yaml"
|
||||
)
|
||||
|
||||
$assemblyFilters = $assemblies -join ";"
|
||||
|
||||
# Generate report for production assemblies only
|
||||
& reportgenerator -reports:"$coverageOutputPath/**/coverage.cobertura.xml" -targetdir:$reportOutputPath -reporttypes:Html -assemblyfilters:$assemblyFilters
|
||||
}
|
||||
else {
|
||||
& reportgenerator -reports:"$coverageOutputPath/**/coverage.cobertura.xml" -targetdir:$reportOutputPath -reporttypes:Html
|
||||
}
|
||||
|
||||
Write-Host "Code coverage report generated at: $reportOutputPath"
|
||||
|
||||
# Open report
|
||||
$reportIndexHtml = Join-Path $reportOutputPath "index.html"
|
||||
Invoke-Item -Path $reportIndexHtml
|
||||
@@ -0,0 +1,87 @@
|
||||
# Experiments
|
||||
|
||||
The following capabilities are marked experimental in the .NET SDK. Once the APIs for these features are stable, the experimental attribute will be removed. In the meantime, these features are subject to change.
|
||||
|
||||
You can use the following diagnostic IDs to ignore warnings or errors for a particular experimental feature. For example, to ignore warnings for the embedding services, add `SKEXP0001` to your list of ignored warnings in your .NET project file as well as the ID for the embedding service you want to use. For example:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);SKEXP0001,SKEXP0010</NoWarn>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
## Experimental Feature Codes
|
||||
|
||||
| SKEXP | Experimental Features Category |
|
||||
|-------|--------------------------------|
|
||||
| SKEXP0001 | Semantic Kernel core features |
|
||||
| SKEXP0010 | OpenAI and Azure OpenAI services |
|
||||
| SKEXP0020 | Memory connectors |
|
||||
| SKEXP0040 | Function types |
|
||||
| SKEXP0050 | Out-of-the-box plugins |
|
||||
| SKEXP0060 | Planners |
|
||||
| SKEXP0070 | AI connectors |
|
||||
| SKEXP0080 | Processes |
|
||||
| SKEXP0100 | Advanced Semantic Kernel features |
|
||||
| SKEXP0110 | Semantic Kernel Agents |
|
||||
| SKEXP0120 | Native-AOT |
|
||||
| SKEXP0130 | AI Context Providers |
|
||||
| MEVD9000 | Microsoft.Extensions.VectorData experimental user-facing APIs |
|
||||
| MEVD9001 | Microsoft.Extensions.VectorData experimental connector-facing APIs |
|
||||
|
||||
## Experimental Features Tracking
|
||||
|
||||
| SKEXP | Features |
|
||||
|-------|----------|
|
||||
| SKEXP0001 | Embedding services |
|
||||
| SKEXP0001 | Image services |
|
||||
| SKEXP0001 | Memory connectors |
|
||||
| SKEXP0001 | Kernel filters |
|
||||
| SKEXP0001 | Audio services |
|
||||
| | | | | | | |
|
||||
| SKEXP0010 | Azure OpenAI with your data service |
|
||||
| SKEXP0010 | OpenAI embedding service |
|
||||
| SKEXP0010 | OpenAI image service |
|
||||
| SKEXP0010 | OpenAI parameters |
|
||||
| SKEXP0010 | OpenAI chat history extension |
|
||||
| SKEXP0010 | OpenAI file service |
|
||||
| | | | | | | |
|
||||
| SKEXP0020 | Azure AI Search memory connector |
|
||||
| SKEXP0020 | Chroma memory connector |
|
||||
| SKEXP0020 | DuckDB memory connector |
|
||||
| SKEXP0020 | Kusto memory connector |
|
||||
| SKEXP0020 | Milvus memory connector |
|
||||
| SKEXP0020 | Qdrant memory connector |
|
||||
| SKEXP0020 | Redis memory connector |
|
||||
| SKEXP0020 | Sqlite memory connector |
|
||||
| SKEXP0020 | Weaviate memory connector |
|
||||
| SKEXP0020 | MongoDB memory connector |
|
||||
| SKEXP0020 | Pinecone memory connector |
|
||||
| SKEXP0020 | Postgres memory connector |
|
||||
| | | | | | | |
|
||||
| SKEXP0040 | GRPC functions |
|
||||
| SKEXP0040 | Markdown functions |
|
||||
| SKEXP0040 | OpenAPI functions |
|
||||
| SKEXP0040 | OpenAPI function extensions - API Manifest |
|
||||
| SKEXP0040 | OpenAPI function extensions - Copilot Agent Plugin |
|
||||
| SKEXP0040 | Prompty Format support |
|
||||
| | | | | | | |
|
||||
| SKEXP0050 | Core plugins |
|
||||
| SKEXP0050 | Document plugins |
|
||||
| SKEXP0050 | Memory plugins |
|
||||
| SKEXP0050 | Microsoft 365 plugins |
|
||||
| SKEXP0050 | Web plugins |
|
||||
| SKEXP0050 | Text chunker plugin |
|
||||
| | | | | | | |
|
||||
| SKEXP0060 | Handlebars planner |
|
||||
| SKEXP0060 | OpenAI Stepwise planner |
|
||||
| | | | | | | |
|
||||
| SKEXP0080 | Process Framework |
|
||||
| SKEXP0081 | Process Framework - Foundry Process
|
||||
| | | | | | | |
|
||||
| SKEXP0101 | Experiment with Assistants |
|
||||
| SKEXP0101 | Experiment with Flow Orchestration |
|
||||
| | | | | | | |
|
||||
| SKEXP0110 | Agent Framework |
|
||||
| | | | | | | |
|
||||
| SKEXP0120 | Native-AOT |
|
||||
@@ -0,0 +1,137 @@
|
||||
# Models
|
||||
|
||||
This document describes the planned models to be supported by Semantic Kernel along with their current status. If you are interested in contributing to the development of a model, please use the attached links to the GitHub issues and comment that you're wanting to help.
|
||||
|
||||
## Supported deployment types
|
||||
|
||||
In the core Semantic Kernel repo, we plan on supporting up to four deployment types of each model:
|
||||
|
||||
- Dedicated API endpoints (e.g., OpenAI's APIs, Mistral.AI, and Google Gemini)
|
||||
- Azure AI deployments via the [model catalog](https://learn.microsoft.com/en-us/azure/ai-studio/how-to/model-catalog)
|
||||
- Local deployments via [Ollama](https://ollama.ai/)
|
||||
- Hugging face deployment using the [Hugging Face inference API](https://huggingface.co/docs/api-inference/index)
|
||||
|
||||
To support these different deployment types, we will follow a similar pattern to the Azure OpenAI and OpenAI connectors. Each connector uses the same underlying model and abstractions, but the connector constructors may take different parameters. For example, the Azure OpenAI connector expects an Azure endpoint and key, whereas the OpenAI connector expects an OpenAI organization ID and API key.
|
||||
|
||||
If there is another deployment type you'd like to see supported, please open an issue. We'll either work with you to add support for it or help you create a custom repository and NuGet package for your use case.
|
||||
|
||||
## Planned models
|
||||
|
||||
The following models are currently prioritized for development. If you'd like to see a model added to this list, please open an issue. If you'd like to contribute to the development of a model, please comment on the issue that you're wanting to help.
|
||||
|
||||
Please note that not all of the model interfaces are defined yet. As part of contributing a new model, we'll work with you to define the interface and then implement it. As part of implementing the connector, you may also determine that the currently planned interface isn't the best fit for the model. If that's the case, we'll work with you to update the interface.
|
||||
|
||||
### OpenAI
|
||||
|
||||
| Priority | Model | Status | Interface | Deployment type | GitHub issue | Developer | Reviewer |
|
||||
| -------- | ----------------------- | ----------- | ------------------------------ | --------------- | ------------ | ------------ | ----------- |
|
||||
| P0 | GPT-3.5-turbo | Complete | `IChatCompletion` | OpenAI API | N/A | N/A | N/A |
|
||||
| P0 | GPT-3.5-turbo | Complete | `IChatCompletion` | Azure AI | N/A | N/A | N/A |
|
||||
| P0 | GPT-4 | Complete | `IChatCompletion` | OpenAI API | N/A | N/A | N/A |
|
||||
| P0 | GPT-4 | Complete | `IChatCompletion` | Azure AI | N/A | N/A | N/A |
|
||||
| P0 | GPT-4v | Complete | `IChatCompletion` | OpenAI API | N/A | N/A | N/A |
|
||||
| P0 | GPT-4v | Complete | `IChatCompletion` | Azure AI | N/A | N/A | N/A |
|
||||
| P0 | text-embedding-ada-002 | Preview | `IEmbeddingGeneration` | OpenAI API | N/A | N/A | N/A |
|
||||
| P0 | text-embedding-ada-002 | Preview | `IEmbeddingGeneration` | Azure AI | N/A | N/A | N/A |
|
||||
| P0 | DALL·E 3 | Preview | `ITextToImage` | OpenAI API | N/A | N/A | N/A |
|
||||
| P0 | DALL·E 3 | Preview | `ITextToImage` | Azure AI | N/A | N/A | N/A |
|
||||
| P0 | Text-to-speech | Complete | `ITextToSpeech` | OpenAI API | TBD | dmytrostruk | TBD |
|
||||
| P0 | Speech-to-text | Complete | `ISpeechRecognition` | OpenAI API | TBD | dmytrostruk | TBD |
|
||||
| P1 | openai-whisper-large-v3 | Not started | `ISpeechRecognition` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | openai-whisper-large-v3 | Not started | `ISpeechRecognition` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | Moderation | In Progress | `ITextClassification` | OpenAI API | #5062 | Krzysztof318 | MarkWallace |
|
||||
| P2 | clip-vit-base-patch32 | Not started | `IZeroShotImageClassification` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | clip-vit-base-patch32 | Not started | `IZeroShotImageClassification` | Hugging Face | TBD | TBD | TBD |
|
||||
|
||||
### Microsoft
|
||||
|
||||
| Priority | Model | Status | Interface | Deployment type | GitHub issue | Developer | Reviewer |
|
||||
| -------- | ----------------- | ----------- | ---------------------- | --------------- | ------------ | --------- | -------- |
|
||||
| P0 | microsoft-phi-1-5 | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | microsoft-phi-1-5 | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P0 | microsoft-phi-2 | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | microsoft-phi-2 | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | resnet-50 | Not started | `IImageClassification` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | resnet-50 | Not started | `IImageClassification` | Hugging Face | TBD | TBD | TBD |
|
||||
|
||||
### Google
|
||||
|
||||
| Priority | Model | Status | Interface | Deployment type | GitHub issue | Developer | Reviewer |
|
||||
| -------- | ----------------- | ----------- | ---------------------- | --------------- | ------------ | ------------ | ------------ |
|
||||
| P0 | gemini-pro | In Progress | `IChatCompletion` | Google API | TBD | Krzysztof318 | RogerBarreto |
|
||||
| P0 | gemini-pro-vision | In Progress | `IChatCompletion` | Google API | TBD | Krzysztof318 | RogerBarreto |
|
||||
| P0 | gemini-ultra | In Progress | `IChatCompletion` | Google API | TBD | Krzysztof318 | RogerBarreto |
|
||||
| P0 | embedding-001 | In Progress | `IEmbeddingGeneration` | Google API | TBD | Krzysztof318 | RogerBarreto |
|
||||
|
||||
### Facebook
|
||||
|
||||
| Priority | Model | Status | Interface | Deployment type | GitHub issue | Developer | Reviewer |
|
||||
| -------- | ------------------------- | ----------- | ----------------- | --------------- | ------------ | --------- | -------- |
|
||||
| P0 | Llama-2-7b-chat | Not started | `IChatCompletion` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | Llama-2-7b-chat | Not started | `IChatCompletion` | Hugging Face | TBD | TBD | TBD |
|
||||
| P0 | Llama-2-13b-chat | Not started | `IChatCompletion` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | Llama-2-13b-chat | Not started | `IChatCompletion` | Hugging Face | TBD | TBD | TBD |
|
||||
| P0 | Llama-2-70b-chat | Not started | `IChatCompletion` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | Llama-2-70b-chat | Not started | `IChatCompletion` | Hugging Face | TBD | TBD | TBD |
|
||||
| P0 | CodeLlama-7b-Instruct-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | CodeLlama-7b-Instruct-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P0 | CodeLlama-13b-Instruct-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | CodeLlama-13b-Instruct-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P0 | CodeLlama-34b-Instruct-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P0 | CodeLlama-34b-Instruct-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-7b | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-7b | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-7b | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-13b | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-13b | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-13b | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-70b | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-70b | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P1 | Llama-2-70b | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-7b-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-7b-hf | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-7b-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-13b-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-13b-hf | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-13b-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-34b-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-34b-hf | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-34b-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-7b-Python-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | CodeLlama-7b-Python-hf | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-7b-Python-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-13b-Python-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-13b-Python-hf | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-13b-Python-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-34b-Python-hf | Not started | `ITextGeneration` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-34b-Python-hf | Not started | `ITextGeneration` | Ollama | TBD | TBD | TBD |
|
||||
| P2 | CodeLlama-34b-Python-hf | Not started | `ITextGeneration` | Hugging Face | TBD | TBD | TBD |
|
||||
|
||||
### Mistral
|
||||
|
||||
| Priority | Model | Status | Interface | Deployment type | GitHub issue | Developer | Reviewer |
|
||||
| -------- | ----------------------- | ----------- | ----------------- | --------------- | ------------ | --------- | -------- |
|
||||
| P2 | Mistral-7B-v0.2 | Not started | `IChatCompletion` | Mistral API | TBD | TBD | TBD |
|
||||
| P2 | Mistral-7B-v0.2 | Not started | `IChatCompletion` | Ollama | TBD | TBD | TBD |
|
||||
| P2 | Mistral-7B-v0.1 | Not started | `IChatCompletion` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | Mistral-7B-v0.1 | Not started | `IChatCompletion` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | Mistral-7B-Instruct-v01 | Not started | `IChatCompletion` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | Mistral-7B-Instruct-v01 | Not started | `IChatCompletion` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | Mixtral-8X7B-v0.1 | Not started | `IChatCompletion` | Mistral API | TBD | TBD | TBD |
|
||||
| P2 | Mixtral-8X7B-v0.1 | Not started | `IChatCompletion` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | Mixtral-8X7B-v0.1 | Not started | `IChatCompletion` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | mistral-medium | Not started | `IChatCompletion` | Mistral API | TBD | TBD | TBD |
|
||||
| P2 | mistral-embed | Not started | `IChatCompletion` | Mistral API | TBD | TBD | TBD |
|
||||
|
||||
### Other
|
||||
|
||||
| Priority | Model | Status | Interface | Deployment type | GitHub issue | Developer | Reviewer |
|
||||
| -------- | ------------------------------ | ----------- | -------------------- | --------------- | ------------ | --------- | -------- |
|
||||
| P0 | wav2vec2-large-xlsr-53-english | Not started | `ISpeechRecognition` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | wav2vec2-large-xlsr-53-english | Not started | `ISpeechRecognition` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | bert-base-uncased | Not started | `IFillMask` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | bert-base-uncased | Not started | `IFillMask` | Hugging Face | TBD | TBD | TBD |
|
||||
| P2 | roberta-large | Not started | `IFillMask` | Azure AI | TBD | TBD | TBD |
|
||||
| P2 | roberta-large | Not started | `IFillMask` | Hugging Face | TBD | TBD | TBD |
|
||||
| P1 | stable-diffusion-xl-base-1.0 | Not started | `ITextToImage` | Azure AI | TBD | TBD | TBD |
|
||||
| P1 | stable-diffusion-xl-base-1.0 | Not started | `ITextToImage` | Hugging Face | TBD | TBD | TBD |
|
||||
@@ -0,0 +1,216 @@
|
||||
# OpenAI Connector Migration Guide
|
||||
|
||||
This manual prepares you for the migration of your OpenAI Connector to the new OpenAI Connector. The new OpenAI Connector is a complete rewrite of the existing OpenAI Connector and is designed to be more efficient, reliable, and scalable. This manual will guide you through the migration process and help you understand the changes that have been made to the OpenAI Connector.
|
||||
|
||||
## 1. Package Setup when Using Azure
|
||||
|
||||
If you are working with Azure and or OpenAI public APIs, you will need to change the package from `Microsoft.SemanticKernel.Connectors.OpenAI` to `Microsoft.SemanticKernel.Connectors.AzureOpenAI`,
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The `Microsoft.SemanticKernel.Connectors.AzureOpenAI` package depends on the `Microsoft.SemanticKernel.Connectors.OpenAI` package so there's no need to add both to your project when using `OpenAI` related types.
|
||||
|
||||
```diff
|
||||
- // Before
|
||||
- using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
+ After
|
||||
+ using Microsoft.SemanticKernel.Connectors.AzureOpenAI;
|
||||
```
|
||||
|
||||
### 1.1 AzureOpenAIClient
|
||||
|
||||
When using Azure with OpenAI, before where you were using `OpenAIClient` you will need to update your code to use the new `AzureOpenAIClient` type.
|
||||
|
||||
### 1.2 Services
|
||||
|
||||
All services below now belong to the `Microsoft.SemanticKernel.Connectors.AzureOpenAI` namespace.
|
||||
|
||||
- `AzureOpenAIAudioToTextService`
|
||||
- `AzureOpenAIChatCompletionService`
|
||||
- `AzureOpenAITextEmbeddingGenerationService`
|
||||
- `AzureOpenAITextToAudioService`
|
||||
- `AzureOpenAITextToImageService`
|
||||
|
||||
## 2. Text Generation Deprecated
|
||||
|
||||
The latest `OpenAI` SDK does not support text generation modality, when migrating to their underlying SDK we had to drop the support and removed `TextGeneration` specific services but the existing `ChatCompletion` ones still supports (implements `ITextGenerationService`).
|
||||
|
||||
If you were using any of the `OpenAITextGenerationService` or `AzureOpenAITextGenerationService` you will need to update your code to target a chat completion model instead, using `OpenAIChatCompletionService` or `AzureOpenAIChatCompletionService` instead.
|
||||
|
||||
> [!NOTE]
|
||||
> OpenAI and AzureOpenAI `ChatCompletion` services also implement the `ITextGenerationService` interface and that may not require any changes to your code if you were targeting the `ITextGenerationService` interface.
|
||||
|
||||
tags:
|
||||
`OpenAITextGenerationService`,`AzureOpenAITextGenerationService`,
|
||||
`AddOpenAITextGeneration`,`AddAzureOpenAITextGeneration`
|
||||
|
||||
## 3. ChatCompletion Multiple Choices Deprecated
|
||||
|
||||
The latest `OpenAI` SDK does not support multiple choices, when migrating to their underlying SDK we had to drop the support and removed `ResultsPerPrompt` also from the `OpenAIPromptExecutionSettings`.
|
||||
|
||||
tags: `ResultsPerPrompt`,`results_per_prompt`
|
||||
|
||||
## 4. OpenAI File Service Deprecation
|
||||
|
||||
The `OpenAIFileService` was deprecated in the latest version of the OpenAI Connector. We strongly recommend to update your code to use the new `OpenAIClient.GetFileClient()` for file management operations.
|
||||
|
||||
## 5. OpenAI ChatCompletion custom endpoint
|
||||
|
||||
The `OpenAIChatCompletionService` **experimental** constructor for custom endpoints will not attempt to auto-correct the endpoint and use it as is.
|
||||
|
||||
We have the two only specific cases where we attempted to auto-correct the endpoint.
|
||||
|
||||
1. If you provided `chat/completions` path before. Now those need to be removed as they are added automatically to the end of your original endpoint by `OpenAI SDK`.
|
||||
|
||||
```diff
|
||||
- http://any-host-and-port/v1/chat/completions
|
||||
+ http://any-host-and-port/v1
|
||||
```
|
||||
|
||||
2. If you provided a custom endpoint without any path. We won't be adding the `v1/` as the first path. Now the `v1` path needs to provided as part of your endpoint.
|
||||
|
||||
```diff
|
||||
- http://any-host-and-port/
|
||||
+ http://any-host-and-port/v1
|
||||
```
|
||||
|
||||
## 6. SemanticKernel MetaPackage
|
||||
|
||||
To be retro compatible with the new OpenAI and AzureOpenAI Connectors, our `Microsoft.SemanticKernel` meta package changed its dependency to use the new `Microsoft.SemanticKernel.Connectors.AzureOpenAI` package that depends on the `Microsoft.SemanticKernel.Connectors.OpenAI` package. This way if you are using the metapackage, no change is needed to get access to `Azure` related types.
|
||||
|
||||
## 7. Contents
|
||||
|
||||
### 7.1 OpenAIChatMessageContent
|
||||
|
||||
- The `Tools` property type has changed from `IReadOnlyList<ChatCompletionsToolCall>` to `IReadOnlyList<ChatToolCall>`.
|
||||
|
||||
- Inner content type has changed from `ChatCompletionsFunctionToolCall` to `ChatToolCall`.
|
||||
|
||||
- Metadata type `FunctionToolCalls` has changed from `IEnumerable<ChatCompletionsFunctionToolCall>` to `IEnumerable<ChatToolCall>`.
|
||||
|
||||
### 7.2 OpenAIStreamingChatMessageContent
|
||||
|
||||
- The `FinishReason` property type has changed from `CompletionsFinishReason` to `FinishReason`.
|
||||
- The `ToolCallUpdate` property has been renamed to `ToolCallUpdates` and its type has changed from `StreamingToolCallUpdate?` to `IReadOnlyList<StreamingToolCallUpdate>?`.
|
||||
- The `AuthorName` property is not initialized because it's not provided by the underlying library anymore.
|
||||
|
||||
## 7.3 Metrics for AzureOpenAI Connector
|
||||
|
||||
The meter `s_meter = new("Microsoft.SemanticKernel.Connectors.OpenAI");` and the relevant counters still have old names that contain "openai" in them, such as:
|
||||
|
||||
- `semantic_kernel.connectors.openai.tokens.prompt`
|
||||
- `semantic_kernel.connectors.openai.tokens.completion`
|
||||
- `semantic_kernel.connectors.openai.tokens.total`
|
||||
|
||||
## 8. Using Azure with your data (Data Sources)
|
||||
|
||||
With the new `AzureOpenAIClient`, you can now specify your datasource thru the options and that requires a small change in your code to the new type.
|
||||
|
||||
Before
|
||||
|
||||
```csharp
|
||||
var promptExecutionSettings = new OpenAIPromptExecutionSettings
|
||||
{
|
||||
AzureChatExtensionsOptions = new AzureChatExtensionsOptions
|
||||
{
|
||||
Extensions = [ new AzureSearchChatExtensionConfiguration
|
||||
{
|
||||
SearchEndpoint = new Uri(TestConfiguration.AzureAISearch.Endpoint),
|
||||
Authentication = new OnYourDataApiKeyAuthenticationOptions(TestConfiguration.AzureAISearch.ApiKey),
|
||||
IndexName = TestConfiguration.AzureAISearch.IndexName
|
||||
}]
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
After
|
||||
|
||||
```csharp
|
||||
var promptExecutionSettings = new AzureOpenAIPromptExecutionSettings
|
||||
{
|
||||
AzureChatDataSource = new AzureSearchChatDataSource
|
||||
{
|
||||
Endpoint = new Uri(TestConfiguration.AzureAISearch.Endpoint),
|
||||
Authentication = DataSourceAuthentication.FromApiKey(TestConfiguration.AzureAISearch.ApiKey),
|
||||
IndexName = TestConfiguration.AzureAISearch.IndexName
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 9. Breaking glass scenarios
|
||||
|
||||
Breaking glass scenarios are scenarios where you may need to update your code to use the new OpenAI Connector. Below are some of the breaking changes that you may need to be aware of.
|
||||
|
||||
#### 9.1 KernelContent Metadata
|
||||
|
||||
Some of the keys in the content metadata dictionary have changed, you will need to update your code to when using the previous key names.
|
||||
|
||||
- `Created` -> `CreatedAt`
|
||||
|
||||
#### 9.2 Prompt Filter Results
|
||||
|
||||
The `PromptFilterResults` metadata type has changed from `IReadOnlyList<ContentFilterResultsForPrompt>` to `ContentFilterResultForPrompt`.
|
||||
|
||||
#### 9.3 Content Filter Results
|
||||
|
||||
The `ContentFilterResultsForPrompt` type has changed from `ContentFilterResultsForChoice` to `ContentFilterResultForResponse`.
|
||||
|
||||
#### 9.4 Finish Reason
|
||||
|
||||
The FinishReason metadata string value has changed from `stop` to `Stop`
|
||||
|
||||
#### 9.5 Tool Calls
|
||||
|
||||
The ToolCalls metadata string value has changed from `tool_calls` to `ToolCalls`
|
||||
|
||||
#### 9.6 LogProbs / Log Probability Info
|
||||
|
||||
The `LogProbabilityInfo` type has changed from `ChatChoiceLogProbabilityInfo` to `IReadOnlyList<ChatTokenLogProbabilityInfo>`.
|
||||
|
||||
#### 9.7 Finish Details, Index, and Enhancements
|
||||
|
||||
All of above have been removed.
|
||||
|
||||
#### 9.8 Token Usage
|
||||
|
||||
The Token usage naming convention from `OpenAI` changed from `Completion`, `Prompt` tokens to `Output` and `Input` respectively. You will need to update your code to use the new naming.
|
||||
|
||||
The type also changed from `CompletionsUsage` to `ChatTokenUsage`.
|
||||
|
||||
[Example of Token Usage Metadata Changes](https://github.com/microsoft/semantic-kernel/pull/7151/files#diff-a323107b9f8dc8559a83e50080c6e34551ddf6d9d770197a473f249589e8fb47)
|
||||
|
||||
```diff
|
||||
- Before
|
||||
- var usage = FunctionResult.Metadata?["Usage"] as CompletionsUsage;
|
||||
- var completionTokesn = usage?.CompletionTokens ?? 0;
|
||||
- var promptTokens = usage?.PromptTokens ?? 0;
|
||||
|
||||
+ After
|
||||
+ var usage = FunctionResult.Metadata?["Usage"] as ChatTokenUsage;
|
||||
+ var promptTokens = usage?.InputTokens ?? 0;
|
||||
+ var completionTokens = completionTokens: usage?.OutputTokens ?? 0;
|
||||
|
||||
totalTokens: usage?.TotalTokens ?? 0;
|
||||
```
|
||||
|
||||
#### 9.9 OpenAIClient
|
||||
|
||||
The `OpenAIClient` type previously was a Azure specific namespace type but now it is an `OpenAI` SDK namespace type, you will need to update your code to use the new `OpenAIClient` type.
|
||||
|
||||
When using Azure, you will need to update your code to use the new `AzureOpenAIClient` type.
|
||||
|
||||
#### 9.10 Pipeline Configuration
|
||||
|
||||
The new `OpenAI` SDK uses a different pipeline configuration, and has a dependency on `System.ClientModel` package. You will need to update your code to use the new `HttpClientPipelineTransport` transport configuration where before you were using `HttpClientTransport` from `Azure.Core.Pipeline`.
|
||||
|
||||
[Example of Pipeline Configuration](https://github.com/microsoft/semantic-kernel/pull/7151/files#diff-fab02d9a75bf43cb57f71dddc920c3f72882acf83fb125d8cad963a643d26eb3)
|
||||
|
||||
```diff
|
||||
var clientOptions = new OpenAIClientOptions
|
||||
{
|
||||
- // Before: From Azure.Core.Pipeline
|
||||
- Transport = new HttpClientTransport(httpClient),
|
||||
|
||||
+ // After: From OpenAI SDK -> System.ClientModel
|
||||
+ Transport = new HttpClientPipelineTransport(httpClient),
|
||||
};
|
||||
```
|
||||
@@ -0,0 +1,133 @@
|
||||
# Telemetry
|
||||
|
||||
Telemetry in Semantic Kernel (SK) .NET implementation includes _logging_, _metering_ and _tracing_.
|
||||
The code is instrumented using native .NET instrumentation tools, which means that it's possible to use different monitoring platforms (e.g. Application Insights, Aspire dashboard, Prometheus, Grafana etc.).
|
||||
|
||||
Code example using Application Insights can be found [here](../samples/Demos/TelemetryWithAppInsights/).
|
||||
|
||||
## Logging
|
||||
|
||||
The logging mechanism in this project relies on the `ILogger` interface from the `Microsoft.Extensions.Logging` namespace. Recent updates have introduced enhancements to the logger creation process. Instead of directly using the `ILogger` interface, instances of `ILogger` are now recommended to be created through an `ILoggerFactory` configured through a `ServiceCollection`.
|
||||
|
||||
By employing the `ILoggerFactory` approach, logger instances are generated with precise type information, facilitating more accurate logging and streamlined control over log filtering across various classes.
|
||||
|
||||
Log levels used in SK:
|
||||
|
||||
- Trace - this type of logs **should not be enabled in production environments**, since it may contain sensitive data. It can be useful in test environments for better observability. Logged information includes:
|
||||
- Goal/Ask to create a plan
|
||||
- Prompt (template and rendered version) for AI to create a plan
|
||||
- Created plan with function arguments (arguments may contain sensitive data)
|
||||
- Prompt (template and rendered version) for AI to execute a function
|
||||
- Arguments to functions (arguments may contain sensitive data)
|
||||
- Debug - contains more detailed messages without sensitive data. Can be enabled in production environments.
|
||||
- Information (default) - log level that is enabled by default and provides information about general flow of the application. Contains following data:
|
||||
- AI model used to create a plan
|
||||
- Plan creation status (Success/Failed)
|
||||
- Plan creation execution time (in seconds)
|
||||
- Created plan without function arguments
|
||||
- AI model used to execute a function
|
||||
- Function execution status (Success/Failed)
|
||||
- Function execution time (in seconds)
|
||||
- Warning - includes information about unusual events that don't cause the application to fail.
|
||||
- Error - used for logging exception details.
|
||||
|
||||
### Examples
|
||||
|
||||
Enable logging for Kernel instance:
|
||||
|
||||
```csharp
|
||||
IKernelBuilder builder = Kernel.CreateBuilder();
|
||||
|
||||
// Assuming loggerFactory is already defined.
|
||||
builder.Services.AddSingleton(loggerFactory);
|
||||
...
|
||||
|
||||
var kernel = builder.Build();
|
||||
```
|
||||
|
||||
All kernel functions and planners will be instrumented. It includes _logs_, _metering_ and _tracing_.
|
||||
|
||||
### Log Filtering Configuration
|
||||
|
||||
Log filtering configuration has been refined to strike a balance between visibility and relevance:
|
||||
|
||||
```csharp
|
||||
using var loggerFactory = LoggerFactory.Create(builder =>
|
||||
{
|
||||
// Add OpenTelemetry as a logging provider
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
// Assuming connectionString is already defined.
|
||||
options.AddAzureMonitorLogExporter(options => options.ConnectionString = connectionString);
|
||||
// Format log messages. This is default to false.
|
||||
options.IncludeFormattedMessage = true;
|
||||
});
|
||||
builder.AddFilter("Microsoft", LogLevel.Warning);
|
||||
builder.AddFilter("Microsoft.SemanticKernel", LogLevel.Information);
|
||||
}
|
||||
```
|
||||
|
||||
> Read more at: https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/docs/logs/customizing-the-sdk/README.md
|
||||
|
||||
## Metering
|
||||
|
||||
Metering is implemented with `Meter` class from `System.Diagnostics.Metrics` namespace.
|
||||
|
||||
Available meters:
|
||||
|
||||
- _Microsoft.SemanticKernel.Planning_ - contains all metrics related to planning. List of metrics:
|
||||
- `semantic_kernel.planning.create_plan.duration` (Histogram) - execution time of plan creation (in seconds)
|
||||
- `semantic_kernel.planning.invoke_plan.duration` (Histogram) - execution time of plan execution (in seconds)
|
||||
- _Microsoft.SemanticKernel_ - captures metrics for `KernelFunction`. List of metrics:
|
||||
- `semantic_kernel.function.invocation.duration` (Histogram) - function execution time (in seconds)
|
||||
- `semantic_kernel.function.streaming.duration` (Histogram) - function streaming execution time (in seconds)
|
||||
- `semantic_kernel.function.invocation.token_usage.prompt` (Histogram) - number of prompt token usage (only for `KernelFunctionFromPrompt`)
|
||||
- `semantic_kernel.function.invocation.token_usage.completion` (Histogram) - number of completion token usage (only for `KernelFunctionFromPrompt`)
|
||||
- _Microsoft.SemanticKernel.Connectors.OpenAI_ - captures metrics for OpenAI functionality. List of metrics:
|
||||
- `semantic_kernel.connectors.openai.tokens.prompt` (Counter) - number of prompt tokens used.
|
||||
- `semantic_kernel.connectors.openai.tokens.completion` (Counter) - number of completion tokens used.
|
||||
- `semantic_kernel.connectors.openai.tokens.total` (Counter) - total number of tokens used.
|
||||
|
||||
Measurements will be associated with tags that will allow data to be categorized for analysis:
|
||||
|
||||
```csharp
|
||||
TagList tags = new() { { "semantic_kernel.function.name", this.Name } };
|
||||
s_invocationDuration.Record(duration.TotalSeconds, in tags);
|
||||
```
|
||||
|
||||
### [Examples](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Demos/TelemetryWithAppInsights/Program.cs)
|
||||
|
||||
Depending on monitoring tool, there are different ways how to subscribe to available meters. Following example shows how to subscribe to available meters and export metrics to Application Insights using `OpenTelemetry.Sdk`:
|
||||
|
||||
```csharp
|
||||
using var meterProvider = Sdk.CreateMeterProviderBuilder()
|
||||
.AddMeter("Microsoft.SemanticKernel*")
|
||||
.AddAzureMonitorMetricExporter(options => options.ConnectionString = connectionString)
|
||||
.Build();
|
||||
```
|
||||
|
||||
> Read more at: https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=net
|
||||
|
||||
> Read more at: https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/docs/metrics/customizing-the-sdk/README.md
|
||||
|
||||
## Tracing
|
||||
|
||||
Tracing is implemented with `Activity` class from `System.Diagnostics` namespace.
|
||||
|
||||
Available activity sources:
|
||||
|
||||
- _Microsoft.SemanticKernel.Planning_ - creates activities for all planners.
|
||||
- _Microsoft.SemanticKernel_ - creates activities for `KernelFunction` as well as requests to models.
|
||||
|
||||
### Examples
|
||||
|
||||
Subscribe to available activity sources using `OpenTelemetry.Sdk`:
|
||||
|
||||
```csharp
|
||||
using var traceProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.AddSource("Microsoft.SemanticKernel*")
|
||||
.AddAzureMonitorTraceExporter(options => options.ConnectionString = connectionString)
|
||||
.Build();
|
||||
```
|
||||
|
||||
> Read more at: https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/docs/trace/customizing-the-sdk/README.md
|
||||
@@ -0,0 +1,45 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# --- config -------------------------------------------------------
|
||||
$exclude = @(
|
||||
'Experimental.Orchestration.Flow.csproj',
|
||||
'Experimental.Orchestration.Flow.UnitTests.csproj',
|
||||
'Experimental.Orchestration.Flow.IntegrationTests.csproj'
|
||||
)
|
||||
$repoRoot = (git rev-parse --show-toplevel).Trim()
|
||||
$repoRoot = (Resolve-Path $repoRoot).Path # canonical form
|
||||
pushd $repoRoot
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
$targets =
|
||||
git diff --name-only main..HEAD |
|
||||
ForEach-Object {
|
||||
$dir = Split-Path (Join-Path $repoRoot $_) -Parent # << absolute
|
||||
while ($dir -and $dir -ne $repoRoot) {
|
||||
$proj = Get-ChildItem -LiteralPath $dir -Filter *.csproj -File -ErrorAction Ignore |
|
||||
Select-Object -First 1
|
||||
|
||||
if ($proj) {
|
||||
if ($exclude -notcontains $proj.Name) { $proj.FullName }
|
||||
break
|
||||
}
|
||||
$dir = Split-Path $dir -Parent
|
||||
}
|
||||
} |
|
||||
Sort-Object -Unique
|
||||
|
||||
popd
|
||||
|
||||
if (-not $targets) {
|
||||
# $targets = Get-ChildItem $repoRoot -Recurse -Filter *.slnx |
|
||||
# Select-Object -Expand FullName
|
||||
Write-Host "No code changes found"
|
||||
}
|
||||
|
||||
foreach ($t in $targets) {
|
||||
Write-Host "Formatting $t"
|
||||
}
|
||||
|
||||
foreach ($t in $targets) {
|
||||
dotnet format --no-restore --verbosity diag $t
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "10.0.301",
|
||||
"rollForward": "major",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Before starting we need to setup some configuration, like which AI backend to use.\n",
|
||||
"\n",
|
||||
"When using the kernel for AI requests, the kernel needs some settings like URL and\n",
|
||||
"credentials to the AI models. The SDK currently supports OpenAI and Azure OpenAI,\n",
|
||||
"other services will be added over time. If you need an Azure OpenAI key, go\n",
|
||||
"[here](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The following code will ask a few questions and save the settings to a local\n",
|
||||
"`settings.json` configuration file, under the [config](config) folder. You can\n",
|
||||
"also edit the file manually if you prefer. **Please keep the file safe.**\n",
|
||||
"\n",
|
||||
"## Step 1\n",
|
||||
"\n",
|
||||
"First step: choose whether you want to use the notebooks with Azure OpenAI or OpenAI,\n",
|
||||
"setting the `useAzureOpenAI` boolean below."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"bool useAzureOpenAI = false;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Step 2\n",
|
||||
"\n",
|
||||
"Run the following code. If you need to find the value and copy and paste, you can\n",
|
||||
"re-run the code and continue from where you left off."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!import config/Settings.cs\n",
|
||||
"\n",
|
||||
"await Settings.AskAzureEndpoint(useAzureOpenAI);\n",
|
||||
"await Settings.AskModel(useAzureOpenAI);\n",
|
||||
"await Settings.AskApiKey(useAzureOpenAI);\n",
|
||||
"\n",
|
||||
"// Uncomment this if you're using OpenAI and need to set the Org Id\n",
|
||||
"// await Settings.AskOrg(useAzureOpenAI);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If the code above doesn't show any error, you're good to go and run the other notebooks.\n",
|
||||
"\n",
|
||||
"## Resetting the configuration\n",
|
||||
"\n",
|
||||
"If you want to reset the configuration and start again, please uncomment and run the code below.\n",
|
||||
"You can also edit the [config/settings.json](config/settings.json) manually if you prefer."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!import config/Settings.cs\n",
|
||||
"\n",
|
||||
"// Uncomment this line to reset your settings and delete the file from disk.\n",
|
||||
"// Settings.Reset();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now that your environment is all set up, let's dive into\n",
|
||||
"[how to do basic loading of the Semantic Kernel](01-basic-loading-the-kernel.ipynb)."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".cs",
|
||||
"mimetype": "text/x-csharp",
|
||||
"name": "C#",
|
||||
"pygments_lexer": "csharp",
|
||||
"version": "11.0"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"#### Watch the Getting Started Quick Start [Video](https://aka.ms/SK-Getting-Started-Notebook)\n",
|
||||
"\n",
|
||||
"> [!IMPORTANT]\n",
|
||||
"> You will need an [.NET 10 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) and [Polyglot](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) to get started with this notebook using .NET Interactive."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**Step 1**: Configure your AI service credentials\n",
|
||||
"\n",
|
||||
"Use [this notebook](0-AI-settings.ipynb) first, to choose whether to run these notebooks with OpenAI or Azure OpenAI,\n",
|
||||
"and to save your credentials in the configuration file."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Load some helper functions, e.g. to load values from settings.json\n",
|
||||
"#!import config/Settings.cs "
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**Step 2**: Import Semantic Kernel SDK from NuGet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Import Semantic Kernel\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**Step 3**: Instantiate the Kernel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"//Create Kernel builder\n",
|
||||
"var builder = Kernel.CreateBuilder();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Configure AI service credentials used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**Step 4**: Load and Run a Plugin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// FunPlugin directory path\n",
|
||||
"var funPluginDirectoryPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"..\", \"..\", \"prompt_template_samples\", \"FunPlugin\");\n",
|
||||
"\n",
|
||||
"// Load the FunPlugin from the Plugins Directory\n",
|
||||
"var funPluginFunctions = kernel.ImportPluginFromPromptDirectory(funPluginDirectoryPath);\n",
|
||||
"\n",
|
||||
"// Construct arguments\n",
|
||||
"var arguments = new KernelArguments() { [\"input\"] = \"time travel to dinosaur age\" };\n",
|
||||
"\n",
|
||||
"// Run the Function called Joke\n",
|
||||
"var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], arguments);\n",
|
||||
"\n",
|
||||
"// Return the result to the Notebook\n",
|
||||
"Console.WriteLine(result);"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Basic Loading of the Kernel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The Semantic Kernel SDK can be imported from the following nuget feed:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"After adding the nuget package, you can instantiate the kernel:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.Extensions.Logging;\n",
|
||||
"using Microsoft.Extensions.Logging.Abstractions;\n",
|
||||
"using Microsoft.Extensions.DependencyInjection;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"// Inject your logger \n",
|
||||
"// see Microsoft.Extensions.Logging.ILogger @ https://learn.microsoft.com/dotnet/core/extensions/logging\n",
|
||||
"ILoggerFactory myLoggerFactory = NullLoggerFactory.Instance;\n",
|
||||
"\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"builder.Services.AddSingleton(myLoggerFactory);\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"When using the kernel for AI requests, the kernel needs some settings like URL and credentials to the AI models.\n",
|
||||
"\n",
|
||||
"The SDK currently supports OpenAI, Azure OpenAI and HuggingFace. It's also possible to create your own connector and use AI provider of your choice.\n",
|
||||
"\n",
|
||||
"If you need an Azure OpenAI key, go [here](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Kernel.CreateBuilder()\n",
|
||||
".AddAzureOpenAIChatCompletion(\n",
|
||||
" \"my-finetuned-model\", // Azure OpenAI *Deployment Name*\n",
|
||||
" \"https://contoso.openai.azure.com/\", // Azure OpenAI *Endpoint*\n",
|
||||
" \"...your Azure OpenAI Key...\", // Azure OpenAI *Key*\n",
|
||||
" serviceId: \"Azure_curie\" // alias used in the prompt templates' config.json\n",
|
||||
")\n",
|
||||
".AddOpenAIChatCompletion(\n",
|
||||
" \"gpt-4o-mini\", // OpenAI Model Name\n",
|
||||
" \"...your OpenAI API Key...\", // OpenAI API key\n",
|
||||
" \"...your OpenAI Org ID...\", // *optional* OpenAI Organization ID\n",
|
||||
" serviceId: \"OpenAI_davinci\" // alias used in the prompt templates' config.json\n",
|
||||
");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"When working with multiple backends and multiple models, the **first backend** defined\n",
|
||||
"is also the \"**default**\" used in these scenarios:\n",
|
||||
"\n",
|
||||
"* a prompt configuration doesn't specify which AI backend to use\n",
|
||||
"* a prompt configuration requires a backend unknown to the kernel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Great, now that you're familiar with setting up the Semantic Kernel, let's see [how we can use it to run prompts](02-running-prompts-from-file.ipynb)."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".cs",
|
||||
"mimetype": "text/x-csharp",
|
||||
"name": "C#",
|
||||
"pygments_lexer": "csharp",
|
||||
"version": "11.0"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# How to run a semantic plugins from file\n",
|
||||
"Now that you're familiar with Kernel basics, let's see how the kernel allows you to run Semantic Plugins and Semantic Functions stored on disk. \n",
|
||||
"\n",
|
||||
"A Semantic Plugin is a collection of Semantic Functions, where each function is defined with natural language that can be provided with a text file. \n",
|
||||
"\n",
|
||||
"Refer to our [glossary](../../docs/GLOSSARY.md) for an in-depth guide to the terms.\n",
|
||||
"\n",
|
||||
"The repository includes some examples under the [samples](https://github.com/microsoft/semantic-kernel/tree/main/samples) folder.\n",
|
||||
"\n",
|
||||
"For instance, [this](../../samples/plugins/FunPlugin/Joke/skprompt.txt) is the **Joke function** part of the **FunPlugin plugin**:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"```\n",
|
||||
"WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE TOPIC BELOW.\n",
|
||||
"JOKE MUST BE:\n",
|
||||
"- G RATED\n",
|
||||
"- WORKPLACE/FAMILY SAFE\n",
|
||||
"NO SEXISM, RACISM OR OTHER BIAS/BIGOTRY.\n",
|
||||
"BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n",
|
||||
"+++++\n",
|
||||
"{{$input}}\n",
|
||||
"+++++\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Note the special **`{{$input}}`** token, which is a variable that is automatically passed when invoking the function, commonly referred to as a \"function parameter\". \n",
|
||||
"\n",
|
||||
"We'll explore later how functions can accept multiple variables, as well as invoke other functions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n",
|
||||
"In the same folder you'll notice a second [config.json](../../samples/plugins/FunPlugin/Joke/config.json) file. The file is optional, and is used to set some parameters for large language models like Temperature, TopP, Stop Sequences, etc.\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"{\n",
|
||||
" \"schema\": 1,\n",
|
||||
" \"description\": \"Generate a funny joke\",\n",
|
||||
" \"execution_settings\": [\n",
|
||||
" {\n",
|
||||
" \"max_tokens\": 1000,\n",
|
||||
" \"temperature\": 0.9,\n",
|
||||
" \"top_p\": 0.0,\n",
|
||||
" \"presence_penalty\": 0.0,\n",
|
||||
" \"frequency_penalty\": 0.0\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
"}\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Given a semantic function defined by these files, this is how to load and use a file based semantic function.\n",
|
||||
"\n",
|
||||
"Configure and create the kernel, as usual, loading also the AI backend settings defined in the [Setup notebook](0-AI-settings.ipynb):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI backend used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Import the plugin and all its functions:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// FunPlugin directory path\n",
|
||||
"var funPluginDirectoryPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"..\", \"..\", \"prompt_template_samples\", \"FunPlugin\");\n",
|
||||
"\n",
|
||||
"// Load the FunPlugin from the Plugins Directory\n",
|
||||
"var funPluginFunctions = kernel.ImportPluginFromPromptDirectory(funPluginDirectoryPath);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"How to use the plugin functions, e.g. generate a joke about \"*time travel to dinosaur age*\":"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Construct arguments\n",
|
||||
"var arguments = new KernelArguments() { [\"input\"] = \"time travel to dinosaur age\" };\n",
|
||||
"\n",
|
||||
"// Run the Function called Joke\n",
|
||||
"var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], arguments);\n",
|
||||
"\n",
|
||||
"// Return the result to the Notebook\n",
|
||||
"Console.WriteLine(result);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Great, now that you know how to load a plugin from disk, let's show how you can [create and run a semantic function inline.](./03-semantic-function-inline.ipynb)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Running Semantic Functions Inline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The [previous notebook](./02-running-prompts-from-file.ipynb)\n",
|
||||
"showed how to define a semantic function using a prompt template stored on a file.\n",
|
||||
"\n",
|
||||
"In this notebook, we'll show how to use the Semantic Kernel to define functions inline with your C# code. This can be useful in a few scenarios:\n",
|
||||
"\n",
|
||||
"* Dynamically generating the prompt using complex rules at runtime\n",
|
||||
"* Writing prompts by editing C# code instead of TXT files. \n",
|
||||
"* Easily creating demos, like this document\n",
|
||||
"\n",
|
||||
"Prompt templates are defined using the SK template language, which allows to reference variables and functions. Read [this doc](https://aka.ms/sk/howto/configurefunction) to learn more about the design decisions for prompt templating. \n",
|
||||
"\n",
|
||||
"For now we'll use only the `{{$input}}` variable, and see more complex templates later.\n",
|
||||
"\n",
|
||||
"Almost all semantic function prompts have a reference to `{{$input}}`, which is the default way\n",
|
||||
"a user can import content from the kernel arguments."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Prepare a semantic kernel instance first, loading also the AI backend settings defined in the [Setup notebook](0-AI-settings.ipynb):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.Connectors.OpenAI;\n",
|
||||
"using Microsoft.SemanticKernel.TemplateEngine;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI service credentials used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's create a semantic function used to summarize content:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"string skPrompt = \"\"\"\n",
|
||||
"{{$input}}\n",
|
||||
"\n",
|
||||
"Summarize the content above.\n",
|
||||
"\"\"\";"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's configure the prompt, e.g. allowing for some creativity and a sufficient number of tokens."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var executionSettings = new OpenAIPromptExecutionSettings \n",
|
||||
"{\n",
|
||||
" MaxTokens = 2000,\n",
|
||||
" Temperature = 0.2,\n",
|
||||
" TopP = 0.5\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The following code prepares an instance of the template, passing in the TXT and configuration above, \n",
|
||||
"and a couple of other parameters (how to render the TXT and how the template can access other functions).\n",
|
||||
"\n",
|
||||
"This allows to see the prompt before it's sent to AI."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var promptTemplateConfig = new PromptTemplateConfig(skPrompt);\n",
|
||||
"\n",
|
||||
"var promptTemplateFactory = new KernelPromptTemplateFactory();\n",
|
||||
"var promptTemplate = promptTemplateFactory.Create(promptTemplateConfig);\n",
|
||||
"\n",
|
||||
"var renderedPrompt = await promptTemplate.RenderAsync(kernel);\n",
|
||||
"\n",
|
||||
"Console.WriteLine(renderedPrompt);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's transform the prompt template into a function that the kernel can execute:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var summaryFunction = kernel.CreateFunctionFromPrompt(skPrompt, executionSettings);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Set up some content to summarize, here's an extract about Demo, an ancient Greek poet, taken from [Wikipedia](https://en.wikipedia.org/wiki/Demo_(ancient_Greek_poet))."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var input = \"\"\"\n",
|
||||
"Demo (ancient Greek poet)\n",
|
||||
"From Wikipedia, the free encyclopedia\n",
|
||||
"Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the Roman period, known for a single epigram, engraved upon the Colossus of Memnon, which bears her name. She speaks of herself therein as a lyric poetess dedicated to the Muses, but nothing is known of her life.[1]\n",
|
||||
"Identity\n",
|
||||
"Demo was evidently Greek, as her name, a traditional epithet of Demeter, signifies. The name was relatively common in the Hellenistic world, in Egypt and elsewhere, and she cannot be further identified. The date of her visit to the Colossus of Memnon cannot be established with certainty, but internal evidence on the left leg suggests her poem was inscribed there at some point in or after AD 196.[2]\n",
|
||||
"Epigram\n",
|
||||
"There are a number of graffiti inscriptions on the Colossus of Memnon. Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the Greek inscription is difficult to read), is a dedication to the Muses.[2] The poem is traditionally published with the works of Balbilla, though the internal evidence suggests a different author.[1]\n",
|
||||
"In the poem, Demo explains that Memnon has shown her special respect. In return, Demo offers the gift for poetry, as a gift to the hero. At the end of this epigram, she addresses Memnon, highlighting his divine status by recalling his strength and holiness.[2]\n",
|
||||
"Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect. The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift', for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2] \n",
|
||||
"\"\"\";"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"...and run the summary function:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var summaryResult = await kernel.InvokeAsync(summaryFunction, new() { [\"input\"] = input });\n",
|
||||
"\n",
|
||||
"Console.WriteLine(summaryResult);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The code above shows all the steps, to understand how the function is composed step by step. However, the kernel\n",
|
||||
"includes also some helpers to achieve the same more concisely.\n",
|
||||
"\n",
|
||||
"The same function above can be executed with less code:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"string skPrompt = \"\"\"\n",
|
||||
"{{$input}}\n",
|
||||
"\n",
|
||||
"Summarize the content above.\n",
|
||||
"\"\"\";\n",
|
||||
"\n",
|
||||
"var result = await kernel.InvokePromptAsync(skPrompt, new() { [\"input\"] = input });\n",
|
||||
"\n",
|
||||
"Console.WriteLine(result);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Here's one more example of how to write an inline Semantic Function that gives a TLDR for a piece of text.\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"string skPrompt = @\"\n",
|
||||
"{{$input}}\n",
|
||||
"\n",
|
||||
"Give me the TLDR in 5 words.\n",
|
||||
"\";\n",
|
||||
"\n",
|
||||
"var textToSummarize = @\"\n",
|
||||
" 1) A robot may not injure a human being or, through inaction,\n",
|
||||
" allow a human being to come to harm.\n",
|
||||
"\n",
|
||||
" 2) A robot must obey orders given it by human beings except where\n",
|
||||
" such orders would conflict with the First Law.\n",
|
||||
"\n",
|
||||
" 3) A robot must protect its own existence as long as such protection\n",
|
||||
" does not conflict with the First or Second Law.\n",
|
||||
"\";\n",
|
||||
"\n",
|
||||
"var result = await kernel.InvokePromptAsync(skPrompt, new() { [\"input\"] = textToSummarize });\n",
|
||||
"\n",
|
||||
"Console.WriteLine(result);"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Creating a basic chat experience with kernel arguments\n",
|
||||
"\n",
|
||||
"In this example, we show how you can build a simple chat bot by sending and updating arguments with your requests. \n",
|
||||
"\n",
|
||||
"We introduce the Kernel Arguments object which in this demo functions similarly as a key-value store that you can use when running the kernel. \n",
|
||||
"\n",
|
||||
"In this chat scenario, as the user talks back and forth with the bot, the arguments get populated with the history of the conversation. During each new run of the kernel, the arguments will be provided to the AI with content. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.Connectors.OpenAI;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI service credentials used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's define a prompt outlining a dialogue chat bot."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"const string skPrompt = @\"\n",
|
||||
"ChatBot can have a conversation with you about any topic.\n",
|
||||
"It can give explicit instructions or say 'I don't know' if it does not have an answer.\n",
|
||||
"\n",
|
||||
"{{$history}}\n",
|
||||
"User: {{$userInput}}\n",
|
||||
"ChatBot:\";\n",
|
||||
"\n",
|
||||
"var executionSettings = new OpenAIPromptExecutionSettings \n",
|
||||
"{\n",
|
||||
" MaxTokens = 2000,\n",
|
||||
" Temperature = 0.7,\n",
|
||||
" TopP = 0.5\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Register your semantic function"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var chatFunction = kernel.CreateFunctionFromPrompt(skPrompt, executionSettings);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Initialize your arguments"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var history = \"\";\n",
|
||||
"var arguments = new KernelArguments()\n",
|
||||
"{\n",
|
||||
" [\"history\"] = history\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Chat with the Bot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var userInput = \"Hi, I'm looking for book suggestions\";\n",
|
||||
"arguments[\"userInput\"] = userInput;\n",
|
||||
"\n",
|
||||
"var bot_answer = await chatFunction.InvokeAsync(kernel, arguments);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Update the history with the output and set this as the new input value for the next request"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"history += $\"\\nUser: {userInput}\\nAI: {bot_answer}\\n\";\n",
|
||||
"arguments[\"history\"] = history;\n",
|
||||
"\n",
|
||||
"Console.WriteLine(history);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Keep Chatting!"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Func<string, Task> Chat = async (string input) => {\n",
|
||||
" // Save new message in the arguments\n",
|
||||
" arguments[\"userInput\"] = input;\n",
|
||||
"\n",
|
||||
" // Process the user message and get an answer\n",
|
||||
" var answer = await chatFunction.InvokeAsync(kernel, arguments);\n",
|
||||
"\n",
|
||||
" // Append the new interaction to the chat history\n",
|
||||
" var result = $\"\\nUser: {input}\\nAI: {answer}\\n\";\n",
|
||||
" history += result;\n",
|
||||
"\n",
|
||||
" arguments[\"history\"] = history;\n",
|
||||
" \n",
|
||||
" // Show the response\n",
|
||||
" Console.WriteLine(result);\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await Chat(\"I would like a non-fiction book suggestion about Greece history. Please only list one book.\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await Chat(\"that sounds interesting, what are some of the topics I will learn about?\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await Chat(\"Which topic from the ones you listed do you think most people find interesting?\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await Chat(\"could you list some more books I could read about the topic(s) you mentioned?\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"After chatting for a while, we have built a growing history, which we are attaching to each prompt and which contains the full conversation. Let's take a look!"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Console.WriteLine(history);"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".cs",
|
||||
"mimetype": "text/x-csharp",
|
||||
"name": "C#",
|
||||
"pygments_lexer": "csharp",
|
||||
"version": "11.0"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Introduction to the Function Calling\n",
|
||||
"\n",
|
||||
"The most powerful feature of chat completion is the ability to call functions from the model. This allows you to create a chat bot that can interact with your existing code, making it possible to automate business processes, create code snippets, and more.\n",
|
||||
"\n",
|
||||
"With Semantic Kernel, we simplify the process of using function calling by automatically describing your functions and their parameters to the model and then handling the back-and-forth communication between the model and your code.\n",
|
||||
"\n",
|
||||
"Read more about it [here](https://learn.microsoft.com/en-us/semantic-kernel/concepts/ai-services/chat-completion/function-calling)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"#!import config/Utils.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.Connectors.OpenAI;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI backend used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Setting Up Execution Settings"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Using `FunctionChoiceBehavior.Auto()` will enable automatic function calling. There are also other options like `Required` or `None` which allow to control function calling behavior. More information about it can be found [here](https://learn.microsoft.com/en-gb/semantic-kernel/concepts/ai-services/chat-completion/function-calling/function-choice-behaviors?pivots=programming-language-csharp)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#pragma warning disable SKEXP0001\n",
|
||||
"\n",
|
||||
"OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() \n",
|
||||
"{\n",
|
||||
" FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Providing plugins to the Kernel\n",
|
||||
"Function calling needs an information about available plugins/functions. Here we'll import the `SummarizePlugin` and `WriterPlugin` we have defined on disk."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"..\", \"..\", \"prompt_template_samples\");\n",
|
||||
"\n",
|
||||
"kernel.ImportPluginFromPromptDirectory(Path.Combine(pluginsDirectory, \"SummarizePlugin\"));\n",
|
||||
"kernel.ImportPluginFromPromptDirectory(Path.Combine(pluginsDirectory, \"WriterPlugin\"));"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Define your ASK. What do you want the Kernel to do?"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var ask = \"Tomorrow is Valentine's day. I need to come up with a few date ideas. My significant other likes poems so write them in the form of a poem.\";"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Since we imported available plugins to Kernel and defined the ask, we can now invoke a prompt with all the provided information. \n",
|
||||
"\n",
|
||||
"We can run function calling with Kernel, if we are interested in result only."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var result = await kernel.InvokePromptAsync(ask, new(openAIPromptExecutionSettings));\n",
|
||||
"\n",
|
||||
"Console.WriteLine(result);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"But we can also run it with `IChatCompletionService` to have an access to `ChatHistory` object, which allows us to see which functions were called as part of a function calling process. Note that passing a Kernel as a parameter to `GetChatMessageContentAsync` method is required, since Kernel holds an information about available plugins."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel.ChatCompletion;\n",
|
||||
"\n",
|
||||
"var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();\n",
|
||||
"\n",
|
||||
"var chatHistory = new ChatHistory();\n",
|
||||
"\n",
|
||||
"chatHistory.AddUserMessage(ask);\n",
|
||||
"\n",
|
||||
"var chatCompletionResult = await chatCompletionService.GetChatMessageContentAsync(chatHistory, openAIPromptExecutionSettings, kernel);\n",
|
||||
"\n",
|
||||
"Console.WriteLine($\"Result: {chatCompletionResult}\\n\");\n",
|
||||
"Console.WriteLine($\"Chat history: {JsonSerializer.Serialize(chatHistory)}\\n\");"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,494 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Vector Stores and Embeddings\n",
|
||||
"\n",
|
||||
"So far, we've mostly been treating the kernel as a stateless orchestration engine.\n",
|
||||
"We send text into a model API and receive text out. \n",
|
||||
"\n",
|
||||
"In a [previous notebook](04-kernel-arguments-chat.ipynb), we used `kernel arguments` to pass in additional\n",
|
||||
"text into prompts to enrich them with more data. This allowed us to create a basic chat experience. \n",
|
||||
"\n",
|
||||
"However, if you solely relied on kernel arguments, you would quickly realize that eventually your prompt\n",
|
||||
"would grow so large that you would run into the model's token limit. What we need is a way to persist state\n",
|
||||
"and build both short-term and long-term memory to empower even more intelligent applications. \n",
|
||||
"\n",
|
||||
"To do this, we dive into the key concept of `Vector Stores` in the Semantic Kernel.\n",
|
||||
"\n",
|
||||
"More information can be found [here](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.24.1\"\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel.Connectors.InMemory, 1.24.1-preview\"\n",
|
||||
"#r \"nuget: Microsoft.Extensions.VectorData.Abstractions, 9.0.0-preview.1.24518.1\"\n",
|
||||
"#r \"nuget: System.Linq.Async, 6.0.1\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"#pragma warning disable SKEXP0010\n",
|
||||
"\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI service credentials used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
"{\n",
|
||||
" builder.AddAzureOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", azureEndpoint, apiKey);\n",
|
||||
"}\n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
" builder.AddOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey, orgId);\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Package `Microsoft.Extensions.VectorData.Abstractions`, which we downloaded in a previous code snippet, contains all necessary abstractions to work with vector stores. \n",
|
||||
"\n",
|
||||
"Together with abstractions, we also need to use an implementation of a concrete database connector, such as Azure AI Search, Azure CosmosDB, Qdrant, Redis and so on. A list of supported connectors can be found [here](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/).\n",
|
||||
"\n",
|
||||
"In this example, we are going to use the in-memory connector for demonstration purposes - `Microsoft.SemanticKernel.Connectors.InMemory`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Define your model\n",
|
||||
"\n",
|
||||
"It all starts from defining your data model. In abstractions, there are three main data model property types:\n",
|
||||
"\n",
|
||||
"1. Key\n",
|
||||
"2. Data\n",
|
||||
"3. Vector\n",
|
||||
"\n",
|
||||
"In most cases, a data model contains one key property, multiple data and vector properties, but some connectors may have restrictions, for example when only one vector property is supported. \n",
|
||||
"\n",
|
||||
"Also, each connector supports a different set of property types. For more information about supported property types in each connector, visit the connector's page, which can be found [here](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/).\n",
|
||||
"\n",
|
||||
"There are two ways how to define your data model - using attributes (declarative way) or record definition (imperative way).\n",
|
||||
"\n",
|
||||
"Here is how a data model could look like with attributes:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.Extensions.VectorData;\n",
|
||||
"\n",
|
||||
"public sealed class Glossary\n",
|
||||
"{\n",
|
||||
" [VectorStoreRecordKey]\n",
|
||||
" public ulong Key { get; set; }\n",
|
||||
"\n",
|
||||
" [VectorStoreRecordData]\n",
|
||||
" public string Term { get; set; }\n",
|
||||
"\n",
|
||||
" [VectorStoreRecordData]\n",
|
||||
" public string Definition { get; set; }\n",
|
||||
"\n",
|
||||
" [VectorStoreRecordVector(Dimensions: 1536)]\n",
|
||||
" public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"More information about each attribute and its properties can be found [here](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/defining-your-data-model#attributes)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"There could be a case when you can't modify the existing class with attributes. In this case, you can define a separate record definition with all the information about your properties. Note that the defined data model class is still required in this case:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"public sealed class GlossaryWithoutAttributes\n",
|
||||
"{\n",
|
||||
" public ulong Key { get; set; }\n",
|
||||
"\n",
|
||||
" public string Term { get; set; }\n",
|
||||
"\n",
|
||||
" public string Definition { get; set; }\n",
|
||||
"\n",
|
||||
" public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"var recordDefinition = new VectorStoreRecordDefinition()\n",
|
||||
"{\n",
|
||||
" Properties = new List<VectorStoreRecordProperty>()\n",
|
||||
" {\n",
|
||||
" new VectorStoreRecordKeyProperty(\"Key\", typeof(ulong)),\n",
|
||||
" new VectorStoreRecordDataProperty(\"Term\", typeof(string)),\n",
|
||||
" new VectorStoreRecordDataProperty(\"Definition\", typeof(string)),\n",
|
||||
" new VectorStoreRecordVectorProperty(\"DefinitionEmbedding\", typeof(ReadOnlyMemory<float>)) { Dimensions = 1536 }\n",
|
||||
" }\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Define main components\n",
|
||||
"\n",
|
||||
"As soon as you define your data model with either attributes or the record definition approach, you can start using it with your database of choice. \n",
|
||||
"\n",
|
||||
"There are a couple of abstractions that allow you to work with your database and collections:\n",
|
||||
"\n",
|
||||
"1. `IVectorStoreRecordCollection<TKey, TRecord>` - represents a collection. This collection may or may not exist, and the interface provides methods to check if the collection exists, create it or delete it. The interface also provides methods to upsert, get and delete records. Finally, the interface inherits from `IVectorizedSearch<TRecord>` providing vector search capabilities.\n",
|
||||
"2. `IVectorStore` - contains operations that spans across all collections in the vector store, e.g. `ListCollectionNames`. It also provides the ability to get `IVectorStoreRecordCollection<TKey, TRecord>` instances.\n",
|
||||
"\n",
|
||||
"Each connector has extension methods to register your vector store and collection using DI - `services.AddInMemoryVectorStore()` or `services.AddInMemoryVectorStoreRecordCollection(\"collection-name\")`. \n",
|
||||
"\n",
|
||||
"It's also possible to initialize these instances directly, which we are going to do in this notebook for simplicity:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel.Connectors.InMemory;\n",
|
||||
"\n",
|
||||
"#pragma warning disable SKEXP0020\n",
|
||||
"\n",
|
||||
"// Define vector store\n",
|
||||
"var vectorStore = new InMemoryVectorStore();\n",
|
||||
"\n",
|
||||
"// Get a collection instance using vector store\n",
|
||||
"var collection = vectorStore.GetCollection<ulong, Glossary>(\"skglossary\");\n",
|
||||
"\n",
|
||||
"// Get a collection instance by initializing it directly\n",
|
||||
"var collection2 = new InMemoryVectorStoreRecordCollection<ulong, Glossary>(\"skglossary\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Initializing a collection instance will allow you to work with your collection and data, but it doesn't mean that this collection already exists in a database. To ensure you are working with existing collection, you can create it if it doesn't exist:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await collection.CreateCollectionIfNotExistsAsync();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now, since we just created a new collection, it is empty, so we want to insert some records using the data model we defined above:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var glossaryEntries = new List<Glossary>()\n",
|
||||
"{\n",
|
||||
" new Glossary() \n",
|
||||
" {\n",
|
||||
" Key = 1,\n",
|
||||
" Term = \"API\",\n",
|
||||
" Definition = \"Application Programming Interface. A set of rules and specifications that allow software components to communicate and exchange data.\"\n",
|
||||
" },\n",
|
||||
" new Glossary() \n",
|
||||
" {\n",
|
||||
" Key = 2,\n",
|
||||
" Term = \"Connectors\",\n",
|
||||
" Definition = \"Connectors allow you to integrate with various services provide AI capabilities, including LLM, AudioToText, TextToAudio, Embedding generation, etc.\"\n",
|
||||
" },\n",
|
||||
" new Glossary() \n",
|
||||
" {\n",
|
||||
" Key = 3,\n",
|
||||
" Term = \"RAG\",\n",
|
||||
" Definition = \"Retrieval Augmented Generation - a term that refers to the process of retrieving additional data to provide as context to an LLM to use when generating a response (completion) to a user's question (prompt).\"\n",
|
||||
" }\n",
|
||||
"};"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If we want to perform a vector search on our records in the database, initializing just the key and data properties is not enough, we also need to generate and initialize vector properties. For that, we can use `ITextEmbeddingGenerationService` which we already registered above.\n",
|
||||
"\n",
|
||||
"The line `#pragma warning disable SKEXP0001` is required because `ITextEmbeddingGenerationService` interface is experimental and may change in the future."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel.Embeddings;\n",
|
||||
"\n",
|
||||
"#pragma warning disable SKEXP0001\n",
|
||||
"\n",
|
||||
"var textEmbeddingGenerationService = kernel.GetRequiredService<ITextEmbeddingGenerationService>();\n",
|
||||
"\n",
|
||||
"var tasks = glossaryEntries.Select(entry => Task.Run(async () =>\n",
|
||||
"{\n",
|
||||
" entry.DefinitionEmbedding = await textEmbeddingGenerationService.GenerateEmbeddingAsync(entry.Definition);\n",
|
||||
"}));\n",
|
||||
"\n",
|
||||
"await Task.WhenAll(tasks);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Upsert records\n",
|
||||
"\n",
|
||||
"Now our glossary records are ready to be inserted into the database. For that, we can use `collection.UpsertAsync` or `collection.UpsertBatchAsync` methods. Note that this operation is idempotent - if a record with a specific key doesn't exist, it will be inserted. If it already exists, it will be updated. As a result, we should receive the keys of the upserted records:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await foreach (var key in collection.UpsertBatchAsync(glossaryEntries))\n",
|
||||
"{\n",
|
||||
" Console.WriteLine(key);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Get records by key\n",
|
||||
"\n",
|
||||
"In order to ensure our records were upserted correctly, we can get these records by a key with `collection.GetAsync` or `collection.GetBatchAsync` methods. \n",
|
||||
"\n",
|
||||
"Both methods accept `GetRecordOptions` class as a parameter, where you can specify if you want to include vector properties in your response or not. Taking into account that the vector dimension value can be high, if you don't need to work with vectors in your code, it's recommended to not fetch them from the database. That's why `GetRecordOptions.IncludeVectors` property is `false` by default. \n",
|
||||
"\n",
|
||||
"In this example, we want to include vectors in the result to ensure that our data was upserted correctly:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var options = new GetRecordOptions() { IncludeVectors = true };\n",
|
||||
"\n",
|
||||
"await foreach (var record in collection.GetBatchAsync(keys: [1, 2, 3], options))\n",
|
||||
"{\n",
|
||||
" Console.WriteLine($\"Key: {record.Key}\");\n",
|
||||
" Console.WriteLine($\"Term: {record.Term}\");\n",
|
||||
" Console.WriteLine($\"Definition: {record.Definition}\");\n",
|
||||
" Console.WriteLine($\"Definition Embedding: {JsonSerializer.Serialize(record.DefinitionEmbedding)}\");\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Perform a search\n",
|
||||
"\n",
|
||||
"Since we ensured that our records are already in the database, we can perform a vector search with `collection.VectorizedSearchAsync` method. \n",
|
||||
"\n",
|
||||
"This method accepts the `VectorSearchOptions` class as a parameter, which allows configuration of the vector search operation - specify the maximum number of records to return, the number of results to skip before returning results, a search filter to use before doing the vector search and so on. More information about it can be found [here](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/vector-search#vector-search-options).\n",
|
||||
"\n",
|
||||
"To perform a vector search, we need a vector generated from our query string:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#pragma warning disable SKEXP0001\n",
|
||||
"\n",
|
||||
"var searchString = \"I want to learn more about Connectors\";\n",
|
||||
"var searchVector = await textEmbeddingGenerationService.GenerateEmbeddingAsync(searchString);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"As soon as we have our search vector, we can perform a search operation. The result of the `collection.VectorizedSearchAsync` method will be a collection of records from the database with their search scores:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var searchResult = await collection.VectorizedSearchAsync(searchVector);\n",
|
||||
"\n",
|
||||
"await foreach (var result in searchResult.Results)\n",
|
||||
"{\n",
|
||||
" Console.WriteLine($\"Search score: {result.Score}\");\n",
|
||||
" Console.WriteLine($\"Key: {result.Record.Key}\");\n",
|
||||
" Console.WriteLine($\"Term: {result.Record.Term}\");\n",
|
||||
" Console.WriteLine($\"Definition: {result.Record.Definition}\");\n",
|
||||
" Console.WriteLine(\"=========\");\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Additional information\n",
|
||||
"\n",
|
||||
"There are more concepts related to the vector stores that will allow you to extend the capabilities. Each of them is described in more detail on the Microsoft Learn portal:\n",
|
||||
"\n",
|
||||
"1. [Generic data model](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/generic-data-model) - allows to store and search data without a concrete data model type, using the generic data model instead.\n",
|
||||
"2. [Custom mapper](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/how-to/vector-store-custom-mapper) - define a custom mapper for a specific connector, when the default mapping logic is not enough to work with a database.\n",
|
||||
"3. [Code samples](https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/code-samples) - end-to-end RAG sample, supporting multiple vectors in the same record, vector search with paging, interoperability with Langchain and more."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Generating images with AI\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use OpenAI DALL-E 3 to generate images, in combination with other LLM features like text and embedding generation.\n",
|
||||
"\n",
|
||||
"Here, we use Chat Completion to generate a random image description and DALL-E 3 to create an image from that description, showing the image inline.\n",
|
||||
"\n",
|
||||
"Lastly, the notebook asks the user to describe the image. The embedding of the user's description is compared to the original description, using Cosine Similarity, and returning a score from 0 to 1, where 1 means exact match."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"tags": [],
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Usual setup: importing Semantic Kernel SDK and SkiaSharp, used to display images inline.\n",
|
||||
"\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"#r \"nuget: System.Numerics.Tensors, 8.0.0\"\n",
|
||||
"#r \"nuget: SkiaSharp, 2.88.3\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"#!import config/Utils.cs\n",
|
||||
"#!import config/SkiaUtils.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.TextToImage;\n",
|
||||
"using Microsoft.SemanticKernel.Embeddings;\n",
|
||||
"using Microsoft.SemanticKernel.Connectors.OpenAI;\n",
|
||||
"using System.Numerics.Tensors;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Setup, using three AI services: images, text, embedding\n",
|
||||
"\n",
|
||||
"The notebook uses:\n",
|
||||
"\n",
|
||||
"* **OpenAI Dall-E 3** to transform the image description into an image\n",
|
||||
"* **text-embedding-ada-002** to compare your guess against the real image description\n",
|
||||
"\n",
|
||||
"**Note:**: For Azure OpenAI, your endpoint should have DALL-E API enabled."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"#pragma warning disable SKEXP0001, SKEXP0010\n",
|
||||
"\n",
|
||||
"// Load OpenAI credentials from config/settings.json\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"// Configure the three AI features: text embedding (using Ada), chat completion, image generation (DALL-E 3)\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"if(useAzureOpenAI)\n",
|
||||
"{\n",
|
||||
" builder.AddAzureOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", azureEndpoint, apiKey);\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
" builder.AddAzureOpenAITextToImage(\"dall-e-3\", azureEndpoint, apiKey);\n",
|
||||
"}\n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
" builder.AddOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey, orgId);\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
" builder.AddOpenAITextToImage(apiKey, orgId);\n",
|
||||
"}\n",
|
||||
" \n",
|
||||
"var kernel = builder.Build();\n",
|
||||
"\n",
|
||||
"// Get AI service instance used to generate images\n",
|
||||
"var dallE = kernel.GetRequiredService<ITextToImageService>();\n",
|
||||
"\n",
|
||||
"// Get AI service instance used to extract embedding from a text\n",
|
||||
"var textEmbedding = kernel.GetRequiredService<ITextEmbeddingGenerationService>();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Generate a (random) image with DALL-E 3\n",
|
||||
"\n",
|
||||
"**genImgDescription** is a Semantic Function used to generate a random image description. \n",
|
||||
"The function takes in input a random number to increase the diversity of its output.\n",
|
||||
"\n",
|
||||
"The random image description is then given to **Dall-E 3** asking to create an image."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"tags": [],
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#pragma warning disable SKEXP0001\n",
|
||||
"\n",
|
||||
"var prompt = @\"\n",
|
||||
"Think about an artificial object correlated to number {{$input}}.\n",
|
||||
"Describe the image with one detailed sentence. The description cannot contain numbers.\";\n",
|
||||
"\n",
|
||||
"var executionSettings = new OpenAIPromptExecutionSettings \n",
|
||||
"{\n",
|
||||
" MaxTokens = 256,\n",
|
||||
" Temperature = 1\n",
|
||||
"};\n",
|
||||
"\n",
|
||||
"// Create a semantic function that generate a random image description.\n",
|
||||
"var genImgDescription = kernel.CreateFunctionFromPrompt(prompt, executionSettings);\n",
|
||||
"\n",
|
||||
"var random = new Random().Next(0, 200);\n",
|
||||
"var imageDescriptionResult = await kernel.InvokeAsync(genImgDescription, new() { [\"input\"] = random });\n",
|
||||
"var imageDescription = imageDescriptionResult.ToString();\n",
|
||||
"\n",
|
||||
"// Use DALL-E 3 to generate an image. OpenAI in this case returns a URL (though you can ask to return a base64 image)\n",
|
||||
"var imageUrl = await dallE.GenerateImageAsync(imageDescription.Trim(), 1024, 1024);\n",
|
||||
"\n",
|
||||
"await SkiaUtils.ShowImage(imageUrl, 1024, 1024);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Let's play a guessing game\n",
|
||||
"\n",
|
||||
"Try to guess what the image is about, describing the content.\n",
|
||||
"\n",
|
||||
"You'll get a score at the end 😉"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"tags": [],
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Prompt the user to guess what the image is\n",
|
||||
"var guess = await InteractiveKernel.GetInputAsync(\"Describe the image in your words\");\n",
|
||||
"\n",
|
||||
"// Compare user guess with real description and calculate score\n",
|
||||
"var origEmbedding = await textEmbedding.GenerateEmbeddingsAsync(new List<string> { imageDescription } );\n",
|
||||
"var guessEmbedding = await textEmbedding.GenerateEmbeddingsAsync(new List<string> { guess } );\n",
|
||||
"var similarity = TensorPrimitives.CosineSimilarity(origEmbedding.First().Span, guessEmbedding.First().Span);\n",
|
||||
"\n",
|
||||
"Console.WriteLine($\"Your description:\\n{Utils.WordWrap(guess, 90)}\\n\");\n",
|
||||
"Console.WriteLine($\"Real description:\\n{Utils.WordWrap(imageDescription.Trim(), 90)}\\n\");\n",
|
||||
"Console.WriteLine($\"Score: {similarity:0.00}\\n\\n\");\n",
|
||||
"\n",
|
||||
"//Uncomment this line to see the URL provided by OpenAI\n",
|
||||
"//Console.WriteLine(imageUrl);"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".cs",
|
||||
"mimetype": "text/x-csharp",
|
||||
"name": "C#",
|
||||
"pygments_lexer": "csharp",
|
||||
"version": "11.0"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Using ChatGPT with the Semantic Kernel featuring DALL-E 3\n",
|
||||
"\n",
|
||||
"This notebook shows how to make use of the new ChatCompletion API from OpenAI, popularized by ChatGPT. This API brings a new ChatML schema which is different from the TextCompletion API. While the text completion API expects input a prompt and returns a simple string, the chat completion API expects in input a Chat history and returns a new message:\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"messages=[\n",
|
||||
" { \"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
|
||||
" { \"role\": \"user\", \"content\": \"Who won the world series in 2020?\"},\n",
|
||||
" { \"role\": \"assistant\", \"content\": \"The Los Angeles Dodgers won the World Series in 2020.\"},\n",
|
||||
" { \"role\": \"user\", \"content\": \"Where was it played?\"}\n",
|
||||
"]\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"Note that there are three message types:\n",
|
||||
"\n",
|
||||
"1. A System message is used to give instructions to the chat model, e.g. setting the context and the kind of conversation your app is offering.\n",
|
||||
"2. User messages store the data received from the user of your app.\n",
|
||||
"3. Assistant messages store the replies generated by the LLM model. \n",
|
||||
"\n",
|
||||
"Your app is responsible for adding information to the chat history and maintaining this object. The Chat Completion API is stateless, and returns only new messages, that your app can use, e.g. to execute commands, generate images, or simply continue the conversation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"When deciding between which one to use, know that ChatGPT models (i.e. gpt-3.5-turbo) are optimized for chat applications and have been fine-tuned for instruction-following and dialogue. As such, for creating semantic plugins with the Semantic Kernel, users may still find the TextCompletion model better suited for certain use cases.\n",
|
||||
"\n",
|
||||
"The code below shows how to setup SK with ChatGPT, how to manage the Chat history object, and to make things a little more interesting asks ChatGPT to reply with image descriptions instead so we can have a dialog using images, leveraging DALL-E 3 integration."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"tags": [],
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"// Usual setup: importing Semantic Kernel SDK and SkiaSharp, used to display images inline.\n",
|
||||
"\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"#r \"nuget: SkiaSharp, 2.88.3\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"#!import config/Utils.cs\n",
|
||||
"#!import config/SkiaUtils.cs\n",
|
||||
"\n",
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.TextToImage;\n",
|
||||
"using Microsoft.SemanticKernel.ChatCompletion;\n",
|
||||
"using Microsoft.SemanticKernel.Connectors.OpenAI;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The notebook uses:\n",
|
||||
"\n",
|
||||
"* **OpenAI ChatGPT** to chat with the user\n",
|
||||
"* **OpenAI Dall-E 3** to transform messages into images"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"#pragma warning disable SKEXP0001, SKEXP0010\n",
|
||||
"\n",
|
||||
"// Load OpenAI credentials from config/settings.json\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"\n",
|
||||
"// Configure the two AI features: OpenAI Chat and DALL-E 3 for image generation\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"if(useAzureOpenAI)\n",
|
||||
"{\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(\"gpt-4o-mini\", azureEndpoint, apiKey);\n",
|
||||
" builder.AddAzureOpenAITextToImage(\"dall-e-3\", azureEndpoint, apiKey);\n",
|
||||
"}\n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
" builder.AddOpenAIChatCompletion(\"gpt-4o-mini\", apiKey, orgId);\n",
|
||||
" builder.AddOpenAITextToImage(apiKey, orgId);\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"var kernel = builder.Build();\n",
|
||||
"\n",
|
||||
"// Get AI service instance used to generate images\n",
|
||||
"var dallE = kernel.GetRequiredService<ITextToImageService>();\n",
|
||||
"\n",
|
||||
"// Get AI service instance used to manage the user chat\n",
|
||||
"var chatGPT = kernel.GetRequiredService<IChatCompletionService>();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Chat configuration\n",
|
||||
"\n",
|
||||
"Before starting the chat, we create a new chat object with some instructions, which are included in the chat history. \n",
|
||||
"\n",
|
||||
"The instructions tell OpenAI what kind of chat we want to have, in this case we ask to reply with \"image descriptions\", so that we can chain ChatGPT with DALL-E 3."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"tags": [],
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"var systemMessage = \"You're chatting with a user. Instead of replying directly to the user\"\n",
|
||||
" + \" provide a description of a cartoonish image that expresses what you want to say.\"\n",
|
||||
" + \" The user won't see your message, they will see only the image.\"\n",
|
||||
" + \" Describe the image with details in one sentence.\";\n",
|
||||
"\n",
|
||||
"var chat = new ChatHistory(systemMessage);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Let's chat\n",
|
||||
"\n",
|
||||
"Run the following code to start the chat. The chat consists of a loop with these main steps:\n",
|
||||
"\n",
|
||||
"1. Ask the user (you) for a message. The user enters a message. Add the user message into the Chat History object.\n",
|
||||
"2. Send the chat object to AI asking to generate a response. Add the bot message into the Chat History object.\n",
|
||||
"3. Show the answer to the user. In our case before showing the answer, generate an image and show that to the user too.\n",
|
||||
"\n",
|
||||
"*Note: to stop the chat in VS Code press ESC on the kyboard or the \"stop\" button on the left side.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
},
|
||||
"vscode": {
|
||||
"languageId": "polyglot-notebook"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#pragma warning disable SKEXP0001\n",
|
||||
"\n",
|
||||
"while (true)\n",
|
||||
"{\n",
|
||||
" // 1. Ask the user for a message. The user enters a message. Add the user message into the Chat History object.\n",
|
||||
" var userMessage = await InteractiveKernel.GetInputAsync(\"Your message\");\n",
|
||||
" Console.WriteLine($\"User: {userMessage}\");\n",
|
||||
" chat.AddUserMessage(userMessage);\n",
|
||||
"\n",
|
||||
" // 2. Send the chat object to AI asking to generate a response. Add the bot message into the Chat History object.\n",
|
||||
" var assistantReply = await chatGPT.GetChatMessageContentAsync(chat, new OpenAIPromptExecutionSettings());\n",
|
||||
" chat.AddAssistantMessage(assistantReply.Content);\n",
|
||||
"\n",
|
||||
" // 3. Show the reply as an image\n",
|
||||
" Console.WriteLine($\"\\nBot:\");\n",
|
||||
" var imageUrl = await dallE.GenerateImageAsync(assistantReply.Content, 1024, 1024);\n",
|
||||
" await SkiaUtils.ShowImage(imageUrl, 1024, 1024);\n",
|
||||
" Console.WriteLine($\"[{assistantReply}]\\n\");\n",
|
||||
"}"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".cs",
|
||||
"mimetype": "text/x-csharp",
|
||||
"name": "C#",
|
||||
"pygments_lexer": "csharp",
|
||||
"version": "11.0"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# RAG with BingSearch \n",
|
||||
"\n",
|
||||
"This notebook explains how to integrate Bing Search with the Semantic Kernel to get the latest information from the internet.\n",
|
||||
"\n",
|
||||
"To use Bing Search you simply need a Bing Search API key. You can get the API key by creating a [Bing Search resource](https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/create-bing-search-service-resource) in Azure. \n",
|
||||
"\n",
|
||||
"To learn more read the following [documentation](https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/overview).\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Prepare a Semantic Kernel instance first, loading also the AI backend settings defined in the [Setup notebook](0-AI-settings.ipynb):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#r \"nuget: Microsoft.SemanticKernel, 1.23.0\"\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel.Plugins.Web, 1.23.0-alpha\"\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel.Plugins.Core, 1.23.0-alpha\"\n",
|
||||
"#r \"nuget: Microsoft.SemanticKernel.PromptTemplates.Handlebars, 1.23.0-alpha\"\n",
|
||||
"\n",
|
||||
"#!import config/Settings.cs\n",
|
||||
"#!import config/Utils.cs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Enter your Bing Search Key in BING_KEY using `InteractiveKernel` method as introduced in [`.NET Interactive`](https://github.com/dotnet/interactive/blob/main/docs/kernels-overview.md)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using InteractiveKernel = Microsoft.DotNet.Interactive.Kernel;\n",
|
||||
"\n",
|
||||
"string BING_KEY = (await InteractiveKernel.GetPasswordAsync(\"Please enter your Bing Search Key\")).GetClearTextPassword();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Basic search plugin\n",
|
||||
"\n",
|
||||
"The sample below shows how to create a plugin named SearchPlugin from an instance of `BingTextSearch`. Using `CreateWithSearch` creates a new plugin with a single Search function that calls the underlying text search implementation. The SearchPlugin is added to the Kernel which makes it available to be called during prompt rendering. The prompt template includes a call to `{{SearchPlugin.Search $query}}` which will invoke the SearchPlugin to retrieve results related to the current query. The results are then inserted into the rendered prompt before it is sent to the AI model."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.Data;\n",
|
||||
"using Microsoft.SemanticKernel.Plugins.Web.Bing;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"// Create a kernel with OpenAI chat completion\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI backend used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"var kernel = builder.Build();\n",
|
||||
"\n",
|
||||
"// Create a text search using Bing search\n",
|
||||
"#pragma warning disable SKEXP0050\n",
|
||||
"var textSearch = new BingTextSearch(apiKey: BING_KEY);\n",
|
||||
"\n",
|
||||
"// Build a text search plugin with Bing search and add to the kernel\n",
|
||||
"var searchPlugin = textSearch.CreateWithSearch(\"SearchPlugin\");\n",
|
||||
"kernel.Plugins.Add(searchPlugin);\n",
|
||||
"\n",
|
||||
"// Invoke prompt and use text search plugin to provide grounding information\n",
|
||||
"var query = \"What is the Semantic Kernel?\";\n",
|
||||
"var prompt = \"{{SearchPlugin.Search $query}}. {{$query}}\";\n",
|
||||
"KernelArguments arguments = new() { { \"query\", query } };\n",
|
||||
"Console.WriteLine(await kernel.InvokePromptAsync(prompt, arguments));"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Search plugin with citations\n",
|
||||
"\n",
|
||||
"The sample below repeats the pattern described in the previous section with a few notable changes:\n",
|
||||
"\n",
|
||||
"1. `CreateWithGetTextSearchResults` is used to create a `SearchPlugin` which calls the `GetTextSearchResults` method from the underlying text search implementation.\n",
|
||||
"2. The prompt template uses Handlebars syntax. This allows the template to iterate over the search results and render the name, value and link for each result.\n",
|
||||
"3. The prompt includes an instruction to include citations, so the AI model will do the work of adding citations to the response."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.Data;\n",
|
||||
"using Microsoft.SemanticKernel.Plugins.Web.Bing;\n",
|
||||
"using Microsoft.SemanticKernel.PromptTemplates.Handlebars;\n",
|
||||
"using Kernel = Microsoft.SemanticKernel.Kernel;\n",
|
||||
"\n",
|
||||
"// Create a kernel with OpenAI chat completion\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI backend used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"var kernel = builder.Build();\n",
|
||||
"\n",
|
||||
"// Create a text search using Bing search\n",
|
||||
"#pragma warning disable SKEXP0050\n",
|
||||
"var textSearch = new BingTextSearch(apiKey: BING_KEY);\n",
|
||||
"\n",
|
||||
"// Build a text search plugin with Bing search and add to the kernel\n",
|
||||
"var searchPlugin = textSearch.CreateWithGetTextSearchResults(\"SearchPlugin\");\n",
|
||||
"kernel.Plugins.Add(searchPlugin);\n",
|
||||
"\n",
|
||||
"// Invoke prompt and use text search plugin to provide grounding information\n",
|
||||
"var query = \"What is the Semantic Kernel?\";\n",
|
||||
"string promptTemplate = \"\"\"\n",
|
||||
"{{#with (SearchPlugin-GetTextSearchResults query)}} \n",
|
||||
" {{#each this}} \n",
|
||||
" Name: {{Name}}\n",
|
||||
" Value: {{Value}}\n",
|
||||
" Link: {{Link}}\n",
|
||||
" -----------------\n",
|
||||
" {{/each}} \n",
|
||||
"{{/with}} \n",
|
||||
"\n",
|
||||
"{{query}}\n",
|
||||
"\n",
|
||||
"Include citations to the relevant information where it is referenced in the response.\n",
|
||||
"\"\"\";\n",
|
||||
"KernelArguments arguments = new() { { \"query\", query } };\n",
|
||||
"HandlebarsPromptTemplateFactory promptTemplateFactory = new();\n",
|
||||
"Console.WriteLine(await kernel.InvokePromptAsync(\n",
|
||||
" promptTemplate,\n",
|
||||
" arguments,\n",
|
||||
" templateFormat: HandlebarsPromptTemplateFactory.HandlebarsTemplateFormat,\n",
|
||||
" promptTemplateFactory: promptTemplateFactory\n",
|
||||
"));"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Search plugin with a filter\n",
|
||||
"\n",
|
||||
"The samples shown so far will use the top ranked web search results to provide the grounding data. To provide more reliability in the data the web search can be restricted to only return results from a specified site.\n",
|
||||
"\n",
|
||||
"The sample below builds on the previous one to add filtering of the search results.\n",
|
||||
"A `TextSearchFilter` with an equality clause is used to specify that only results from the Microsoft Developer Blogs site (`site == 'devblogs.microsoft.com'`) are to be included in the search results.\n",
|
||||
"\n",
|
||||
"The sample uses `KernelPluginFactory.CreateFromFunctions` to create the `SearchPlugin`.\n",
|
||||
"A custom description is provided for the plugin.\n",
|
||||
"The `ITextSearch.CreateGetTextSearchResults` extension method is used to create the `KernelFunction` which invokes the text search service."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Microsoft.SemanticKernel;\n",
|
||||
"using Microsoft.SemanticKernel.Data;\n",
|
||||
"using Microsoft.SemanticKernel.PromptTemplates.Handlebars;\n",
|
||||
"using Microsoft.SemanticKernel.Plugins.Web.Bing;\n",
|
||||
"\n",
|
||||
"// Create a kernel with OpenAI chat completion\n",
|
||||
"var builder = Kernel.CreateBuilder();\n",
|
||||
"\n",
|
||||
"// Configure AI backend used by the kernel\n",
|
||||
"var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n",
|
||||
"if (useAzureOpenAI)\n",
|
||||
" builder.AddAzureOpenAIChatCompletion(model, azureEndpoint, apiKey);\n",
|
||||
"else\n",
|
||||
" builder.AddOpenAIChatCompletion(model, apiKey, orgId);\n",
|
||||
"var kernel = builder.Build();\n",
|
||||
"\n",
|
||||
"// Create a text search using Bing search\n",
|
||||
"#pragma warning disable SKEXP0050\n",
|
||||
"var textSearch = new BingTextSearch(apiKey: BING_KEY);\n",
|
||||
"\n",
|
||||
"// Create a filter to search only the Microsoft Developer Blogs site\n",
|
||||
"#pragma warning disable SKEXP0001\n",
|
||||
"var filter = new TextSearchFilter().Equality(\"site\", \"devblogs.microsoft.com\");\n",
|
||||
"var searchOptions = new TextSearchOptions() { Filter = filter };\n",
|
||||
"\n",
|
||||
"// Build a text search plugin with Bing search and add to the kernel\n",
|
||||
"var searchPlugin = KernelPluginFactory.CreateFromFunctions(\n",
|
||||
" \"SearchPlugin\", \"Search Microsoft Developer Blogs site only\",\n",
|
||||
" [textSearch.CreateGetTextSearchResults(searchOptions: searchOptions)]);\n",
|
||||
"kernel.Plugins.Add(searchPlugin);\n",
|
||||
"\n",
|
||||
"// Invoke prompt and use text search plugin to provide grounding information\n",
|
||||
"var query = \"What is the Semantic Kernel?\";\n",
|
||||
"string promptTemplate = \"\"\"\n",
|
||||
"{{#with (SearchPlugin-GetTextSearchResults query)}} \n",
|
||||
" {{#each this}} \n",
|
||||
" Name: {{Name}}\n",
|
||||
" Value: {{Value}}\n",
|
||||
" Link: {{Link}}\n",
|
||||
" -----------------\n",
|
||||
" {{/each}} \n",
|
||||
"{{/with}} \n",
|
||||
"\n",
|
||||
"{{query}}\n",
|
||||
"\n",
|
||||
"Include citations to the relevant information where it is referenced in the response.\n",
|
||||
"\"\"\";\n",
|
||||
"KernelArguments arguments = new() { { \"query\", query } };\n",
|
||||
"HandlebarsPromptTemplateFactory promptTemplateFactory = new();\n",
|
||||
"Console.WriteLine(await kernel.InvokePromptAsync(\n",
|
||||
" promptTemplate,\n",
|
||||
" arguments,\n",
|
||||
" templateFormat: HandlebarsPromptTemplateFactory.HandlebarsTemplateFormat,\n",
|
||||
" promptTemplateFactory: promptTemplateFactory\n",
|
||||
"));\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
# Semantic Kernel C# Notebooks
|
||||
|
||||
The current folder contains a few C# Jupyter Notebooks that demonstrate how to get started with
|
||||
the Semantic Kernel. The notebooks are organized in order of increasing complexity.
|
||||
|
||||
To run the notebooks, we recommend the following steps:
|
||||
|
||||
- [Install .NET 10](https://dotnet.microsoft.com/download/dotnet/10.0)
|
||||
- [Install Visual Studio Code (VS Code)](https://code.visualstudio.com)
|
||||
- Launch VS Code and [install the "Polyglot" extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode).
|
||||
Min version required: v1.0.4606021 (Dec 2023).
|
||||
|
||||
The steps above should be sufficient, you can now **open all the C# notebooks in VS Code**.
|
||||
|
||||
VS Code screenshot example:
|
||||
|
||||

|
||||
|
||||
## Set your OpenAI API key
|
||||
|
||||
To start using these notebooks, be sure to add the appropriate API keys to `config/settings.json`.
|
||||
|
||||
You can create the file manually or run [the Setup notebook](0-AI-settings.ipynb).
|
||||
|
||||
For Azure OpenAI:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "azure",
|
||||
"model": "...", // Azure OpenAI Deployment Name
|
||||
"endpoint": "...", // Azure OpenAI endpoint
|
||||
"apikey": "..." // Azure OpenAI key
|
||||
}
|
||||
```
|
||||
|
||||
For OpenAI:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "openai",
|
||||
"model": "gpt-3.5-turbo", // OpenAI model name
|
||||
"apikey": "...", // OpenAI API Key
|
||||
"org": "" // only for OpenAI accounts with multiple orgs
|
||||
}
|
||||
```
|
||||
|
||||
If you need an Azure OpenAI key, go [here](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api).
|
||||
If you need an OpenAI key, go [here](https://platform.openai.com/account/api-keys)
|
||||
|
||||
# Topics
|
||||
|
||||
Before starting, make sure you configured `config/settings.json`,
|
||||
see the previous section.
|
||||
|
||||
For a quick dive, look at the [getting started notebook](00-getting-started.ipynb).
|
||||
|
||||
1. [Loading and configuring Semantic Kernel](01-basic-loading-the-kernel.ipynb)
|
||||
2. [Running AI prompts from file](02-running-prompts-from-file.ipynb)
|
||||
3. [Creating Semantic Functions at runtime (i.e. inline functions)](03-semantic-function-inline.ipynb)
|
||||
4. [Using Kernel Arguments to Build a Chat Experience](04-kernel-arguments-chat.ipynb)
|
||||
5. [Introduction to the Function Calling](05-using-function-calling.ipynb)
|
||||
6. [Vector Stores and Embeddings](06-vector-stores-and-embeddings.ipynb)
|
||||
7. [Creating images with DALL-E 3](07-DALL-E-3.ipynb)
|
||||
8. [Chatting with ChatGPT and Images](08-chatGPT-with-DALL-E-3.ipynb)
|
||||
9. [BingSearch using Kernel](09-RAG-with-BingSearch.ipynb)
|
||||
|
||||
# Run notebooks in the browser with JupyterLab
|
||||
|
||||
You can run the notebooks also in the browser with JupyterLab. These steps
|
||||
should be sufficient to start:
|
||||
|
||||
Install Python 3, Pip and .NET 10 in your system, then:
|
||||
|
||||
pip install jupyterlab
|
||||
dotnet tool install -g Microsoft.dotnet-interactive
|
||||
dotnet tool update -g Microsoft.dotnet-interactive
|
||||
dotnet interactive jupyter install
|
||||
|
||||
This command will confirm that Jupyter now supports C# notebooks:
|
||||
|
||||
jupyter kernelspec list
|
||||
|
||||
Enter the notebooks folder, and run this to launch the browser interface:
|
||||
|
||||
jupyter-lab
|
||||
|
||||

|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## Nuget
|
||||
|
||||
If you are unable to get the Nuget package, first list your Nuget sources:
|
||||
|
||||
```sh
|
||||
dotnet nuget list source
|
||||
```
|
||||
|
||||
If you see `No sources found.`, add the NuGet official package source:
|
||||
|
||||
```sh
|
||||
dotnet nuget add source "https://api.nuget.org/v3/index.json" --name "nuget.org"
|
||||
```
|
||||
|
||||
Run `dotnet nuget list source` again to verify the source was added.
|
||||
|
||||
## Polyglot Notebooks
|
||||
|
||||
If somehow the notebooks don't work, run these commands:
|
||||
|
||||
- Install .NET Interactive: `dotnet tool install -g Microsoft.dotnet-interactive`
|
||||
- Register .NET kernels into Jupyter: `dotnet interactive jupyter install` (this might return some errors, ignore them)
|
||||
- If you are still stuck, read the following pages:
|
||||
- https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode
|
||||
- https://devblogs.microsoft.com/dotnet/net-core-with-juypter-notebooks-is-here-preview-1/
|
||||
- https://docs.servicestack.net/jupyter-notebooks-csharp
|
||||
- https://developers.refinitiv.com/en/article-catalog/article/using--net-core-in-jupyter-notebook
|
||||
|
||||
Note: ["Polyglot Notebooks" used to be called ".NET Interactive Notebooks"](https://devblogs.microsoft.com/dotnet/dotnet-interactive-notebooks-is-now-polyglot-notebooks/),
|
||||
so you might find online some documentation referencing the old name.
|
||||
@@ -0,0 +1,9 @@
|
||||
*.json
|
||||
bin
|
||||
obj
|
||||
.ipy*
|
||||
*.csproj
|
||||
*.ini
|
||||
*.cache
|
||||
*.log
|
||||
*.tmp
|
||||
@@ -0,0 +1,252 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.DotNet.Interactive;
|
||||
using InteractiveKernel = Microsoft.DotNet.Interactive.Kernel;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
public static class Settings
|
||||
{
|
||||
private const string DefaultConfigFile = "config/settings.json";
|
||||
private const string TypeKey = "type";
|
||||
private const string ModelKey = "model";
|
||||
private const string EndpointKey = "endpoint";
|
||||
private const string SecretKey = "apikey";
|
||||
private const string OrgKey = "org";
|
||||
private const bool StoreConfigOnFile = true;
|
||||
|
||||
// Prompt user for Azure Endpoint URL
|
||||
public static async Task<string> AskAzureEndpoint(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile)
|
||||
{
|
||||
var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile);
|
||||
|
||||
// If needed prompt user for Azure endpoint
|
||||
if (useAzureOpenAI && string.IsNullOrWhiteSpace(azureEndpoint))
|
||||
{
|
||||
azureEndpoint = await InteractiveKernel.GetInputAsync("Please enter your Azure OpenAI endpoint");
|
||||
}
|
||||
|
||||
WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId);
|
||||
|
||||
// Print report
|
||||
if (useAzureOpenAI)
|
||||
{
|
||||
Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(azureEndpoint)
|
||||
? "ERROR: Azure OpenAI endpoint is empty"
|
||||
: $"OK: Azure OpenAI endpoint configured [{configFile}]"));
|
||||
}
|
||||
|
||||
return azureEndpoint;
|
||||
}
|
||||
|
||||
// Prompt user for OpenAI model name / Azure OpenAI deployment name
|
||||
public static async Task<string> AskModel(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile)
|
||||
{
|
||||
var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile);
|
||||
|
||||
// If needed prompt user for model name / deployment name
|
||||
if (string.IsNullOrWhiteSpace(model))
|
||||
{
|
||||
if (useAzureOpenAI)
|
||||
{
|
||||
model = await InteractiveKernel.GetInputAsync("Please enter your Azure OpenAI deployment name");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the best model by default, and reduce the setup friction, particularly in VS Studio.
|
||||
model = "gpt-4o-mini";
|
||||
}
|
||||
}
|
||||
|
||||
WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId);
|
||||
|
||||
// Print report
|
||||
if (useAzureOpenAI)
|
||||
{
|
||||
Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(model)
|
||||
? "ERROR: deployment name is empty"
|
||||
: $"OK: deployment name configured [{configFile}]"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(model)
|
||||
? "ERROR: model name is empty"
|
||||
: $"OK: AI model configured [{configFile}]"));
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
// Prompt user for API Key
|
||||
public static async Task<string> AskApiKey(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile)
|
||||
{
|
||||
var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile);
|
||||
|
||||
// If needed prompt user for API key
|
||||
if (string.IsNullOrWhiteSpace(apiKey))
|
||||
{
|
||||
if (useAzureOpenAI)
|
||||
{
|
||||
apiKey = (await InteractiveKernel.GetPasswordAsync("Please enter your Azure OpenAI API key")).GetClearTextPassword();
|
||||
orgId = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
apiKey = (await InteractiveKernel.GetPasswordAsync("Please enter your OpenAI API key")).GetClearTextPassword();
|
||||
}
|
||||
}
|
||||
|
||||
WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId);
|
||||
|
||||
// Print report
|
||||
Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(apiKey)
|
||||
? "ERROR: API key is empty"
|
||||
: $"OK: API key configured [{configFile}]"));
|
||||
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
// Prompt user for OpenAI Organization Id
|
||||
public static async Task<string> AskOrg(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile)
|
||||
{
|
||||
var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile);
|
||||
|
||||
// If needed prompt user for OpenAI Org Id
|
||||
if (!useAzureOpenAI && string.IsNullOrWhiteSpace(orgId))
|
||||
{
|
||||
orgId = await InteractiveKernel.GetInputAsync("Please enter your OpenAI Organization Id (enter 'NONE' to skip)");
|
||||
}
|
||||
|
||||
WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId);
|
||||
|
||||
return orgId;
|
||||
}
|
||||
|
||||
// Load settings from file
|
||||
public static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId)
|
||||
LoadFromFile(string configFile = DefaultConfigFile)
|
||||
{
|
||||
if (!File.Exists(configFile))
|
||||
{
|
||||
Console.WriteLine("Configuration not found: " + configFile);
|
||||
Console.WriteLine("\nPlease run the Setup Notebook (0-AI-settings.ipynb) to configure your AI backend first.\n");
|
||||
throw new Exception("Configuration not found, please setup the notebooks first using notebook 0-AI-settings.pynb");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var config = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(configFile));
|
||||
bool useAzureOpenAI = config[TypeKey] == "azure";
|
||||
string model = config[ModelKey];
|
||||
string azureEndpoint = config[EndpointKey];
|
||||
string apiKey = config[SecretKey];
|
||||
string orgId = config[OrgKey];
|
||||
if (orgId == "none") { orgId = ""; }
|
||||
|
||||
return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Something went wrong: " + e.Message);
|
||||
return (true, "", "", "", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Delete settings file
|
||||
public static void Reset(string configFile = DefaultConfigFile)
|
||||
{
|
||||
if (!File.Exists(configFile)) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(configFile);
|
||||
Console.WriteLine("Settings deleted. Run the notebook again to configure your AI backend.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Something went wrong: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Read and return settings from file
|
||||
private static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId)
|
||||
ReadSettings(bool _useAzureOpenAI, string configFile)
|
||||
{
|
||||
// Save the preference set in the notebook
|
||||
bool useAzureOpenAI = _useAzureOpenAI;
|
||||
string model = "";
|
||||
string azureEndpoint = "";
|
||||
string apiKey = "";
|
||||
string orgId = "";
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(configFile))
|
||||
{
|
||||
(useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = LoadFromFile(configFile);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Something went wrong: " + e.Message);
|
||||
}
|
||||
|
||||
// If the preference in the notebook is different from the value on file, then reset
|
||||
if (useAzureOpenAI != _useAzureOpenAI)
|
||||
{
|
||||
Reset(configFile);
|
||||
useAzureOpenAI = _useAzureOpenAI;
|
||||
model = "";
|
||||
azureEndpoint = "";
|
||||
apiKey = "";
|
||||
orgId = "";
|
||||
}
|
||||
|
||||
return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId);
|
||||
}
|
||||
|
||||
// Write settings to file
|
||||
private static void WriteSettings(
|
||||
string configFile, bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (StoreConfigOnFile)
|
||||
{
|
||||
var data = new Dictionary<string, string>
|
||||
{
|
||||
{ TypeKey, useAzureOpenAI ? "azure" : "openai" },
|
||||
{ ModelKey, model },
|
||||
{ EndpointKey, azureEndpoint },
|
||||
{ SecretKey, apiKey },
|
||||
{ OrgKey, orgId },
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||
File.WriteAllText(configFile, JsonSerializer.Serialize(data, options));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Something went wrong: " + e.Message);
|
||||
}
|
||||
|
||||
// If asked then delete the credentials stored on disk
|
||||
if (!StoreConfigOnFile && File.Exists(configFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(configFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Something went wrong: " + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using SkiaSharp;
|
||||
using System.Net.Http;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
public static class SkiaUtils
|
||||
{
|
||||
// Function used to display images in the notebook
|
||||
public static async Task ShowImage(string url, int width, int height)
|
||||
{
|
||||
SKImageInfo info = new SKImageInfo(width, height);
|
||||
SKSurface surface = SKSurface.Create(info);
|
||||
SKCanvas canvas = surface.Canvas;
|
||||
canvas.Clear(SKColors.White);
|
||||
var httpClient = new HttpClient();
|
||||
using (Stream stream = await httpClient.GetStreamAsync(url))
|
||||
using (MemoryStream memStream = new MemoryStream())
|
||||
{
|
||||
await stream.CopyToAsync(memStream);
|
||||
memStream.Seek(0, SeekOrigin.Begin);
|
||||
SKBitmap webBitmap = SKBitmap.Decode(memStream);
|
||||
canvas.DrawBitmap(webBitmap, 0, 0, null);
|
||||
surface.Draw(canvas, 0, 0, null);
|
||||
};
|
||||
surface.Snapshot().Display();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
public static class Utils
|
||||
{
|
||||
// Function used to wrap long lines of text
|
||||
public static string WordWrap(string text, int maxLineLength)
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
int i;
|
||||
var last = 0;
|
||||
var space = new[] { ' ', '\r', '\n', '\t' };
|
||||
do
|
||||
{
|
||||
i = last + maxLineLength > text.Length
|
||||
? text.Length
|
||||
: (text.LastIndexOfAny(new[] { ' ', ',', '.', '?', '!', ':', ';', '-', '\n', '\r', '\t' }, Math.Min(text.Length - 1, last + maxLineLength)) + 1);
|
||||
if (i <= last) i = Math.Min(last + maxLineLength, text.Length);
|
||||
result.AppendLine(text.Substring(last, i - last).Trim(space));
|
||||
last = i;
|
||||
} while (i < text.Length);
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "azure",
|
||||
"model": "... your Azure OpenAI deployment name ...",
|
||||
"endpoint": "https:// ... your endpoint ... .openai.azure.com/",
|
||||
"apikey": "... your Azure OpenAI key ...",
|
||||
"org": "" // it's not used for azure, but the parser requires it so do not delete
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "openai",
|
||||
"endpoint": "NOT-USED-BUT-REQUIRED-FOR-PARSER",
|
||||
"model": "gpt-4o-mini",
|
||||
"apikey": "... your OpenAI key ...",
|
||||
"org": ""
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
|
||||
<packageSourceMapping>
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,22 @@
|
||||
# About Semantic Kernel
|
||||
|
||||
**Semantic Kernel (SK)** is a lightweight SDK enabling integration of AI Large
|
||||
Language Models (LLMs) with conventional programming languages. The SK
|
||||
extensible programming model combines natural language **semantic functions**,
|
||||
traditional code **native functions**, and **embeddings-based memory** unlocking
|
||||
new potential and adding value to applications with AI.
|
||||
|
||||
Semantic Kernel incorporates cutting-edge design patterns from the latest in AI
|
||||
research. This enables developers to augment their applications with advanced
|
||||
capabilities, such as prompt engineering, prompt chaining, retrieval-augmented
|
||||
generation, contextual and long-term vectorized memory, embeddings,
|
||||
summarization, zero or few-shot learning, semantic indexing, recursive
|
||||
reasoning, intelligent planning, and access to external knowledge stores and
|
||||
proprietary data.
|
||||
|
||||
# Getting Started ⚡
|
||||
|
||||
- Learn more at the [documentation site](https://aka.ms/SK-Docs).
|
||||
- Join the [Discord community](https://aka.ms/SKDiscord).
|
||||
- Follow the team on [Semantic Kernel blog](https://aka.ms/sk/blog).
|
||||
- Check out the [GitHub repository](https://github.com/microsoft/semantic-kernel) for the latest updates.
|
||||
@@ -0,0 +1,24 @@
|
||||
# VectorData Implementations by Semantic Kernel
|
||||
|
||||
**Microsoft.Extensions.VectorData.Abstractions** provides abstractions for
|
||||
accessing Vector Databases and Vector Indexes. It includes base abstract classes
|
||||
and interfaces for Vector Database implementations.
|
||||
|
||||
**Semantic Kernel (SK)** is a lightweight SDK allowing integration of AI experiences
|
||||
into your application.
|
||||
|
||||
**Semantic Kernel (SK)** provides a set of implementations for the
|
||||
Microsoft.Extensions.VectorData.Abstractions interfaces, allowing developers
|
||||
to easily connect to various vector databases. This package is one of these
|
||||
implementations.
|
||||
|
||||
This package can be used with Semantic Kernel or independently and
|
||||
does not depend on any Semantic Kernel abstractions or core libraries.
|
||||
|
||||
## Getting Started ⚡
|
||||
|
||||
- Learn more about using the VectorData abstractions and implementations at the [documentation site](https://learn.microsoft.com/semantic-kernel/concepts/vector-store-connectors).
|
||||
- Learn more about Semantic Kernel at the [documentation site](https://aka.ms/SK-Docs).
|
||||
- Join the [Discord community](https://aka.ms/SKDiscord).
|
||||
- Follow the team on [Semantic Kernel blog](https://aka.ms/sk/blog).
|
||||
- Check out the [GitHub repository](https://github.com/microsoft/semantic-kernel) for the latest updates.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,70 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<!-- Central version prefix - applies to all nuget packages. -->
|
||||
<VersionPrefix>1.78.0</VersionPrefix>
|
||||
<PackageVersion Condition="'$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix)</PackageVersion>
|
||||
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(VersionPrefix)</PackageVersion>
|
||||
|
||||
<Configurations>Debug;Release;Publish</Configurations>
|
||||
<IsPackable>true</IsPackable>
|
||||
|
||||
<!-- Package validation. Baseline Version should be the latest version available on NuGet. -->
|
||||
<PackageValidationBaselineVersion>1.77.0</PackageValidationBaselineVersion>
|
||||
<!-- Validate assembly attributes only for Publish builds -->
|
||||
<NoWarn Condition="'$(Configuration)' != 'Publish'">$(NoWarn);CP0003</NoWarn>
|
||||
<!-- Do not validate reference assemblies -->
|
||||
<NoWarn>$(NoWarn);CP1002</NoWarn>
|
||||
|
||||
<!-- Enable NuGet package auditing -->
|
||||
<NuGetAudit>true</NuGetAudit>
|
||||
|
||||
<!-- Audit direct and transitive packages -->
|
||||
<NuGetAuditMode>all</NuGetAuditMode>
|
||||
|
||||
<!-- Report low, moderate, high and critical advisories -->
|
||||
<NuGetAuditLevel>low</NuGetAuditLevel>
|
||||
|
||||
<!-- Default description and tags. Packages can override. -->
|
||||
<Authors>Microsoft</Authors>
|
||||
<Company>Microsoft</Company>
|
||||
<Product>Semantic Kernel</Product>
|
||||
<Description>Empowers app owners to integrate cutting-edge LLM technology quickly and easily into their apps.</Description>
|
||||
<PackageTags>AI, Artificial Intelligence, SDK</PackageTags>
|
||||
<PackageId>$(AssemblyName)</PackageId>
|
||||
|
||||
<!-- Required license, copyright, and repo information. Packages can override. -->
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<PackageProjectUrl>https://aka.ms/semantic-kernel</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/microsoft/semantic-kernel</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
|
||||
<!-- Use icon and NUGET readme from dotnet/nuget folder -->
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageIconUrl>icon.png</PackageIconUrl>
|
||||
<PackageReadmeFile>NUGET.md</PackageReadmeFile>
|
||||
|
||||
<!-- Build symbol package (.snupkg) to distribute the PDB containing Source Link -->
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
|
||||
<!-- Include the XML documentation file in the NuGet package. -->
|
||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- SourceLink allows step-through debugging for source hosted on GitHub. -->
|
||||
<!-- https://github.com/dotnet/sourcelink -->
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Include icon.png and NUGET.md in the project. -->
|
||||
<None Include="$(RepoRoot)/dotnet/nuget/icon.png" Link="icon.png" Pack="true" PackagePath="." />
|
||||
<None Include="$(RepoRoot)/dotnet/nuget/NUGET.md" Link="NUGET.md" Pack="true" PackagePath="." />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
# Setting errors for SDK projects under samples folder
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
dotnet_diagnostic.CA2007.severity = error # Do not directly await a Task
|
||||
dotnet_diagnostic.VSTHRD111.severity = error # Use .ConfigureAwait(bool)
|
||||
dotnet_diagnostic.IDE1006.severity = error # Naming rule violations
|
||||
dotnet_diagnostic.RCS1110.severity = none # Declare type inside namespace
|
||||
dotnet_diagnostic.CA2201.severity = none # Exception is not sufficiently specific
|
||||
dotnet_diagnostic.CS1998.severity = none # Async method lacks 'await' operators and will run synchronously
|
||||
dotnet_diagnostic.CA1851.severity = none # Possible multiple enumerations of 'IEnumerable' collection
|
||||
dotnet_diagnostic.CA1819.severity = none # Properties should not return arrays
|
||||
dotnet_diagnostic.CA1812.severity = none # Avoid uninstantiated internal classes
|
||||
dotnet_diagnostic.VSTHRD002.severity = none # Avoid problematic synchronous waits
|
||||
dotnet_diagnostic.CS1587.severity = none # XML comment is not placed on a valid language element
|
||||
dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types
|
||||
dotnet_diagnostic.CA2000.severity = none # Dispose objects before losing scope
|
||||
dotnet_diagnostic.RCS1110.severity = none # Declare type inside namespace
|
||||
dotnet_diagnostic.CA5394.severity = none # Do not use insecure randomness
|
||||
|
||||
# Resharper disabled rules: https://www.jetbrains.com/help/resharper/Reference__Code_Inspections_CSHARP.html#CodeSmell
|
||||
resharper_condition_is_always_true_or_false_according_to_nullable_api_contract_highlighting = none # ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
resharper_inconsistent_naming_highlighting = none # InconsistentNaming
|
||||
resharper_equal_expression_comparison_highlighting = none # EqualExpressionComparison
|
||||
resharper_check_namespace_highlighting = none # CheckNamespace
|
||||
resharper_arrange_object_creation_when_type_not_evident_highlighting = none # Disable "Arrange object creation when type is not evident" highlighting
|
||||
resharper_arrange_this_qualifier_highlighting = none # Disable "Arrange 'this.' qualifier" highlighting
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111;VSTHRD200</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Orchestration\Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Runtime\InProcess\Runtime.InProcess.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration.Concurrent;
|
||||
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
var agentInstructions = "You are a translation assistant who only responds in {0}. Respond to any input by outputting the name of the input language and then translating the input to {0}.";
|
||||
|
||||
// This sample compares running concurrent orchestrations using
|
||||
// Semantic Kernel and the Agent Framework.
|
||||
Console.WriteLine("=== Semantic Kernel Concurrent Orchestration ===");
|
||||
await SKConcurrentOrchestration();
|
||||
|
||||
Console.WriteLine("\n=== Agent Framework Concurrent Agent Workflow ===");
|
||||
await AFConcurrentAgentWorkflow();
|
||||
|
||||
# region SKConcurrentOrchestration
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
async Task SKConcurrentOrchestration()
|
||||
{
|
||||
ConcurrentOrchestration orchestration = new([
|
||||
GetSKTranslationAgent("French"),
|
||||
GetSKTranslationAgent("Spanish")])
|
||||
{
|
||||
StreamingResponseCallback = StreamingResultCallback,
|
||||
};
|
||||
|
||||
InProcessRuntime runtime = new();
|
||||
await runtime.StartAsync();
|
||||
|
||||
// Run the orchestration
|
||||
OrchestrationResult<string[]> result = await orchestration.InvokeAsync("Hello, world!", runtime);
|
||||
string[] texts = await result.GetValueAsync(TimeSpan.FromSeconds(20));
|
||||
|
||||
await runtime.RunUntilIdleAsync();
|
||||
}
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
return new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = string.Format(agentInstructions, targetLanguage),
|
||||
Description = $"Agent that translates texts to {targetLanguage}",
|
||||
Name = $"SKTranslationAgent_{targetLanguage}"
|
||||
};
|
||||
}
|
||||
|
||||
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
||||
{
|
||||
Console.Write(streamedResponse.Content);
|
||||
|
||||
if (isFinal)
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region AFConcurrentAgentWorkflow
|
||||
async Task AFConcurrentAgentWorkflow()
|
||||
{
|
||||
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
||||
var frenchAgent = GetAFTranslationAgent("French", client);
|
||||
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
||||
var concurrentAgentWorkflow = AgentWorkflowBuilder.BuildConcurrent([frenchAgent, spanishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(concurrentAgentWorkflow, "Hello, world!");
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.ExecutorId != lastExecutorId)
|
||||
{
|
||||
lastExecutorId = e.ExecutorId;
|
||||
Console.WriteLine();
|
||||
Console.Write($"{e.Update.AuthorName}: ");
|
||||
}
|
||||
|
||||
Console.Write(e.Update.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
|
||||
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
|
||||
# endregion
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111;VSTHRD200</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Orchestration\Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Runtime\InProcess\Runtime.InProcess.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration.Sequential;
|
||||
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
var agentInstructions = "You are a translation assistant who only responds in {0}. Respond to any input by outputting the name of the input language and then translating the input to {0}.";
|
||||
|
||||
// This sample compares running sequential orchestrations using
|
||||
// Semantic Kernel and the Agent Framework.
|
||||
Console.WriteLine("=== Semantic Kernel Sequential Orchestration ===");
|
||||
await SKSequentialOrchestration();
|
||||
|
||||
Console.WriteLine("\n=== Agent Framework Sequential Agent Workflow ===");
|
||||
await AFSequentialAgentWorkflow();
|
||||
|
||||
# region SKSequentialOrchestration
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
async Task SKSequentialOrchestration()
|
||||
{
|
||||
SequentialOrchestration orchestration = new([
|
||||
GetSKTranslationAgent("French"),
|
||||
GetSKTranslationAgent("Spanish"),
|
||||
GetSKTranslationAgent("English")])
|
||||
{
|
||||
StreamingResponseCallback = StreamingResultCallback,
|
||||
};
|
||||
|
||||
InProcessRuntime runtime = new();
|
||||
await runtime.StartAsync();
|
||||
|
||||
// Run the orchestration
|
||||
OrchestrationResult<string> result = await orchestration.InvokeAsync("Hello, world!", runtime);
|
||||
string text = await result.GetValueAsync(TimeSpan.FromSeconds(20));
|
||||
|
||||
await runtime.RunUntilIdleAsync();
|
||||
}
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
return new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = string.Format(agentInstructions, targetLanguage),
|
||||
Description = $"Agent that translates texts to {targetLanguage}",
|
||||
Name = $"SKTranslationAgent_{targetLanguage}"
|
||||
};
|
||||
}
|
||||
|
||||
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
||||
{
|
||||
Console.Write(streamedResponse.Content);
|
||||
|
||||
if (isFinal)
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region AFSequentialAgentWorkflow
|
||||
async Task AFSequentialAgentWorkflow()
|
||||
{
|
||||
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
||||
var frenchAgent = GetAFTranslationAgent("French", client);
|
||||
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
||||
var englishAgent = GetAFTranslationAgent("English", client);
|
||||
var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential(
|
||||
[frenchAgent, spanishAgent, englishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(sequentialAgentWorkflow, "Hello, world!");
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.ExecutorId != lastExecutorId)
|
||||
{
|
||||
lastExecutorId = e.ExecutorId;
|
||||
Console.WriteLine();
|
||||
Console.Write($"{e.Update.AuthorName}: ");
|
||||
}
|
||||
|
||||
Console.Write(e.Update.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
|
||||
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
|
||||
# endregion
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111;VSTHRD200</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Orchestration\Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Runtime\InProcess\Runtime.InProcess.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,249 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable MAAIW001 // Experimental: HandoffWorkflowBuilder
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration.Handoff;
|
||||
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Queries to simulate user input during the interactive orchestration
|
||||
List<string> Queries = [
|
||||
"I'd like to track the status of my first order 123.",
|
||||
"I want to return another order of mine whose ID is 456 because it arrived damaged.",
|
||||
];
|
||||
|
||||
// This sample compares running handoff orchestrations using
|
||||
// Semantic Kernel and the Agent Framework.
|
||||
Console.WriteLine("=== Semantic Kernel Handoff Orchestration ===");
|
||||
// State to help format the streaming output
|
||||
bool newAgentTurn = true;
|
||||
string previousFunctionCallId = string.Empty;
|
||||
await SKHandoffOrchestration();
|
||||
|
||||
Console.WriteLine("\n=== Agent Framework Handoff Agent Workflow ===");
|
||||
await AFHandoffAgentWorkflow();
|
||||
|
||||
# region SKHandoffOrchestration
|
||||
[KernelFunction]
|
||||
string SKCheckOrderStatus(string orderId) => $"Order {orderId} is shipped and will arrive in 2-3 days.";
|
||||
|
||||
[KernelFunction]
|
||||
string SKProcessReturn(string orderId, string reason) => $"Return for order {orderId} has been processed successfully.";
|
||||
|
||||
[KernelFunction]
|
||||
string SKProcessRefund(string orderId, string reason) => $"Refund for order {orderId} has been processed successfully.";
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
async Task SKHandoffOrchestration()
|
||||
{
|
||||
// Create agents
|
||||
var triageAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that triages issues.",
|
||||
name: "TriageAgent",
|
||||
description: "Handle customer requests.");
|
||||
var statusAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that checks order status.",
|
||||
name: "OrderStatusAgent",
|
||||
description: "Handle order status requests.");
|
||||
statusAgent.Kernel.Plugins.AddFromFunctions("OrderStatusPlugin", [KernelFunctionFactory.CreateFromMethod(SKCheckOrderStatus)]);
|
||||
var returnAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that handles order returns.",
|
||||
name: "OrderReturnAgent",
|
||||
description: "Handle order return requests.");
|
||||
returnAgent.Kernel.Plugins.AddFromFunctions("OrderReturnPlugin", [KernelFunctionFactory.CreateFromMethod(SKProcessReturn)]);
|
||||
var refundAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that handles order refunds.",
|
||||
name: "OrderRefundAgent",
|
||||
description: "Handle order refund requests.");
|
||||
refundAgent.Kernel.Plugins.AddFromFunctions("OrderRefundPlugin", [KernelFunctionFactory.CreateFromMethod(SKProcessRefund)]);
|
||||
|
||||
Queue<string> queries = new(Queries);
|
||||
|
||||
// Create orchestration with handoffs
|
||||
HandoffOrchestration orchestration =
|
||||
new(OrchestrationHandoffs
|
||||
.StartWith(triageAgent)
|
||||
.Add(triageAgent, statusAgent, returnAgent, refundAgent)
|
||||
.Add(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related")
|
||||
.Add(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related")
|
||||
.Add(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related"),
|
||||
triageAgent,
|
||||
statusAgent,
|
||||
returnAgent,
|
||||
refundAgent)
|
||||
{
|
||||
InteractiveCallback = () =>
|
||||
{
|
||||
string input = queries.Count > 0 ? queries.Dequeue() : "exit";
|
||||
Console.WriteLine($"\nUser: {input}");
|
||||
return ValueTask.FromResult(new ChatMessageContent(AuthorRole.User, input));
|
||||
},
|
||||
StreamingResponseCallback = StreamingResultCallback,
|
||||
};
|
||||
|
||||
InProcessRuntime runtime = new();
|
||||
await runtime.StartAsync();
|
||||
|
||||
// Run the orchestration
|
||||
OrchestrationResult<string> result = await orchestration.InvokeAsync(
|
||||
"I am a customer that needs help with my two orders",
|
||||
runtime);
|
||||
string text = await result.GetValueAsync();
|
||||
Console.WriteLine($"\nFinal Result: {text}");
|
||||
|
||||
await runtime.RunUntilIdleAsync();
|
||||
}
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent GetSKAgent(string instructions, string name, string description)
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
return new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = instructions,
|
||||
Description = description,
|
||||
Name = name
|
||||
};
|
||||
}
|
||||
|
||||
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
||||
{
|
||||
if (newAgentTurn)
|
||||
{
|
||||
Console.Write($"\n{streamedResponse.AuthorName}: ");
|
||||
newAgentTurn = false;
|
||||
}
|
||||
Console.Write(streamedResponse.Content);
|
||||
|
||||
if (streamedResponse.Items.OfType<StreamingFunctionCallUpdateContent>().FirstOrDefault()
|
||||
is StreamingFunctionCallUpdateContent call)
|
||||
{
|
||||
if (call.CallId is not null && previousFunctionCallId != call.CallId)
|
||||
{
|
||||
Console.Write($"\nCalling function '{call.Name}' with arguments: ");
|
||||
previousFunctionCallId = call.CallId;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(call.Arguments))
|
||||
{
|
||||
Console.Write($"{call.Arguments}");
|
||||
}
|
||||
}
|
||||
|
||||
if (isFinal)
|
||||
{
|
||||
newAgentTurn = true;
|
||||
previousFunctionCallId = string.Empty;
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region AFHandoffAgentWorkflow
|
||||
[Description("Get the order status for a given order ID.")]
|
||||
static string AFCheckOrderStatus([Description("The order ID to check the status for.")] string orderId)
|
||||
=> $"Order {orderId} is shipped and will arrive in 2-3 days.";
|
||||
|
||||
[Description("Process a return for a given order ID.")]
|
||||
static string AFProcessReturn(
|
||||
[Description("The order ID to process the return for.")] string orderId,
|
||||
[Description("The reason for the return.")] string reason)
|
||||
=> $"Return for order {orderId} has been processed successfully for the following reason: {reason}.";
|
||||
|
||||
[Description("Process a refund for a given order ID.")]
|
||||
static string AFProcessRefund([Description("The order ID to process the refund for.")] string orderId)
|
||||
=> $"Refund for order {orderId} has been processed successfully.";
|
||||
|
||||
async Task AFHandoffAgentWorkflow()
|
||||
{
|
||||
// Create agents
|
||||
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
||||
|
||||
ChatClientAgent triageAgent = new(client,
|
||||
instructions: "A customer support agent that triages issues.",
|
||||
name: "TriageAgent",
|
||||
description: "Handle customer requests.");
|
||||
ChatClientAgent statusAgent = new(client,
|
||||
name: "OrderStatusAgent",
|
||||
instructions: "Handle order status requests.",
|
||||
description: "A customer support agent that checks order status.",
|
||||
tools: [AIFunctionFactory.Create(AFCheckOrderStatus)]);
|
||||
ChatClientAgent returnAgent = new(client,
|
||||
name: "OrderReturnAgent",
|
||||
instructions: "Handle order return requests.",
|
||||
description: "A customer support agent that handles order returns.",
|
||||
tools: [AIFunctionFactory.Create(AFProcessReturn)]);
|
||||
ChatClientAgent refundAgent = new(client,
|
||||
name: "OrderRefundAgent",
|
||||
instructions: "Handle order refund requests.",
|
||||
description: "A customer support agent that handles order refund.",
|
||||
tools: [AIFunctionFactory.Create(AFProcessRefund)]);
|
||||
|
||||
// Create workflow with handoffs
|
||||
var handoffAgentWorkflow = AgentWorkflowBuilder.CreateHandoffBuilderWith(triageAgent)
|
||||
.WithHandoffs(triageAgent, [statusAgent, returnAgent, refundAgent])
|
||||
.WithHandoff(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related")
|
||||
.WithHandoff(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related")
|
||||
.WithHandoff(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related")
|
||||
.Build();
|
||||
|
||||
// Run the workflow
|
||||
List<ChatMessage> messages = [];
|
||||
foreach (var query in Queries)
|
||||
{
|
||||
Console.WriteLine($"User: {query}");
|
||||
messages.Add(new(ChatRole.User, query));
|
||||
|
||||
await using var run = await InProcessExecution.RunStreamingAsync(handoffAgentWorkflow, messages);
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text) && e.Update.Contents.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.ExecutorId != lastExecutorId)
|
||||
{
|
||||
lastExecutorId = e.ExecutorId;
|
||||
Console.WriteLine();
|
||||
Console.Write($"{e.Update.AuthorName}: ");
|
||||
}
|
||||
|
||||
Console.Write(e.Update.Text);
|
||||
|
||||
if (e.Update.Contents.OfType<Microsoft.Extensions.AI.FunctionCallContent>().FirstOrDefault()
|
||||
is Microsoft.Extensions.AI.FunctionCallContent call)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Calling function '{call.Name}' with arguments: {JsonSerializer.Serialize(call.Arguments)}");
|
||||
}
|
||||
}
|
||||
else if (evt is WorkflowOutputEvent output)
|
||||
{
|
||||
Console.WriteLine("\n");
|
||||
messages.AddRange(output.As<List<ChatMessage>>()!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endregion
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient);
|
||||
|
||||
var thread = new AzureAIAgentThread(azureAgentClient);
|
||||
|
||||
AzureAIAgentInvokeOptions options = new() { MaxPromptTokens = 1000 };
|
||||
var result = await agent.InvokeAsync(userInput, thread, options).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
AzureAIAgent skAgent = new(definition, azureAgentClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
// AF 1.0: Use AIProjectClient.AsAIAgent() from Microsoft.Agents.AI.Foundry
|
||||
var projectClient = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential());
|
||||
|
||||
var agent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, instructions: "You are a helpful assistant");
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient)
|
||||
{
|
||||
Kernel = Kernel.CreateBuilder().Build(),
|
||||
Name = "Host",
|
||||
Instructions = "You are a helpful assistant",
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
var thread = new AzureAIAgentThread(azureAgentClient);
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (ChatMessageContent update in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, instructions: "You are a helpful assistant");
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
AzureAIAgent skAgent = new(definition, azureAgentClient)
|
||||
{
|
||||
Kernel = Kernel.CreateBuilder().Build(),
|
||||
Name = "Host",
|
||||
Instructions = "You are a helpful assistant",
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(model: deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AzureAIAgent>((sp) =>
|
||||
{
|
||||
var azureAgentClient = sp.GetRequiredService<PersistentAgentsClient>();
|
||||
|
||||
Console.Write("Creating agent in the cloud...");
|
||||
|
||||
PersistentAgent definition = azureAgentClient.Administration
|
||||
.CreateAgent(deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
Console.Write("Done\n");
|
||||
|
||||
return new(definition, azureAgentClient);
|
||||
});
|
||||
serviceCollection.AddKernel();
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AzureAIAgent>();
|
||||
|
||||
var thread = new AzureAIAgentThread(agent.Client);
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (ChatMessageContent update in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await agent.Client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AzureAIAgent>((sp) =>
|
||||
{
|
||||
var azureAgentClient = sp.GetRequiredService<PersistentAgentsClient>();
|
||||
|
||||
Console.Write("Creating agent in the cloud...");
|
||||
|
||||
PersistentAgent definition = azureAgentClient.Administration
|
||||
.CreateAgent(deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
Console.Write("Done\n");
|
||||
|
||||
return new(definition, azureAgentClient);
|
||||
});
|
||||
serviceCollection.AddKernel();
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<AzureAIAgent>();
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var azureAgentClient = serviceProvider.GetRequiredService<PersistentAgentsClient>();
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AIAgent>((sp) =>
|
||||
{
|
||||
var client = sp.GetRequiredService<AIProjectClient>();
|
||||
return client.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]);
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient);
|
||||
var thread = new AzureAIAgentThread(azureAgentClient);
|
||||
|
||||
// SK Azure AI Agent provides the code interpreter content and the assistant message as different contents in the call iteration.
|
||||
await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(content.Message.Content))
|
||||
{
|
||||
bool isCode = content.Message.Metadata?.ContainsKey(AzureAIAgent.CodeInterpreterMetadataKey) ?? false;
|
||||
Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var item in content.Message.Items)
|
||||
{
|
||||
// Process each item in the message
|
||||
if (item is AnnotationContent annotation)
|
||||
{
|
||||
if (annotation.Kind != AnnotationKind.UrlCitation)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
|
||||
}
|
||||
}
|
||||
else if (item is FileReferenceContent fileReference)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]);
|
||||
|
||||
AzureAIAgent skAgent = new(definition, azureAgentClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
// To capture the code interpreter input we need to break glass all the updates raw representations, to check for the RunStepDetailsUpdate type and
|
||||
// get the CodeInterpreterInput property which contains the generated code.
|
||||
// Note: Similar logic would needed for each individual update if used in the agent.RunStreamingAsync streaming API to aggregate or yield the generated code.
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Update the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
// Note: Code interpreter via hosted APIs requires versioned Foundry Agents.
|
||||
// This sample creates a basic agent without code interpreter capabilities.
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(deploymentName, instructions: "You are a helpful assistant with code execution capabilities.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
};
|
||||
|
||||
var thread = new ChatHistoryAgentThread();
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new AgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
}.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
ChatCompletionAgent agent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent agent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var afAgent = agent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var result = await afAgent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<ChatCompletionAgent>();
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
}.AsAIAgent());
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Functions\Functions.OpenApi\Functions.OpenApi.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="OpenAPISpec.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
{
|
||||
"openapi": "3.0.1",
|
||||
"info": {
|
||||
"title": "Github Versions API",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://api.github.com"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"basic-error": {
|
||||
"title": "Basic Error",
|
||||
"description": "Basic Error",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"documentation_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"title": "Label",
|
||||
"description": "Color-coded labels help you categorize and filter your issues (just like labels in Gmail).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique identifier for the label.",
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"example": 208045946
|
||||
},
|
||||
"node_id": {
|
||||
"type": "string",
|
||||
"example": "MDU6TGFiZWwyMDgwNDU5NDY="
|
||||
},
|
||||
"url": {
|
||||
"description": "URL for the label",
|
||||
"example": "https://api.github.com/repositories/42/labels/bug",
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the label.",
|
||||
"example": "bug",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Optional description of the label, such as its purpose.",
|
||||
"type": "string",
|
||||
"example": "Something isn't working",
|
||||
"nullable": true
|
||||
},
|
||||
"color": {
|
||||
"description": "6-character hex code, without the leading #, identifying the color",
|
||||
"example": "FFFFFF",
|
||||
"type": "string"
|
||||
},
|
||||
"default": {
|
||||
"description": "Whether this label comes by default in a new repository.",
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"node_id",
|
||||
"url",
|
||||
"name",
|
||||
"description",
|
||||
"color",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"title": "Tag",
|
||||
"description": "Tag",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "v0.1"
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sha": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"sha",
|
||||
"url"
|
||||
]
|
||||
},
|
||||
"zipball_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"example": "https://github.com/octocat/Hello-World/zipball/v0.1"
|
||||
},
|
||||
"tarball_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"example": "https://github.com/octocat/Hello-World/tarball/v0.1"
|
||||
},
|
||||
"node_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"node_id",
|
||||
"commit",
|
||||
"zipball_url",
|
||||
"tarball_url"
|
||||
]
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"label-items": {
|
||||
"value": [
|
||||
{
|
||||
"id": 208045946,
|
||||
"node_id": "MDU6TGFiZWwyMDgwNDU5NDY=",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
|
||||
"name": "bug",
|
||||
"description": "Something isn't working",
|
||||
"color": "f29513",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": 208045947,
|
||||
"node_id": "MDU6TGFiZWwyMDgwNDU5NDc=",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/labels/enhancement",
|
||||
"name": "enhancement",
|
||||
"description": "New feature or request",
|
||||
"color": "a2eeef",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"tag-items": {
|
||||
"value": [
|
||||
{
|
||||
"name": "v0.1",
|
||||
"commit": {
|
||||
"sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc"
|
||||
},
|
||||
"zipball_url": "https://github.com/octocat/Hello-World/zipball/v0.1",
|
||||
"tarball_url": "https://github.com/octocat/Hello-World/tarball/v0.1",
|
||||
"node_id": "MDQ6VXNlcjE="
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"owner": {
|
||||
"name": "owner",
|
||||
"description": "The account owner of the repository. The name is not case sensitive.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"repo": {
|
||||
"name": "repo",
|
||||
"description": "The name of the repository without the `.git` extension. The name is not case sensitive.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"per-page": {
|
||||
"name": "per_page",
|
||||
"description": "The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 30
|
||||
}
|
||||
},
|
||||
"page": {
|
||||
"name": "page",
|
||||
"description": "The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"not_found": {
|
||||
"description": "Resource not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/basic-error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"link": {
|
||||
"example": "<https://api.github.com/resource?page=2>; rel=\"next\", <https://api.github.com/resource?page=5>; rel=\"last\"",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/repos/{owner}/{repo}/tags": {
|
||||
"get": {
|
||||
"summary": "List repository tags",
|
||||
"description": "",
|
||||
"tags": [
|
||||
"repos"
|
||||
],
|
||||
"operationId": "repos/list-tags",
|
||||
"externalDocs": {
|
||||
"description": "API method documentation",
|
||||
"url": "https://docs.github.com/rest/repos/repos#list-repository-tags"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/owner"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/repo"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/per-page"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/page"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/tag"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"default": {
|
||||
"$ref": "#/components/examples/tag-items"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Link": {
|
||||
"$ref": "#/components/headers/link"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-github": {
|
||||
"githubCloudOnly": false,
|
||||
"enabledForGitHubApps": true,
|
||||
"category": "repos",
|
||||
"subcategory": "repos"
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/labels": {
|
||||
"get": {
|
||||
"summary": "List labels for a repository",
|
||||
"description": "Lists all labels for a repository.",
|
||||
"tags": [
|
||||
"issues"
|
||||
],
|
||||
"operationId": "issues/list-labels-for-repo",
|
||||
"externalDocs": {
|
||||
"description": "API method documentation",
|
||||
"url": "https://docs.github.com/rest/issues/labels#list-labels-for-a-repository"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/owner"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/repo"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/per-page"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/page"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/label"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"default": {
|
||||
"$ref": "#/components/examples/label-items"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Link": {
|
||||
"$ref": "#/components/headers/link"
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/not_found"
|
||||
}
|
||||
},
|
||||
"x-github": {
|
||||
"githubCloudOnly": false,
|
||||
"enabledForGitHubApps": true,
|
||||
"category": "issues",
|
||||
"subcategory": "labels"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use an Agent with function tools provided via an OpenAPI spec with both Semantic Kernel and Agent Framework.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Plugins.OpenApi;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
await SKAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
// Create a kernel with an Azure OpenAI chat client.
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
|
||||
// Load the OpenAPI Spec from a file.
|
||||
var plugin = await kernel.ImportPluginFromOpenApiAsync("github", "OpenAPISpec.json");
|
||||
|
||||
// Create the agent, and provide the kernel with the OpenAPI function tools to the agent.
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = "You are a helpful assistant",
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Run the agent with the OpenAPI function tools.
|
||||
await foreach (var result in agent.InvokeAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github."))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
// Load the OpenAPI Spec from a file.
|
||||
KernelPlugin plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync("github", "OpenAPISpec.json");
|
||||
|
||||
// Convert the Semantic Kernel plugin to Agent Framework function tools.
|
||||
// This requires a dummy Kernel instance, since KernelFunctions cannot execute without one.
|
||||
Kernel kernel = new();
|
||||
List<AITool> tools = plugin.Select(x => x.WithKernel(kernel)).Cast<AITool>().ToList();
|
||||
|
||||
// Create the chat client and agent, and provide the OpenAPI function tools to the agent.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: tools);
|
||||
|
||||
// Run the agent with the OpenAPI function tools.
|
||||
Console.WriteLine(await agent.RunAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github."));
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions() { ResponseCreationOptions = new() { MaxOutputTokenCount = 1000 } };
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "o4-mini";
|
||||
var userInput =
|
||||
"""
|
||||
Instructions:
|
||||
- Given the React component below, think about it and change it so that nonfiction books have red
|
||||
text.
|
||||
- Return only the code in your reply
|
||||
- Do not include any additional formatting, such as markdown code blocks
|
||||
- For formatting, use four space tabs, and do not allow any lines of code to
|
||||
exceed 80 columns
|
||||
const books = [
|
||||
{ title: 'Dune', category: 'fiction', id: 1 },
|
||||
{ title: 'Frankenstein', category: 'fiction', id: 2 },
|
||||
{ title: 'Moneyball', category: 'nonfiction', id: 3 },
|
||||
];
|
||||
export default function BookList() {
|
||||
const listItems = books.map(book =>
|
||||
<li>
|
||||
{book.title}
|
||||
</li>
|
||||
);
|
||||
return (
|
||||
<ul>{listItems}</ul>
|
||||
);
|
||||
}
|
||||
""";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are good at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions()
|
||||
{
|
||||
ResponseCreationOptions = new()
|
||||
{
|
||||
MaxOutputTokenCount = 8000,
|
||||
ReasoningOptions = new()
|
||||
{
|
||||
ReasoningEffortLevel = OpenAI.Responses.ResponseReasoningEffortLevel.High,
|
||||
ReasoningSummaryVerbosity = OpenAI.Responses.ResponseReasoningSummaryVerbosity.Detailed
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
if (content is ReasoningContent thinking)
|
||||
{
|
||||
Console.Write($"Thinking: \n{thinking}\n---\n");
|
||||
}
|
||||
else if (content is Microsoft.SemanticKernel.TextContent text)
|
||||
{
|
||||
Console.Write($"Assistant: {text}");
|
||||
}
|
||||
}
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
var userMessage = new ChatMessageContent(AuthorRole.User, userInput);
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userMessage, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
// Currently SK Agent doesn't output thinking in streaming mode.
|
||||
// SK Issue: https://github.com/microsoft/semantic-kernel/issues/13046
|
||||
// OpenAI SDK Issue: https://github.com/openai/openai-dotnet/issues/643
|
||||
if (content is StreamingReasoningContent thinking)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{thinking}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (content is StreamingTextContent text)
|
||||
{
|
||||
Console.WriteLine($"Response: [{text}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are good at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Thinker", instructions: "You are good at thinking hard before answering.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
OpenAIResponseAgent agent = new(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{ StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
await foreach (ChatMessageContent responseItem in agent.InvokeAsync(userInput))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(responseItem.Content))
|
||||
{
|
||||
Console.WriteLine(responseItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
OpenAIResponseAgent skAgent = new(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{ StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var agent = (skAgent as OpenAIResponseAgent)!.AsAIAgent();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
// Example of Semantic Kernel Agent code
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
};
|
||||
|
||||
var thread = new ChatHistoryAgentThread();
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new AgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
}.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of a fully migrated Agent Framework Agent code
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
ChatCompletionAgent agent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
await foreach (var item in agent.InvokeAsync(userInput))
|
||||
{
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
ChatCompletionAgent skAgent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
var agent = skAgent.AsAIAgent();
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n---\n");
|
||||
await foreach (var item in skAgent.InvokeAsync(userInput))
|
||||
{
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model).AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<ChatCompletionAgent>();
|
||||
|
||||
await foreach (var item in agent.InvokeAsync(userInput))
|
||||
{
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
}.AsAIAgent());
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new OpenAIClient(apiKey)
|
||||
.GetChatClient(model)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions() { ResponseCreationOptions = new() { MaxOutputTokenCount = 1000 } };
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(item.Message);
|
||||
thread = item.Thread;
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
// Thread need to be updated for subsequent calls
|
||||
thread = item.Thread;
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "o4-mini";
|
||||
var userInput =
|
||||
"""
|
||||
Instructions:
|
||||
- Given the React component below, think about it and change it so that nonfiction books have red
|
||||
text.
|
||||
- Return only the code in your reply
|
||||
- Do not include any additional formatting, such as markdown code blocks
|
||||
- For formatting, use four space tabs, and do not allow any lines of code to
|
||||
exceed 80 columns
|
||||
const books = [
|
||||
{ title: 'Dune', category: 'fiction', id: 1 },
|
||||
{ title: 'Frankenstein', category: 'fiction', id: 2 },
|
||||
{ title: 'Moneyball', category: 'nonfiction', id: 3 },
|
||||
];
|
||||
export default function BookList() {
|
||||
const listItems = books.map(book =>
|
||||
<li>
|
||||
{book.title}
|
||||
</li>
|
||||
);
|
||||
return (
|
||||
<ul>{listItems}</ul>
|
||||
);
|
||||
}
|
||||
""";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are good at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions()
|
||||
{
|
||||
ResponseCreationOptions = new()
|
||||
{
|
||||
MaxOutputTokenCount = 8000,
|
||||
ReasoningOptions = new()
|
||||
{
|
||||
ReasoningEffortLevel = OpenAI.Responses.ResponseReasoningEffortLevel.High,
|
||||
ReasoningSummaryVerbosity = OpenAI.Responses.ResponseReasoningSummaryVerbosity.Detailed
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
if (content is ReasoningContent thinking)
|
||||
{
|
||||
Console.Write($"Thinking: \n{thinking}\n---\n");
|
||||
}
|
||||
else if (content is Microsoft.SemanticKernel.TextContent text)
|
||||
{
|
||||
Console.Write($"Assistant: {text}");
|
||||
}
|
||||
}
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
var userMessage = new ChatMessageContent(AuthorRole.User, userInput);
|
||||
thread = null;
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userMessage, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
// Currently SK Agent doesn't output thinking in streaming mode.
|
||||
// SK Issue: https://github.com/microsoft/semantic-kernel/issues/13046
|
||||
// OpenAI SDK Issue: https://github.com/openai/openai-dotnet/issues/643
|
||||
if (content is StreamingReasoningContent thinking)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{thinking}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (content is StreamingTextContent text)
|
||||
{
|
||||
Console.WriteLine($"Response: [{text}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Thinker", instructions: "You are at thinking hard before answering.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
OpenAIResponseAgent agent = new(new OpenAIClient(apiKey).GetResponsesClient(), model) { StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
await foreach (ChatMessageContent responseItem in agent.InvokeAsync(userInput))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(responseItem.Content))
|
||||
{
|
||||
Console.WriteLine(responseItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
OpenAIResponseAgent skAgent = new(new OpenAIClient(apiKey).GetResponsesClient(), model) { StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsAIAgent(
|
||||
model: model,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#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 SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new OpenAIClient(apiKey).GetResponsesClient(), model)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new OpenAIClient(apiKey).GetResponsesClient(), model)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var agent = (skAgent as OpenAIResponseAgent)!.AsAIAgent();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient((sp) => new OpenAIClient(apiKey)
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Semantic Kernel Migration Playground
|
||||
|
||||
This is a playground folder with different **Semantic Kernel** projects that can be used to test automatic AI migration to the new **Agent Framework (AF)**.
|
||||
|
||||
## Prompting
|
||||
|
||||
Open your IDE Agentic extension and create a new chat providing the following prompt:
|
||||
|
||||
```
|
||||
I need to convert code from Semantic Kernel to the Agent Framework.
|
||||
Please use the migration guide provided in the #SemanticKernelToAgentFramework.md as a reference.
|
||||
|
||||
The current solution is using central package manager, when referencing the projects in the csproj don't provide the versions.
|
||||
|
||||
Check external references provided by the migration guide if needed.
|
||||
|
||||
You don't need to look for the Central Package Management file, just focus on the project file and the code files.
|
||||
|
||||
When you need help or don't know how to proceed, please ask.
|
||||
```
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.Identity;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var client = new PersistentAgentsClient(Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT"), new AzureCliCredential());
|
||||
|
||||
// Define the agent
|
||||
PersistentAgent definition = await client.Administration.CreateAgentAsync(
|
||||
Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME"),
|
||||
instructions: "You are a coding assistant that always generates code using the code interpreter tool.",
|
||||
tools: [new CodeInterpreterToolDefinition()]);
|
||||
|
||||
AzureAIAgent agent = new(definition, client);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
AgentThread thread = new AzureAIAgentThread(client);
|
||||
|
||||
try
|
||||
{
|
||||
await InvokeAgentAsync("Create a python file where it determines the values in the Fibonacci sequence that that are less then the value of 101.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await thread.DeleteAsync();
|
||||
await client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
WriteAgentChatMessage(message);
|
||||
|
||||
await foreach (ChatMessageContent response in agent.InvokeAsync(message, thread))
|
||||
{
|
||||
WriteAgentChatMessage(response);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteAgentChatMessage(ChatMessageContent message)
|
||||
{
|
||||
// Include ChatMessageContent.AuthorName in output, if present.
|
||||
string authorExpression = message.Role == AuthorRole.User ? string.Empty : FormatAuthor();
|
||||
// Include TextContent (via ChatMessageContent.Content), if present.
|
||||
string contentExpression = string.IsNullOrWhiteSpace(message.Content) ? string.Empty : message.Content;
|
||||
bool isCode = message.Metadata?.ContainsKey(AzureAIAgent.CodeInterpreterMetadataKey) ?? false;
|
||||
string codeMarker = isCode ? "\n [CODE]\n" : " ";
|
||||
Console.WriteLine($"\n# {message.Role}{authorExpression}:{codeMarker}{contentExpression}");
|
||||
|
||||
// Provide visibility for inner content (that isn't TextContent).
|
||||
foreach (KernelContent item in message.Items)
|
||||
{
|
||||
if (item is AnnotationContent annotation)
|
||||
{
|
||||
if (annotation.Kind == AnnotationKind.UrlCitation)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: {annotation.ReferenceId} - {annotation.Title}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
|
||||
}
|
||||
}
|
||||
else if (item is ActionContent action)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {action.Text}");
|
||||
}
|
||||
else if (item is ReasoningContent reasoning)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {reasoning.Text ?? "Thinking..."}");
|
||||
}
|
||||
else if (item is FileReferenceContent fileReference)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
|
||||
}
|
||||
}
|
||||
|
||||
if ((message.Metadata?.TryGetValue("Usage", out object? usage) ?? false) && usage is RunStepCompletionUsage agentUsage)
|
||||
{
|
||||
Console.WriteLine($" [Usage] Tokens: {agentUsage.TotalTokens}, Input: {agentUsage.PromptTokens}, Output: {agentUsage.CompletionTokens}");
|
||||
}
|
||||
|
||||
string FormatAuthor() => message.AuthorName is not null ? $" - {message.AuthorName ?? " * "}" : string.Empty;
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents.Persistent" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="../../../../../.github/upgrades/prompts/*" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,405 @@
|
||||
# Semantic Kernel to Agent Framework Migration Guide
|
||||
|
||||
## What's Changed?
|
||||
- **Namespace Updates**: From `Microsoft.SemanticKernel.Agents` to `Microsoft.Agents.AI`
|
||||
- **Agent Creation**: Single fluent API calls vs multi-step builder patterns
|
||||
- **Thread Management**: Built-in thread management vs manual thread creation
|
||||
- **Tool Registration**: Direct function registration vs plugin wrapper systems
|
||||
- **Dependency Injection**: Simplified service registration patterns
|
||||
- **Invocation Patterns**: Streamlined options and result handling
|
||||
|
||||
## Benefits of Migration
|
||||
- **Simplified API**: Reduced complexity and boilerplate code
|
||||
- **Better Performance**: Optimized object creation and memory usage
|
||||
- **Unified Interface**: Consistent patterns across different AI providers
|
||||
- **Enhanced Developer Experience**: More intuitive and discoverable APIs
|
||||
|
||||
## Key Changes
|
||||
|
||||
### 1. Namespace Updates
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
```csharp
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
Agent Framework namespaces are under `Microsoft.Agents.AI`.
|
||||
Agent Framework uses the core AI message and content types from `Microsoft.Extensions.AI` for communication between components.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Agents.AI;
|
||||
```
|
||||
|
||||
### 2. Agent Creation Simplification
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
Every agent in Semantic Kernel depends on a `Kernel` instance and will have
|
||||
an empty `Kernel` if not provided.
|
||||
|
||||
```csharp
|
||||
Kernel kernel = Kernel
|
||||
.AddOpenAIChatClient(modelId, apiKey)
|
||||
.Build();
|
||||
|
||||
ChatCompletionAgent agent = new() { Instructions = ParrotInstructions, Kernel = kernel };
|
||||
```
|
||||
|
||||
Azure AI Foundry requires an agent resource to be created in the cloud before creating a local agent class that uses it.
|
||||
|
||||
```csharp
|
||||
PersistentAgentsClient azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(
|
||||
deploymentName,
|
||||
instructions: ParrotInstructions);
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient);
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
Agent creation in Agent Framework is made simpler with extensions provided by all main providers.
|
||||
|
||||
```csharp
|
||||
AIAgent openAIAgent = chatClient.CreateAIAgent(instructions: ParrotInstructions);
|
||||
AIAgent azureFoundryAgent = await persistentAgentsClient.CreateAIAgentAsync(instructions: ParrotInstructions);
|
||||
AIAgent openAIAssistantAgent = await assistantClient.CreateAIAgentAsync(instructions: ParrotInstructions);
|
||||
```
|
||||
|
||||
Additionally for hosted agent providers you can also use the `GetAIAgent` to retrieve an agent from an existing hosted agent.
|
||||
|
||||
```csharp
|
||||
AIAgent azureFoundryAgent = await persistentAgentsClient.GetAIAgentAsync(agentId);
|
||||
```
|
||||
|
||||
### 3. Agent Thread Creation
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
The caller has to know the thread type and create it manually.
|
||||
|
||||
```csharp
|
||||
// Create a thread for the agent conversation.
|
||||
AgentThread thread = new OpenAIAssistantAgentThread(this.AssistantClient);
|
||||
AgentThread thread = new AzureAIAgentThread(this.Client);
|
||||
AgentThread thread = new OpenAIResponseAgentThread(this.Client);
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The agent is responsible for creating the thread.
|
||||
|
||||
```csharp
|
||||
// New
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
```
|
||||
|
||||
### 4. Hosted Agent Thread Cleanup
|
||||
|
||||
This case applies exclusively to a few AI providers that still provide hosted threads.
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
Threads have a `self` deletion method
|
||||
|
||||
i.e: OpenAI Assistants Provider
|
||||
```csharp
|
||||
await thread.DeleteAsync();
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
> [!NOTE]
|
||||
> OpenAI Responses introduced a new conversation model that simplifies how conversations are handled. This simplifies hosted thread management compared to the now deprecated OpenAI Assistants model. For more information see the [OpenAI Assistants migration guide](https://platform.openai.com/docs/assistants/migration).
|
||||
|
||||
Agent Framework doesn't have a thread deletion API in the `AgentThread` type as not all providers support hosted threads or thread deletion and this will become more common as more providers shift to responses based architectures.
|
||||
|
||||
If you require thread deletion and the provider allows this, the caller **should** keep track of the created threads and delete them later when necessary via the provider's sdk.
|
||||
|
||||
i.e: OpenAI Assistants Provider
|
||||
```csharp
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
```
|
||||
|
||||
### 5. Tool Registration
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
In semantic kernel to expose a function as a tool you must:
|
||||
|
||||
1. Decorate the function with a `[KernelFunction]` attribute.
|
||||
2. Have a `Plugin` class or use the `KernelPluginFactory` to wrap the function.
|
||||
3. Have a `Kernel` to add your plugin to.
|
||||
4. Pass the `Kernel` to the agent.
|
||||
|
||||
```csharp
|
||||
KernelFunction function = KernelFunctionFactory.CreateFromMethod(GetWeather);
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromFunctions("KernelPluginName", [function]);
|
||||
Kernel kernel = ... // Create kernel
|
||||
kernel.Plugins.Add(plugin);
|
||||
|
||||
ChatCompletionAgent agent = new() { Kernel = kernel, ... };
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
In agent framework in a single call you can register tools directly in the agent creation process.
|
||||
|
||||
```csharp
|
||||
AIAgent agent = chatClient.CreateAIAgent(tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
```
|
||||
|
||||
### 6. Agent Non-Streaming Invocation
|
||||
|
||||
Key differences can be seen in the method names from `Invoke` to `Run`, return types and parameters `AgentRunOptions`.
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
The Non-Streaming uses a streaming pattern `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` for returning multiple agent messages.
|
||||
|
||||
```csharp
|
||||
await foreach (AgentResponseItem<ChatMessageContent> result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The Non-Streaming returns a single `AgentRunResponse` with the agent response that can contain multiple messages.
|
||||
The text result of the run is available in `AgentRunResponse.Text` or `AgentRunResponse.ToString()`.
|
||||
All messages created as part of the response is returned in the `AgentRunResponse.Messages` list.
|
||||
This may include tool call messages, function results, reasoning updates and final results.
|
||||
|
||||
```csharp
|
||||
AgentRunResponse agentResponse = await agent.RunAsync(userInput, thread);
|
||||
```
|
||||
|
||||
### 7. Agent Streaming Invocation
|
||||
|
||||
Key differences in the method names from `Invoke` to `Run`, return types and parameters `AgentRunOptions`.
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
```csharp
|
||||
await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
Similar streaming API pattern with the key difference being that it returns `AgentRunResponseUpdate` objects including more agent related information per update.
|
||||
|
||||
All updates produced by any service underlying the AIAgent is returned. The textual result of the agent is available by concatenating the `AgentRunResponse.Text` values.
|
||||
|
||||
```csharp
|
||||
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update); // Update is ToString() friendly
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Tool Function Signatures
|
||||
|
||||
**Problem**: SK plugin methods need `[KernelFunction]` attributes
|
||||
|
||||
```csharp
|
||||
public class MenuPlugin
|
||||
{
|
||||
[KernelFunction] // Required for SK
|
||||
public static MenuItem[] GetMenu() => ...;
|
||||
}
|
||||
```
|
||||
|
||||
**Solution**: AF can use methods directly without attributes
|
||||
|
||||
```csharp
|
||||
public class MenuTools
|
||||
{
|
||||
[Description("Get menu items")] // Optional description
|
||||
public static MenuItem[] GetMenu() => ...;
|
||||
}
|
||||
```
|
||||
|
||||
### 9. Options Configuration
|
||||
|
||||
**Problem**: Complex options setup in SK
|
||||
|
||||
```csharp
|
||||
OpenAIPromptExecutionSettings settings = new() { MaxTokens = 1000 };
|
||||
AgentInvokeOptions options = new() { KernelArguments = new(settings) };
|
||||
```
|
||||
|
||||
**Solution**: Simplified options in AF
|
||||
|
||||
```csharp
|
||||
ChatClientAgentRunOptions options = new(new() { MaxOutputTokens = 1000 });
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This example shows passing implementation specific options to a `ChatClientAgent`. Not all `AIAgents` support `ChatClientAgentRunOptions`.
|
||||
> `ChatClientAgent` is provided to build agents based on underlying inference services, and therefore supports inference options like `MaxOutputTokens`.
|
||||
|
||||
### 10. Dependency Injection
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
A `Kernel` registration is required in the service container to be able to create an agent
|
||||
as every agent abstractions needs to be initialized with a `Kernel` property.
|
||||
|
||||
Semantic Kernel uses the `Agent` type as the base abstraction class for agents.
|
||||
|
||||
```csharp
|
||||
services.AddKernel().AddProvider(...);
|
||||
serviceContainer.AddKeyedSingleton<SemanticKernel.Agents.Agent>(
|
||||
TutorName,
|
||||
(sp, key) =>
|
||||
new ChatCompletionAgent()
|
||||
{
|
||||
// Passing the kernel is required
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
});
|
||||
```
|
||||
|
||||
### 11. **Agent Type Consolidation**
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
Semantic kernel provides specific agent classes for various services, e.g.
|
||||
|
||||
- `ChatCompletionAgent` for use with chat-completion-based inference services.
|
||||
- `OpenAIAssistantAgent` for use with the OpenAI Assistants service.
|
||||
- `AzureAIAgent` for use with the Azure AI Foundry Agents service.
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The agent framework supports all the abovementioned services via a single agent type, `ChatClientAgent`.
|
||||
|
||||
`ChatClientAgent` can be used to build agents using any underlying service that provides an SDK implementing the `Microsoft.Extensions.AI.IChatClient` interface.
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The Agent framework provides the `AIAgent` type as the base abstraction class.
|
||||
|
||||
```csharp
|
||||
services.AddKeyedSingleton<AIAgent>(() => client.CreateAIAgent(...));
|
||||
```
|
||||
|
||||
## Migration Samples
|
||||
|
||||
This folder contains **separate console application projects** demonstrating how to transition from **Semantic Kernel (SK)** to the new **Agent Framework (AF)**.
|
||||
|
||||
Each project shows side-by-side comparisons of equivalent functionality in both frameworks and can be run independently.
|
||||
|
||||
Each sample code contains the following:
|
||||
1. **SK Agent** (Semantic Kernel before)
|
||||
2. **AF Agent** (Agent Framework after)
|
||||
|
||||
### Running the samples from Visual Studio
|
||||
|
||||
Open the solution in Visual Studio and set the desired sample project as the startup project. Then, run the project using the built-in debugger or by pressing `F5`.
|
||||
|
||||
You will be prompted for any required environment variables if they are not already set.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following:
|
||||
|
||||
- [.NET 10.0 SDK or later](https://dotnet.microsoft.com/download)
|
||||
- For Azure AI Foundry samples: Azure OpenAI service endpoint and deployment configured
|
||||
- For OpenAI samples: OpenAI API key
|
||||
- For OpenAI Assistants samples: OpenAI API key with Assistant API access
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Set the appropriate environment variables based on the sample type you want to run:
|
||||
|
||||
**For Azure AI Foundry projects:**
|
||||
```powershell
|
||||
$env:AZURE_FOUNDRY_PROJECT_ENDPOINT = "https://<your-project>-resource.services.ai.azure.com/api/projects/<your-project>"
|
||||
```
|
||||
|
||||
**For OpenAI and OpenAI Assistants projects:**
|
||||
```powershell
|
||||
$env:OPENAI_API_KEY = "sk-..."
|
||||
```
|
||||
|
||||
**For Azure OpenAI and Azure OpenAI Assistants projects:**
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT = "https://<your-project>.cognitiveservices.azure.com/"
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME = "gpt-4o" # Optional, defaults to gpt-4o
|
||||
```
|
||||
|
||||
**Optional debug mode:**
|
||||
```powershell
|
||||
$env:AF_SHOW_ALL_DEMO_SETTING_VALUES = "Y"
|
||||
```
|
||||
|
||||
If environment variables are not set, the demos will prompt you to enter values interactively.
|
||||
|
||||
### Samples
|
||||
|
||||
The migration samples are organized into different categories, each demonstrating different AI service integrations and orchestration patterns:
|
||||
|
||||
|Category|Description|
|
||||
|---|---|
|
||||
|[AzureAIFoundry](./AzureAIFoundry/)|Azure OpenAI service integration samples|
|
||||
|[AzureOpenAI](./AzureOpenAI/)|Direct Azure OpenAI API integration samples|
|
||||
|[AzureOpenAIAssistants](./AzureOpenAIAssistants/)|Azure OpenAI Assistants API integration samples|
|
||||
|[AzureOpenAIResponses](./AzureOpenAIResponses/)|Azure OpenAI Responses API integration samples|
|
||||
|[OpenAI](./OpenAI/)|Direct OpenAI API integration samples|
|
||||
|[OpenAIAssistants](./OpenAIAssistants/)|OpenAI Assistants API integration samples|
|
||||
|[OpenAIResponses](./OpenAIResponses/)|OpenAI Responses API integration samples|
|
||||
|[AgentOrchestrations](./AgentOrchestrations/)|Agent orchestration patterns including concurrent, sequential, and handoff workflows|
|
||||
|
||||
## Running the samples from the console
|
||||
|
||||
To run any migration sample, navigate to the desired sample directory:
|
||||
|
||||
```powershell
|
||||
# Azure AI Foundry Examples
|
||||
cd "AzureAIFoundry\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Azure OpenAI Examples
|
||||
cd "AzureOpenAI\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Azure OpenAI Assistants Examples
|
||||
cd "AzureOpenAIAssistants\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Azure OpenAI Responses Examples
|
||||
cd "AzureOpenAIResponses\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# OpenAI Examples
|
||||
cd "OpenAI\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# OpenAI Assistants Examples
|
||||
cd "OpenAIAssistants\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# OpenAI Responses Examples
|
||||
cd "OpenAIResponses\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Agent Orchestrations Examples
|
||||
cd "AgentOrchestrations\Step01_Concurrent"
|
||||
dotnet run
|
||||
|
||||
cd "AgentOrchestrations\Step02_Sequential"
|
||||
dotnet run
|
||||
|
||||
cd "AgentOrchestrations\Step03_Handoff"
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Resources;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate using code-interpreter to manipulate and generate csv files with <see cref="AzureAIAgent"/> .
|
||||
/// </summary>
|
||||
public class AzureAIAgent_FileManipulation(ITestOutputHelper output) : BaseAzureAgentTest(output)
|
||||
{
|
||||
[Fact]
|
||||
public async Task AnalyzeCSVFileUsingAzureAIAgentAsync()
|
||||
{
|
||||
await using Stream stream = EmbeddedResource.ReadStream("sales.csv")!;
|
||||
PersistentAgentFileInfo fileInfo = await this.Client.Files.UploadFileAsync(stream, PersistentAgentFilePurpose.Agents, "sales.csv");
|
||||
|
||||
// Define the agent
|
||||
PersistentAgent definition = await this.Client.Administration.CreateAgentAsync(
|
||||
TestConfiguration.AzureAI.ChatModelId,
|
||||
tools: [new CodeInterpreterToolDefinition()],
|
||||
toolResources:
|
||||
new()
|
||||
{
|
||||
CodeInterpreter = new()
|
||||
{
|
||||
FileIds = { fileInfo.Id },
|
||||
}
|
||||
});
|
||||
AzureAIAgent agent = new(definition, this.Client);
|
||||
AzureAIAgentThread thread = new(this.Client);
|
||||
|
||||
// Respond to user input
|
||||
try
|
||||
{
|
||||
await InvokeAgentAsync("Which segment had the most sales?");
|
||||
await InvokeAgentAsync("List the top 5 countries that generated the most profit.");
|
||||
await InvokeAgentAsync("Create a tab delimited file report of profit by each country per month.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await thread.DeleteAsync();
|
||||
await this.Client.Administration.DeleteAgentAsync(agent.Id);
|
||||
await this.Client.Files.DeleteFileAsync(fileInfo.Id);
|
||||
}
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
await foreach (ChatMessageContent response in agent.InvokeAsync(message, thread))
|
||||
{
|
||||
this.WriteAgentChatMessage(response);
|
||||
await this.DownloadContentAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate consuming "streaming" message for <see cref="AzureAIAgent"/>.
|
||||
/// </summary>
|
||||
public class AzureAIAgent_Streaming(ITestOutputHelper output) : BaseAzureAgentTest(output)
|
||||
{
|
||||
[Fact]
|
||||
public async Task UseStreamingAgentAsync()
|
||||
{
|
||||
const string AgentName = "Parrot";
|
||||
const string AgentInstructions = "Repeat the user message in the voice of a pirate and then end with a parrot sound.";
|
||||
|
||||
// Define the agent
|
||||
PersistentAgent definition = await this.Client.Administration.CreateAgentAsync(
|
||||
TestConfiguration.AzureAI.ChatModelId,
|
||||
AgentName,
|
||||
null,
|
||||
AgentInstructions);
|
||||
AzureAIAgent agent = new(definition, this.Client);
|
||||
|
||||
try
|
||||
{
|
||||
// Create a thread for the agent conversation.
|
||||
AzureAIAgentThread agentThread = new(this.Client, metadata: SampleMetadata);
|
||||
|
||||
// Respond to user input
|
||||
await InvokeAgentAsync(agent, agentThread, "Fortune favors the bold.");
|
||||
await InvokeAgentAsync(agent, agentThread, "I came, I saw, I conquered.");
|
||||
await InvokeAgentAsync(agent, agentThread, "Practice makes perfect.");
|
||||
|
||||
// Output the entire chat history
|
||||
await DisplayChatHistoryAsync(agentThread);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await this.Client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UseStreamingAssistantAgentWithPluginAsync()
|
||||
{
|
||||
const string AgentName = "Host";
|
||||
const string AgentInstructions = "Answer questions about the menu.";
|
||||
|
||||
// Define the agent
|
||||
PersistentAgent definition = await this.Client.Administration.CreateAgentAsync(
|
||||
TestConfiguration.AzureAI.ChatModelId,
|
||||
AgentName,
|
||||
null,
|
||||
AgentInstructions);
|
||||
AzureAIAgent agent = new(definition, this.Client);
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
|
||||
agent.Kernel.Plugins.Add(plugin);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
AzureAIAgentThread agentThread = new(this.Client, metadata: SampleMetadata);
|
||||
|
||||
try
|
||||
{
|
||||
// Respond to user input
|
||||
await InvokeAgentAsync(agent, agentThread, "What is the special soup and its price?");
|
||||
await InvokeAgentAsync(agent, agentThread, "What is the special drink and its price?");
|
||||
|
||||
// Output the entire chat history
|
||||
await DisplayChatHistoryAsync(agentThread);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await this.Client.Threads.DeleteThreadAsync(agentThread.Id);
|
||||
await this.Client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UseStreamingAssistantWithCodeInterpreterAsync()
|
||||
{
|
||||
const string AgentName = "MathGuy";
|
||||
const string AgentInstructions = "Solve math problems with code.";
|
||||
|
||||
// Define the agent
|
||||
PersistentAgent definition = await this.Client.Administration.CreateAgentAsync(
|
||||
TestConfiguration.AzureAI.ChatModelId,
|
||||
AgentName,
|
||||
null,
|
||||
AgentInstructions,
|
||||
[new CodeInterpreterToolDefinition()]);
|
||||
AzureAIAgent agent = new(definition, this.Client);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
AzureAIAgentThread agentThread = new(this.Client, metadata: SampleMetadata);
|
||||
|
||||
try
|
||||
{
|
||||
// Respond to user input
|
||||
await InvokeAgentAsync(agent, agentThread, "Is 191 a prime number?");
|
||||
await InvokeAgentAsync(agent, agentThread, "Determine the values in the Fibonacci sequence that that are less then the value of 101");
|
||||
|
||||
// Output the entire chat history
|
||||
await DisplayChatHistoryAsync(agentThread);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await this.Client.Threads.DeleteThreadAsync(agentThread.Id);
|
||||
await this.Client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
}
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
private async Task InvokeAgentAsync(AzureAIAgent agent, Microsoft.SemanticKernel.Agents.AgentThread agentThread, string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
// For this sample, also capture fully formed messages so we can display them later.
|
||||
ChatHistory history = [];
|
||||
Task OnNewMessage(ChatMessageContent message)
|
||||
{
|
||||
history.Add(message);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
bool isFirst = false;
|
||||
bool isCode = false;
|
||||
await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread, new AgentInvokeOptions() { OnIntermediateMessage = OnNewMessage }))
|
||||
{
|
||||
if (string.IsNullOrEmpty(response.Content))
|
||||
{
|
||||
StreamingFunctionCallUpdateContent? functionCall = response.Items.OfType<StreamingFunctionCallUpdateContent>().SingleOrDefault();
|
||||
if (functionCall?.Name != null)
|
||||
{
|
||||
(string? pluginName, string functionName) = this.ParseFunctionName(functionCall.Name);
|
||||
Console.WriteLine($"\n# {response.Role} - {response.AuthorName ?? "*"}: FUNCTION CALL - {$"{pluginName}." ?? string.Empty}{functionName}");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Differentiate between assistant and tool messages
|
||||
if (isCode != (response.Metadata?.ContainsKey(AzureAIAgent.CodeInterpreterMetadataKey) ?? false))
|
||||
{
|
||||
isFirst = false;
|
||||
isCode = !isCode;
|
||||
}
|
||||
|
||||
if (!isFirst)
|
||||
{
|
||||
Console.WriteLine($"\n# {response.Role} - {response.AuthorName ?? "*"}:");
|
||||
isFirst = true;
|
||||
}
|
||||
|
||||
Console.WriteLine($"\t > streamed: '{response.Content}'");
|
||||
}
|
||||
|
||||
foreach (ChatMessageContent content in history)
|
||||
{
|
||||
this.WriteAgentChatMessage(content);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DisplayChatHistoryAsync(AzureAIAgentThread agentThread)
|
||||
{
|
||||
Console.WriteLine("================================");
|
||||
Console.WriteLine("CHAT HISTORY");
|
||||
Console.WriteLine("================================");
|
||||
|
||||
ChatMessageContent[] messages = await agentThread.GetMessagesAsync().ToArrayAsync();
|
||||
for (int index = messages.Length - 1; index >= 0; --index)
|
||||
{
|
||||
this.WriteAgentChatMessage(messages[index]);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MenuPlugin
|
||||
{
|
||||
[KernelFunction, Description("Provides a list of specials from the menu.")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = "Too smart")]
|
||||
public string GetSpecials()
|
||||
{
|
||||
return
|
||||
"""
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
""";
|
||||
}
|
||||
|
||||
[KernelFunction, Description("Provides the price of the requested menu item.")]
|
||||
public string GetItemPrice(
|
||||
[Description("The name of the menu item.")]
|
||||
string menuItem)
|
||||
{
|
||||
return "$9.99";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
||||
using Microsoft.SemanticKernel.Functions;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
#pragma warning disable SKEXP0130 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrates the creation of a <see cref="ChatCompletionAgent"/> and adding capabilities
|
||||
/// for contextual function selection to it. Contextual function selection involves using
|
||||
/// Retrieval-Augmented Generation (RAG) to identify and select the most relevant functions
|
||||
/// based on the current context. The provider vectorizes the function names and descriptions,
|
||||
/// stores them in a specified vector store, and performs a vector search to find and provide
|
||||
/// the most pertinent functions to the AI model/agent for a given context.
|
||||
/// </summary>
|
||||
public class ChatCompletion_ContextualFunctionSelection(ITestOutputHelper output) : BaseTest(output)
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows how to configure agent to use <see cref="ContextualFunctionProvider"/>
|
||||
/// to enable contextual function selection based on the current invocation context.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
private async Task SelectFunctionsRelevantToCurrentInvocationContext()
|
||||
{
|
||||
var embeddingGenerator = new AzureOpenAIClient(new Uri(TestConfiguration.AzureOpenAIEmbeddings.Endpoint), new AzureCliCredential())
|
||||
.GetEmbeddingClient(TestConfiguration.AzureOpenAIEmbeddings.DeploymentName)
|
||||
.AsIEmbeddingGenerator(1536);
|
||||
|
||||
// Create our agent.
|
||||
Kernel kernel = this.CreateKernelWithChatCompletion();
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Name = "ReviewGuru",
|
||||
Instructions = "You are a friendly assistant that summarizes key points and sentiments from customer reviews. " +
|
||||
"For each response, list available functions",
|
||||
Kernel = kernel,
|
||||
Arguments = new(new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(options: new FunctionChoiceBehaviorOptions { RetainArgumentTypes = true }) })
|
||||
};
|
||||
|
||||
// Create a thread and register context based function selection provider that will do RAG on
|
||||
// provided functions to advertise only those that are relevant to the current context.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
var allAvailableFunctions = GetAvailableFunctions();
|
||||
|
||||
agentThread.AIContextProviders.Add(
|
||||
new ContextualFunctionProvider(
|
||||
vectorStore: new InMemoryVectorStore(new InMemoryVectorStoreOptions() { EmbeddingGenerator = embeddingGenerator }),
|
||||
vectorDimensions: 1536,
|
||||
functions: allAvailableFunctions,
|
||||
maxNumberOfFunctions: 3, // Instruct the provider to return a maximum of 3 relevant functions
|
||||
loggerFactory: this.LoggerFactory
|
||||
)
|
||||
);
|
||||
|
||||
// Invoke and display assistant response
|
||||
ChatMessageContent message = await agent.InvokeAsync("Get and summarize customer review.", agentThread).FirstAsync();
|
||||
Console.WriteLine(message.Content);
|
||||
|
||||
//Expected output:
|
||||
/*
|
||||
Retrieves and summarizes customer reviews.
|
||||
|
||||
### Customer Reviews:
|
||||
1. **John D.** - ★★★★★
|
||||
*Comment:* Great product and fast shipping!
|
||||
*Date:* 2023-10-01
|
||||
2. **Jane S.** - ★★★★
|
||||
*Comment:* Good quality, but delivery was a bit slow.
|
||||
*Date:* 2023-09-28
|
||||
3. **Mike J.** - ★★★
|
||||
*Comment:* Average. Works as expected.
|
||||
*Date:* 2023-09-25
|
||||
|
||||
### Summary:
|
||||
The reviews indicate overall customer satisfaction, with highlights on product quality and shipping efficiency.
|
||||
While some customers experienced excellent service, others mentioned areas for improvement, particularly regarding delivery times.
|
||||
|
||||
If you need further analysis or insights, feel free to ask!
|
||||
|
||||
Available functions:
|
||||
- Tools-GetCustomerReviews
|
||||
- Tools-Summarize
|
||||
- Tools-CollectSentiments
|
||||
*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows how to configure agent to use <see cref="ContextualFunctionProvider"/>
|
||||
/// to enable contextual function selection based on the previous and current invocation context.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
private async Task SelectFunctionsBasedOnPreviousAndCurrentInvocationContext()
|
||||
{
|
||||
var embeddingGenerator = new AzureOpenAIClient(new Uri(TestConfiguration.AzureOpenAIEmbeddings.Endpoint), new AzureCliCredential())
|
||||
.GetEmbeddingClient(TestConfiguration.AzureOpenAIEmbeddings.DeploymentName)
|
||||
.AsIEmbeddingGenerator(1536);
|
||||
|
||||
// Create our agent.
|
||||
Kernel kernel = this.CreateKernelWithChatCompletion();
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Name = "AzureAssistant",
|
||||
Instructions = "You are a helpful assistant that helps with Azure resource management. " +
|
||||
"Avoid including the phrase like 'If you need further assistance or have any additional tasks, feel free to let me know!' in any responses.",
|
||||
Kernel = kernel,
|
||||
Arguments = new(new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(options: new FunctionChoiceBehaviorOptions { RetainArgumentTypes = true }) })
|
||||
};
|
||||
|
||||
// Create a thread and register context based function selection provider that will do RAG on
|
||||
// provided functions to advertise only those that are relevant to the current context.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
var allAvailableFunctions = GetAvailableFunctions();
|
||||
|
||||
agentThread.AIContextProviders.Add(
|
||||
new ContextualFunctionProvider(
|
||||
vectorStore: new InMemoryVectorStore(new InMemoryVectorStoreOptions() { EmbeddingGenerator = embeddingGenerator }),
|
||||
vectorDimensions: 1536,
|
||||
functions: allAvailableFunctions,
|
||||
maxNumberOfFunctions: 1, // Instruct the provider to return only one relevant function
|
||||
loggerFactory: this.LoggerFactory,
|
||||
options: new ContextualFunctionProviderOptions
|
||||
{
|
||||
NumberOfRecentMessagesInContext = 1 // Use only the last message from the previous agent invocation
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Ask agent to provision a VM on Azure. The contextual function selection provider will return only one relevant function: `ProvisionVM`
|
||||
ChatMessageContent message = await agent.InvokeAsync("Please provision a VM on Azure", agentThread).FirstAsync();
|
||||
Console.WriteLine(message.Content);
|
||||
|
||||
//Expected output: "A virtual machine has been successfully provisioned on Azure with the ID: 7f2aa1e4-13ac-4875-9e63-278ee82f3729."
|
||||
|
||||
// Ask the agent to deploy the VM, intentionally referring to the VM as "it".
|
||||
// This demonstrates that the contextual function selection provider uses the last message from the previous invocation
|
||||
// to infer that the user is referring to the VM provisioned in the invocation and not any other Azure resource.
|
||||
// The provider will return only one relevant function to deploy the VM: `DeployVM`
|
||||
message = await agent.InvokeAsync("Deploy it", agentThread).FirstAsync();
|
||||
Console.WriteLine(message.Content);
|
||||
|
||||
//Expected output: "The virtual machine with ID: 7f2aa1e4-13ac-4875-9e63-278ee82f3729 has been successfully deployed."
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of functions that belong to different categories.
|
||||
/// Some categories/functions are related to the prompt, while others
|
||||
/// are not. This is intentionally done to demonstrate the contextual
|
||||
/// function selection capabilities of the provider.
|
||||
/// </summary>
|
||||
private IReadOnlyList<AIFunction> GetAvailableFunctions()
|
||||
{
|
||||
List<AIFunction> reviewFunctions = [
|
||||
AIFunctionFactory.Create(() => """
|
||||
[
|
||||
{
|
||||
"reviewer": "John D.",
|
||||
"date": "2023-10-01",
|
||||
"rating": 5,
|
||||
"comment": "Great product and fast shipping!"
|
||||
},
|
||||
{
|
||||
"reviewer": "Jane S.",
|
||||
"date": "2023-09-28",
|
||||
"rating": 4,
|
||||
"comment": "Good quality, but delivery was a bit slow."
|
||||
},
|
||||
{
|
||||
"reviewer": "Mike J.",
|
||||
"date": "2023-09-25",
|
||||
"rating": 3,
|
||||
"comment": "Average. Works as expected."
|
||||
}
|
||||
]
|
||||
"""
|
||||
, "GetCustomerReviews"),
|
||||
];
|
||||
|
||||
List<AIFunction> sentimentFunctions = [
|
||||
AIFunctionFactory.Create((string text) => "The collected sentiment is mostly positive with a few neutral and negative opinions.", "CollectSentiments"),
|
||||
AIFunctionFactory.Create((string text) => "Sentiment trend identified: predominantly positive with increasing positive feedback.", "IdentifySentimentTrend"),
|
||||
];
|
||||
|
||||
List<AIFunction> summaryFunctions = [
|
||||
AIFunctionFactory.Create((string text) => "Summary generated based on input data: key points include market growth and customer satisfaction.", "Summarize"),
|
||||
AIFunctionFactory.Create((string text) => "Extracted themes: innovation, efficiency, customer satisfaction.", "ExtractThemes"),
|
||||
];
|
||||
|
||||
List<AIFunction> communicationFunctions = [
|
||||
AIFunctionFactory.Create((string address, string content) => "Email sent.", "SendEmail"),
|
||||
AIFunctionFactory.Create((string number, string text) => "Message sent.", "SendSms"),
|
||||
AIFunctionFactory.Create(() => "user@domain.com", "MyEmail"),
|
||||
];
|
||||
|
||||
List<AIFunction> dateTimeFunctions = [
|
||||
AIFunctionFactory.Create(() => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "GetCurrentDateTime"),
|
||||
AIFunctionFactory.Create(() => DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"), "GetCurrentUtcDateTime"),
|
||||
];
|
||||
|
||||
List<AIFunction> azureFunctions = [
|
||||
AIFunctionFactory.Create(() => $"Resource group provisioned: Id:{Guid.NewGuid()}", "ProvisionResourceGroup"),
|
||||
AIFunctionFactory.Create((Guid id) => $"Resource group deployed: Id:{id}", "DeployResourceGroup"),
|
||||
|
||||
AIFunctionFactory.Create(() => $"Storage account provisioned: Id:{Guid.NewGuid()}", "ProvisionStorageAccount"),
|
||||
AIFunctionFactory.Create((Guid id) => $"Storage account deployed: Id:{id}", "DeployStorageAccount"),
|
||||
|
||||
AIFunctionFactory.Create(() => $"VM provisioned: Id:{Guid.NewGuid()}", "ProvisionVM"),
|
||||
AIFunctionFactory.Create((Guid id) => $"VM deployed: Id:{id}", "DeployVM"),
|
||||
];
|
||||
|
||||
return [.. reviewFunctions, .. sentimentFunctions, .. summaryFunctions, .. communicationFunctions, .. dateTimeFunctions, .. azureFunctions];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate usage of <see cref="IAutoFunctionInvocationFilter"/> for both direction invocation
|
||||
/// of <see cref="ChatCompletionAgent"/> and via <see cref="AgentChat"/>.
|
||||
/// </summary>
|
||||
public class ChatCompletion_FunctionTermination(ITestOutputHelper output) : BaseAgentsTest(output)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task UseAutoFunctionInvocationFilterWithAgentInvocation(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Instructions = "Answer questions about the menu.",
|
||||
Kernel = CreateKernelWithFilter(useChatClient),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
|
||||
agent.Kernel.Plugins.Add(plugin);
|
||||
|
||||
/// Create the thread to capture the agent interaction.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
// Respond to user input, invoking functions where appropriate.
|
||||
await InvokeAgentAsync("Hello");
|
||||
await InvokeAgentAsync("What is the special soup?");
|
||||
await InvokeAgentAsync("What is the special drink?");
|
||||
await InvokeAgentAsync("Thank you");
|
||||
|
||||
// Display the entire chat history.
|
||||
WriteChatHistory(await agentThread.GetMessagesAsync().ToArrayAsync());
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
await foreach (ChatMessageContent response in agent.InvokeAsync(message, agentThread))
|
||||
{
|
||||
this.WriteAgentChatMessage(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task UseAutoFunctionInvocationFilterWithAgentChat(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Instructions = "Answer questions about the menu.",
|
||||
Kernel = CreateKernelWithFilter(useChatClient),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
|
||||
agent.Kernel.Plugins.Add(plugin);
|
||||
|
||||
// Create a chat for agent interaction.
|
||||
AgentGroupChat chat = new();
|
||||
|
||||
// Respond to user input, invoking functions where appropriate.
|
||||
await InvokeAgentAsync("Hello");
|
||||
await InvokeAgentAsync("What is the special soup?");
|
||||
await InvokeAgentAsync("What is the special drink?");
|
||||
await InvokeAgentAsync("Thank you");
|
||||
|
||||
// Display the entire chat history.
|
||||
WriteChatHistory(await chat.GetChatMessagesAsync().ToArrayAsync());
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
chat.AddChatMessage(message);
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
await foreach (ChatMessageContent response in chat.InvokeAsync(agent))
|
||||
{
|
||||
this.WriteAgentChatMessage(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task UseAutoFunctionInvocationFilterWithStreamingAgentInvocation(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Instructions = "Answer questions about the menu.",
|
||||
Kernel = CreateKernelWithFilter(useChatClient),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
|
||||
agent.Kernel.Plugins.Add(plugin);
|
||||
|
||||
/// Create the thread to capture the agent interaction.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
// Respond to user input, invoking functions where appropriate.
|
||||
await InvokeAgentAsync("Hello");
|
||||
await InvokeAgentAsync("What is the special soup?");
|
||||
await InvokeAgentAsync("What is the special drink?");
|
||||
await InvokeAgentAsync("Thank you");
|
||||
|
||||
// Display the entire chat history.
|
||||
WriteChatHistory(await agentThread.GetMessagesAsync().ToArrayAsync());
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
int historyCount = agentThread.ChatHistory.Count;
|
||||
|
||||
bool isFirst = false;
|
||||
await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread))
|
||||
{
|
||||
if (string.IsNullOrEmpty(response.Content))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isFirst)
|
||||
{
|
||||
Console.WriteLine($"\n# {response.Role} - {response.AuthorName ?? "*"}:");
|
||||
isFirst = true;
|
||||
}
|
||||
|
||||
Console.WriteLine($"\t > streamed: '{response.Content}'");
|
||||
}
|
||||
|
||||
if (historyCount <= agentThread.ChatHistory.Count)
|
||||
{
|
||||
for (int index = historyCount; index < agentThread.ChatHistory.Count; index++)
|
||||
{
|
||||
this.WriteAgentChatMessage(agentThread.ChatHistory[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task UseAutoFunctionInvocationFilterWithStreamingAgentChat(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Instructions = "Answer questions about the menu.",
|
||||
Kernel = CreateKernelWithFilter(useChatClient),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
|
||||
agent.Kernel.Plugins.Add(plugin);
|
||||
|
||||
// Create a chat for agent interaction.
|
||||
AgentGroupChat chat = new();
|
||||
|
||||
// Respond to user input, invoking functions where appropriate.
|
||||
await InvokeAgentAsync("Hello");
|
||||
await InvokeAgentAsync("What is the special soup?");
|
||||
await InvokeAgentAsync("What is the special drink?");
|
||||
await InvokeAgentAsync("Thank you");
|
||||
|
||||
// Display the entire chat history.
|
||||
WriteChatHistory(await chat.GetChatMessagesAsync().ToArrayAsync());
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
chat.AddChatMessage(message);
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
bool isFirst = false;
|
||||
await foreach (StreamingChatMessageContent response in chat.InvokeStreamingAsync(agent))
|
||||
{
|
||||
if (string.IsNullOrEmpty(response.Content))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isFirst)
|
||||
{
|
||||
Console.WriteLine($"\n# {response.Role} - {response.AuthorName ?? "*"}:");
|
||||
isFirst = true;
|
||||
}
|
||||
|
||||
Console.WriteLine($"\t > streamed: '{response.Content}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteChatHistory(IEnumerable<ChatMessageContent> chat)
|
||||
{
|
||||
Console.WriteLine("================================");
|
||||
Console.WriteLine("CHAT HISTORY");
|
||||
Console.WriteLine("================================");
|
||||
foreach (ChatMessageContent message in chat)
|
||||
{
|
||||
this.WriteAgentChatMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private Kernel CreateKernelWithFilter(bool useChatClient)
|
||||
{
|
||||
IKernelBuilder builder = Kernel.CreateBuilder();
|
||||
|
||||
if (useChatClient)
|
||||
{
|
||||
base.AddChatClientToKernel(builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.AddChatCompletionToKernel(builder);
|
||||
}
|
||||
|
||||
builder.Services.AddSingleton<IAutoFunctionInvocationFilter>(new AutoInvocationFilter());
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
private sealed class MenuPlugin
|
||||
{
|
||||
[KernelFunction, Description("Provides a list of specials from the menu.")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = "Too smart")]
|
||||
public string GetSpecials()
|
||||
{
|
||||
return
|
||||
"""
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
""";
|
||||
}
|
||||
|
||||
[KernelFunction, Description("Provides the price of the requested menu item.")]
|
||||
public string GetItemPrice(
|
||||
[Description("The name of the menu item.")]
|
||||
string menuItem)
|
||||
{
|
||||
return "$9.99";
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class AutoInvocationFilter(bool terminate = true) : IAutoFunctionInvocationFilter
|
||||
{
|
||||
public async Task OnAutoFunctionInvocationAsync(AutoFunctionInvocationContext context, Func<AutoFunctionInvocationContext, Task> next)
|
||||
{
|
||||
// Execution the function
|
||||
await next(context);
|
||||
|
||||
// Signal termination if the function is from the MenuPlugin
|
||||
if (context.Function.PluginName == nameof(MenuPlugin))
|
||||
{
|
||||
context.Terminate = terminate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate creation of <see cref="ChatCompletionAgent"/> and
|
||||
/// eliciting its response to three explicit user messages.
|
||||
/// </summary>
|
||||
public class ChatCompletion_HistoryReducer(ITestOutputHelper output) : BaseTest(output)
|
||||
{
|
||||
private const string TranslatorName = "NumeroTranslator";
|
||||
private const string TranslatorInstructions = "Add one to latest user number and spell it in spanish without explanation.";
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate the use of <see cref="ChatHistoryTruncationReducer"/> when directly
|
||||
/// invoking a <see cref="ChatCompletionAgent"/>.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task TruncatedAgentReduction(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent = CreateTruncatingAgent(10, 10, useChatClient, out var chatClient);
|
||||
|
||||
await InvokeAgentAsync(agent, 50);
|
||||
|
||||
chatClient?.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate the use of <see cref="ChatHistorySummarizationReducer"/> when directly
|
||||
/// invoking a <see cref="ChatCompletionAgent"/>.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task SummarizedAgentReduction(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent = CreateSummarizingAgent(10, 10, useChatClient, out var chatClient);
|
||||
|
||||
await InvokeAgentAsync(agent, 50);
|
||||
|
||||
chatClient?.Dispose();
|
||||
}
|
||||
|
||||
// Proceed with dialog by directly invoking the agent and explicitly managing the history.
|
||||
private async Task InvokeAgentAsync(ChatCompletionAgent agent, int messageCount)
|
||||
{
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
int index = 1;
|
||||
while (index <= messageCount)
|
||||
{
|
||||
// Provide user input
|
||||
Console.WriteLine($"# {AuthorRole.User}: '{index}'");
|
||||
|
||||
// Reduce prior to invoking the agent
|
||||
bool isReduced = await agent.ReduceAsync(agentThread.ChatHistory);
|
||||
|
||||
// Invoke and display assistant response
|
||||
await foreach (ChatMessageContent message in agent.InvokeAsync(new ChatMessageContent(AuthorRole.User, $"{index}"), agentThread))
|
||||
{
|
||||
Console.WriteLine($"# {message.Role} - {message.AuthorName ?? "*"}: '{message.Content}'");
|
||||
}
|
||||
|
||||
index += 2;
|
||||
|
||||
// Display the message count of the chat-history for visibility into reduction
|
||||
Console.WriteLine($"@ Message Count: {agentThread.ChatHistory.Count}\n");
|
||||
|
||||
// Display summary messages (if present) if reduction has occurred
|
||||
if (isReduced)
|
||||
{
|
||||
int summaryIndex = 0;
|
||||
while (agentThread.ChatHistory[summaryIndex].Metadata?.ContainsKey(ChatHistorySummarizationReducer.SummaryMetadataKey) ?? false)
|
||||
{
|
||||
Console.WriteLine($"\tSummary: {agentThread.ChatHistory[summaryIndex].Content}");
|
||||
++summaryIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ChatCompletionAgent CreateSummarizingAgent(int reducerMessageCount, int reducerThresholdCount, bool useChatClient, out IChatClient? chatClient)
|
||||
{
|
||||
Kernel kernel = this.CreateKernelWithChatCompletion(useChatClient, out chatClient);
|
||||
|
||||
var service = useChatClient
|
||||
? kernel.GetRequiredService<IChatClient>().AsChatCompletionService()
|
||||
: kernel.GetRequiredService<IChatCompletionService>();
|
||||
|
||||
return
|
||||
new()
|
||||
{
|
||||
Name = TranslatorName,
|
||||
Instructions = TranslatorInstructions,
|
||||
Kernel = kernel,
|
||||
HistoryReducer = new ChatHistorySummarizationReducer(service, reducerMessageCount, reducerThresholdCount),
|
||||
};
|
||||
}
|
||||
|
||||
private ChatCompletionAgent CreateTruncatingAgent(int reducerMessageCount, int reducerThresholdCount, bool useChatClient, out IChatClient? chatClient) =>
|
||||
new()
|
||||
{
|
||||
Name = TranslatorName,
|
||||
Instructions = TranslatorInstructions,
|
||||
Kernel = this.CreateKernelWithChatCompletion(useChatClient, out chatClient),
|
||||
HistoryReducer = new ChatHistoryTruncationReducer(reducerMessageCount, reducerThresholdCount),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Net.Http.Headers;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
#pragma warning disable SKEXP0130 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate creation of <see cref="ChatCompletionAgent"/> and
|
||||
/// adding memory capabilities to it using https://mem0.ai/.
|
||||
/// </summary>
|
||||
public class ChatCompletion_Mem0(ITestOutputHelper output) : BaseTest(output)
|
||||
{
|
||||
private const string AgentName = "FriendlyAssistant";
|
||||
private const string AgentInstructions = "You are a friendly assistant";
|
||||
|
||||
/// <summary>
|
||||
/// Shows how to allow an agent to remember user preferences across multiple threads.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
private async Task UseMemoryAsync()
|
||||
{
|
||||
// Create a new HttpClient with the base address of the mem0 service and a token for authentication.
|
||||
using var httpClient = new HttpClient()
|
||||
{
|
||||
BaseAddress = new Uri(TestConfiguration.Mem0.BaseAddress ?? "https://api.mem0.ai")
|
||||
};
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", TestConfiguration.Mem0.ApiKey);
|
||||
|
||||
// Create a mem0 component with the current user's id, so that it stores memories for that user.
|
||||
var mem0Provider = new Mem0Provider(httpClient, options: new()
|
||||
{
|
||||
UserId = "U1"
|
||||
});
|
||||
|
||||
// Clear out any memories from previous runs, if any, to demonstrate a first run experience.
|
||||
await mem0Provider.ClearStoredMemoriesAsync();
|
||||
|
||||
// Create our agent and add our finance plugin with auto function invocation.
|
||||
Kernel kernel = this.CreateKernelWithChatCompletion();
|
||||
kernel.Plugins.AddFromType<FinancePlugin>();
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Name = AgentName,
|
||||
Instructions = AgentInstructions,
|
||||
Kernel = kernel,
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() })
|
||||
};
|
||||
|
||||
Console.WriteLine("----- First Conversation -----");
|
||||
|
||||
// Create a thread for the agent and add the mem0 component to it.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
agentThread.AIContextProviders.Add(mem0Provider);
|
||||
|
||||
// First ask the agent to retrieve a company report with no previous context.
|
||||
// The agent will not be able to invoke the plugin, since it doesn't know
|
||||
// the company code or the report format, so it should ask for clarification.
|
||||
string userMessage = "Please retrieve my company report";
|
||||
Console.WriteLine($"User: {userMessage}");
|
||||
|
||||
ChatMessageContent message = await agent.InvokeAsync(userMessage, agentThread).FirstAsync();
|
||||
Console.WriteLine($"Assistant:\n{message.Content}");
|
||||
|
||||
// Now tell the agent the company code and the report format that you want to use
|
||||
// and it should be able to invoke the plugin and return the report.
|
||||
userMessage = "I always work with CNTS and I always want a detailed report format";
|
||||
Console.WriteLine($"User: {userMessage}");
|
||||
|
||||
message = await agent.InvokeAsync(userMessage, agentThread).FirstAsync();
|
||||
Console.WriteLine($"Assistant:\n{message.Content}");
|
||||
|
||||
Console.WriteLine("----- Second Conversation -----");
|
||||
|
||||
// Create a new thread for the agent and add our mem0 component to it again
|
||||
// The new thread has no context of the previous conversation.
|
||||
agentThread = new();
|
||||
agentThread.AIContextProviders.Add(mem0Provider);
|
||||
|
||||
// Since we have the mem0 component in the thread, the agent should be able to
|
||||
// retrieve the company report without asking for clarification, as it will
|
||||
// be able to remember the user preferences from the last thread.
|
||||
userMessage = "Please retrieve my company report";
|
||||
Console.WriteLine($"User: {userMessage}");
|
||||
|
||||
message = await agent.InvokeAsync(userMessage, agentThread).FirstAsync();
|
||||
Console.WriteLine($"Assistant:\n{message.Content}");
|
||||
}
|
||||
|
||||
private sealed class FinancePlugin
|
||||
{
|
||||
[KernelFunction]
|
||||
public string RetrieveCompanyReport(string companyCode, ReportFormat reportFormat)
|
||||
{
|
||||
if (companyCode != "CNTS")
|
||||
{
|
||||
throw new ArgumentException("Company code not found");
|
||||
}
|
||||
|
||||
return reportFormat switch
|
||||
{
|
||||
ReportFormat.Brief => "CNTS is a company that specializes in technology.",
|
||||
ReportFormat.Detailed => "CNTS is a company that specializes in technology. It had a revenue of $10 million in 2022. It has 100 employees.",
|
||||
_ => throw new ArgumentException("Report format not found")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private enum ReportFormat
|
||||
{
|
||||
Brief,
|
||||
Detailed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
||||
using Microsoft.SemanticKernel.Data;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
#pragma warning disable SKEXP0130 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate creation of <see cref="ChatCompletionAgent"/> and
|
||||
/// adding simple retrieval augmented generation (RAG) capabilities to it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This example shows how to use the <see cref="TextSearchStore{TKey}"/> class which is designed
|
||||
/// to simplify the process of storing and searching text documents by having a built in schema.
|
||||
/// If you want to control the schema yourself, you can use an implementation of <see cref="VectorStoreCollection{TKey, TRecord}"/>
|
||||
/// with the <see cref="VectorStoreTextSearch{TRecord}"/> class instead.
|
||||
/// </remarks>
|
||||
public class ChatCompletion_Rag(ITestOutputHelper output) : BaseTest(output)
|
||||
{
|
||||
private const string AgentName = "FriendlyAssistant";
|
||||
private const string AgentInstructions = "You are a friendly assistant";
|
||||
|
||||
/// <summary>
|
||||
/// Shows how to do Retrieval Augmented Generation (RAG) with some basic text strings.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
private async Task UseChatCompletionAgentWithBasicRag()
|
||||
{
|
||||
var embeddingGenerator = new AzureOpenAIClient(new Uri(TestConfiguration.AzureOpenAIEmbeddings.Endpoint), new AzureCliCredential())
|
||||
.GetEmbeddingClient(TestConfiguration.AzureOpenAIEmbeddings.DeploymentName)
|
||||
.AsIEmbeddingGenerator(1536);
|
||||
|
||||
// Create a vector store to store our documents.
|
||||
// Note that the embedding generator provided here must be able to generate embeddings matching the
|
||||
// number of dimensions configured for the TextSearchStore below.
|
||||
var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
// Create a store that uses a built in schema for storing text documents
|
||||
// and provides easy upload and search capabilities.
|
||||
// The data is stored in the `FinancialData` collection and embeddings have 1536 dimensions.
|
||||
// When searching results will be limited to those with the `group/g2` namespace.
|
||||
using var textSearchStore = new TextSearchStore<string>(vectorStore, collectionName: "FinancialData", vectorDimensions: 1536);
|
||||
|
||||
// Upsert documents into the store.
|
||||
await textSearchStore.UpsertTextAsync(
|
||||
[
|
||||
"The financial results of Contoso Corp for 2024 is as follows:\nIncome EUR 154 000 000\nExpenses EUR 142 000 000",
|
||||
"The financial results of Contoso Corp for 2023 is as follows:\nIncome EUR 174 000 000\nExpenses EUR 152 000 000",
|
||||
"The financial results of Contoso Corp for 2022 is as follows:\nIncome EUR 184 000 000\nExpenses EUR 162 000 000",
|
||||
"The Contoso Corporation is a multinational business with its headquarters in Paris. The company is a manufacturing, sales, and support organization with more than 100,000 products.",
|
||||
"The financial results of AdventureWorks for 2021 is as follows:\nIncome USD 223 000 000\nExpenses USD 210 000 000",
|
||||
"AdventureWorks is a large American business that specializes in adventure parks and family entertainment.",
|
||||
]);
|
||||
|
||||
// Create our agent.
|
||||
Kernel kernel = this.CreateKernelWithChatCompletion();
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Name = AgentName,
|
||||
Instructions = AgentInstructions,
|
||||
Kernel = kernel,
|
||||
};
|
||||
|
||||
// Create a thread for the agent.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
// Create a text search provider that can automatically search the vector store
|
||||
// for documents that match the user's query and inject them into the agent's prompt.
|
||||
var textSearchProvider = new TextSearchProvider(textSearchStore);
|
||||
agentThread.AIContextProviders.Add(textSearchProvider);
|
||||
|
||||
// Invoke and display assistant response
|
||||
ChatMessageContent message = await agent.InvokeAsync("Where is Contoso based?", agentThread).FirstAsync();
|
||||
Console.WriteLine(message.Content);
|
||||
|
||||
message = await agent.InvokeAsync("What was its expenses for 2022?", agentThread).FirstAsync();
|
||||
Console.WriteLine(message.Content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows how to do Retrieval Augmented Generation (RAG) with citations and filtering.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
private async Task RagWithCitationsAndFiltering()
|
||||
{
|
||||
var embeddingGenerator = new AzureOpenAIClient(new Uri(TestConfiguration.AzureOpenAIEmbeddings.Endpoint), new AzureCliCredential())
|
||||
.GetEmbeddingClient(TestConfiguration.AzureOpenAIEmbeddings.DeploymentName)
|
||||
.AsIEmbeddingGenerator(1536);
|
||||
|
||||
// Create a vector store to store our documents.
|
||||
// Note that the embedding generator provided here must be able to generate embeddings matching the
|
||||
// number of dimensions configured for the TextSearchStore below.
|
||||
var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
// Create a store that uses a built in schema for storing text documents
|
||||
// and provides easy upload and search capabilities.
|
||||
// The data is stored in the `FinancialData` collection and embeddings have 1536 dimensions.
|
||||
// When searching results will be limited to those with the `group/g2` namespace.
|
||||
using var textSearchStore = new TextSearchStore<string>(vectorStore, collectionName: "FinancialData", vectorDimensions: 1536, new() { SearchNamespace = "group/g2" });
|
||||
|
||||
// Upsert documents into the store.
|
||||
// Not that documents have different namespaces, and only the ones
|
||||
// with the `group/g2` namespace will be matched.
|
||||
await textSearchStore.UpsertDocumentsAsync(GetSampleDocuments());
|
||||
|
||||
// Create our agent.
|
||||
Kernel kernel = this.CreateKernelWithChatCompletion();
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Name = AgentName,
|
||||
Instructions = AgentInstructions,
|
||||
Kernel = kernel,
|
||||
};
|
||||
|
||||
// Create a thread for the agent.
|
||||
ChatHistoryAgentThread agentThread = new();
|
||||
|
||||
// Create a text search provider that can automatically search the vector store
|
||||
// for documents that match the user's query and inject them into the agent's prompt.
|
||||
var textSearchProvider = new TextSearchProvider(textSearchStore);
|
||||
agentThread.AIContextProviders.Add(textSearchProvider);
|
||||
|
||||
// Invoke and display assistant response
|
||||
ChatMessageContent message = await agent.InvokeAsync("What was the income of Contoso for 2023", agentThread).FirstAsync();
|
||||
Console.WriteLine(message.Content);
|
||||
}
|
||||
|
||||
private static IEnumerable<TextSearchDocument> GetSampleDocuments()
|
||||
{
|
||||
yield return new TextSearchDocument
|
||||
{
|
||||
Text = "The financial results of Contoso Corp for 2024 is as follows:\nIncome EUR 154 000 000\nExpenses EUR 142 000 000",
|
||||
SourceName = "Contoso 2024 Financial Report",
|
||||
SourceLink = "https://www.consoso.com/reports/2024.pdf",
|
||||
Namespaces = ["group/g1"]
|
||||
};
|
||||
yield return new TextSearchDocument
|
||||
{
|
||||
Text = "The financial results of Contoso Corp for 2023 is as follows:\nIncome EUR 174 000 000\nExpenses EUR 152 000 000",
|
||||
SourceName = "Contoso 2023 Financial Report",
|
||||
SourceLink = "https://www.consoso.com/reports/2023.pdf",
|
||||
Namespaces = ["group/g2"]
|
||||
};
|
||||
yield return new TextSearchDocument
|
||||
{
|
||||
Text = "The financial results of Contoso Corp for 2022 is as follows:\nIncome EUR 184 000 000\nExpenses EUR 162 000 000",
|
||||
SourceName = "Contoso 2022 Financial Report",
|
||||
SourceLink = "https://www.consoso.com/reports/2022.pdf",
|
||||
Namespaces = ["group/g2"]
|
||||
};
|
||||
yield return new TextSearchDocument
|
||||
{
|
||||
Text = "The Contoso Corporation is a multinational business with its headquarters in Paris. The company is a manufacturing, sales, and support organization with more than 100,000 products.",
|
||||
SourceName = "About Contoso",
|
||||
SourceLink = "https://www.consoso.com/about-us",
|
||||
Namespaces = ["group/g2"]
|
||||
};
|
||||
yield return new TextSearchDocument
|
||||
{
|
||||
Text = "The financial results of AdventureWorks for 2021 is as follows:\nIncome USD 223 000 000\nExpenses USD 210 000 000",
|
||||
SourceName = "AdventureWorks 2021 Financial Report",
|
||||
SourceLink = "https://www.adventure-works.com/reports/2021.pdf",
|
||||
Namespaces = ["group/g1", "group/g2"]
|
||||
};
|
||||
yield return new TextSearchDocument
|
||||
{
|
||||
Text = "AdventureWorks is a large American business that specializes in adventure parks and family entertainment.",
|
||||
SourceName = "About AdventureWorks",
|
||||
SourceLink = "https://www.adventure-works.com/about-us",
|
||||
Namespaces = ["group/g1", "group/g2"]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using System.ComponentModel;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
namespace Agents;
|
||||
/// <summary>
|
||||
/// Demonstrate that serialization of <see cref="AgentGroupChat"/> in with a <see cref="ChatCompletionAgent"/> participant.
|
||||
/// </summary>
|
||||
public class ChatCompletion_Serialization(ITestOutputHelper output) : BaseAgentsTest(output)
|
||||
{
|
||||
private const string HostName = "Host";
|
||||
private const string HostInstructions = "Answer questions about the menu.";
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task SerializeAndRestoreAgentGroupChat(bool useChatClient)
|
||||
{
|
||||
// Define the agent
|
||||
ChatCompletionAgent agent =
|
||||
new()
|
||||
{
|
||||
Instructions = HostInstructions,
|
||||
Name = HostName,
|
||||
Kernel = this.CreateKernelWithChatCompletion(useChatClient, out var chatClient),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
|
||||
agent.Kernel.Plugins.Add(plugin);
|
||||
|
||||
AgentGroupChat chat = CreateGroupChat();
|
||||
|
||||
// Invoke chat and display messages.
|
||||
Console.WriteLine("============= Dynamic Agent Chat - Primary (prior to serialization) ==============");
|
||||
await InvokeAgentAsync(chat, "Hello");
|
||||
await InvokeAgentAsync(chat, "What is the special soup?");
|
||||
|
||||
AgentGroupChat copy = CreateGroupChat();
|
||||
Console.WriteLine("\n=========== Serialize and restore the Agent Chat into a new instance ============");
|
||||
await CloneChatAsync(chat, copy);
|
||||
|
||||
Console.WriteLine("\n============ Continue with the dynamic Agent Chat (after deserialization) ===============");
|
||||
await InvokeAgentAsync(copy, "What is the special drink?");
|
||||
await InvokeAgentAsync(copy, "Thank you");
|
||||
|
||||
Console.WriteLine("\n============ The entire Agent Chat (includes messages prior to serialization and those after deserialization) ==============");
|
||||
await foreach (ChatMessageContent content in copy.GetChatMessagesAsync())
|
||||
{
|
||||
this.WriteAgentChatMessage(content);
|
||||
}
|
||||
|
||||
chatClient?.Dispose();
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(AgentGroupChat chat, string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
chat.AddChatMessage(message);
|
||||
|
||||
this.WriteAgentChatMessage(message);
|
||||
|
||||
await foreach (ChatMessageContent content in chat.InvokeAsync())
|
||||
{
|
||||
this.WriteAgentChatMessage(content);
|
||||
}
|
||||
}
|
||||
|
||||
async Task CloneChatAsync(AgentGroupChat source, AgentGroupChat clone)
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
await AgentChatSerializer.SerializeAsync(source, stream);
|
||||
|
||||
stream.Position = 0;
|
||||
using StreamReader reader = new(stream);
|
||||
Console.WriteLine(await reader.ReadToEndAsync());
|
||||
|
||||
stream.Position = 0;
|
||||
AgentChatSerializer serializer = await AgentChatSerializer.DeserializeAsync(stream);
|
||||
await serializer.DeserializeAsync(clone);
|
||||
}
|
||||
|
||||
AgentGroupChat CreateGroupChat() => new(agent);
|
||||
}
|
||||
|
||||
private sealed class MenuPlugin
|
||||
{
|
||||
[KernelFunction, Description("Provides a list of specials from the menu.")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1024:Use properties where appropriate", Justification = "Too smart")]
|
||||
public string GetSpecials() =>
|
||||
"""
|
||||
Special Soup: Clam Chowder
|
||||
Special Salad: Cobb Salad
|
||||
Special Drink: Chai Tea
|
||||
""";
|
||||
|
||||
[KernelFunction, Description("Provides the price of the requested menu item.")]
|
||||
public string GetItemPrice(
|
||||
[Description("The name of the menu item.")]
|
||||
string menuItem) =>
|
||||
"$9.99";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using System.ClientModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrate service selection for <see cref="ChatCompletionAgent"/> through setting service-id
|
||||
/// on <see cref="Agent.Arguments"/> and also providing override <see cref="KernelArguments"/>
|
||||
/// when calling <see cref="ChatCompletionAgent.InvokeAsync(ICollection{ChatMessageContent}, AgentThread?, AgentInvokeOptions?, CancellationToken)"/>
|
||||
/// </summary>
|
||||
public class ChatCompletion_ServiceSelection(ITestOutputHelper output) : BaseAgentsTest(output)
|
||||
{
|
||||
private const string ServiceKeyGood = "chat-good";
|
||||
private const string ServiceKeyBad = "chat-bad";
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task UseServiceSelectionWithChatCompletionAgent(bool useChatClient)
|
||||
{
|
||||
// Create kernel with two instances of chat services - one good, one bad
|
||||
Kernel kernel = CreateKernelWithTwoServices(useChatClient);
|
||||
|
||||
// Define the agent targeting ServiceId = ServiceKeyGood
|
||||
ChatCompletionAgent agentGood =
|
||||
new()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { ServiceId = ServiceKeyGood }),
|
||||
};
|
||||
|
||||
// Define the agent targeting ServiceId = ServiceKeyBad
|
||||
ChatCompletionAgent agentBad =
|
||||
new()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { ServiceId = ServiceKeyBad }),
|
||||
};
|
||||
|
||||
// Define the agent with no explicit ServiceId defined
|
||||
ChatCompletionAgent agentDefault = new() { Kernel = kernel };
|
||||
|
||||
// Invoke agent as initialized with ServiceId = ServiceKeyGood: Expect agent response
|
||||
Console.WriteLine("\n[Agent With Good ServiceId]");
|
||||
await InvokeAgentAsync(agentGood);
|
||||
|
||||
// Invoke agent as initialized with ServiceId = ServiceKeyBad: Expect failure due to invalid service key
|
||||
Console.WriteLine("\n[Agent With Bad ServiceId]");
|
||||
await InvokeAgentAsync(agentBad);
|
||||
|
||||
// Invoke agent as initialized with no explicit ServiceId: Expect agent response
|
||||
Console.WriteLine("\n[Agent With No ServiceId]");
|
||||
await InvokeAgentAsync(agentDefault);
|
||||
|
||||
// Invoke agent with override arguments where ServiceId = ServiceKeyGood: Expect agent response
|
||||
Console.WriteLine("\n[Bad Agent: Good ServiceId Override]");
|
||||
await InvokeAgentAsync(agentBad, new(new PromptExecutionSettings() { ServiceId = ServiceKeyGood }));
|
||||
|
||||
// Invoke agent with override arguments where ServiceId = ServiceKeyBad: Expect failure due to invalid service key
|
||||
Console.WriteLine("\n[Good Agent: Bad ServiceId Override]");
|
||||
await InvokeAgentAsync(agentGood, new(new PromptExecutionSettings() { ServiceId = ServiceKeyBad }));
|
||||
Console.WriteLine("\n[Default Agent: Bad ServiceId Override]");
|
||||
await InvokeAgentAsync(agentDefault, new(new PromptExecutionSettings() { ServiceId = ServiceKeyBad }));
|
||||
|
||||
// Invoke agent with override arguments with no explicit ServiceId: Expect agent response
|
||||
Console.WriteLine("\n[Good Agent: No ServiceId Override]");
|
||||
await InvokeAgentAsync(agentGood, new(new PromptExecutionSettings()));
|
||||
Console.WriteLine("\n[Bad Agent: No ServiceId Override]");
|
||||
await InvokeAgentAsync(agentBad, new(new PromptExecutionSettings()));
|
||||
Console.WriteLine("\n[Default Agent: No ServiceId Override]");
|
||||
await InvokeAgentAsync(agentDefault, new(new PromptExecutionSettings()));
|
||||
|
||||
// Local function to invoke agent and display the conversation messages.
|
||||
async Task InvokeAgentAsync(ChatCompletionAgent agent, KernelArguments? arguments = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await foreach (ChatMessageContent response in agent.InvokeAsync(
|
||||
new ChatMessageContent(AuthorRole.User, "Hello"),
|
||||
options: new() { KernelArguments = arguments }))
|
||||
{
|
||||
Console.WriteLine(response.Content);
|
||||
}
|
||||
}
|
||||
catch (HttpOperationException exception)
|
||||
{
|
||||
Console.WriteLine($"Status: {exception.StatusCode}");
|
||||
}
|
||||
catch (ClientResultException cre)
|
||||
{
|
||||
Console.WriteLine($"Status: {cre.Status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Kernel CreateKernelWithTwoServices(bool useChatClient)
|
||||
{
|
||||
IKernelBuilder builder = Kernel.CreateBuilder();
|
||||
|
||||
if (useChatClient)
|
||||
{
|
||||
// Add chat clients
|
||||
if (this.UseOpenAIConfig)
|
||||
{
|
||||
builder.Services.AddKeyedChatClient(
|
||||
ServiceKeyBad,
|
||||
new OpenAI.OpenAIClient("bad-key").GetChatClient(TestConfiguration.OpenAI.ChatModelId).AsIChatClient());
|
||||
|
||||
builder.Services.AddKeyedChatClient(
|
||||
ServiceKeyGood,
|
||||
new OpenAI.OpenAIClient(TestConfiguration.OpenAI.ApiKey).GetChatClient(TestConfiguration.OpenAI.ChatModelId).AsIChatClient());
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Services.AddKeyedChatClient(
|
||||
ServiceKeyBad,
|
||||
new Azure.AI.OpenAI.AzureOpenAIClient(
|
||||
new Uri(TestConfiguration.AzureOpenAI.Endpoint),
|
||||
new Azure.AzureKeyCredential("bad-key"))
|
||||
.GetChatClient(TestConfiguration.AzureOpenAI.ChatDeploymentName)
|
||||
.AsIChatClient());
|
||||
|
||||
builder.Services.AddKeyedChatClient(
|
||||
ServiceKeyGood,
|
||||
new Azure.AI.OpenAI.AzureOpenAIClient(
|
||||
new Uri(TestConfiguration.AzureOpenAI.Endpoint),
|
||||
new Azure.AzureKeyCredential(TestConfiguration.AzureOpenAI.ApiKey))
|
||||
.GetChatClient(TestConfiguration.AzureOpenAI.ChatDeploymentName)
|
||||
.AsIChatClient());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add chat completion services
|
||||
if (this.UseOpenAIConfig)
|
||||
{
|
||||
builder.AddOpenAIChatCompletion(
|
||||
TestConfiguration.OpenAI.ChatModelId,
|
||||
"bad-key",
|
||||
serviceId: ServiceKeyBad);
|
||||
|
||||
builder.AddOpenAIChatCompletion(
|
||||
TestConfiguration.OpenAI.ChatModelId,
|
||||
TestConfiguration.OpenAI.ApiKey,
|
||||
serviceId: ServiceKeyGood);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddAzureOpenAIChatCompletion(
|
||||
TestConfiguration.AzureOpenAI.ChatDeploymentName,
|
||||
TestConfiguration.AzureOpenAI.Endpoint,
|
||||
"bad-key",
|
||||
serviceId: ServiceKeyBad);
|
||||
|
||||
builder.AddAzureOpenAIChatCompletion(
|
||||
TestConfiguration.AzureOpenAI.ChatDeploymentName,
|
||||
TestConfiguration.AzureOpenAI.Endpoint,
|
||||
TestConfiguration.AzureOpenAI.ApiKey,
|
||||
serviceId: ServiceKeyGood);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user