Skip to content

Commit

Permalink
New nugets (Abstractions, Connectors.AI.OpenAI); add AAD auth, Azure …
Browse files Browse the repository at this point in the history
…ChatGPT, text+chat streaming (#420)

### Motivation and Context

New features:
* AAD auth for Azure OpenAI
* Azure ChatGPT
* Completion streaming
* Chat streaming
* log probs

### Description

* Split kernel core nuget in 3 nugets and add dependency on Azure OpenAI
SDK:
* MS.SK.Abstractions: interfaces and common classes, ideally no business
logic
  * MS.SK: SK runtime, depends on SK.Abstractions
* MS.SK.Connectors.AI.OpenAI: OpenAI/Azure OpenAI code, depends on
SK.Abstractions and Azure OpenAI SDK
* Rewrote TextCompletion, ChatCompletion, EmbeddingGeneration clients to
use Azure OpenAI SDK
* Deleted unused code. The old OpenAI client is still in use only for
DALL-E2

Note: custom retry logic doesn't work with Azure OpenAI SDK. The SDK
already retries internally, using a different approach.

Nugets:
* Microsoft.SemanticKernel.0.12.0.nupkg
* **Microsoft.SemanticKernel.Abstractions.0.12.0.nupkg**
* **Microsoft.SemanticKernel.Connectors.AI.OpenAI.0.12.0.nupkg**
* Microsoft.SemanticKernel.Connectors.Memory.Qdrant.0.12.0.nupkg
* Microsoft.SemanticKernel.Connectors.Memory.Sqlite.0.12.0.nupkg
* Microsoft.SemanticKernel.Skills.MsGraph.0.12.0.nupkg
* Microsoft.SemanticKernel.Skills.Document.0.12.0.nupkg
* Microsoft.SemanticKernel.Skills.OpenAPI.0.12.0.nupkg
* Microsoft.SemanticKernel.Skills.Web.0.12.0.nupkg
  • Loading branch information
dluc authored Apr 14, 2023
1 parent bc2d7d7 commit 8621c7b
Show file tree
Hide file tree
Showing 153 changed files with 1,608 additions and 1,728 deletions.
40 changes: 32 additions & 8 deletions .github/workflows/markdown-link-check-config.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
{
"ignorePatterns": [
{ "pattern": "/github/" },
{ "pattern": "./actions" },
{ "pattern": "./blob" },
{ "pattern": "./issues" },
{ "pattern": "./discussions" },
{ "pattern": "./pulls" }
{
"pattern": "/github/"
},
{
"pattern": "./actions"
},
{
"pattern": "./blob"
},
{
"pattern": "./issues"
},
{
"pattern": "./discussions"
},
{
"pattern": "./pulls"
},
{
"pattern": "^http://localhost"
},
{
"pattern": "^https://localhost"
}
],
"timeout": "20s",
"retryOn429": true,
"retryCount": 3,
"fallbackRetryDelay": "30s",
"aliveStatusCodes": [200, 206]
}
"aliveStatusCodes": [
200,
206,
429,
500,
503
]
}
1 change: 1 addition & 0 deletions dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Text.Json" Version="7.0.2" />
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.5" />

<!-- Microsoft.Extensions.Logging -->
<PackageVersion Include="Microsoft.Extensions.Logging" Version="7.0.0" />
Expand Down
14 changes: 14 additions & 0 deletions dotnet/SK-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.Sqlite",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.CosmosDB", "src\Connectors\Connectors.Memory.CosmosDB\Connectors.Memory.CosmosDB.csproj", "{EA61C289-7928-4B78-A9C1-7AAD61F907CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Connectors.AI.OpenAI", "src\Connectors\Connectors.AI.OpenAI\Connectors.AI.OpenAI.csproj", "{AFA81EB7-F869-467D-8A90-744305D80AAC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SemanticKernel.Abstractions", "src\SemanticKernel.Abstractions\SemanticKernel.Abstractions.csproj", "{627742DB-1E52-468A-99BD-6FF1A542D25B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -153,6 +157,14 @@ Global
{EA61C289-7928-4B78-A9C1-7AAD61F907CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA61C289-7928-4B78-A9C1-7AAD61F907CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA61C289-7928-4B78-A9C1-7AAD61F907CD}.Release|Any CPU.Build.0 = Release|Any CPU
{AFA81EB7-F869-467D-8A90-744305D80AAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFA81EB7-F869-467D-8A90-744305D80AAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFA81EB7-F869-467D-8A90-744305D80AAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFA81EB7-F869-467D-8A90-744305D80AAC}.Release|Any CPU.Build.0 = Release|Any CPU
{627742DB-1E52-468A-99BD-6FF1A542D25B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{627742DB-1E52-468A-99BD-6FF1A542D25B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{627742DB-1E52-468A-99BD-6FF1A542D25B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{627742DB-1E52-468A-99BD-6FF1A542D25B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -181,6 +193,8 @@ Global
{5DEBAA62-F117-496A-8778-FED3604B70E2} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C}
{EC004F12-2F60-4EDD-B3CD-3A504900D929} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C}
{EA61C289-7928-4B78-A9C1-7AAD61F907CD} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C}
{AFA81EB7-F869-467D-8A90-744305D80AAC} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C}
{627742DB-1E52-468A-99BD-6FF1A542D25B} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FBDC56A3-86AD-4323-AA0F-201E59123B83}
Expand Down
1 change: 1 addition & 0 deletions dotnet/SK-dotnet.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ public void It$SOMENAME$()
<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/=davinci/@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/=lessthan/@EntryIndexedValue">True</s:Boolean>
Expand Down
2 changes: 1 addition & 1 deletion dotnet/nuget/nuget-package.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPackable>true</IsPackable>
<!-- Central version prefix - applies to all nuget packages -->
<Version>0.11</Version>
<Version>0.12</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft. All rights reserved.

