diff --git a/OpenAI-DotNet.sln b/OpenAI-DotNet.sln index 85eae7ee..22d9c2ad 100644 --- a/OpenAI-DotNet.sln +++ b/OpenAI-DotNet.sln @@ -11,11 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI-DotNet-Tests", "Open EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI-DotNet-Tests-Proxy", "OpenAI-DotNet-Tests-Proxy\OpenAI-DotNet-Tests-Proxy.csproj", "{F8B5D079-FD33-4A9E-92C4-CC88C911CFF3}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{01FAF825-F72B-4FBD-9CFF-57FDAB089F36}" - ProjectSection(SolutionItems) = preProject - Directory.Build.props = Directory.Build.props - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/OpenAI-DotNet/Models/ModelsEndpoint.cs b/OpenAI-DotNet/Models/ModelsEndpoint.cs index 22b23612..5670550a 100644 --- a/OpenAI-DotNet/Models/ModelsEndpoint.cs +++ b/OpenAI-DotNet/Models/ModelsEndpoint.cs @@ -9,7 +9,7 @@ namespace OpenAI.Models { /// /// List and describe the various models available in the API. - /// You can refer to the Models documentation to understand what are available and the differences between them. + /// You can refer to the Models documentation to understand what are available and the differences between them.
/// ///
public sealed class ModelsEndpoint : BaseEndPoint diff --git a/OpenAI-DotNet/OpenAI-DotNet.csproj b/OpenAI-DotNet/OpenAI-DotNet.csproj index fc0d8d55..1bc74194 100644 --- a/OpenAI-DotNet/OpenAI-DotNet.csproj +++ b/OpenAI-DotNet/OpenAI-DotNet.csproj @@ -17,7 +17,9 @@ More context [on Roger Pincombe's blog](https://rogerpincombe.com/openai-dotnet- https://github.com/RageAgainstThePixel/OpenAI-DotNet OpenAI, AI, ML, API, gpt-4, gpt-3.5-tubo, gpt-3, chatGPT, chat-gpt, gpt-2, gpt OpenAI API - Bump version to 6.4.2 + Bump version to 6.4.3 +- Fixed support for Azure Active Directory authentication for Azure OpenAI +Bump version to 6.4.2 - Misc fixes and added validation for OpenAICLientSettings - Updated docs - Decoupled proxy version from main package @@ -92,7 +94,7 @@ Bump version to 4.4.0 OpenAI-DotNet.pfx true OpenAI-DotNet - 6.4.2 + 6.4.3 RageAgainstThePixel README.md Assets\OpenAI-DotNet-Icon.png diff --git a/OpenAI-DotNet/OpenAIClient.cs b/OpenAI-DotNet/OpenAIClient.cs index cdd8d411..34669d75 100644 --- a/OpenAI-DotNet/OpenAIClient.cs +++ b/OpenAI-DotNet/OpenAIClient.cs @@ -84,15 +84,16 @@ private HttpClient SetupClient(HttpClient client = null) client ??= new HttpClient(); client.DefaultRequestHeaders.Add("User-Agent", "OpenAI-DotNet"); - if (!OpenAIClientSettings.BaseRequestUrlFormat.Contains(OpenAIClientSettings.AzureOpenAIDomain)) - { - if (string.IsNullOrWhiteSpace(OpenAIAuthentication.ApiKey) || + if (!OpenAIClientSettings.BaseRequestUrlFormat.Contains(OpenAIClientSettings.AzureOpenAIDomain) + && (string.IsNullOrWhiteSpace(OpenAIAuthentication.ApiKey) || (!OpenAIAuthentication.ApiKey.Contains(AuthInfo.SecretKeyPrefix) && - !OpenAIAuthentication.ApiKey.Contains(AuthInfo.SessionKeyPrefix))) - { - throw new InvalidCredentialException($"{OpenAIAuthentication.ApiKey} must start with '{AuthInfo.SecretKeyPrefix}'"); - } + !OpenAIAuthentication.ApiKey.Contains(AuthInfo.SessionKeyPrefix)))) + { + throw new InvalidCredentialException($"{OpenAIAuthentication.ApiKey} must start with '{AuthInfo.SecretKeyPrefix}'"); + } + if (OpenAIClientSettings.UseOAuthAuthentication) + { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", OpenAIAuthentication.ApiKey); } else @@ -130,6 +131,8 @@ private HttpClient SetupClient(HttpClient client = null) /// /// List and describe the various models available in the API. + /// You can refer to the Models documentation to understand what are available and the differences between them.
+ /// ///
public ModelsEndpoint ModelsEndpoint { get; } diff --git a/OpenAI-DotNet/OpenAIClientSettings.cs b/OpenAI-DotNet/OpenAIClientSettings.cs index 603345d4..0dab6abb 100644 --- a/OpenAI-DotNet/OpenAIClientSettings.cs +++ b/OpenAI-DotNet/OpenAIClientSettings.cs @@ -22,6 +22,7 @@ public OpenAIClientSettings() DeploymentId = string.Empty; BaseRequest = $"/{ApiVersion}/"; BaseRequestUrlFormat = $"https://{ResourceName}{BaseRequest}{{0}}"; + UseOAuthAuthentication = true; } /// @@ -52,6 +53,7 @@ public OpenAIClientSettings(string domain, string apiVersion = DefaultOpenAIApiV DeploymentId = string.Empty; BaseRequest = $"/{ApiVersion}/"; BaseRequestUrlFormat = $"https://{ResourceName}{BaseRequest}{{0}}"; + UseOAuthAuthentication = true; } /// @@ -67,7 +69,10 @@ public OpenAIClientSettings(string domain, string apiVersion = DefaultOpenAIApiV /// /// Optional, defaults to 2022-12-01 /// - public OpenAIClientSettings(string resourceName, string deploymentId, string apiVersion = DefaultAzureApiVersion) + /// + /// Optional, set to true if you want to use Azure Active Directory for Authentication. + /// + public OpenAIClientSettings(string resourceName, string deploymentId, string apiVersion = DefaultAzureApiVersion, bool useActiveDirectoryAuthentication = false) { if (string.IsNullOrWhiteSpace(resourceName)) { @@ -90,6 +95,7 @@ public OpenAIClientSettings(string resourceName, string deploymentId, string api ApiVersion = apiVersion; BaseRequest = $"/openai/deployments/{DeploymentId}/"; BaseRequestUrlFormat = $"https://{ResourceName}.{AzureOpenAIDomain}{BaseRequest}{{0}}?api-version={ApiVersion}"; + UseOAuthAuthentication = useActiveDirectoryAuthentication; } public string ResourceName { get; } @@ -102,6 +108,8 @@ public OpenAIClientSettings(string resourceName, string deploymentId, string api internal string BaseRequestUrlFormat { get; } + internal bool UseOAuthAuthentication { get; } + public static OpenAIClientSettings Default { get; } = new OpenAIClientSettings(); } } diff --git a/README.md b/README.md index 23371ece..795bc80f 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Install-Package OpenAI-DotNet - [Authentication](#authentication) - [Azure OpenAI](#azure-openai) + - [Azure Active Directory Authentication](#azure-active-directory-authentication) :new: - [OpenAI API Proxy](#openai-api-proxy) :new: - [Models](#models) - [List Models](#list-models) @@ -150,6 +151,20 @@ var settings = new OpenAIClientSettings(resourceName: "your-resource", deploymen var api = new OpenAIClient(auth, settings); ``` +#### [Azure Active Directory Authentication](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/reference#authentication) + +[Authenticate with MSAL](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) as usual and get access token, then use the access token when creating your `OpenAIAuthentication`. Then be sure to set useAzureActiveDirectory to true when creating your `OpenAIClientSettings`. + +[Tutorial: Desktop app that calls web APIs: Acquire a token](https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-desktop-acquire-token?tabs=dotnet) + +```csharp +// get your access token using any of the MSAL methods +var accessToken = result.AccessToken; +var auth = new OpenAIAuthentication(accessToken); +var settings = new OpenAIClientSettings(resourceName: "your-resource", deploymentId: "your-deployment-id", useActiveDirectoryAuthentication: true); +var api = new OpenAIClient(auth, settings); +``` + ### [OpenAI API Proxy](OpenAI-DotNet-Proxy/Readme.md) [![NuGet version (OpenAI-DotNet-Proxy)](https://img.shields.io/nuget/v/OpenAI-DotNet-Proxy.svg?label=OpenAI-DotNet-Proxy&logo=nuget)](https://www.nuget.org/packages/OpenAI-DotNet-Proxy/)