Files
semantic-kernel/dotnet/samples/KernelSyntaxExamples/Example52_ApimAuth.cs
T
2e84b30e21 .Net: Change public APIs to accept ILoggerFactory (#2472)
### Motivation and Context

Following best practices for libraries outlined at
https://learn.microsoft.com/en-us/dotnet/core/extensions/logging-library-authors,
SK should generally be taking an ILoggerFactory rather than an ILogger.
This allows individual components to each get a logger with its own
category applied.

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄

---------

Co-authored-by: Shawn Callegari <[email protected]>
Co-authored-by: Lee Miller <[email protected]>
2023-08-21 23:39:58 +00:00

106 lines
3.9 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System;
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.Logging;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.AI.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.AI.OpenAI.ChatCompletion;
using Microsoft.SemanticKernel.Diagnostics;
using RepoUtils;
// ReSharper disable once InconsistentNaming
public static class Example52_ApimAuth
{
public static 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" },
ApplicationId = Telemetry.HttpUserAgent,
IsTelemetryEnabled = Telemetry.IsTelemetryEnabled,
}
};
var openAIClient = new OpenAIClient(apimUri, new BearerTokenCredential(accessToken), clientOptions);
// Create logger factory with default level as warning
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder
.SetMinimumLevel(LogLevel.Warning)
.AddConsole();
});
var kernel = Kernel.Builder
.WithLoggerFactory(loggerFactory)
.WithAIService<IChatCompletion>(TestConfiguration.AzureOpenAI.ChatDeploymentName, (loggerFactory, config) =>
new AzureChatCompletion(TestConfiguration.AzureOpenAI.ChatDeploymentName, openAIClient, loggerFactory))
.Build();
// Load semantic skill defined with prompt templates
string folder = RepoFiles.SampleSkillsPath();
var funSkill = kernel.ImportSemanticSkillFromDirectory(
folder,
"FunSkill");
// Run
var result = await kernel.RunAsync(
"I have no homework",
funSkill["Excuses"]
);
Console.WriteLine(result);
httpClient.Dispose();
}
}
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<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
{
return new ValueTask<AccessToken>(this._accessToken);
}
}