diff --git a/OpenAI.Playground/ApiSettings.json b/OpenAI.Playground/ApiSettings.json index 55b72509..ea8b9798 100644 --- a/OpenAI.Playground/ApiSettings.json +++ b/OpenAI.Playground/ApiSettings.json @@ -1,7 +1,7 @@ { // How to use user secret => right click your project name in solution explorer then click Manage User Secret, it is a good way to keep your api keys :) - "OpenAISdkSettings": { + "OpenAIServiceOptions": { // "Organization": "Put your Organization Id to here or to User Secret file" //https:// beta.openai.com/account/org-settings //,"ApiKey":"Put your api key to here or to User Secret file" //How can I get an app key? visit here: https://openai.com/ }, diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs index 174c887f..552e6879 100644 --- a/OpenAI.Playground/Program.cs +++ b/OpenAI.Playground/Program.cs @@ -2,10 +2,12 @@ using LaserCatEyes.HttpClientListener; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using OpenAI.Playground.TestHelpers; using OpenAI.GPT3; +using OpenAI.GPT3.Extensions; using OpenAI.GPT3.Interfaces; using OpenAI.GPT3.Managers; +using OpenAI.GPT3.Models; +using OpenAI.Playground.TestHelpers; var builder = new ConfigurationBuilder() .AddJsonFile("ApiSettings.json") @@ -13,29 +15,27 @@ IConfiguration configuration = builder.Build(); var serviceCollection = new ServiceCollection(); -serviceCollection.AddOptions(); serviceCollection.AddScoped(_ => configuration); // Laser cat eyes will help us to track request and responses between OpenAI server and our client //It is in Beta version, if you have consider about your data privacy or if you don't want to use it just comment out from here serviceCollection.Configure(configuration.GetSection("LaserCatEyesOptions")); -serviceCollection.AddHttpClient(); serviceCollection.AddLaserCatEyesHttpClientListener(); +serviceCollection.AddOpenAIService(settings => { settings.ApiKey = "TEST"; }); + //// to here, and uncomment from here -//serviceCollection.AddHttpClient(); +//serviceCollection.AddHttpClient(); //// to here - -serviceCollection.Configure(configuration.GetSection(OpenAiSettings.SettingKey)); var serviceProvider = serviceCollection.BuildServiceProvider(); -var sdk = serviceProvider.GetRequiredService(); -//await EngineTestHelper.FetchEnginesTest(sdk); +var sdk = serviceProvider.GetRequiredService(); +await EngineTestHelper.FetchEnginesTest(sdk); //await CompletionTestHelper.RunSimpleCompletionTest(sdk); //await SearchTestHelper.SearchDocuments(sdk); //await ClassificationsTestHelper.RunSimpleClassificationTest(sdk); //await AnswerTestHelper.RunSimpleAnswerTest(sdk); //await FileTestHelper.RunSimpleFileTest(sdk); -////await FineTuningTestHelper.CleanUpAllFineTunings(sdk); -await FineTuningTestHelper.RunCaseStudyIsTheModelMakingUntrueStatements(sdk); +////await FineTuningTestHelper.CleanUpAllFineTunings(sdk); //!!!!! will delete all fine-tunings +//await FineTuningTestHelper.RunCaseStudyIsTheModelMakingUntrueStatements(sdk); Console.ReadLine(); \ No newline at end of file diff --git a/OpenAI.Playground/SampleData/FineTuningSample1.jsonl b/OpenAI.Playground/SampleData/FineTuningSample1.jsonl index 8fde35d4..fbfb9d00 100644 --- a/OpenAI.Playground/SampleData/FineTuningSample1.jsonl +++ b/OpenAI.Playground/SampleData/FineTuningSample1.jsonl @@ -1,2 +1,100 @@ {"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} +{"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} +{"prompt":"Overjoyed with the new iPhone! ->", "completion":" positive"} {"prompt":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "completion":" negative"} \ No newline at end of file diff --git a/OpenAI.Playground/TestHelpers/AnswerTestHelper.cs b/OpenAI.Playground/TestHelpers/AnswerTestHelper.cs index b99daf55..d182fb90 100644 --- a/OpenAI.Playground/TestHelpers/AnswerTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/AnswerTestHelper.cs @@ -6,7 +6,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class AnswerTestHelper { - public static async Task RunSimpleAnswerTest(IOpenAISdk sdk) + public static async Task RunSimpleAnswerTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Completion Testing is starting:", ConsoleColor.Cyan); diff --git a/OpenAI.Playground/TestHelpers/ClassificationsTestHelper.cs b/OpenAI.Playground/TestHelpers/ClassificationsTestHelper.cs index 1a3d15a0..1dbe6a4f 100644 --- a/OpenAI.Playground/TestHelpers/ClassificationsTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/ClassificationsTestHelper.cs @@ -6,7 +6,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class ClassificationsTestHelper { - public static async Task RunSimpleClassificationTest(IOpenAISdk sdk) + public static async Task RunSimpleClassificationTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Run Simple Classification Test is starting:", ConsoleColor.Cyan); diff --git a/OpenAI.Playground/TestHelpers/CompletionTestHelper.cs b/OpenAI.Playground/TestHelpers/CompletionTestHelper.cs index 187c82d0..f55f6f6f 100644 --- a/OpenAI.Playground/TestHelpers/CompletionTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/CompletionTestHelper.cs @@ -6,7 +6,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class CompletionTestHelper { - public static async Task RunSimpleCompletionTest(IOpenAISdk sdk) + public static async Task RunSimpleCompletionTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Completion Testing is starting:", ConsoleColor.Cyan); @@ -19,6 +19,18 @@ public static async Task RunSimpleCompletionTest(IOpenAISdk sdk) MaxTokens = 5 }, Engines.Engine.Davinci); + if (completionResult.Successful) + { + Console.WriteLine(completionResult.Choices.FirstOrDefault()); + } + else + { + if (completionResult.Error == null) + { + throw new Exception("Unknown Error"); + } + Console.WriteLine($"{completionResult.Error.Code}: {completionResult.Error.Message}"); + } Console.WriteLine(completionResult.Choices.FirstOrDefault()); } catch (Exception e) diff --git a/OpenAI.Playground/TestHelpers/EngineTestHelper.cs b/OpenAI.Playground/TestHelpers/EngineTestHelper.cs index 1cf3631f..e24fc9c8 100644 --- a/OpenAI.Playground/TestHelpers/EngineTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/EngineTestHelper.cs @@ -4,7 +4,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class EngineTestHelper { - public static async Task FetchEnginesTest(IOpenAISdk sdk) + public static async Task FetchEnginesTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Engine List Testing is starting:", ConsoleColor.Cyan); diff --git a/OpenAI.Playground/TestHelpers/FileTestHelper.cs b/OpenAI.Playground/TestHelpers/FileTestHelper.cs index eb741756..108e6012 100644 --- a/OpenAI.Playground/TestHelpers/FileTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/FileTestHelper.cs @@ -5,7 +5,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class FileTestHelper { - public static async Task RunSimpleFileTest(IOpenAISdk sdk) + public static async Task RunSimpleFileTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("File Testing is starting:", ConsoleColor.Cyan); @@ -66,7 +66,7 @@ public static async Task RunSimpleFileTest(IOpenAISdk sdk) } - public static async Task CleanAllFiles(IOpenAISdk sdk) + public static async Task CleanAllFiles(IOpenAIService sdk) { try { diff --git a/OpenAI.Playground/TestHelpers/FineTuningTestHelper.cs b/OpenAI.Playground/TestHelpers/FineTuningTestHelper.cs index af05d43d..c89e107b 100644 --- a/OpenAI.Playground/TestHelpers/FineTuningTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/FineTuningTestHelper.cs @@ -7,7 +7,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class FineTuningTestHelper { - public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISdk sdk) + public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Run Case Study Is The Model Making Untrue Statements:", ConsoleColor.Cyan); @@ -30,7 +30,7 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISdk var createFineTuneResponse = await sdk.FineTunes.CreateFineTune(new FineTuneCreateRequest() { TrainingFile = uploadFilesResponse.Id, - Model = Engines.Curie + Model = Engines.Ada }); var listFineTuneEventsStream = await sdk.FineTunes.ListFineTuneEvents(createFineTuneResponse.Id, true); @@ -54,20 +54,27 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISdk await Task.Delay(10_000); } while (true); - var completionResult = await sdk.FineTunes.FineTuneCompletions(new FineTuneCompletionsRequest() - { - MaxTokens = 1, - Prompt = @"https://t.co/f93xEd2 Excited to share my latest blog post! ->", - Model = retrieveFineTuneResponse.FineTunedModel - }); - if (completionResult.Successful) - { - Console.WriteLine(completionResult.Choices.FirstOrDefault()); - } - else + do { - throw new Exception($"failed{completionResult.Error?.Message}"); - } + var completionResult = await sdk.FineTunes.FineTuneCompletions(new FineTuneCompletionsRequest() + { + MaxTokens = 1, + Prompt = @"https://t.co/f93xEd2 Excited to share my latest blog post! ->", + Model = retrieveFineTuneResponse.FineTunedModel, + Logprobs = 2 + }); + if (completionResult.Successful) + { + Console.WriteLine(completionResult.Choices.FirstOrDefault()); + break; + } + else + { + ConsoleExtensions.WriteLine($"failed{completionResult.Error?.Message}",ConsoleColor.DarkRed); + } + + } while (true); + } catch (Exception e) { @@ -76,7 +83,7 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISdk } } - public static async Task CleanUpAllFineTunings(IOpenAISdk sdk) + public static async Task CleanUpAllFineTunings(IOpenAIService sdk) { var fineTunes = await sdk.FineTunes.ListFineTunes(); foreach (var datum in fineTunes.Data) diff --git a/OpenAI.Playground/TestHelpers/SearchTestHelper.cs b/OpenAI.Playground/TestHelpers/SearchTestHelper.cs index ba064d09..7fea0916 100644 --- a/OpenAI.Playground/TestHelpers/SearchTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/SearchTestHelper.cs @@ -6,7 +6,7 @@ namespace OpenAI.Playground.TestHelpers { internal static class SearchTestHelper { - public static async Task SearchDocuments(IOpenAISdk sdk) + public static async Task SearchDocuments(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Search Documents Test is starting:", ConsoleColor.Cyan); @@ -38,7 +38,7 @@ public static async Task SearchDocuments(IOpenAISdk sdk) } } - public static async Task UploadSampleFileAndGetSearchResponse(IOpenAISdk sdk) + public static async Task UploadSampleFileAndGetSearchResponse(IOpenAIService sdk) { const string fileName = "SearchSample.jsonl"; @@ -94,7 +94,7 @@ public static async Task UploadSampleFileAndGetSearchResponse(IOpenAISdk sdk) } } - public static async Task UploadSampleFile(IOpenAISdk sdk) + public static async Task UploadSampleFile(IOpenAIService sdk) { const string fileName = "SearchSample.json"; diff --git a/OpenAI.SDK/Extensions/OpenAIServiceCollectionExtensions.cs b/OpenAI.SDK/Extensions/OpenAIServiceCollectionExtensions.cs new file mode 100644 index 00000000..d7273198 --- /dev/null +++ b/OpenAI.SDK/Extensions/OpenAIServiceCollectionExtensions.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using OpenAI.GPT3.Interfaces; +using OpenAI.GPT3.Managers; + +namespace OpenAI.GPT3.Extensions +{ + public static class OpenAIServiceCollectionExtensions + { + public static IServiceCollection AddOpenAIService(this IServiceCollection services) + { + services.AddOptions(); + services.AddHttpClient(); + var configuration = services.BuildServiceProvider().GetRequiredService(); + services.Configure(configuration.GetSection(OpenAiOptions.SettingKey)); + return services; + } + + public static IServiceCollection AddOpenAIService(this IServiceCollection services, Action setupAction) + { + services.AddOptions().Configure(setupAction); + services.AddHttpClient(); + return services; + } + } +} \ No newline at end of file diff --git a/OpenAI.SDK/Interfaces/IOpenAISdk.cs b/OpenAI.SDK/Interfaces/IOpenAISdk.cs index f87970b5..2b53ce12 100644 --- a/OpenAI.SDK/Interfaces/IOpenAISdk.cs +++ b/OpenAI.SDK/Interfaces/IOpenAISdk.cs @@ -1,6 +1,6 @@ namespace OpenAI.GPT3.Interfaces; -public interface IOpenAISdk +public interface IOpenAIService { /// /// Engines describe and provide access to the various models available in the API. You can refer to the diff --git a/OpenAI.SDK/Managers/OpenAICompletions.cs b/OpenAI.SDK/Managers/OpenAICompletions.cs index 74ed3fef..f82e9c63 100644 --- a/OpenAI.SDK/Managers/OpenAICompletions.cs +++ b/OpenAI.SDK/Managers/OpenAICompletions.cs @@ -5,7 +5,7 @@ namespace OpenAI.GPT3.Managers; -public partial class OpenAISdk : ICompletion +public partial class OpenAIService : ICompletion { public async Task Create(CompletionCreateRequest createCompletionRequest, string? engineId = null) { diff --git a/OpenAI.SDK/Managers/OpenAIEngine.cs b/OpenAI.SDK/Managers/OpenAIEngine.cs index aa37a78b..eb673faf 100644 --- a/OpenAI.SDK/Managers/OpenAIEngine.cs +++ b/OpenAI.SDK/Managers/OpenAIEngine.cs @@ -4,7 +4,7 @@ namespace OpenAI.GPT3.Managers; -public partial class OpenAISdk : IEngine +public partial class OpenAIService : IEngine { public async Task EngineList() { diff --git a/OpenAI.SDK/Managers/OpenAIFile.cs b/OpenAI.SDK/Managers/OpenAIFile.cs index 3872f506..fdaef2f6 100644 --- a/OpenAI.SDK/Managers/OpenAIFile.cs +++ b/OpenAI.SDK/Managers/OpenAIFile.cs @@ -5,7 +5,7 @@ namespace OpenAI.GPT3.Managers; -public partial class OpenAISdk : IFile +public partial class OpenAIService : IFile { public async Task FileList() { diff --git a/OpenAI.SDK/Managers/OpenAIFineTune.cs b/OpenAI.SDK/Managers/OpenAIFineTune.cs index 66fe63ac..100781f1 100644 --- a/OpenAI.SDK/Managers/OpenAIFineTune.cs +++ b/OpenAI.SDK/Managers/OpenAIFineTune.cs @@ -6,7 +6,7 @@ namespace OpenAI.GPT3.Managers; -public partial class OpenAISdk : IFineTune +public partial class OpenAIService : IFineTune { public async Task CreateFineTune(FineTuneCreateRequest createFineTuneRequest) { diff --git a/OpenAI.SDK/Managers/OpenAI.cs b/OpenAI.SDK/Managers/OpenAIService.cs similarity index 68% rename from OpenAI.SDK/Managers/OpenAI.cs rename to OpenAI.SDK/Managers/OpenAIService.cs index 79c18bd5..82245ed1 100644 --- a/OpenAI.SDK/Managers/OpenAI.cs +++ b/OpenAI.SDK/Managers/OpenAIService.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using OpenAI.GPT3.Extensions; using OpenAI.GPT3.Interfaces; using OpenAI.GPT3.Models.RequestModels; @@ -8,14 +9,17 @@ namespace OpenAI.GPT3.Managers { //TODO Find a way to show default request values in documentation //TODO Move endpoints to a setting file - public partial class OpenAISdk : IOpenAISdk, ISearch, IClassification, IAnswer + public partial class OpenAIService : IOpenAIService, ISearch, IClassification, IAnswer { private readonly IOpenAiEndpointProvider _endpointProvider; private readonly HttpClient _httpClient; private string? _engineId; - public OpenAISdk(HttpClient httpClient, IOptions settings) + [ActivatorUtilitiesConstructor] + public OpenAIService(HttpClient httpClient, IOptions settings) { + settings.Value.Validate(); + _httpClient = httpClient; _httpClient.BaseAddress = new Uri(settings.Value.BaseDomain); var authKey = settings.Value.ApiKey; @@ -24,7 +28,25 @@ public OpenAISdk(HttpClient httpClient, IOptions settings) _httpClient.DefaultRequestHeaders.Add("OpenAI-Organization", $"{organization}"); _endpointProvider = new OpenAiEndpointProvider(settings.Value.ApiVersion); - _engineId = OpenAiSettings.DefaultEngineId; + _engineId = OpenAiOptions.DefaultEngineId; + } + + public OpenAIService(OpenAiOptions settings, HttpClient? httpClient = null) + { + settings.Validate(); + + _httpClient = httpClient ?? HttpClientFactory.Create(); + _httpClient.BaseAddress = new Uri(settings.BaseDomain); + var authKey = settings.ApiKey; + _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {authKey}"); + var organization = settings.Organization; + if (!string.IsNullOrEmpty(organization)) + { + _httpClient.DefaultRequestHeaders.Add("OpenAI-Organization", $"{organization}"); + } + + _endpointProvider = new OpenAiEndpointProvider(settings.ApiVersion); + _engineId = OpenAiOptions.DefaultEngineId; } //TODO Not tested yet diff --git a/OpenAI.SDK/Models/RequestModels/FineTuneCompletionsRequest.cs b/OpenAI.SDK/Models/RequestModels/FineTuneCompletionsRequest.cs index 2607999d..cae87e0d 100644 --- a/OpenAI.SDK/Models/RequestModels/FineTuneCompletionsRequest.cs +++ b/OpenAI.SDK/Models/RequestModels/FineTuneCompletionsRequest.cs @@ -1,13 +1,13 @@ using System.Text.Json.Serialization; +using OpenAI.GPT3.Models.SharedModels; namespace OpenAI.GPT3.Models.RequestModels { - public record FineTuneCompletionsRequest + public record FineTuneCompletionsRequest : IOpenAiModels.ILogprobs { [JsonPropertyName("prompt")] public string Prompt { get; set; } - [JsonPropertyName("max_tokens")] public int? MaxTokens { get; set; } - [JsonPropertyName("model")] public string Model { get; set; } + [JsonPropertyName("logprobs")] public int? Logprobs { get; set; } } } \ No newline at end of file diff --git a/OpenAI.SDK/OpenAI.GPT3.csproj b/OpenAI.SDK/OpenAI.GPT3.csproj index 56bdc771..928a2079 100644 --- a/OpenAI.SDK/OpenAI.GPT3.csproj +++ b/OpenAI.SDK/OpenAI.GPT3.csproj @@ -9,13 +9,13 @@ https://openai.com/ OpenAI-Logo.png true - 0.0.1 + 0.0.2 Tolga Kayhan, Betalgo Betalgo Up Ltd. OpenAI GPT-3 dotnet SDK - (BETA) Unofficial API wrapper for OpenAI GPT-3 + Dotnet SDK for OpenAI GTP-3 (Unofficial) https://github.com/betalgo/openai/ - openAI,gpt-3,ai,betalgo + openAI,gpt-3,ai,betalgo,NLP Betalgo.$(AssemblyName) Readme.md False @@ -31,7 +31,9 @@ - + + + \ No newline at end of file diff --git a/OpenAI.SDK/OpenAISettings.cs b/OpenAI.SDK/OpenAiOptions.cs similarity index 72% rename from OpenAI.SDK/OpenAISettings.cs rename to OpenAI.SDK/OpenAiOptions.cs index d220c468..6b9513bd 100644 --- a/OpenAI.SDK/OpenAISettings.cs +++ b/OpenAI.SDK/OpenAiOptions.cs @@ -1,8 +1,8 @@ namespace OpenAI.GPT3 { - public class OpenAiSettings + public class OpenAiOptions { - public static readonly string SettingKey = "OpenAISdkSettings"; + public static readonly string SettingKey = "OpenAIServiceOptions"; /// /// For users who belong to multiple organizations, you can pass a header to specify which organization is used for an @@ -30,5 +30,23 @@ public class OpenAiSettings /// Default engine id. If you are working with only one engine, this will save you from few line extra code. /// public static string? DefaultEngineId { get; set; } + + public void Validate() + { + if (string.IsNullOrEmpty(ApiKey)) + { + throw new ArgumentNullException(nameof(ApiKey)); + } + + if (string.IsNullOrEmpty(ApiVersion)) + { + throw new ArgumentNullException(nameof(ApiVersion)); + } + + if (string.IsNullOrEmpty(BaseDomain)) + { + throw new ArgumentNullException(nameof(BaseDomain)); + } + } } } \ No newline at end of file diff --git a/Readme.md b/Readme.md index db8df6e8..a3b93094 100644 --- a/Readme.md +++ b/Readme.md @@ -1,3 +1,75 @@ -Work in progress +Dotnet SDK for OpenAI GTP-3 (Unofficial) -Open AI gpt-3 sdk for dotnet \ No newline at end of file +*I was building an SDK for myself then I decide to share it, I hope it will be useful for you. I haven't maintained any open source projects before. Any help would be much appreciated. I am open to suggestions If you would like to contribute somehow.* + +I will be using the latest libraries all the time *(including dotnet 6)*. Also, next releasing will include breaking changes frequently *(as I mentioned before I was building the SDK for myself. Unfortunately I do not have time to plan these changes and support lower version apps)*. So please be aware of that before starting to use the library. + +As you can guess I do not accept any damage caused by use of the library. You are always free to use other libraries or OpenAI Web-API. + + +## Sample Usages +The repository includes one sample project already **"OpenAI.Playground"** You can check playground project to see how I was testing it while I was developing the library. Be carefull while playing with it. Some test methods will delete your files or fine tunings. **I would suggest to use different account than your main account while you use playground.** + +### Using dependcy injection: +#### secrets.json: +*(How to use [user secret](https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0&tabs=windows)? => right click your project name in "solution explorer" then click "Manage User Secret", it is a good way to keep your api keys) * +```csharp + "OpenAIServiceOptions": { + //"ApiKey":"Your api key goes here" + //,"Organization": "Your Organization Id goes here (optional)" + }, +``` +#### Program.cs +```csharp +serviceCollection.AddOpenAIService(); +``` + +or use it like below but do NOT put your API key directly to your source code, you may expose your API key, which will cost you $$. +#### Program.cs +```csharp +serviceCollection.AddOpenAIService(settings => { settings.ApiKey = "TEST"; }); +``` + +After injecting your service you will be able to get it from service provider +```csharp +var openAiService = serviceProvider.GetRequiredService(); +``` + +Without dependcy injection: +```csharp +var openAiService = new OpenAIService(new OpenAiOptions() +{ + ApiKey = "MY_API_KEY" +}); +``` + +You can set default engine(optional): +```csharp +openAiService.SetDefaultEngineId(Engines.Davinci); +``` + +## Completions Sample +```csharp +var completionResult = await openAiService.Completions.Create(new CompletionCreateRequest() +{ + Prompt = "Once upon a time", + MaxTokens = 5 +}, Engines.Engine.Davinci); + +if (completionResult.Successful) +{ + Console.WriteLine(completionResult.Choices.FirstOrDefault()); +} +else +{ + if (completionResult.Error == null) + { + throw new Exception("Unknown Error"); + } + Console.WriteLine($"{completionResult.Error.Code}: {completionResult.Error.Message}"); + } +``` + + +Notes: +I couldn't find enough time to test all the methods or improve the documenations. My main target was make fine-tunig avalibale. If you hit any issue please report it or pull request always appricater it \ No newline at end of file