diff --git a/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs b/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs deleted file mode 100644 index 6ac99961479e..000000000000 --- a/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; -using System.IO; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using Azure.AI.OpenAI; -using Azure.Core; -using Azure.Core.Pipeline; -using Azure.Identity; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.SemanticKernel; -using RepoUtils; -using Xunit.Abstractions; - -namespace Examples; - -public class Example52_ApimAuth : BaseTest -{ - public async Task RunAsync() - { - // Azure API Management details - // For more information see 'Protect your Azure OpenAI API keys with Azure API Management' here: https://learn.microsoft.com/en-us/semantic-kernel/deploy/ - var apimUri = new Uri(Env.Var("Apim__Endpoint")); - var subscriptionKey = Env.Var("Apim__SubscriptionKey"); - - // Use interactive browser login - string[] scopes = new string[] { "https://cognitiveservices.azure.com/.default" }; - var credential = new InteractiveBrowserCredential(); - var requestContext = new TokenRequestContext(scopes); - var accessToken = await credential.GetTokenAsync(requestContext); - - // Create HttpClient and include subscription key as a default header - var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey); - - // Configure OpenAIClient to use - // - Custom HttpClient with subscription key header - // - Diagnostics to log error response headers from APIM to aid problem determination - // - Authentication using BearerTokenCredential retrieved via interactive browser login - var clientOptions = new OpenAIClientOptions - { - Transport = new HttpClientTransport(httpClient), - Diagnostics = - { - LoggedHeaderNames = { "ErrorSource", "ErrorReason", "ErrorMessage", "ErrorScope", "ErrorSection", "ErrorStatusCode" }, - } - }; - var openAIClient = new OpenAIClient(apimUri, new BearerTokenCredential(accessToken), clientOptions); - - IKernelBuilder builder = Kernel.CreateBuilder(); - builder.Services.AddLogging(c => c.SetMinimumLevel(LogLevel.Warning).AddConsole()); - builder.AddAzureOpenAIChatCompletion( - deploymentName: TestConfiguration.AzureOpenAI.ChatDeploymentName, - openAIClient: openAIClient); - Kernel kernel = builder.Build(); - - // Load semantic plugin defined with prompt templates - string folder = RepoFiles.SamplePluginsPath(); - - kernel.ImportPluginFromPromptDirectory(Path.Combine(folder, "FunPlugin")); - - // Run - var result = await kernel.InvokeAsync( - kernel.Plugins["FunPlugin"]["Excuses"], - new() { ["input"] = "I have no homework" } - ); - Console.WriteLine(result.GetValue()); - - httpClient.Dispose(); - } - - public Example52_ApimAuth(ITestOutputHelper output) : base(output) - { - } -} - -public class BearerTokenCredential : TokenCredential -{ - private readonly AccessToken _accessToken; - - // Constructor that takes a Bearer token string and its expiration date - public BearerTokenCredential(AccessToken accessToken) - { - this._accessToken = accessToken; - } - - public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken) - { - return this._accessToken; - } - - public override ValueTask GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken) - { - return new ValueTask(this._accessToken); - } -} diff --git a/dotnet/samples/KernelSyntaxExamples/Example52_CustomOpenAIClient.cs b/dotnet/samples/KernelSyntaxExamples/Example52_CustomOpenAIClient.cs new file mode 100644 index 000000000000..5512db6de839 --- /dev/null +++ b/dotnet/samples/KernelSyntaxExamples/Example52_CustomOpenAIClient.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using Azure; +using Azure.AI.OpenAI; +using Azure.Core.Pipeline; +using Microsoft.SemanticKernel; +using RepoUtils; + +public static class Example52_CustomOpenAIClient +{ + public static async Task RunAsync() + { + Console.WriteLine("======== Using a custom OpenAI client ========"); + + string endpoint = TestConfiguration.AzureOpenAI.Endpoint; + string deploymentName = TestConfiguration.AzureOpenAI.ChatDeploymentName; + string apiKey = TestConfiguration.AzureOpenAI.ApiKey; + + if (endpoint is null || deploymentName is null || apiKey is null) + { + Console.WriteLine("Azure OpenAI credentials not found. Skipping example."); + return; + } + + // Create an HttpClient and include your custom header(s) + var httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Add("x-my-custom-header", "My custom value"); + + // Configure OpenAIClient to use the customized HttpClient + var clientOptions = new OpenAIClientOptions + { + Transport = new HttpClientTransport(httpClient), + }; + var openAIClient = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(apiKey), clientOptions); + + IKernelBuilder builder = Kernel.CreateBuilder(); + builder.AddAzureOpenAIChatCompletion(deploymentName, openAIClient); + Kernel kernel = builder.Build(); + + // Load semantic plugin defined with prompt templates + string folder = RepoFiles.SamplePluginsPath(); + + kernel.ImportPluginFromPromptDirectory(Path.Combine(folder, "FunPlugin")); + + // Run + var result = await kernel.InvokeAsync( + kernel.Plugins["FunPlugin"]["Excuses"], + new() { ["input"] = "I have no homework" } + ); + Console.WriteLine(result.GetValue()); + + httpClient.Dispose(); + } +} diff --git a/dotnet/samples/KernelSyntaxExamples/README.md b/dotnet/samples/KernelSyntaxExamples/README.md index 4360c4b9b840..8c8996efa323 100644 --- a/dotnet/samples/KernelSyntaxExamples/README.md +++ b/dotnet/samples/KernelSyntaxExamples/README.md @@ -103,9 +103,6 @@ dotnet user-secrets set "Google:SearchEngineId" "..." dotnet user-secrets set "Github:PAT" "github_pat_..." -dotnet user-secrets set "Apim:Endpoint" "https://apim...azure-api.net/" -dotnet user-secrets set "Apim:SubscriptionKey" "..." - dotnet user-secrets set "Postgres:ConnectionString" "..." dotnet user-secrets set "Redis:Configuration" "..." dotnet user-secrets set "Kusto:ConnectionString" "..." @@ -173,10 +170,6 @@ Google__SearchEngineId # Github Github__PAT -# Azure API Management (APIM) -Apim__Endpoint -Apim__SubscriptionKey - # Other Postgres__ConnectionString Redis__Configuration