From 350ae6fcd48a5a287af9bb40eae3a66b2ea9c4e8 Mon Sep 17 00:00:00 2001 From: Rodion Mostovoi Date: Sat, 21 Oct 2023 03:09:31 +0800 Subject: [PATCH] Add registration of IOpenAiClient as a dependency --- samples/ChatGpt.BlazorExample/Program.cs | 3 +- src/Directory.Build.props | 2 +- .../ChatGPTFactory.cs | 7 +--- .../Extensions/ServiceCollectionExtensions.cs | 37 +++++++++++++++++-- .../Extensions/ServiceCollectionExtensions.cs | 5 ++- src/OpenAI.ChatGpt/OpenAI.ChatGpt.csproj | 1 + src/OpenAI.ChatGpt/OpenAiClient.cs | 3 +- .../ChatGptServicesIntegrationTests.cs | 1 + 8 files changed, 44 insertions(+), 15 deletions(-) diff --git a/samples/ChatGpt.BlazorExample/Program.cs b/samples/ChatGpt.BlazorExample/Program.cs index 12ce7af..bac98a6 100644 --- a/samples/ChatGpt.BlazorExample/Program.cs +++ b/samples/ChatGpt.BlazorExample/Program.cs @@ -10,7 +10,8 @@ // make sure that you have added the OpenAICredentials:ApiKey to your secrets.json // or environment variables builder.Services.AddChatGptEntityFrameworkIntegration( - options => options.UseSqlite("Data Source=chats.db")); + options => options.UseSqlite("Data Source=chats.db")) + .AddServerSideBlazor(); var app = builder.Build(); diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 91d5f22..35874f0 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - 2.8.0 + 2.9.0 enable enable 12 diff --git a/src/OpenAI.ChatGpt.AspNetCore/ChatGPTFactory.cs b/src/OpenAI.ChatGpt.AspNetCore/ChatGPTFactory.cs index 6153511..637c044 100644 --- a/src/OpenAI.ChatGpt.AspNetCore/ChatGPTFactory.cs +++ b/src/OpenAI.ChatGpt.AspNetCore/ChatGPTFactory.cs @@ -7,10 +7,7 @@ namespace OpenAI.ChatGpt.AspNetCore; /// Factory for creating instances from DI. /// /// -/// builder.Services.AddHttpClient<ChatGPTFactory<(client => -/// { -/// client.DefaultRequestHeaders.Authorization = builder.Configuration["OpenAICredentials:ApiKey"]; -/// }) +/// builder.Services.AddHttpClient<ChatGPTFactory<("OpenAiClient") /// .AddPolicyHandler(GetRetryPolicy()) /// .AddPolicyHandler(GetCircuitBreakerPolicy()); /// @@ -72,7 +69,7 @@ private OpenAiClient CreateOpenAiClient( IHttpClientFactory httpClientFactory, IOptions credentials) { - var httpClient = httpClientFactory.CreateClient(nameof(ChatGPTFactory)); + var httpClient = httpClientFactory.CreateClient(OpenAiClient.HttpClientName); httpClient.DefaultRequestHeaders.Authorization = credentials.Value.GetAuthHeader(); httpClient.BaseAddress = new Uri(credentials.Value.ApiHost); return new OpenAiClient(httpClient); diff --git a/src/OpenAI.ChatGpt.AspNetCore/Extensions/ServiceCollectionExtensions.cs b/src/OpenAI.ChatGpt.AspNetCore/Extensions/ServiceCollectionExtensions.cs index 3637117..b9b002e 100644 --- a/src/OpenAI.ChatGpt.AspNetCore/Extensions/ServiceCollectionExtensions.cs +++ b/src/OpenAI.ChatGpt.AspNetCore/Extensions/ServiceCollectionExtensions.cs @@ -13,6 +13,7 @@ public static class ServiceCollectionExtensions public static IServiceCollection AddChatGptInMemoryIntegration( this IServiceCollection services, bool injectInMemoryChatService = true, + bool injectOpenAiClient = true, string credentialsConfigSectionPath = CredentialsConfigSectionPathDefault, string completionsConfigSectionPath = ChatGPTConfigSectionPathDefault) { @@ -27,12 +28,17 @@ public static IServiceCollection AddChatGptInMemoryIntegration( throw new ArgumentException("Value cannot be null or whitespace.", nameof(completionsConfigSectionPath)); } - services.AddChatGptIntegrationCore(credentialsConfigSectionPath, completionsConfigSectionPath); + services.AddChatGptIntegrationCore( + credentialsConfigSectionPath, + completionsConfigSectionPath, + injectOpenAiClient: injectOpenAiClient + ); services.AddSingleton(); if(injectInMemoryChatService) { services.AddScoped(CreateChatService); } + return services; } @@ -62,7 +68,8 @@ public static IServiceCollection AddChatGptIntegrationCore( this IServiceCollection services, string credentialsConfigSectionPath = CredentialsConfigSectionPathDefault, string completionsConfigSectionPath = ChatGPTConfigSectionPathDefault, - ServiceLifetime serviceLifetime = ServiceLifetime.Scoped + ServiceLifetime serviceLifetime = ServiceLifetime.Scoped, + bool injectOpenAiClient = true ) { ArgumentNullException.ThrowIfNull(services); @@ -86,12 +93,34 @@ public static IServiceCollection AddChatGptIntegrationCore( .Configure(_ => { }) //optional .ValidateDataAnnotations() .ValidateOnStart(); - - services.AddHttpClient(); + + if (services.All(it => it.ServiceType != typeof(IHttpClientFactory))) + { + services.AddHttpClient(OpenAiClient.HttpClientName); + } services.AddSingleton(); services.Add(new ServiceDescriptor(typeof(ChatGPTFactory), typeof(ChatGPTFactory), serviceLifetime)); + if (injectOpenAiClient) + { + AddOpenAiClient(services); + } + return services; } + + private static void AddOpenAiClient(IServiceCollection services) + { + services.AddSingleton(provider => + { + var credentials = provider.GetRequiredService>().Value; + var factory = provider.GetRequiredService(); + var httpClient = factory.CreateClient(OpenAiClient.HttpClientName); + httpClient.DefaultRequestHeaders.Authorization = credentials.GetAuthHeader(); + httpClient.BaseAddress = new Uri(credentials.ApiHost); + var client = new OpenAiClient(httpClient); + return client; + }); + } } \ No newline at end of file diff --git a/src/OpenAI.ChatGpt.EntityFrameworkCore/Extensions/ServiceCollectionExtensions.cs b/src/OpenAI.ChatGpt.EntityFrameworkCore/Extensions/ServiceCollectionExtensions.cs index db7cf86..6cb201d 100644 --- a/src/OpenAI.ChatGpt.EntityFrameworkCore/Extensions/ServiceCollectionExtensions.cs +++ b/src/OpenAI.ChatGpt.EntityFrameworkCore/Extensions/ServiceCollectionExtensions.cs @@ -14,7 +14,8 @@ public static IServiceCollection AddChatGptEntityFrameworkIntegration( Action optionsAction, string credentialsConfigSectionPath = CredentialsConfigSectionPathDefault, string completionsConfigSectionPath = ChatGPTConfigSectionPathDefault, - ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) + ServiceLifetime serviceLifetime = ServiceLifetime.Scoped, + bool injectOpenAiClient = true) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(optionsAction); @@ -30,7 +31,7 @@ public static IServiceCollection AddChatGptEntityFrameworkIntegration( } services.AddChatGptIntegrationCore( - credentialsConfigSectionPath, completionsConfigSectionPath, serviceLifetime); + credentialsConfigSectionPath, completionsConfigSectionPath, serviceLifetime, injectOpenAiClient); services.AddDbContext(optionsAction, serviceLifetime); switch (serviceLifetime) { diff --git a/src/OpenAI.ChatGpt/OpenAI.ChatGpt.csproj b/src/OpenAI.ChatGpt/OpenAI.ChatGpt.csproj index 0957f40..9ec483e 100644 --- a/src/OpenAI.ChatGpt/OpenAI.ChatGpt.csproj +++ b/src/OpenAI.ChatGpt/OpenAI.ChatGpt.csproj @@ -27,6 +27,7 @@ + diff --git a/src/OpenAI.ChatGpt/OpenAiClient.cs b/src/OpenAI.ChatGpt/OpenAiClient.cs index 69dffc8..24e35f4 100644 --- a/src/OpenAI.ChatGpt/OpenAiClient.cs +++ b/src/OpenAI.ChatGpt/OpenAiClient.cs @@ -6,7 +6,6 @@ using OpenAI.ChatGpt.Exceptions; using OpenAI.ChatGpt.Models.ChatCompletion; using OpenAI.ChatGpt.Models.ChatCompletion.Messaging; -using OpenAI.ChatGpt.Models.Images; namespace OpenAI.ChatGpt; @@ -14,8 +13,8 @@ namespace OpenAI.ChatGpt; [Fody.ConfigureAwait(false)] public class OpenAiClient : IOpenAiClient, IDisposable { + internal const string HttpClientName = "OpenAiClient"; private const string DefaultHost = "https://api.openai.com/v1/"; - private const string ImagesEndpoint = "images/generations"; private const string ChatCompletionsEndpoint = "chat/completions"; private static readonly Uri DefaultHostUri = new(DefaultHost); diff --git a/tests/OpenAI.ChatGpt.UnitTests/DependencyInjectionTests/ChatGptServicesIntegrationTests.cs b/tests/OpenAI.ChatGpt.UnitTests/DependencyInjectionTests/ChatGptServicesIntegrationTests.cs index bb61b16..3713630 100644 --- a/tests/OpenAI.ChatGpt.UnitTests/DependencyInjectionTests/ChatGptServicesIntegrationTests.cs +++ b/tests/OpenAI.ChatGpt.UnitTests/DependencyInjectionTests/ChatGptServicesIntegrationTests.cs @@ -28,6 +28,7 @@ public void AddChatGptCoreIntegration_added_expected_services() provider.GetRequiredService(); provider.GetRequiredService(); + provider.GetRequiredService(); } [Fact]