-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
196 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
using System.Net.Http; | ||
using Azure.AI.Projects; | ||
using Azure.Core; | ||
using Azure.Core.Pipeline; | ||
using Microsoft.SemanticKernel.Http; | ||
|
||
namespace Microsoft.SemanticKernel.Agents.AzureAI; | ||
|
||
/// <summary> | ||
/// Provides an <see cref="AIProjectClient"/> for use by <see cref="AzureAIAgent"/>. | ||
/// </summary> | ||
public sealed partial class AzureAIAgent : KernelAgent | ||
{ | ||
/// <summary> | ||
/// Produces a <see cref="AIProjectClient"/>. | ||
/// </summary> | ||
/// <param name="connectionString">The Azure AI Foundry project connection string, in the form `endpoint;subscription_id;resource_group_name;project_name`.</param> | ||
/// <param name="credential"> A credential used to authenticate to an Azure Service.</param> | ||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param> | ||
public static AIProjectClient CreateAzureAIClient( | ||
string connectionString, | ||
TokenCredential credential, | ||
HttpClient? httpClient = null) | ||
{ | ||
Verify.NotNullOrWhiteSpace(connectionString, nameof(connectionString)); | ||
Verify.NotNull(credential, nameof(credential)); | ||
|
||
AIProjectClientOptions clientOptions = CreateAzureClientOptions(httpClient); | ||
|
||
return new AIProjectClient(connectionString, credential, clientOptions); | ||
} | ||
|
||
private static AIProjectClientOptions CreateAzureClientOptions(HttpClient? httpClient) | ||
{ | ||
AIProjectClientOptions options = | ||
new() | ||
{ | ||
Diagnostics = { | ||
ApplicationId = HttpHeaderConstant.Values.UserAgent, | ||
} | ||
}; | ||
|
||
options.AddPolicy(new SemanticKernelHeadersPolicy(), HttpPipelinePosition.PerCall); | ||
|
||
if (httpClient is not null) | ||
{ | ||
options.Transport = new HttpClientTransport(httpClient); | ||
// Disable retry policy if and only if a custom HttpClient is provided. | ||
options.RetryPolicy = new RetryPolicy(maxRetries: 0); | ||
} | ||
|
||
return options; | ||
} | ||
|
||
private class SemanticKernelHeadersPolicy : HttpPipelineSynchronousPolicy | ||
{ | ||
public override void OnSendingRequest(HttpMessage message) | ||
{ | ||
message.Request.Headers.Add( | ||
HttpHeaderConstant.Names.SemanticKernelVersion, | ||
HttpHeaderConstant.Values.GetAssemblyVersion(typeof(AzureAIAgent))); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
dotnet/src/Agents/OpenAI/OpenAIAssistantAgent.ClientFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
using System; | ||
using System.ClientModel; | ||
using System.ClientModel.Primitives; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using Azure.AI.OpenAI; | ||
using Azure.Core; | ||
using Microsoft.SemanticKernel.Http; | ||
using OpenAI; | ||
|
||
namespace Microsoft.SemanticKernel.Agents.OpenAI; | ||
|
||
public sealed partial class OpenAIAssistantAgent : KernelAgent | ||
{ | ||
/// <summary> | ||
/// Specifies a key that avoids an exception from OpenAI Client when a custom endpoint is provided without an API key. | ||
/// </summary> | ||
private const string SingleSpaceKey = " "; | ||
|
||
/// <summary> | ||
/// Produces an <see cref="AzureOpenAIClient"/>. | ||
/// </summary> | ||
/// <param name="apiKey">The API key.</param> | ||
/// <param name="endpoint">The service endpoint.</param> | ||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param> | ||
public static AzureOpenAIClient CreateAzureOpenAIClient(ApiKeyCredential apiKey, Uri endpoint, HttpClient? httpClient = null) | ||
{ | ||
Verify.NotNull(apiKey, nameof(apiKey)); | ||
Verify.NotNull(endpoint, nameof(endpoint)); | ||
|
||
AzureOpenAIClientOptions clientOptions = CreateAzureClientOptions(httpClient); | ||
|
||
return new AzureOpenAIClient(endpoint, apiKey!, clientOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Produces an <see cref="AzureOpenAIClient"/>. | ||
/// </summary> | ||
/// <param name="credential">The credentials.</param> | ||
/// <param name="endpoint">The service endpoint.</param> | ||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param> | ||
public static AzureOpenAIClient CreateAzureOpenAIClient(TokenCredential credential, Uri endpoint, HttpClient? httpClient = null) | ||
{ | ||
Verify.NotNull(credential, nameof(credential)); | ||
Verify.NotNull(endpoint, nameof(endpoint)); | ||
|
||
AzureOpenAIClientOptions clientOptions = CreateAzureClientOptions(httpClient); | ||
|
||
return new AzureOpenAIClient(endpoint, credential, clientOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Produces an <see cref="OpenAIClient"/>. | ||
/// </summary> | ||
/// <param name="endpoint">An optional endpoint.</param> | ||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param> | ||
public static OpenAIClient CreateOpenAIClient(Uri? endpoint = null, HttpClient? httpClient = null) | ||
{ | ||
OpenAIClientOptions clientOptions = CreateOpenAIClientOptions(endpoint, httpClient); | ||
return new OpenAIClient(new ApiKeyCredential(SingleSpaceKey), clientOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Produces an <see cref="OpenAIClient"/>. | ||
/// </summary> | ||
/// <param name="apiKey">The API key.</param> | ||
/// <param name="endpoint">An optional endpoint.</param> | ||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param> | ||
public static OpenAIClient CreateOpenAIClient(ApiKeyCredential apiKey, Uri? endpoint = null, HttpClient? httpClient = null) | ||
{ | ||
OpenAIClientOptions clientOptions = CreateOpenAIClientOptions(endpoint, httpClient); | ||
return new OpenAIClient(apiKey, clientOptions); | ||
} | ||
|
||
private static AzureOpenAIClientOptions CreateAzureClientOptions(HttpClient? httpClient) | ||
{ | ||
AzureOpenAIClientOptions options = new() | ||
{ | ||
UserAgentApplicationId = HttpHeaderConstant.Values.UserAgent | ||
}; | ||
|
||
ConfigureClientOptions(httpClient, options); | ||
|
||
return options; | ||
} | ||
|
||
private static OpenAIClientOptions CreateOpenAIClientOptions(Uri? endpoint, HttpClient? httpClient) | ||
{ | ||
OpenAIClientOptions options = new() | ||
{ | ||
UserAgentApplicationId = HttpHeaderConstant.Values.UserAgent, | ||
Endpoint = endpoint ?? httpClient?.BaseAddress, | ||
}; | ||
|
||
ConfigureClientOptions(httpClient, options); | ||
|
||
return options; | ||
} | ||
|
||
private static void ConfigureClientOptions(HttpClient? httpClient, ClientPipelineOptions options) | ||
{ | ||
options.AddPolicy(CreateRequestHeaderPolicy(HttpHeaderConstant.Names.SemanticKernelVersion, HttpHeaderConstant.Values.GetAssemblyVersion(typeof(OpenAIAssistantAgent))), PipelinePosition.PerCall); | ||
|
||
if (httpClient is not null) | ||
{ | ||
options.Transport = new HttpClientPipelineTransport(httpClient); | ||
options.RetryPolicy = new ClientRetryPolicy(maxRetries: 0); // Disable retry policy if and only if a custom HttpClient is provided. | ||
options.NetworkTimeout = Timeout.InfiniteTimeSpan; // Disable default timeout | ||
} | ||
} | ||
|
||
private static GenericActionPipelinePolicy CreateRequestHeaderPolicy(string headerName, string headerValue) | ||
=> | ||
new((message) => | ||
{ | ||
if (message?.Request?.Headers?.TryGetValue(headerName, out string? _) == false) | ||
{ | ||
message.Request.Headers.Set(headerName, headerValue); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters