diff --git a/src/libs/Directory.Build.props b/src/libs/Directory.Build.props index 8956e03f..3aea4954 100755 --- a/src/libs/Directory.Build.props +++ b/src/libs/Directory.Build.props @@ -16,7 +16,7 @@ - 1.8.2 + 2.0.0-alpha.0 true true tryAGI and contributors diff --git a/src/libs/OpenAI/Extensions/ResponseMessageExtensions.cs b/src/libs/OpenAI/Extensions/ResponseMessageExtensions.cs index 8e3a4da0..8099a77a 100755 --- a/src/libs/OpenAI/Extensions/ResponseMessageExtensions.cs +++ b/src/libs/OpenAI/Extensions/ResponseMessageExtensions.cs @@ -1,4 +1,6 @@ -namespace tryAGI.OpenAI; +using OpenAI.Chat; + +namespace tryAGI.OpenAI; /// /// @@ -11,29 +13,12 @@ public static class ResponseMessageExtensions /// /// /// - public static ChatCompletionRequestMessage AsRequestMessage(this ChatCompletionResponseMessage message) + public static ChatRequest AsRequestMessage(this Message message) { message = message ?? throw new ArgumentNullException(nameof(message)); - return new ChatCompletionRequestMessage - { - Role = message.Role switch - { - ChatCompletionResponseMessageRole.System => ChatCompletionRequestMessageRole.System, - ChatCompletionResponseMessageRole.User => ChatCompletionRequestMessageRole.User, - ChatCompletionResponseMessageRole.Assistant => ChatCompletionRequestMessageRole.Assistant, - ChatCompletionResponseMessageRole.Function => ChatCompletionRequestMessageRole.Function, - _ => throw new ArgumentOutOfRangeException(nameof(message), $"Unknown role: {message.Role}"), - }, - Content = message.Content ?? string.Empty, - Function_call = message.Function_call != null ? - new Function_call - { - Arguments = message.Function_call.Arguments ?? string.Empty, - Name = message.Function_call.Name ?? string.Empty, - } - : null, - }; + return new ChatRequest( + messages: new []{ message }); } /// @@ -42,11 +27,11 @@ public static ChatCompletionRequestMessage AsRequestMessage(this ChatCompletionR /// /// /// - public static ChatCompletionResponseMessage GetFirstChoiceMessage(this CreateChatCompletionResponse response) + public static Message GetFirstChoiceMessage(this ChatResponse response) { response = response ?? throw new ArgumentNullException(nameof(response)); - return response.Choices.First().Message ?? + return response.Choices[0].Message ?? throw new ArgumentException("No message in the first choice."); } @@ -56,11 +41,11 @@ public static ChatCompletionResponseMessage GetFirstChoiceMessage(this CreateCha /// /// /// - public static ChatCompletionStreamResponseDelta GetFirstChoiceDelta(this CreateChatCompletionStreamResponse response) + public static Delta GetFirstChoiceDelta(this ChatResponse response) { response = response ?? throw new ArgumentNullException(nameof(response)); - return response.Choices.First().Delta ?? + return response.Choices[0].Delta ?? throw new ArgumentException("No delta in the first choice."); } } \ No newline at end of file diff --git a/src/libs/OpenAI/Extensions/StringExtensions.cs b/src/libs/OpenAI/Extensions/StringExtensions.cs index e21ea10e..af4dede0 100755 --- a/src/libs/OpenAI/Extensions/StringExtensions.cs +++ b/src/libs/OpenAI/Extensions/StringExtensions.cs @@ -1,4 +1,6 @@ -namespace tryAGI.OpenAI; +using OpenAI.Chat; + +namespace tryAGI.OpenAI; /// /// @@ -10,13 +12,9 @@ public static class StringExtensions /// /// /// - public static ChatCompletionRequestMessage AsSystemMessage(this string content) + public static Message AsSystemMessage(this string content) { - return new ChatCompletionRequestMessage - { - Role = ChatCompletionRequestMessageRole.System, - Content = content, - }; + return new Message(Role.System, content); } /// @@ -24,13 +22,9 @@ public static ChatCompletionRequestMessage AsSystemMessage(this string content) /// /// /// - public static ChatCompletionRequestMessage AsUserMessage(this string content) + public static Message AsUserMessage(this string content) { - return new ChatCompletionRequestMessage - { - Role = ChatCompletionRequestMessageRole.User, - Content = content, - }; + return new Message(Role.User, content); } /// @@ -38,13 +32,9 @@ public static ChatCompletionRequestMessage AsUserMessage(this string content) /// /// /// - public static ChatCompletionRequestMessage AsAssistantMessage(this string content) + public static Message AsAssistantMessage(this string content) { - return new ChatCompletionRequestMessage - { - Role = ChatCompletionRequestMessageRole.Assistant, - Content = content, - }; + return new Message(Role.Assistant, content); } /// @@ -53,13 +43,8 @@ public static ChatCompletionRequestMessage AsAssistantMessage(this string conten /// /// /// - public static ChatCompletionRequestMessage AsFunctionMessage(this string json, string name) + public static Message AsFunctionMessage(this string json, string name) { - return new ChatCompletionRequestMessage - { - Role = ChatCompletionRequestMessageRole.Function, - Name = name, - Content = json, - }; + return new Message(new Tool(new Function(name)), json); } } \ No newline at end of file diff --git a/src/libs/OpenAI/Helpers/ApiHelpers.cs b/src/libs/OpenAI/Helpers/ApiHelpers.cs index 153f20c8..b5e47802 100644 --- a/src/libs/OpenAI/Helpers/ApiHelpers.cs +++ b/src/libs/OpenAI/Helpers/ApiHelpers.cs @@ -1,172 +1,172 @@ -namespace tryAGI.OpenAI; - -#pragma warning disable CS0618 - -/// -/// -/// -public static class ApiHelpers -{ - /// - /// Supports embedding models and GPT models
- /// According https://openai.com/pricing/
- /// According https://platform.openai.com/docs/guides/embeddings/embedding-models
- ///
- /// The model id we want to know the context size for. - /// - /// - /// The maximum context size - /// - public static double? TryCalculatePriceInUsd(string modelId, int completionTokens, int promptTokens) - { - var (promptPricePerToken, completionPricePerToken) = modelId switch - { - // GPT models - ModelIds.Gpt4 => (0.03 * 0.001, 0.06 * 0.001), - ModelIds.Gpt4_0314 => (0.03 * 0.001, 0.06 * 0.001), - ModelIds.Gpt4_0613 => (0.03 * 0.001, 0.06 * 0.001), - - ModelIds.Gpt4_32k => (0.06 * 0.001, 0.12 * 0.001), - ModelIds.Gpt4_32k_0314 => (0.06 * 0.001, 0.12 * 0.001), - ModelIds.Gpt4_32k_0613 => (0.06 * 0.001, 0.12 * 0.001), - - ModelIds.Gpt35Turbo => (0.0015 * 0.001, 0.002 * 0.001), - ModelIds.Gpt35Turbo_0301 => (0.0015 * 0.001, 0.002 * 0.001), - ModelIds.Gpt35Turbo_0613 => (0.0015 * 0.001, 0.002 * 0.001), - - ModelIds.Gpt35Turbo_16k =>(0.003 * 0.001, 0.004 * 0.001), - ModelIds.Gpt35Turbo_16k_0613 => (0.003 * 0.001, 0.004 * 0.001), - - // Embedding models - EmbeddingModelIds.Ada002 => (0.0001 * 0.001, 0.0), - - _ => (-1.0, -1.0) - }; - if (promptPricePerToken < 0.0) - { - return null; - } - - return completionTokens * completionPricePerToken + - promptTokens * promptPricePerToken; - } - - /// - public static double CalculatePriceInUsd(string modelId, int completionTokens, int promptTokens) - { - return TryCalculatePriceInUsd(modelId, completionTokens, promptTokens) ?? - throw new NotImplementedException(); - } - - /// - /// Build DALL·E directly into your apps to generate and edit novel images and art.
- /// Our image models offer three tiers of resolution for flexibility.
- /// According https://openai.com/pricing/
- ///
- /// - /// - /// - public static double? TryCalculatePriceInUsd(CreateImageRequestSize size) - { - return size switch - { - CreateImageRequestSize._256x256 => 0.020, - CreateImageRequestSize._512x512 => 0.018, - CreateImageRequestSize._1024x1024 => 0.016, - - _ => null, - }; - } - - /// - public static double CalculatePriceInUsd(CreateImageRequestSize size) - { - return TryCalculatePriceInUsd(size) ?? - throw new NotImplementedException(); - } - - /// - /// According https://openai.com/pricing/
- ///
- /// - /// rounded to the nearest second - /// - /// - public static double? TryCalculatePriceInUsd(string modelId, int minutes) - { - var pricePerMinute = modelId switch - { - AudioModelIds.Whisper1 => 0.006, - - _ => -1.0, - }; - if (pricePerMinute < 0.0) - { - return null; - } - - return pricePerMinute * minutes; - } - - /// - public static double CalculatePriceInUsd(string modelId, int minutes) - { - return TryCalculatePriceInUsd(modelId, minutes) ?? - throw new NotImplementedException(); - } - - /// - /// Calculates the maximum number of tokens possible to generate for a model.
- /// Returns the maximum input number of tokens for a embedding model.
- /// According https://platform.openai.com/docs/models/overview
- ///
- /// - /// - /// - public static int? TryCalculateContextLength(string modelId) - { - return modelId switch - { - // GPT models - ModelIds.Gpt4 => 8_192, - ModelIds.Gpt4_0314 => 8_192, - ModelIds.Gpt4_0613 => 8_192, - - ModelIds.Gpt4_32k => 32_768, - ModelIds.Gpt4_32k_0314 => 32_768, - ModelIds.Gpt4_32k_0613 => 32_768, - - ModelIds.Gpt35Turbo => 4_096, - ModelIds.Gpt35Turbo_0301 => 4_096, - ModelIds.Gpt35Turbo_0613 => 4_096, - - ModelIds.Gpt35Turbo_16k => 16_384, - ModelIds.Gpt35Turbo_16k_0613 => 16_384, - - // Embedding models - EmbeddingModelIds.Ada002 => 8_191, - - "ada" or "text-ada-001" => 2_049, - "text-babbage-001" => 2_040, - "babbage" => 2_049, - "text-curie-001" => 2_049, - "curie" => 2_049, - "davinci" => 2_049, - "text-davinci-003" => 4_097, - "text-davinci-002" => 4_097, - "code-davinci-002" => 8_001, - "code-davinci-001" => 8_001, - "code-cushman-002" => 2_048, - "code-cushman-001" => 2_048, - - _ => null, - }; - } - - /// - public static int CalculateContextLength(string modelId) - { - return TryCalculateContextLength(modelId) ?? - throw new NotImplementedException(); - } -} \ No newline at end of file +// namespace tryAGI.OpenAI; +// +// #pragma warning disable CS0618 +// +// /// +// /// +// /// +// public static class ApiHelpers +// { +// /// +// /// Supports embedding models and GPT models
+// /// According https://openai.com/pricing/
+// /// According https://platform.openai.com/docs/guides/embeddings/embedding-models
+// ///
+// /// The model id we want to know the context size for. +// /// +// /// +// /// The maximum context size +// /// +// public static double? TryCalculatePriceInUsd(string modelId, int completionTokens, int promptTokens) +// { +// var (promptPricePerToken, completionPricePerToken) = modelId switch +// { +// // GPT models +// ModelIds.Gpt4 => (0.03 * 0.001, 0.06 * 0.001), +// ModelIds.Gpt4_0314 => (0.03 * 0.001, 0.06 * 0.001), +// ModelIds.Gpt4_0613 => (0.03 * 0.001, 0.06 * 0.001), +// +// ModelIds.Gpt4_32k => (0.06 * 0.001, 0.12 * 0.001), +// ModelIds.Gpt4_32k_0314 => (0.06 * 0.001, 0.12 * 0.001), +// ModelIds.Gpt4_32k_0613 => (0.06 * 0.001, 0.12 * 0.001), +// +// ModelIds.Gpt35Turbo => (0.0015 * 0.001, 0.002 * 0.001), +// ModelIds.Gpt35Turbo_0301 => (0.0015 * 0.001, 0.002 * 0.001), +// ModelIds.Gpt35Turbo_0613 => (0.0015 * 0.001, 0.002 * 0.001), +// +// ModelIds.Gpt35Turbo_16k =>(0.003 * 0.001, 0.004 * 0.001), +// ModelIds.Gpt35Turbo_16k_0613 => (0.003 * 0.001, 0.004 * 0.001), +// +// // Embedding models +// EmbeddingModelIds.Ada002 => (0.0001 * 0.001, 0.0), +// +// _ => (-1.0, -1.0) +// }; +// if (promptPricePerToken < 0.0) +// { +// return null; +// } +// +// return completionTokens * completionPricePerToken + +// promptTokens * promptPricePerToken; +// } +// +// /// +// public static double CalculatePriceInUsd(string modelId, int completionTokens, int promptTokens) +// { +// return TryCalculatePriceInUsd(modelId, completionTokens, promptTokens) ?? +// throw new NotImplementedException(); +// } +// +// /// +// /// Build DALL·E directly into your apps to generate and edit novel images and art.
+// /// Our image models offer three tiers of resolution for flexibility.
+// /// According https://openai.com/pricing/
+// ///
+// /// +// /// +// /// +// public static double? TryCalculatePriceInUsd(CreateImageRequest request) +// { +// return (request.Model, request.Quality, request.Size) switch +// { +// (CreateImageRequest_size.TwoFiveSixx256) => 0.020, +// CreateImageRequest_size.FiveOneTwox512 => 0.018, +// CreateImageRequest_size.OneZeroTwoFourx1024 => 0.016, +// +// _ => null, +// }; +// } +// +// /// +// public static double CalculatePriceInUsd(CreateImageRequest createImageRequest) +// { +// return TryCalculatePriceInUsd(size) ?? +// throw new NotImplementedException(); +// } +// +// /// +// /// According https://openai.com/pricing/
+// ///
+// /// +// /// rounded to the nearest second +// /// +// /// +// public static double? TryCalculatePriceInUsd(string modelId, int minutes) +// { +// var pricePerMinute = modelId switch +// { +// AudioModelIds.Whisper1 => 0.006, +// +// _ => -1.0, +// }; +// if (pricePerMinute < 0.0) +// { +// return null; +// } +// +// return pricePerMinute * minutes; +// } +// +// /// +// public static double CalculatePriceInUsd(string modelId, int minutes) +// { +// return TryCalculatePriceInUsd(modelId, minutes) ?? +// throw new NotImplementedException(); +// } +// +// /// +// /// Calculates the maximum number of tokens possible to generate for a model.
+// /// Returns the maximum input number of tokens for a embedding model.
+// /// According https://platform.openai.com/docs/models/overview
+// ///
+// /// +// /// +// /// +// public static int? TryCalculateContextLength(string modelId) +// { +// return modelId switch +// { +// // GPT models +// ModelIds.Gpt4 => 8_192, +// ModelIds.Gpt4_0314 => 8_192, +// ModelIds.Gpt4_0613 => 8_192, +// +// ModelIds.Gpt4_32k => 32_768, +// ModelIds.Gpt4_32k_0314 => 32_768, +// ModelIds.Gpt4_32k_0613 => 32_768, +// +// ModelIds.Gpt35Turbo => 4_096, +// ModelIds.Gpt35Turbo_0301 => 4_096, +// ModelIds.Gpt35Turbo_0613 => 4_096, +// +// ModelIds.Gpt35Turbo_16k => 16_384, +// ModelIds.Gpt35Turbo_16k_0613 => 16_384, +// +// // Embedding models +// EmbeddingModelIds.Ada002 => 8_191, +// +// "ada" or "text-ada-001" => 2_049, +// "text-babbage-001" => 2_040, +// "babbage" => 2_049, +// "text-curie-001" => 2_049, +// "curie" => 2_049, +// "davinci" => 2_049, +// "text-davinci-003" => 4_097, +// "text-davinci-002" => 4_097, +// "code-davinci-002" => 8_001, +// "code-davinci-001" => 8_001, +// "code-cushman-002" => 2_048, +// "code-cushman-001" => 2_048, +// +// _ => null, +// }; +// } +// +// /// +// public static int CalculateContextLength(string modelId) +// { +// return TryCalculateContextLength(modelId) ?? +// throw new NotImplementedException(); +// } +// } \ No newline at end of file diff --git a/src/tests/OpenAI.Generators.IntegrationTests/MaintenanceFunctions.cs b/src/tests/OpenAI.Generators.IntegrationTests/MaintenanceFunctions.cs index 891af17f..e1450c0a 100644 --- a/src/tests/OpenAI.Generators.IntegrationTests/MaintenanceFunctions.cs +++ b/src/tests/OpenAI.Generators.IntegrationTests/MaintenanceFunctions.cs @@ -1,25 +1,25 @@ -using System.Threading; -using System.Threading.Tasks; -using tryAGI.OpenAI; - -namespace H.Ipc.Generator.IntegrationTests; - -[OpenAiFunctions] -public interface IMaintenanceFunctions -{ - [System.ComponentModel.Description("Get the tasks to extract from a contract")] - public Task GetContractTasksAsync([System.ComponentModel.Description("The tasks extracted from the contract")] ExtractTasksRequest tasks, CancellationToken cancellationToken = default); -} - -public class MaintenanceService : IMaintenanceFunctions -{ - public Task GetContractTasksAsync(ExtractTasksRequest tasks, CancellationToken cancellationToken = default) - { - return Task.FromResult(tasks); - } -} - -public class ExtractTasksRequest -{ - public string[] Tasks { get; set; } -} \ No newline at end of file +// using System.Threading; +// using System.Threading.Tasks; +// using tryAGI.OpenAI; +// +// namespace H.Ipc.Generator.IntegrationTests; +// +// [OpenAiFunctions] +// public interface IMaintenanceFunctions +// { +// [System.ComponentModel.Description("Get the tasks to extract from a contract")] +// public Task GetContractTasksAsync([System.ComponentModel.Description("The tasks extracted from the contract")] ExtractTasksRequest tasks, CancellationToken cancellationToken = default); +// } +// +// public class MaintenanceService : IMaintenanceFunctions +// { +// public Task GetContractTasksAsync(ExtractTasksRequest tasks, CancellationToken cancellationToken = default) +// { +// return Task.FromResult(tasks); +// } +// } +// +// public class ExtractTasksRequest +// { +// public string[] Tasks { get; set; } +// } \ No newline at end of file diff --git a/src/tests/OpenAI.Generators.IntegrationTests/Tests.Functions.cs b/src/tests/OpenAI.Generators.IntegrationTests/Tests.Functions.cs index 8df80d2f..6060fb6b 100755 --- a/src/tests/OpenAI.Generators.IntegrationTests/Tests.Functions.cs +++ b/src/tests/OpenAI.Generators.IntegrationTests/Tests.Functions.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; +using OpenAI; +using OpenAI.Chat; using tryAGI.OpenAI; namespace H.Ipc.Generator.IntegrationTests; @@ -9,282 +11,281 @@ namespace H.Ipc.Generator.IntegrationTests; [TestClass] public partial class Tests { - [TestMethod] - [Ignore] - public async Task SimpleMethod() - { - var messages = new List - { - "You are a helpful weather assistant.".AsSystemMessage(), - "What's the weather like today?".AsUserMessage(), - }; - - try - { - var apiKey = - Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? - throw new AssertInconclusiveException("OPENAI_API_KEY is not set."); - using var httpClient = new HttpClient(); - var api = new OpenAiApi(apiKey, httpClient); - var service = new WeatherService(); - var functions = service.AsFunctions(); - var result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest - { - Messages = messages, - Functions = functions, - Function_call = Function_call4.Auto, - Model = ModelIds.Gpt35Turbo_0613, - }); - var resultMessage = result.GetFirstChoiceMessage(); - messages.Add(resultMessage.AsRequestMessage()); - - messages.Add("Dubai, UAE".AsUserMessage()); - result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest - { - Messages = messages, - Functions = functions, - Function_call = Function_call4.Auto, - Model = ModelIds.Gpt35Turbo_0613, - }); - resultMessage = result.GetFirstChoiceMessage(); - messages.Add(resultMessage.AsRequestMessage()); - - // It's possible that the assistant will also ask you which units you want the temperature in. - if (!string.IsNullOrWhiteSpace(resultMessage.Content)) - { - messages.Add("celsius".AsUserMessage()); - result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest - { - Messages = messages, - Functions = functions, - Function_call = Function_call4.Auto, - Model = ModelIds.Gpt35Turbo_0613, - }); - resultMessage = result.GetFirstChoiceMessage(); - messages.Add(resultMessage.AsRequestMessage()); - } - - if (resultMessage.Function_call == null) - { - throw new InvalidOperationException("Expected a function call."); - } - - var json = await service.CallAsync( - functionName: resultMessage.Function_call.Name ?? string.Empty, - argumentsAsJson: resultMessage.Function_call.Arguments ?? string.Empty); - messages.Add(json.AsFunctionMessage(resultMessage.Function_call?.Name ?? string.Empty)); - - result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest - { - Messages = messages, - Functions = functions, - Function_call = Function_call4.Auto, - Model = ModelIds.Gpt35Turbo_0613, - }); - resultMessage = result.GetFirstChoiceMessage(); - messages.Add(resultMessage.AsRequestMessage()); - } - finally - { - PrintMessages(messages); - } - } - - private static void PrintMessages(List messages) - { - foreach (var message in messages) - { - if (message.Function_call != null) - { - Console.WriteLine($"{message.Role}(FunctionCall): {message.Function_call.Name}"); - Console.WriteLine($"{message.Function_call.Arguments}"); - continue; - } - - Console.WriteLine($"{message.Role}: {message.Content}"); - } - } - - [TestMethod] - public async Task Call() - { - var json = /* lang=json */ """ - { - "location": "Dubai, UAE" - } - """; - var result = new WeatherService().CallGetCurrentWeather(json); - - result.Should().Be(/* lang=json */ """ - {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"} - """); - - var result2 = await new WeatherService().CallAsync("GetCurrentWeather", json); - result2.Should().Be(/* lang=json */ """ - {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"} - """); - } - - [TestMethod] - [Ignore] - public async Task UpdateCode() - { - var apiKey = - Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? - throw new AssertInconclusiveException("OPENAI_API_KEY is not set."); - using var httpClient = new HttpClient(); - var api = new OpenAiApi(apiKey, httpClient); - var service = new UpdateCodeService(); - var messages = new List - { - "You are a Senior C# programmer.".AsSystemMessage(), - /* lang=markdown */""" -You solve the issue with this description: -``` -Hey there. My boss asked me to refactor our legacy project. Can you do that for me? They asked me to use SOLID principles, KISS, YAGNI and DRY as well as clean code -The IUserCreditService and IUserCreditServiceChannel interfaces and the UserCreditServiceClient class are generated code so please don't change them. -Keep in mind that anything withing LegacyApp.Consumer is someone else's code and MUST NOT be changed. -Please don't introduce any breaking changes in the UserService class and its AddUser method. -``` -I need new steps to prevent these errors: -``` -Non-nullable property 'Firstname' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. -``` -``` -Non-nullable property 'Surname' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. -``` -``` -Non-nullable property 'EmailAddress' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. -``` -``` -Non-nullable property 'Client' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. -``` -``` -Possible null reference assignment. -``` -Here is the code: - -LegacyApp/User.cs -```csharp -using System; - -namespace LegacyApp -{ - public class User - { - public int Id { get; set; } - - public string Firstname { get; set; } - - public string Surname { get; set; } - - public DateTime DateOfBirth { get; set; } - - public string EmailAddress { get; set; } - - public bool HasCreditLimit { get; set; } - - public int CreditLimit { get; set; } - - public Client Client { get; set; } - } -} -``` - -LegacyApp/UserService.cs -```csharp -using System; - -#nullable enable -namespace LegacyApp -{ - public class UserService - { - public bool AddUser(string? firname, string? surname, string? email, DateTime dateOfBirth, int clientId) - { - if (string.IsNullOrEmpty(firname) || string.IsNullOrEmpty(surname)) - { - return false; - } - - if (email == null || (!email.Contains(""@"") && !email.Contains("".""))) - { - return false; - } - - var now = DateTime.Now; - int age = now.Year - dateOfBirth.Year; - if (now.Month < dateOfBirth.Month || (now.Month == dateOfBirth.Month && now.Day < dateOfBirth.Day)) age--; - - if (age < 21) - { - return false; - } - - var clientRepository = new ClientRepository(); - var client = clientRepository.GetById(clientId); - - var user = new User - { - Client = client, - DateOfBirth = dateOfBirth, - EmailAddress = email, - Firstname = firname, - Surname = surname - }; - - if (client?.Name == ""VeryImportantClient"") - { - // Skip credit check - user.HasCreditLimit = false; - } - else if (client?.Name == ""ImportantClient"") - { - // Do credit check and double credit limit - user.HasCreditLimit = true; - using (var userCreditService = new UserCreditServiceClient()) - { - var creditLimit = userCreditService.GetCreditLimit(user.Firstname, user.Surname, user.DateOfBirth); - creditLimit = creditLimit * 2; - user.CreditLimit = creditLimit; - } - } - else - { - // Do credit check - user.HasCreditLimit = true; - using (var userCreditService = new UserCreditServiceClient()) - { - var creditLimit = userCreditService.GetCreditLimit(user.Firstname, user.Surname, user.DateOfBirth); - user.CreditLimit = creditLimit; - } - } - - if (user.HasCreditLimit && user.CreditLimit < 500) - { - return false; - } - - UserDataAccess.AddUser(user); - - return true; - } - } -} -``` -""".AsUserMessage(), - }; - var result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest - { - Messages = messages, - Functions = service.AsFunctions(), - Function_call = Function_call4.Auto, - Model = ModelIds.Gpt35Turbo_0613, - }); - var json = result.GetFirstChoiceMessage().Function_call?.Arguments ?? string.Empty; - Console.WriteLine(json); - - var args = service.AsUpdateCodeArgs(json); - args.Changes.Should().NotBeEmpty(); - } +// [TestMethod] +// [Ignore] +// public async Task SimpleMethod() +// { +// var messages = new List +// { +// "You are a helpful weather assistant.".AsSystemMessage(), +// "What's the weather like today?".AsUserMessage(), +// }; +// +// try +// { +// var apiKey = +// Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? +// throw new AssertInconclusiveException("OPENAI_API_KEY is not set."); +// var api = new OpenAIClient(apiKey); +// var service = new WeatherService(); +// var functions = service.AsFunctions(); +// var result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest +// { +// Messages = messages, +// Functions = functions, +// Function_call = Function_call4.Auto, +// Model = ModelIds.Gpt35Turbo_0613, +// }); +// var resultMessage = result.GetFirstChoiceMessage(); +// messages.Add(resultMessage.AsRequestMessage()); +// +// messages.Add("Dubai, UAE".AsUserMessage()); +// result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest +// { +// Messages = messages, +// Functions = functions, +// Function_call = Function_call4.Auto, +// Model = ModelIds.Gpt35Turbo_0613, +// }); +// resultMessage = result.GetFirstChoiceMessage(); +// messages.Add(resultMessage.AsRequestMessage()); +// +// // It's possible that the assistant will also ask you which units you want the temperature in. +// if (!string.IsNullOrWhiteSpace(resultMessage.Content)) +// { +// messages.Add("celsius".AsUserMessage()); +// result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest +// { +// Messages = messages, +// Functions = functions, +// Function_call = Function_call4.Auto, +// Model = ModelIds.Gpt35Turbo_0613, +// }); +// resultMessage = result.GetFirstChoiceMessage(); +// messages.Add(resultMessage.AsRequestMessage()); +// } +// +// if (resultMessage.Function_call == null) +// { +// throw new InvalidOperationException("Expected a function call."); +// } +// +// var json = await service.CallAsync( +// functionName: resultMessage.Function_call.Name ?? string.Empty, +// argumentsAsJson: resultMessage.Function_call.Arguments ?? string.Empty); +// messages.Add(json.AsFunctionMessage(resultMessage.Function_call?.Name ?? string.Empty)); +// +// result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest +// { +// Messages = messages, +// Functions = functions, +// Function_call = Function_call4.Auto, +// Model = ModelIds.Gpt35Turbo_0613, +// }); +// resultMessage = result.GetFirstChoiceMessage(); +// messages.Add(resultMessage.AsRequestMessage()); +// } +// finally +// { +// PrintMessages(messages); +// } +// } +// +// private static void PrintMessages(List messages) +// { +// foreach (var message in messages) +// { +// if (message.Function_call != null) +// { +// Console.WriteLine($"{message.Role}(FunctionCall): {message.Function_call.Name}"); +// Console.WriteLine($"{message.Function_call.Arguments}"); +// continue; +// } +// +// Console.WriteLine($"{message.Role}: {message.Content}"); +// } +// } +// +// [TestMethod] +// public async Task Call() +// { +// var json = /* lang=json */ """ +// { +// "location": "Dubai, UAE" +// } +// """; +// var result = new WeatherService().CallGetCurrentWeather(json); +// +// result.Should().Be(/* lang=json */ """ +// {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"} +// """); +// +// var result2 = await new WeatherService().CallAsync("GetCurrentWeather", json); +// result2.Should().Be(/* lang=json */ """ +// {"location":"Dubai, UAE","temperature":22,"unit":"celsius","description":"Sunny"} +// """); +// } +// +// [TestMethod] +// [Ignore] +// public async Task UpdateCode() +// { +// var apiKey = +// Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? +// throw new AssertInconclusiveException("OPENAI_API_KEY is not set."); +// using var httpClient = new HttpClient(); +// var api = new OpenAiApi(apiKey, httpClient); +// var service = new UpdateCodeService(); +// var messages = new List +// { +// "You are a Senior C# programmer.".AsSystemMessage(), +// /* lang=markdown */""" +// You solve the issue with this description: +// ``` +// Hey there. My boss asked me to refactor our legacy project. Can you do that for me? They asked me to use SOLID principles, KISS, YAGNI and DRY as well as clean code +// The IUserCreditService and IUserCreditServiceChannel interfaces and the UserCreditServiceClient class are generated code so please don't change them. +// Keep in mind that anything withing LegacyApp.Consumer is someone else's code and MUST NOT be changed. +// Please don't introduce any breaking changes in the UserService class and its AddUser method. +// ``` +// I need new steps to prevent these errors: +// ``` +// Non-nullable property 'Firstname' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. +// ``` +// ``` +// Non-nullable property 'Surname' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. +// ``` +// ``` +// Non-nullable property 'EmailAddress' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. +// ``` +// ``` +// Non-nullable property 'Client' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. +// ``` +// ``` +// Possible null reference assignment. +// ``` +// Here is the code: +// +// LegacyApp/User.cs +// ```csharp +// using System; +// +// namespace LegacyApp +// { +// public class User +// { +// public int Id { get; set; } +// +// public string Firstname { get; set; } +// +// public string Surname { get; set; } +// +// public DateTime DateOfBirth { get; set; } +// +// public string EmailAddress { get; set; } +// +// public bool HasCreditLimit { get; set; } +// +// public int CreditLimit { get; set; } +// +// public Client Client { get; set; } +// } +// } +// ``` +// +// LegacyApp/UserService.cs +// ```csharp +// using System; +// +// #nullable enable +// namespace LegacyApp +// { +// public class UserService +// { +// public bool AddUser(string? firname, string? surname, string? email, DateTime dateOfBirth, int clientId) +// { +// if (string.IsNullOrEmpty(firname) || string.IsNullOrEmpty(surname)) +// { +// return false; +// } +// +// if (email == null || (!email.Contains(""@"") && !email.Contains("".""))) +// { +// return false; +// } +// +// var now = DateTime.Now; +// int age = now.Year - dateOfBirth.Year; +// if (now.Month < dateOfBirth.Month || (now.Month == dateOfBirth.Month && now.Day < dateOfBirth.Day)) age--; +// +// if (age < 21) +// { +// return false; +// } +// +// var clientRepository = new ClientRepository(); +// var client = clientRepository.GetById(clientId); +// +// var user = new User +// { +// Client = client, +// DateOfBirth = dateOfBirth, +// EmailAddress = email, +// Firstname = firname, +// Surname = surname +// }; +// +// if (client?.Name == ""VeryImportantClient"") +// { +// // Skip credit check +// user.HasCreditLimit = false; +// } +// else if (client?.Name == ""ImportantClient"") +// { +// // Do credit check and double credit limit +// user.HasCreditLimit = true; +// using (var userCreditService = new UserCreditServiceClient()) +// { +// var creditLimit = userCreditService.GetCreditLimit(user.Firstname, user.Surname, user.DateOfBirth); +// creditLimit = creditLimit * 2; +// user.CreditLimit = creditLimit; +// } +// } +// else +// { +// // Do credit check +// user.HasCreditLimit = true; +// using (var userCreditService = new UserCreditServiceClient()) +// { +// var creditLimit = userCreditService.GetCreditLimit(user.Firstname, user.Surname, user.DateOfBirth); +// user.CreditLimit = creditLimit; +// } +// } +// +// if (user.HasCreditLimit && user.CreditLimit < 500) +// { +// return false; +// } +// +// UserDataAccess.AddUser(user); +// +// return true; +// } +// } +// } +// ``` +// """.AsUserMessage(), +// }; +// var result = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest +// { +// Messages = messages, +// Functions = service.AsFunctions(), +// Function_call = Function_call4.Auto, +// Model = ModelIds.Gpt35Turbo_0613, +// }); +// var json = result.GetFirstChoiceMessage().Function_call?.Arguments ?? string.Empty; +// Console.WriteLine(json); +// +// var args = service.AsUpdateCodeArgs(json); +// args.Changes.Should().NotBeEmpty(); +// } } \ No newline at end of file diff --git a/src/tests/OpenAI.Generators.IntegrationTests/Tests.Streaming.cs b/src/tests/OpenAI.Generators.IntegrationTests/Tests.Streaming.cs index b83fcf76..66f7228e 100755 --- a/src/tests/OpenAI.Generators.IntegrationTests/Tests.Streaming.cs +++ b/src/tests/OpenAI.Generators.IntegrationTests/Tests.Streaming.cs @@ -1,47 +1,47 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using tryAGI.OpenAI; - -namespace H.Ipc.Generator.IntegrationTests; - -public partial class Tests -{ - [TestMethod] - public async Task Streaming() - { - var messages = new List - { - "You are a helpful weather assistant.".AsSystemMessage(), - "What's the weather like today?".AsUserMessage(), - }; - - var apiKey = - Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? - throw new AssertInconclusiveException("OPENAI_API_KEY is not set."); - using var httpClient = new HttpClient(); - var api = new OpenAiApi(apiKey, httpClient); - var result = api.CreateChatCompletionAsStreamAsync(new CreateChatCompletionRequest - { - Messages = messages, - Model = ModelIds.Gpt35Turbo_0613, - }); - await foreach (var response in result) - { - var delta = response.GetFirstChoiceDelta(); - if (delta.Role != null) - { - Console.WriteLine($"Role: {delta.Role}"); - } - if (delta.Content != null) - { - Console.WriteLine($"Content: {delta.Content}"); - } - if (delta.Function_call != null) - { - Console.WriteLine($"Function_call: {delta.Function_call.Name} {delta.Function_call.Arguments}"); - } - } - } -} \ No newline at end of file +// using System; +// using System.Collections.Generic; +// using System.Net.Http; +// using System.Threading.Tasks; +// using tryAGI.OpenAI; +// +// namespace H.Ipc.Generator.IntegrationTests; +// +// public partial class Tests +// { +// [TestMethod] +// public async Task Streaming() +// { +// var messages = new List +// { +// "You are a helpful weather assistant.".AsSystemMessage(), +// "What's the weather like today?".AsUserMessage(), +// }; +// +// var apiKey = +// Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? +// throw new AssertInconclusiveException("OPENAI_API_KEY is not set."); +// using var httpClient = new HttpClient(); +// var api = new OpenAiApi(apiKey, httpClient); +// var result = api.CreateChatCompletionAsStreamAsync(new CreateChatCompletionRequest +// { +// Messages = messages, +// Model = ModelIds.Gpt35Turbo_0613, +// }); +// await foreach (var response in result) +// { +// var delta = response.GetFirstChoiceDelta(); +// if (delta.Role != null) +// { +// Console.WriteLine($"Role: {delta.Role}"); +// } +// if (delta.Content != null) +// { +// Console.WriteLine($"Content: {delta.Content}"); +// } +// if (delta.Function_call != null) +// { +// Console.WriteLine($"Function_call: {delta.Function_call.Name} {delta.Function_call.Arguments}"); +// } +// } +// } +// } \ No newline at end of file diff --git a/src/tests/OpenAI.Generators.IntegrationTests/UpdateCodeFunctions.cs b/src/tests/OpenAI.Generators.IntegrationTests/UpdateCodeFunctions.cs index 963a973a..0a853bec 100755 --- a/src/tests/OpenAI.Generators.IntegrationTests/UpdateCodeFunctions.cs +++ b/src/tests/OpenAI.Generators.IntegrationTests/UpdateCodeFunctions.cs @@ -1,99 +1,99 @@ -using System; -using System.Collections.Generic; -using tryAGI.OpenAI; -using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; - -namespace H.Ipc.Generator.IntegrationTests; - -/// -/// -/// -public enum ChangeType -{ - /// - /// - /// - CreateFile, - - /// - /// - /// - ReplaceFragment, - - /// - /// - /// - DeleteFragment, - - /// - /// - /// - RenameFile, - - /// - /// - /// - DeleteFile, - - /// - /// - /// - End, -} - -public class Change -{ - /// - /// - /// - [Description("Describes the type of change to be made")] - public ChangeType Type { get; set; } - - /// - /// - /// - [Description("Specifies the path to a file")] - public string Path { get; set; } = string.Empty; - - /// - /// - /// - [Description("Specifies the code to be removed. Used when deleting or replacing code.")] - public string RemoveCode { get; set; } = string.Empty; - - /// - /// - /// - [Description("Specifies the code to add. Used when creating a file or replacing code.")] - public string AddCode { get; set; } = string.Empty; - - /// - /// - /// - [Description("Specifies the new path for the file. Used when renaming a file.")] - public string NewPath { get; set; } = string.Empty; -} - -[OpenAiFunctions] -public interface IUpdateCodeFunctions -{ - [Description("Allows to change the project code")] - public void UpdateCode( - [Description("A series of code changes that must end with END change type")] IReadOnlyCollection changes); -} - -public class UpdateCodeService : IUpdateCodeFunctions -{ - public void UpdateCode(IReadOnlyCollection changes) - { - changes = changes ?? throw new ArgumentNullException(nameof(changes)); - - foreach (var change in changes) - { - Console.WriteLine($"Type: {change.Type}, Path: {change.Path}"); - Console.WriteLine($"RemoveCode: {change.RemoveCode}"); - Console.WriteLine($"AddCode: {change.AddCode}"); - Console.WriteLine($"NewPath: {change.NewPath}"); - } - } -} \ No newline at end of file +// using System; +// using System.Collections.Generic; +// using tryAGI.OpenAI; +// using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; +// +// namespace H.Ipc.Generator.IntegrationTests; +// +// /// +// /// +// /// +// public enum ChangeType +// { +// /// +// /// +// /// +// CreateFile, +// +// /// +// /// +// /// +// ReplaceFragment, +// +// /// +// /// +// /// +// DeleteFragment, +// +// /// +// /// +// /// +// RenameFile, +// +// /// +// /// +// /// +// DeleteFile, +// +// /// +// /// +// /// +// End, +// } +// +// public class Change +// { +// /// +// /// +// /// +// [Description("Describes the type of change to be made")] +// public ChangeType Type { get; set; } +// +// /// +// /// +// /// +// [Description("Specifies the path to a file")] +// public string Path { get; set; } = string.Empty; +// +// /// +// /// +// /// +// [Description("Specifies the code to be removed. Used when deleting or replacing code.")] +// public string RemoveCode { get; set; } = string.Empty; +// +// /// +// /// +// /// +// [Description("Specifies the code to add. Used when creating a file or replacing code.")] +// public string AddCode { get; set; } = string.Empty; +// +// /// +// /// +// /// +// [Description("Specifies the new path for the file. Used when renaming a file.")] +// public string NewPath { get; set; } = string.Empty; +// } +// +// [OpenAiFunctions] +// public interface IUpdateCodeFunctions +// { +// [Description("Allows to change the project code")] +// public void UpdateCode( +// [Description("A series of code changes that must end with END change type")] IReadOnlyCollection changes); +// } +// +// public class UpdateCodeService : IUpdateCodeFunctions +// { +// public void UpdateCode(IReadOnlyCollection changes) +// { +// changes = changes ?? throw new ArgumentNullException(nameof(changes)); +// +// foreach (var change in changes) +// { +// Console.WriteLine($"Type: {change.Type}, Path: {change.Path}"); +// Console.WriteLine($"RemoveCode: {change.RemoveCode}"); +// Console.WriteLine($"AddCode: {change.AddCode}"); +// Console.WriteLine($"NewPath: {change.NewPath}"); +// } +// } +// } \ No newline at end of file diff --git a/src/tests/OpenAI.Generators.IntegrationTests/VariousTypesFunctions.cs b/src/tests/OpenAI.Generators.IntegrationTests/VariousTypesFunctions.cs index 81661264..9a4e06e9 100755 --- a/src/tests/OpenAI.Generators.IntegrationTests/VariousTypesFunctions.cs +++ b/src/tests/OpenAI.Generators.IntegrationTests/VariousTypesFunctions.cs @@ -1,34 +1,34 @@ -using System; -using tryAGI.OpenAI; -using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; - -namespace H.Ipc.Generator.IntegrationTests; - -[OpenAiFunctions] -public interface IVariousTypesFunctions -{ - [Description("Get the current weather in a given location")] - public bool GetCurrentWeather( - long parameter1, - int parameter2, - double parameter3, - float parameter4, - bool parameter5, - DateTime dateTime, - DateOnly date); -} - -public class VariousTypesService : IVariousTypesFunctions -{ - public bool GetCurrentWeather( - long parameter1, - int parameter2, - double parameter3, - float parameter4, - bool parameter5, - DateTime dateTime, - DateOnly date) - { - return true; - } -} \ No newline at end of file +// using System; +// using tryAGI.OpenAI; +// using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; +// +// namespace H.Ipc.Generator.IntegrationTests; +// +// [OpenAiFunctions] +// public interface IVariousTypesFunctions +// { +// [Description("Get the current weather in a given location")] +// public bool GetCurrentWeather( +// long parameter1, +// int parameter2, +// double parameter3, +// float parameter4, +// bool parameter5, +// DateTime dateTime, +// DateOnly date); +// } +// +// public class VariousTypesService : IVariousTypesFunctions +// { +// public bool GetCurrentWeather( +// long parameter1, +// int parameter2, +// double parameter3, +// float parameter4, +// bool parameter5, +// DateTime dateTime, +// DateOnly date) +// { +// return true; +// } +// } \ No newline at end of file diff --git a/src/tests/OpenAI.Generators.IntegrationTests/WeatherFunctions.cs b/src/tests/OpenAI.Generators.IntegrationTests/WeatherFunctions.cs index 202ec6c3..90813041 100755 --- a/src/tests/OpenAI.Generators.IntegrationTests/WeatherFunctions.cs +++ b/src/tests/OpenAI.Generators.IntegrationTests/WeatherFunctions.cs @@ -1,60 +1,60 @@ -using System.Threading; -using System.Threading.Tasks; -using tryAGI.OpenAI; -using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; - -namespace H.Ipc.Generator.IntegrationTests; - -public enum Unit -{ - Celsius, - Fahrenheit, -} - -public class Weather -{ - public string Location { get; set; } = string.Empty; - public double Temperature { get; set; } - public Unit Unit { get; set; } - public string Description { get; set; } = string.Empty; -} - -[OpenAiFunctions] -public interface IWeatherFunctions -{ - [Description("Get the current weather in a given location")] - public Weather GetCurrentWeather( - [Description("The city and state, e.g. San Francisco, CA")] string location, - Unit unit = Unit.Celsius); - - [Description("Get the current weather in a given location")] - public Task GetCurrentWeatherAsync( - [Description("The city and state, e.g. San Francisco, CA")] string location, - Unit unit = Unit.Celsius, - CancellationToken cancellationToken = default); -} - -public class WeatherService : IWeatherFunctions -{ - public Weather GetCurrentWeather(string location, Unit unit = Unit.Celsius) - { - return new Weather - { - Location = location, - Temperature = 22.0, - Unit = unit, - Description = "Sunny", - }; - } - - public Task GetCurrentWeatherAsync(string location, Unit unit = Unit.Celsius, CancellationToken cancellationToken = default) - { - return Task.FromResult(new Weather - { - Location = location, - Temperature = 22.0, - Unit = unit, - Description = "Sunny", - }); - } -} \ No newline at end of file +// using System.Threading; +// using System.Threading.Tasks; +// using tryAGI.OpenAI; +// using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; +// +// namespace H.Ipc.Generator.IntegrationTests; +// +// public enum Unit +// { +// Celsius, +// Fahrenheit, +// } +// +// public class Weather +// { +// public string Location { get; set; } = string.Empty; +// public double Temperature { get; set; } +// public Unit Unit { get; set; } +// public string Description { get; set; } = string.Empty; +// } +// +// [OpenAiFunctions] +// public interface IWeatherFunctions +// { +// [Description("Get the current weather in a given location")] +// public Weather GetCurrentWeather( +// [Description("The city and state, e.g. San Francisco, CA")] string location, +// Unit unit = Unit.Celsius); +// +// [Description("Get the current weather in a given location")] +// public Task GetCurrentWeatherAsync( +// [Description("The city and state, e.g. San Francisco, CA")] string location, +// Unit unit = Unit.Celsius, +// CancellationToken cancellationToken = default); +// } +// +// public class WeatherService : IWeatherFunctions +// { +// public Weather GetCurrentWeather(string location, Unit unit = Unit.Celsius) +// { +// return new Weather +// { +// Location = location, +// Temperature = 22.0, +// Unit = unit, +// Description = "Sunny", +// }; +// } +// +// public Task GetCurrentWeatherAsync(string location, Unit unit = Unit.Celsius, CancellationToken cancellationToken = default) +// { +// return Task.FromResult(new Weather +// { +// Location = location, +// Temperature = 22.0, +// Unit = unit, +// Description = "Sunny", +// }); +// } +// } \ No newline at end of file diff --git a/src/tests/OpenAI.IntegrationTests/Tests.Chat.cs b/src/tests/OpenAI.IntegrationTests/Tests.Chat.cs index 72004df9..cd8ef4be 100755 --- a/src/tests/OpenAI.IntegrationTests/Tests.Chat.cs +++ b/src/tests/OpenAI.IntegrationTests/Tests.Chat.cs @@ -1,3 +1,5 @@ +using OpenAI.Chat; + namespace tryAGI.OpenAI.IntegrationTests; public partial class Tests @@ -6,16 +8,14 @@ public partial class Tests public async Task CreateChatCompletion() { var api = GetAuthorizedApi(); - var response = await api.CreateChatCompletionAsync(new CreateChatCompletionRequest - { - Messages = new List + var response = await api.ChatEndpoint.GetCompletionAsync(new ChatRequest( + new[] { "You are a helpful weather assistant.".AsSystemMessage(), "What's the weather like today?".AsUserMessage(), }, - Model = ModelIds.Gpt35Turbo_0613, - User = "tryAGI.OpenAI.IntegrationTests.Tests.CreateChatCompletion", - }); + model: ModelIds.Gpt35Turbo_0613, + user: "tryAGI.OpenAI.IntegrationTests.Tests.CreateChatCompletion")); response.Choices.ElementAt(0).Message.Content.Should().NotBeEmpty(); Console.WriteLine(response.Choices.ElementAt(0).Message.Content); @@ -25,16 +25,15 @@ public async Task CreateChatCompletion() public async Task CreateChatCompletionAsStreamAsync() { var api = GetAuthorizedApi(); - var enumerable = api.CreateChatCompletionAsStreamAsync(new CreateChatCompletionRequest - { - Messages = new List + var enumerable = api.ChatEndpoint.StreamCompletionEnumerableAsync(new ChatRequest( + new[] { "You are a helpful weather assistant.".AsSystemMessage(), "What's the weather like today?".AsUserMessage(), }, - Model = ModelIds.Gpt35Turbo_0613, - User = "tryAGI.OpenAI.IntegrationTests.Tests.CreateChatCompletion", - }); + model: ModelIds.Gpt35Turbo_0613, + user: "tryAGI.OpenAI.IntegrationTests.Tests.CreateChatCompletion")); + await foreach (var response in enumerable) { Console.WriteLine(response.Choices.ElementAt(0).Delta.Content); diff --git a/src/tests/OpenAI.IntegrationTests/Tests.Embeddings.cs b/src/tests/OpenAI.IntegrationTests/Tests.Embeddings.cs index 74b72c71..396d2f14 100755 --- a/src/tests/OpenAI.IntegrationTests/Tests.Embeddings.cs +++ b/src/tests/OpenAI.IntegrationTests/Tests.Embeddings.cs @@ -1,3 +1,5 @@ +using OpenAI.Embeddings; + namespace tryAGI.OpenAI.IntegrationTests; public partial class Tests @@ -6,15 +8,13 @@ public partial class Tests public async Task CreateEmbedding() { var api = GetAuthorizedApi(); - var response = await api.CreateEmbeddingAsync(new CreateEmbeddingRequest - { - Input = "Hello, world", - Model = EmbeddingModelIds.Ada002, - User = "tryAGI.OpenAI.IntegrationTests.Tests.CreateEmbedding", - }); - response.Data.ElementAt(0).Embedding1.Should().NotBeEmpty(); + var response = await api.EmbeddingsEndpoint.CreateEmbeddingAsync(new EmbeddingsRequest( + input: "Hello, world", + model: EmbeddingModelIds.Ada002, + user: "tryAGI.OpenAI.IntegrationTests.Tests.CreateEmbedding")); + response.Data.ElementAt(0).Embedding.Should().NotBeEmpty(); - foreach (var data in response.Data.ElementAt(0).Embedding1) + foreach (var data in response.Data.ElementAt(0).Embedding) { Console.WriteLine($"{data}"); } diff --git a/src/tests/OpenAI.IntegrationTests/Tests.Helpers.cs b/src/tests/OpenAI.IntegrationTests/Tests.Helpers.cs index 7a73d56c..179ed074 100755 --- a/src/tests/OpenAI.IntegrationTests/Tests.Helpers.cs +++ b/src/tests/OpenAI.IntegrationTests/Tests.Helpers.cs @@ -1,15 +1,16 @@ +using OpenAI; + namespace tryAGI.OpenAI.IntegrationTests; [TestClass] public partial class Tests { - private static OpenAiApi GetAuthorizedApi() + private static OpenAIClient GetAuthorizedApi() { var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new AssertInconclusiveException("OPENAI_API_KEY environment variable is not found."); - var client = new HttpClient(); - return new OpenAiApi(apiKey, client); + return new OpenAIClient(apiKey); } } diff --git a/src/tests/OpenAI.IntegrationTests/Tests.Images.cs b/src/tests/OpenAI.IntegrationTests/Tests.Images.cs index b1e06a0c..c07b2c07 100755 --- a/src/tests/OpenAI.IntegrationTests/Tests.Images.cs +++ b/src/tests/OpenAI.IntegrationTests/Tests.Images.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using OpenAI.Images; namespace tryAGI.OpenAI.IntegrationTests; @@ -8,44 +9,42 @@ public partial class Tests public async Task CreateImage_Url() { var api = GetAuthorizedApi(); - var response = await api.CreateImageAsync(new CreateImageRequest - { - Prompt = "a white siamese cat", - N = 1, - Size = CreateImageRequestSize._256x256, - Response_format = CreateImageRequestResponse_format.Url, - User = "tryAGI.OpenAI.IntegrationTests.Tests.CreateImage_Url", - }); - response.Data.ElementAt(0).Url.Should().NotBeEmpty(); + var response = await api.ImagesEndPoint.GenerateImageAsync(new ImageGenerationRequest( + prompt: "a white siamese cat", + numberOfResults: 1, + size: "256x256", + responseFormat: ResponseFormat.Url, + user: "tryAGI.OpenAI.IntegrationTests.Tests.CreateImage_Url")); + response.ElementAt(0).Should().NotBeEmpty(); - Process.Start(new ProcessStartInfo(response.Data.ElementAt(0).Url!) + Process.Start(new ProcessStartInfo(response.ElementAt(0)) { UseShellExecute = true, }); } - [TestMethod] - public async Task CreateImage_Base64() - { - var api = GetAuthorizedApi(); - var response = await api.CreateImageAsync(new CreateImageRequest - { - Prompt = "a white siamese cat", - N = 1, - Size = CreateImageRequestSize._256x256, - Response_format = CreateImageRequestResponse_format.B64_json, - User = "tryAGI.OpenAI.IntegrationTests.Tests.CreateImage_Base64", - }); - var base64 = response.Data.ElementAt(0).B64_json; - base64.Should().NotBeEmpty(); - - var bytes = Convert.FromBase64String(base64!); - var path = Path.Combine(Path.GetTempPath(), "cat.png"); - await File.WriteAllBytesAsync(path, bytes); - - Process.Start(new ProcessStartInfo(path) - { - UseShellExecute = true, - }); - } + // [TestMethod] + // public async Task CreateImage_Base64() + // { + // var api = GetAuthorizedApi(); + // var response = await api.CreateImageAsync(new CreateImageRequest + // { + // Prompt = "a white siamese cat", + // N = 1, + // Size = CreateImageRequestSize._256x256, + // Response_format = CreateImageRequestResponse_format.B64_json, + // User = "tryAGI.OpenAI.IntegrationTests.Tests.CreateImage_Base64", + // }); + // var base64 = response.Data.ElementAt(0).B64_json; + // base64.Should().NotBeEmpty(); + // + // var bytes = Convert.FromBase64String(base64!); + // var path = Path.Combine(Path.GetTempPath(), "cat.png"); + // await File.WriteAllBytesAsync(path, bytes); + // + // Process.Start(new ProcessStartInfo(path) + // { + // UseShellExecute = true, + // }); + // } } diff --git a/src/tests/OpenAI.IntegrationTests/Tests.ListModels.cs b/src/tests/OpenAI.IntegrationTests/Tests.ListModels.cs index 12a85c0f..7444e4a9 100755 --- a/src/tests/OpenAI.IntegrationTests/Tests.ListModels.cs +++ b/src/tests/OpenAI.IntegrationTests/Tests.ListModels.cs @@ -6,10 +6,10 @@ public partial class Tests public async Task ListModels() { var api = GetAuthorizedApi(); - var models = await api.ListModelsAsync(); - models.Data.Should().NotBeEmpty(); + var models = await api.ModelsEndpoint.GetModelsAsync(); + models.Should().NotBeEmpty(); - foreach (var model in models.Data) + foreach (var model in models) { Console.WriteLine($"{model.Id}"); } diff --git a/src/tests/OpenAI.IntegrationTests/Tests.Moderation.cs b/src/tests/OpenAI.IntegrationTests/Tests.Moderation.cs index 8227c296..7705a23e 100755 --- a/src/tests/OpenAI.IntegrationTests/Tests.Moderation.cs +++ b/src/tests/OpenAI.IntegrationTests/Tests.Moderation.cs @@ -1,3 +1,5 @@ +using OpenAI.Moderations; + namespace tryAGI.OpenAI.IntegrationTests; public partial class Tests @@ -6,11 +8,10 @@ public partial class Tests public async Task CreateModeration() { var api = GetAuthorizedApi(); - var response = await api.CreateModerationAsync(new CreateModerationRequest - { - Input = "Hello, world", - Model = ModerationModelIds.Latest, - }); + var response = await api.ModerationsEndpoint.CreateModerationAsync(new ModerationsRequest( + input: "Hello, world", + model: ModerationModelIds.Latest)); + response.Results.First().Flagged.Should().BeFalse(); } @@ -18,11 +19,9 @@ public async Task CreateModeration() public async Task CreateModeration_Flagged() { var api = GetAuthorizedApi(); - var response = await api.CreateModerationAsync(new CreateModerationRequest - { - Input = "Fuck you", - Model = ModerationModelIds.Latest, - }); + var response = await api.ModerationsEndpoint.CreateModerationAsync(new ModerationsRequest( + input: "Fuck you", + model: ModerationModelIds.Latest)); response.Results.First().Flagged.Should().BeTrue(); } }