using Azure.Core;
using Azure.Core.Pipeline;

namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.AzureSdk;

/// <summary>
/// Helper class to inject headers into Azure SDK HTTP pipeline
/// </summary>
internal class AddHeaderRequestPolicy : HttpPipelineSynchronousPolicy
{
private readonly string _headerName;
private readonly string _headerValue;

public AddHeaderRequestPolicy(string headerName, string headerValue)
{
this._headerName = headerName;
this._headerValue = headerValue;
}

public override void OnSendingRequest(HttpMessage message)
{
message.Request.Headers.Add(this._headerName, this._headerValue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using Azure;
using Azure.AI.OpenAI;
using Azure.Core;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel.Diagnostics;
using Microsoft.SemanticKernel.Reliability;

namespace Microsoft.SemanticKernel.Connectors.AI.OpenAI.AzureSdk;

public abstract class AzureOpenAIClientBase : ClientBase
{
/// <summary>
/// OpenAI / Azure OpenAI Client
/// </summary>
protected override OpenAIClient Client { get; }

/// <summary>
/// Creates a new AzureTextCompletion client instance using API Key auth
/// </summary>
/// <param name="modelId">Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource</param>
/// <param name="endpoint">Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart</param>
/// <param name="apiKey">Azure OpenAI API key, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart</param>
/// <param name="handlerFactory">Retry handler factory for HTTP requests.</param>
/// <param name="log">Application logger</param>
protected AzureOpenAIClientBase(
string modelId,
string endpoint,
string apiKey,
IDelegatingHandlerFactory? handlerFactory = null,
ILogger? log = null)
{
Verify.NotEmpty(modelId, "The Model Id/Deployment Name cannot be empty");
this.ModelId = modelId;

var options = new OpenAIClientOptions();

// TODO: reimplement
// Doesn't work
// if (handlerFactory != null)
// {
// options.Transport = new HttpClientTransport(handlerFactory.Create(log));
// }

Verify.NotEmpty(endpoint, "The Azure endpoint cannot be empty");
Verify.StartsWith(endpoint, "https://", "The Azure OpenAI endpoint must start with 'https://'");
Verify.NotEmpty(apiKey, "The Azure API key cannot be empty");
this.Client = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(apiKey), options);
}

/// <summary>
/// Creates a new AzureTextCompletion client instance supporting AAD auth
/// </summary>
/// <param name="modelId">Azure OpenAI model ID or deployment name, see https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource</param>
/// <param name="endpoint">Azure OpenAI deployment URL, see https://learn.microsoft.com/azure/cognitive-services/openai/quickstart</param>
/// <param name="credentials">Token credentials, e.g. DefaultAzureCredential, ManagedIdentityCredential, EnvironmentCredential, etc.</param>
/// <param name="handlerFactory">Retry handler factory for HTTP requests.</param>
/// <param name="log">Application logger</param>
protected AzureOpenAIClientBase(
string modelId,
string endpoint,
TokenCredential credentials,
IDelegatingHandlerFactory? handlerFactory = null,
ILogger? log = null)
{
Verify.NotEmpty(modelId, "The Model Id/Deployment Name cannot be empty");
this.ModelId = modelId;

var options = new OpenAIClientOptions();

// TODO: reimplement
// Doesn't work
// if (handlerFactory != null)
// {
// options.Transport = new HttpClientTransport(handlerFactory.Create(log));
// }

Verify.NotEmpty(endpoint, "The Azure endpoint cannot be empty");
Verify.StartsWith(endpoint, "https://", "The Azure OpenAI endpoint must start with 'https://'");
this.Client = new OpenAIClient(new Uri(endpoint), credentials, options);
}
}
Loading

0 comments on commit 8621c7b

Please sign in to comment.