Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed DI issue and Cleaned up code #77

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ public async Task ShouldPromptCompletionAsync()
Completion expectedCompletion = inputCompletion.DeepClone();
expectedCompletion = ConvertToCompletion(inputCompletion, completionResponse);

var jsonSerializationSettings = new JsonSerializerSettings();
jsonSerializationSettings.DefaultValueHandling = DefaultValueHandling.Ignore;
JsonSerializerSettings jsonSerializationSettings = new()
{
DefaultValueHandling = DefaultValueHandling.Ignore,
};

this.wireMockServer.Given(
Request.Create()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public partial class CompletionClientTests : IDisposable
private readonly string apiKey;
private readonly string organizationId;

/// <summary>
/// Initializes a new instance of the <see cref="CompletionClientTests"/> class.
/// </summary>
public CompletionClientTests()
{
this.wireMockServer = WireMockServer.Start(1989);
Expand All @@ -30,7 +33,7 @@ public CompletionClientTests()
{
ApiUrl = "http://localhost:1989",
ApiKey = this.apiKey,
OrganizationId = this.organizationId
OrganizationId = this.organizationId,
};

this.openAIClient = new OpenAIClient(openAiConfiguration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private static dynamic CreateRandomCompletionProperties()
Created = GetRandomNumber(),
ResponseModel = GetRandomString(),
Choices = CreateRandomChoicesList(),
Usage = CreateRandomUsage()
Usage = CreateRandomUsage(),
};
}

Expand Down
54 changes: 54 additions & 0 deletions OpenAI.NET/Brokers/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Microsoft.Extensions.DependencyInjection;

using OpenAI.NET.Brokers.HttpMessageHandlers;
using OpenAI.NET.Brokers.OpenAIs;
using OpenAI.NET.Models.Configurations;

using RESTFulSense.Clients;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace OpenAI.NET.Brokers
{
internal static class DependencyInjection
{
public static IServiceCollection AddBrokers(
this IServiceCollection services)
{
services
.AddRestfulHttpClient()
.AddScoped<IOpenAIBroker, OpenAIBroker>();

return services;
}

private static IServiceCollection AddRestfulHttpClient(
this IServiceCollection services)
{
services
.AddHttpClient<RESTFulApiFactoryClient>((configuration, httpClient) =>
{
ApiConfigurations apiConfigurations = configuration.GetRequiredService<ApiConfigurations>();
httpClient.BaseAddress = new Uri(uriString: apiConfigurations.ApiUrl);
})
.AddHttpMessageHandler<AuthorizationMessageHandler>()
.Services
.AddScoped<AuthorizationMessageHandler>();

services
.AddScoped<IRESTFulApiFactoryClient>(configuration =>
{
IHttpClientFactory clientFactory = configuration.GetRequiredService<IHttpClientFactory>();
HttpClient httpClient = clientFactory.CreateClient(nameof(RESTFulApiFactoryClient));
return new RESTFulApiFactoryClient(httpClient);
});

return services;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;

using OpenAI.NET.Models.Configurations;

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;

namespace OpenAI.NET.Brokers.HttpMessageHandlers
{
internal class AuthorizationMessageHandler : DelegatingHandler
{
private const string OpenAIOrganizationIdHeaderKey = "OpenAI-Organization";
private readonly ApiConfigurations apiConfigurations;

public AuthorizationMessageHandler(ApiConfigurations apiConfigurations)
{
this.apiConfigurations = apiConfigurations;
}

protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
{
this.AddRequestHeaders(request);

return base.Send(request, cancellationToken);
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
this.AddRequestHeaders(request);

return base.SendAsync(request, cancellationToken);
}

private void AddRequestHeaders(HttpRequestMessage request)
{
request.Headers.Add(
name: OpenAIOrganizationIdHeaderKey,
value: this.apiConfigurations.OrganizationId);

request.Headers.Authorization ??=
new AuthenticationHeaderValue(
scheme: JwtBearerDefaults.AuthenticationScheme,
parameter: this.apiConfigurations.ApiKey);
}
}
}
45 changes: 12 additions & 33 deletions OpenAI.NET/Brokers/OpenAIs/OpenAIBroker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@
// Copyright (c) Coalition of the Good-Hearted Engineers
// ---------------------------------------------------------------

using Microsoft.Extensions.DependencyInjection;

using RESTFulSense.Clients;

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Threading.Tasks;
using OpenAI.NET.Models.Configurations;
using RESTFulSense.Clients;

namespace OpenAI.NET.Brokers.OpenAIs
{
internal partial class OpenAIBroker : IOpenAIBroker
{
private readonly ApiConfigurations apiConfigurations;
private readonly IRESTFulApiFactoryClient apiClient;
private readonly HttpClient httpClient;

public OpenAIBroker(ApiConfigurations apiConfigurations)
/// <summary>
/// Initializes a new instance of the <see cref="OpenAIBroker"/> class.
/// </summary>
/// <param name="apiClient">The RESTFulSenses Api Client.</param>
public OpenAIBroker(IRESTFulApiFactoryClient apiClient)
{
this.apiConfigurations = apiConfigurations;
this.httpClient = SetupHttpClient();
this.apiClient = SetupApiClient();
this.apiClient = apiClient;
}

private async ValueTask<T> GetAsync<T>(string relativeUrl) =>
Expand All @@ -35,7 +37,7 @@ private async ValueTask<TResult> PostAsync<TRequest, TResult>(string relativeUrl
return await this.apiClient.PostContentAsync<TRequest, TResult>(
relativeUrl,
content,
mediaType: "application/json",
mediaType: MediaTypeNames.Application.Json,
ignoreNulls: true);
}

Expand All @@ -45,28 +47,5 @@ private async ValueTask<T> PutAsync<T>(string relativeUrl, T content) =>

private async ValueTask<T> DeleteAsync<T>(string relativeUrl) =>
await this.apiClient.DeleteContentAsync<T>(relativeUrl);

private HttpClient SetupHttpClient()
{
var httpClient = new HttpClient()
{
BaseAddress =
new Uri(uriString: this.apiConfigurations.ApiUrl),
};

httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(
scheme: "Bearer",
parameter: this.apiConfigurations.ApiKey);

httpClient.DefaultRequestHeaders.Add(
name: "OpenAI-Organization",
value: this.apiConfigurations.OrganizationId);

return httpClient;
}

private IRESTFulApiFactoryClient SetupApiClient() =>
new RESTFulApiFactoryClient(this.httpClient);
}
}
11 changes: 8 additions & 3 deletions OpenAI.NET/Clients/OpenAIs/OpenAIClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenAI.NET.Brokers.OpenAIs;

using OpenAI.NET.Brokers;
using OpenAI.NET.Clients.Completions;
using OpenAI.NET.Models.Configurations;
using OpenAI.NET.Services.Foundations.Completions;
Expand All @@ -13,6 +14,10 @@ namespace OpenAI.NET.Clients.OpenAIs
{
public class OpenAIClient : IOpenAIClient
{
/// <summary>
/// Initializes a new instance of the <see cref="OpenAIClient"/> class.
/// </summary>
/// <param name="apiConfigurations">The api configurations.</param>
public OpenAIClient(ApiConfigurations apiConfigurations)
{
IHost host = RegisterServices(apiConfigurations);
Expand All @@ -30,10 +35,10 @@ private static IHost RegisterServices(ApiConfigurations apiConfigurations)

builder.ConfigureServices(configuration =>
{
configuration.AddTransient<IOpenAIBroker, OpenAIBroker>();
configuration.AddSingleton(_ => apiConfigurations);
configuration.AddBrokers();
configuration.AddTransient<ICompletionService, CompletionService>();
configuration.AddTransient<ICompletionsClient, CompletionsClient>();
configuration.AddSingleton(options => apiConfigurations);
});

IHost host = builder.Build();
Expand Down
2 changes: 2 additions & 0 deletions OpenAI.NET/OpenAI.NET.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="RESTFulSense" Version="2.11.0" />
</ItemGroup>

Expand Down