From 668522aeb0bfa31c38751aaa055e6fa65d540392 Mon Sep 17 00:00:00 2001 From: Denis Papp Date: Fri, 24 May 2024 19:19:00 -0500 Subject: [PATCH 01/14] + Assistant Attachments: - updated Assistant test with Attachment to be working - AssistantCreateRequest: removed FileIds which is no longer supported in the API - Message.Attachments: updated documentation to clarify restrictions on defining these + Cleanup: fixed a few warnings --- OpenAI.Playground/Program.cs | 4 +++- .../AssistantHelpers/AssistantTestHelper3.cs | 23 +++++++++++++++---- .../AssistantHelpers/VectorTestHelper.cs | 6 ++--- OpenAI.SDK/ObjectModels/Models.cs | 1 + .../RequestModels/AssistantCreateRequest.cs | 9 ++------ .../RequestModels/MessageCreateRequest.cs | 5 ++-- .../CreateModerationResponse.cs | 2 +- 7 files changed, 31 insertions(+), 19 deletions(-) diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs index 4cc419bb..cbcf0555 100644 --- a/OpenAI.Playground/Program.cs +++ b/OpenAI.Playground/Program.cs @@ -4,6 +4,7 @@ using OpenAI.Extensions; using OpenAI.Interfaces; using OpenAI.Playground.TestHelpers; +using OpenAI.Playground.TestHelpers.AssistantHelpers; var builder = new ConfigurationBuilder().AddJsonFile("ApiSettings.json") .AddUserSecrets(); @@ -48,7 +49,8 @@ //await AssistantTestHelper.ThreadsTestHelper.RunTests(sdk); //await AssistantTestHelper.MessagesTestHelper.RunTests(sdk); //await AssistantTestHelper.RunTestHelper.RunTests(sdk); -//await AssistantTestHelper.VectorTestHelper.RunTests(sdk); +//await AssistantTestHelper.VectorTestHelper.RunTests(sd +//await AssistantTestHelper3.RunTests(sdk); // Vision //await VisionTestHelper.RunSimpleVisionTest(sdk); diff --git a/OpenAI.Playground/TestHelpers/AssistantHelpers/AssistantTestHelper3.cs b/OpenAI.Playground/TestHelpers/AssistantHelpers/AssistantTestHelper3.cs index 0f8e11a2..57d7c8d8 100644 --- a/OpenAI.Playground/TestHelpers/AssistantHelpers/AssistantTestHelper3.cs +++ b/OpenAI.Playground/TestHelpers/AssistantHelpers/AssistantTestHelper3.cs @@ -10,6 +10,12 @@ namespace OpenAI.Playground.TestHelpers.AssistantHelpers; internal static class AssistantTestHelper3 { + public static async Task RunTests(IOpenAIService sdk) + { + await RunAssistantApiTest(sdk); + await RunHowAssistantsWorkTest(sdk); + } + /// /// Test Assistant api /// @@ -133,8 +139,11 @@ public static async Task RunHowAssistantsWorkTest(IOpenAIService sdk) var sampleFile = await FileExtensions.ReadAllBytesAsync($"SampleData/{fileName}"); var sampleFileAsString = Encoding.UTF8.GetString(sampleFile); + // HACK: drp052424 - CSV format is not supported for Assistant, so we tell OpenAI it's a TXT. A better solution would be to update the test asset. + var fileNameForOpenAI = Path.ChangeExtension(fileName, ".txt"); + ConsoleExtensions.WriteLine($"Uploading file: {fileName}", ConsoleColor.DarkCyan); - var uploadFilesResponse = await sdk.Files.FileUpload(UploadFilePurposes.UploadFilePurpose.Assistants, sampleFile, fileName); + var uploadFilesResponse = await sdk.Files.FileUpload(UploadFilePurposes.UploadFilePurpose.Assistants, sampleFile, fileNameForOpenAI); if (uploadFilesResponse.Successful) { ConsoleExtensions.WriteLine($"{fileName} uploaded", ConsoleColor.DarkGreen); @@ -145,8 +154,8 @@ public static async Task RunHowAssistantsWorkTest(IOpenAIService sdk) return; } - var uplaodFileId = uploadFilesResponse.Id; - ConsoleExtensions.WriteLine($"uplaodFileId:{uplaodFileId}, purpose:{uploadFilesResponse.Purpose}"); + var uploadFileId = uploadFilesResponse.Id; + ConsoleExtensions.WriteLine($"uploadFileId:{uploadFileId}, purpose:{uploadFilesResponse.Purpose}"); #endregion @@ -163,7 +172,6 @@ public static async Task RunHowAssistantsWorkTest(IOpenAIService sdk) Name = "Qicha", Model = Models.Gpt_3_5_Turbo_1106, Tools = new List() { ToolDefinition.DefineCodeInterpreter(), ToolDefinition.DefineFileSearch(), ToolDefinition.DefineFunction(func) }, - FileIds = new List() { uplaodFileId } }); if (assistantResult.Successful) @@ -207,7 +215,12 @@ public static async Task RunHowAssistantsWorkTest(IOpenAIService sdk) { Role = StaticValues.AssistantsStatics.MessageStatics.Roles.User, Content =new("Where is Zhejiang Jiacheng Supply Chain Co., LTD."), - Attachments = [new() { FileId = uplaodFileId }] + // Tools must be specified for Attachments + Attachments = [new() + { + FileId = uploadFileId, + Tools = [ ToolDefinition.DefineFileSearch() ] + }] }); if (messageResult.Successful) diff --git a/OpenAI.Playground/TestHelpers/AssistantHelpers/VectorTestHelper.cs b/OpenAI.Playground/TestHelpers/AssistantHelpers/VectorTestHelper.cs index f0ebdb84..3b313612 100644 --- a/OpenAI.Playground/TestHelpers/AssistantHelpers/VectorTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/AssistantHelpers/VectorTestHelper.cs @@ -502,11 +502,11 @@ public static async Task CancelVectorStoreFileBatch(IOpenAIService openAI) private static async Task Cleanup(IOpenAIService sdk) { - - if (!string.IsNullOrWhiteSpace(CreatedVectorFileId)) + if (!string.IsNullOrWhiteSpace(CreatedVectorFileId) && !string.IsNullOrWhiteSpace(CreatedVectorId)) { await sdk.Beta.VectorStoreFiles.DeleteVectorStoreFile(CreatedVectorId, CreatedVectorFileId); } + if (!string.IsNullOrWhiteSpace(CreatedFileId1)) { await sdk.Files.DeleteFile(CreatedFileId1); @@ -523,4 +523,4 @@ private static async Task Cleanup(IOpenAIService sdk) } } } -} \ No newline at end of file +} diff --git a/OpenAI.SDK/ObjectModels/Models.cs b/OpenAI.SDK/ObjectModels/Models.cs index 9cfb7f1f..6b170353 100644 --- a/OpenAI.SDK/ObjectModels/Models.cs +++ b/OpenAI.SDK/ObjectModels/Models.cs @@ -270,6 +270,7 @@ public enum Subject public static string TextModeration007 => ModelNameBuilder(BaseModel.None, Subject.TextModeration, "007"); public static string TextModerationLatest => ModelNameBuilder(BaseModel.None, Subject.TextModeration, "latest"); public static string TextModerationStable => ModelNameBuilder(BaseModel.None, Subject.TextModeration, "stable"); + /// /// Most capable GPT-3.5 model and optimized for chat at 1/10th the cost of text-davinci-003. Will be updated with our /// latest model iteration. diff --git a/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs index 1bcdc7ca..a93cceff 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs @@ -3,7 +3,8 @@ namespace OpenAI.ObjectModels.RequestModels; -public class AssistantCreateRequest : IOpenAiModels.IModel, IOpenAiModels.IFileIds, IOpenAiModels.IMetaData, IOpenAiModels.ITemperature +// REMOVED: drp052424 - IOpenAiModels.IFileIds property is no longer in the API reference, and will not work if you use it +public class AssistantCreateRequest : IOpenAiModels.IModel, IOpenAiModels.IMetaData, IOpenAiModels.ITemperature { /// /// The name of the assistant. The maximum length is 256 characters. @@ -65,12 +66,6 @@ public class AssistantCreateRequest : IOpenAiModels.IModel, IOpenAiModels.IFileI [JsonPropertyName("response_format")] public ResponseFormatOneOfType? ResponseFormat { get; set; } - /// - /// A list of file IDs attached to this assistant. - /// - [JsonPropertyName("file_ids")] - public List? FileIds { get; set; } - /// /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information /// about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of diff --git a/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs index 1f164d2e..5c45df69 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs @@ -49,12 +49,13 @@ public MessageCreateRequest(string role, MessageContentOneOfType content, List - /// The ID of the file to attach to + /// The ID of the file to attach to. See https://platform.openai.com/docs/assistants/tools/file-search/supported-files for a list of supported file extensions. /// [JsonPropertyName("file_id")] public string FileId { get; set; } + /// - /// The tools to add this file to. + /// The tools to add this file to. This is required and may contain CodeInterpreter and/or FileSearch /// [JsonPropertyName("tools")] public List Tools { get; set; } diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs index d997dca1..ffd8ce12 100644 --- a/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs +++ b/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs @@ -9,7 +9,7 @@ public record CreateModerationResponse : BaseResponse, IOpenAiModels.IModel, IOp [JsonPropertyName("id")] public string Id { get; set; } - [JsonPropertyName("model")] public string Model { get; set; } + [JsonPropertyName("model")] public string? Model { get; set; } } public record Result From 2bf51c9ae29db1cbaf085a416fb06c6c01134303 Mon Sep 17 00:00:00 2001 From: Denis Papp Date: Fri, 24 May 2024 19:22:58 -0500 Subject: [PATCH 02/14] + AssistantCreateRequest: restored deleted field and c hanged to [Obsolete] --- .../ObjectModels/RequestModels/AssistantCreateRequest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs index a93cceff..39a9eb09 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs @@ -66,6 +66,13 @@ public class AssistantCreateRequest : IOpenAiModels.IModel, IOpenAiModels.IMetaD [JsonPropertyName("response_format")] public ResponseFormatOneOfType? ResponseFormat { get; set; } + /// + /// A list of file IDs attached to this assistant. + /// + [JsonPropertyName("file_ids")] + [Obsolete("This field is no longer supported by the API.")] + public List? FileIds { get; set; } + /// /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information /// about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of From 37f1ba21542ebe1700baf0b0c349fbd8beb4a923 Mon Sep 17 00:00:00 2001 From: Denis Papp Date: Fri, 24 May 2024 19:37:07 -0500 Subject: [PATCH 03/14] + Files: updated Purpose enum to match API - added vision, batch - removed FineTuneResults + Audio: updated description of AudioCreateTranscriptionRequest.FileName to emphasize that an extension is required and important --- .../AudioCreateTranscriptionRequest.cs | 2 +- OpenAI.SDK/ObjectModels/UploadFilePurposes.cs | 23 +++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs index da6fc583..fce95d8a 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs @@ -42,7 +42,7 @@ public record AudioCreateTranscriptionRequest : IOpenAiModels.IModel, IOpenAiMod public Stream? FileStream { get; set; } /// - /// FileName + /// FileName. Note the API keys off the extension of the FileName to know the format. /// public string FileName { get; set; } diff --git a/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs b/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs index 0204e952..f71a0e6c 100644 --- a/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs +++ b/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs @@ -4,22 +4,30 @@ public static class UploadFilePurposes { public enum UploadFilePurpose { - FineTune, - FineTuneResults, Assistants, + Vision, + Batch, + FineTune, + [Obsolete("Not supported by the API")] + FineTuneResults } + // REF: https://platform.openai.com/docs/api-reference/files/create + public const string Assistants = "assistants"; + public const string Vision = "vision"; + public const string Batch = "batch"; public const string FineTune = "fine-tune"; + [Obsolete("Not supported by the API")] public const string FineTuneResults = "fine-tune-results"; - public const string Assistants = "assistants"; public static string EnumToString(this UploadFilePurpose uploadFilePurpose) { return uploadFilePurpose switch { - UploadFilePurpose.FineTune => FineTune, - UploadFilePurpose.FineTuneResults => FineTuneResults, UploadFilePurpose.Assistants => Assistants, + UploadFilePurpose.Vision => Vision, + UploadFilePurpose.Batch => Batch, + UploadFilePurpose.FineTune => FineTune, _ => throw new ArgumentOutOfRangeException(nameof(uploadFilePurpose), uploadFilePurpose, null) }; } @@ -28,9 +36,10 @@ public static UploadFilePurpose ToEnum(string filePurpose) { return filePurpose switch { - FineTune => UploadFilePurpose.FineTune, - FineTuneResults => UploadFilePurpose.FineTuneResults, Assistants => UploadFilePurpose.Assistants, + Vision => UploadFilePurpose.Vision, + Batch => UploadFilePurpose.Batch, + FineTune => UploadFilePurpose.FineTune, _ => throw new ArgumentOutOfRangeException(nameof(filePurpose), filePurpose, null) }; } From cc5992972a87384b432993b747573b2429e20ce1 Mon Sep 17 00:00:00 2001 From: Denis Papp Date: Sat, 25 May 2024 18:01:55 -0500 Subject: [PATCH 04/14] + MessageContent.ImageFileContent: fixed serialization to "file_id" to match what API is expecting - MessagesTestHelper: added CreateMessageWithImage() test --- OpenAI.Playground/Program.cs | 1 + .../AssistantHelpers/MessagesTestHelper.cs | 128 ++++++++++++++++++ .../TestHelpers/VisionTestHelper.cs | 27 +++- .../RequestModels/VisionImageUrl.cs | 2 +- 4 files changed, 152 insertions(+), 6 deletions(-) diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs index cbcf0555..9d48972b 100644 --- a/OpenAI.Playground/Program.cs +++ b/OpenAI.Playground/Program.cs @@ -54,6 +54,7 @@ // Vision //await VisionTestHelper.RunSimpleVisionTest(sdk); +//await VisionTestHelper.RunSimpleVisionTestUsingBase64EncodedImage(sdk); //await VisionTestHelper.RunSimpleVisionStreamTest(sdk); //await VisionTestHelper.RunSimpleVisionTestUsingBase64EncodedImage(sdk); diff --git a/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs b/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs index 99d0765b..f7f6ac57 100644 --- a/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs @@ -1,7 +1,12 @@ using OpenAI.Interfaces; using OpenAI.ObjectModels; +using OpenAI.ObjectModels.RequestModels; using OpenAI.ObjectModels.SharedModels; using OpenAI.Playground.ExtensionsAndHelpers; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using static OpenAI.ObjectModels.StaticValues; namespace OpenAI.Playground.TestHelpers.AssistantHelpers; @@ -16,6 +21,7 @@ public static async Task RunTests(IOpenAIService openAI) { ConsoleExtensions.WriteLine("Message Basics Testing is starting:", ConsoleColor.Blue); await CreateMessage(openAI); + await CreateMessageWithImage(openAI); await ListMessages(openAI); await RetrieveMessage(openAI); await ModifyMessage(openAI); @@ -51,6 +57,128 @@ public static async Task CreateMessage(IOpenAIService openAI) } } + public static async Task CreateMessageWithImage(IOpenAIService openAI) + { + ConsoleExtensions.WriteLine("Create MessageWithImage Testing is starting:", ConsoleColor.Cyan); + + #region Create Thread + + var thread = await openAI.Beta.Threads.ThreadCreate(); + if (!thread.Successful) + { + if (thread.Error == null) + { + throw new("Unknown Error"); + } + + ConsoleExtensions.WriteLine($"{thread.Error.Code}: {thread.Error.Message}", ConsoleColor.Red); + return; + } + CreatedThreadId = thread.Id; + + #endregion + + #region Message.ImageBinaryContent + + ConsoleExtensions.WriteLine("Message with ImageBinaryContent Test:", ConsoleColor.DarkCyan); + + var prompt = "Tell me about this image"; + var filename = "image_edit_mask.png"; + var filePath = $"SampleData/{filename}"; + + var sampleBytes = await FileExtensions.ReadAllBytesAsync(filePath); + + var result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId, new() + { + Role = StaticValues.AssistantsStatics.MessageStatics.Roles.User, + Content = new([ + MessageContent.TextContent(prompt), + MessageContent.ImageBinaryContent( + sampleBytes, + ImageStatics.ImageFileTypes.Png, + ImageStatics.ImageDetailTypes.High + ) + ]), + } + ); + if (result.Successful) + { + CreatedMessageId = result.Id; + ConsoleExtensions.WriteLine($"Message Created Successfully with ID: {result.Id}", ConsoleColor.Green); + } + else + { + ConsoleExtensions.WriteError(result.Error); + } + + #endregion + + #region Upload File + + ConsoleExtensions.WriteLine("Upload File Test", ConsoleColor.DarkCyan); + + ConsoleExtensions.WriteLine($"Uploading file: {filename}", ConsoleColor.DarkCyan); + var uploadFilesResponse = await openAI.Files.FileUpload(UploadFilePurposes.UploadFilePurpose.Vision, sampleBytes, filename); + if (uploadFilesResponse.Successful) + { + ConsoleExtensions.WriteLine($"{filename} uploaded", ConsoleColor.DarkGreen); + } + else + { + ConsoleExtensions.WriteLine($"{filename} failed", ConsoleColor.DarkRed); + return; + } + + var uploadFileId = uploadFilesResponse.Id; + ConsoleExtensions.WriteLine($"uploadFileId:{uploadFileId}, purpose:{uploadFilesResponse.Purpose}"); + + #endregion + + #region Message.ImageFileContent + + ConsoleExtensions.WriteLine("Message with ImageFileContent Test:", ConsoleColor.DarkCyan); + + MessageContentOneOfType content = new([ + MessageContent.TextContent(prompt), + MessageContent.ImageFileContent( + uploadFileId, + ImageStatics.ImageDetailTypes.High + ) + ]); + + MessageCreateRequest request = new() + { + Role = StaticValues.AssistantsStatics.MessageStatics.Roles.User, + Content = content, + }; + + /* DEBUG + var options = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + var serialized = JsonSerializer.Serialize(request, options); + ConsoleExtensions.WriteLine($"MessageRequest: {serialized}", ConsoleColor.White); + */ + + result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId, request); + if (result.Successful) + { + CreatedMessageId = result.Id; + ConsoleExtensions.WriteLine($"Message Created Successfully with ID: {result.Id}", ConsoleColor.Green); + } + else + { + ConsoleExtensions.WriteError(result.Error); + } + + #endregion + + // TODO: add Run()... + + } + public static async Task ListMessages(IOpenAIService openAI) { ConsoleExtensions.WriteLine("List Messages Testing is starting:", ConsoleColor.Cyan); diff --git a/OpenAI.Playground/TestHelpers/VisionTestHelper.cs b/OpenAI.Playground/TestHelpers/VisionTestHelper.cs index 2c92a52d..0659d499 100644 --- a/OpenAI.Playground/TestHelpers/VisionTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/VisionTestHelper.cs @@ -2,6 +2,8 @@ using OpenAI.ObjectModels; using OpenAI.ObjectModels.RequestModels; using OpenAI.Playground.ExtensionsAndHelpers; +using System.Text.Json.Serialization; +using System.Text.Json; using static OpenAI.ObjectModels.StaticValues; namespace OpenAI.Playground.TestHelpers; @@ -127,6 +129,9 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi try { + + ConsoleExtensions.WriteLine("Vision Test With EncodedImage:", ConsoleColor.DarkCyan); + ConsoleExtensions.WriteLine( "Vision with base64 encoded image Test:", ConsoleColor.DarkCyan @@ -137,10 +142,7 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi $"SampleData/{originalFileName}" ); - var completionResult = await sdk.ChatCompletion.CreateCompletion( - new ChatCompletionCreateRequest - { - Messages = new List + var messages = new List { ChatMessage.FromSystem("You are an image analyzer assistant."), ChatMessage.FromUser( @@ -154,7 +156,22 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi ) } ), - }, + }; + + /* DEBUG + var options = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + var serialized = JsonSerializer.Serialize(messages, options); + ConsoleExtensions.WriteLine($"MessageRequest: {serialized}", ConsoleColor.White); + */ + + var completionResult = await sdk.ChatCompletion.CreateCompletion( + new ChatCompletionCreateRequest + { + Messages = messages, MaxTokens = 300, Model = Models.Gpt_4_vision_preview, N = 1 diff --git a/OpenAI.SDK/ObjectModels/RequestModels/VisionImageUrl.cs b/OpenAI.SDK/ObjectModels/RequestModels/VisionImageUrl.cs index 973cb69e..2175ccf3 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/VisionImageUrl.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/VisionImageUrl.cs @@ -41,7 +41,7 @@ public class MessageImageFile /// /// The File ID of the image in the message content. Set purpose="vision" when uploading the File if you need to later display the file content. /// - [JsonPropertyName("file_Id")] + [JsonPropertyName("file_id")] public string FileId { get; set; } /// /// Specifies the detail level of the image if specified by the user. low uses fewer tokens, you can opt in to high resolution using high. From ae62c0810d8df378f879b24516ab5a2fa4b2970f Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Sun, 2 Jun 2024 14:11:34 +0100 Subject: [PATCH 05/14] Updated PR changes --- OpenAI.Playground/Program.cs | 4 +- .../AssistantHelpers/MessagesTestHelper.cs | 94 ++--------- .../TestHelpers/VisionTestHelper.cs | 151 ++++++------------ .../RequestModels/AssistantCreateRequest.cs | 10 +- .../AudioCreateTranscriptionRequest.cs | 2 +- .../RequestModels/MessageCreateRequest.cs | 4 +- OpenAI.SDK/ObjectModels/UploadFilePurposes.cs | 24 ++- 7 files changed, 92 insertions(+), 197 deletions(-) diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs index 9d48972b..914c1673 100644 --- a/OpenAI.Playground/Program.cs +++ b/OpenAI.Playground/Program.cs @@ -4,7 +4,6 @@ using OpenAI.Extensions; using OpenAI.Interfaces; using OpenAI.Playground.TestHelpers; -using OpenAI.Playground.TestHelpers.AssistantHelpers; var builder = new ConfigurationBuilder().AddJsonFile("ApiSettings.json") .AddUserSecrets(); @@ -49,14 +48,13 @@ //await AssistantTestHelper.ThreadsTestHelper.RunTests(sdk); //await AssistantTestHelper.MessagesTestHelper.RunTests(sdk); //await AssistantTestHelper.RunTestHelper.RunTests(sdk); -//await AssistantTestHelper.VectorTestHelper.RunTests(sd +//await AssistantTestHelper.VectorTestHelper.RunTests(sdk); //await AssistantTestHelper3.RunTests(sdk); // Vision //await VisionTestHelper.RunSimpleVisionTest(sdk); //await VisionTestHelper.RunSimpleVisionTestUsingBase64EncodedImage(sdk); //await VisionTestHelper.RunSimpleVisionStreamTest(sdk); -//await VisionTestHelper.RunSimpleVisionTestUsingBase64EncodedImage(sdk); // Tools //await ChatCompletionTestHelper.RunChatFunctionCallTest(sdk); diff --git a/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs b/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs index f7f6ac57..e8bbf899 100644 --- a/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/AssistantHelpers/MessagesTestHelper.cs @@ -3,9 +3,6 @@ using OpenAI.ObjectModels.RequestModels; using OpenAI.ObjectModels.SharedModels; using OpenAI.Playground.ExtensionsAndHelpers; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; using static OpenAI.ObjectModels.StaticValues; namespace OpenAI.Playground.TestHelpers.AssistantHelpers; @@ -16,6 +13,7 @@ internal static partial class MessagesTestHelper { private static string? CreatedMessageId { get; set; } private static string? CreatedThreadId { get; set; } + private static string? CreatedFileId { get; set; } public static async Task RunTests(IOpenAIService openAI) { @@ -45,7 +43,7 @@ public static async Task CreateMessage(IOpenAIService openAI) } CreatedThreadId = thread.Id; - var result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId, new(StaticValues.AssistantsStatics.MessageStatics.Roles.User, new("How does AI work? Explain it in simple terms."))); + var result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId, new(AssistantsStatics.MessageStatics.Roles.User, new("How does AI work? Explain it in simple terms."))); if (result.Successful) { CreatedMessageId = result.Id; @@ -61,60 +59,13 @@ public static async Task CreateMessageWithImage(IOpenAIService openAI) { ConsoleExtensions.WriteLine("Create MessageWithImage Testing is starting:", ConsoleColor.Cyan); - #region Create Thread - - var thread = await openAI.Beta.Threads.ThreadCreate(); - if (!thread.Successful) - { - if (thread.Error == null) - { - throw new("Unknown Error"); - } - - ConsoleExtensions.WriteLine($"{thread.Error.Code}: {thread.Error.Message}", ConsoleColor.Red); - return; - } - CreatedThreadId = thread.Id; - - #endregion - - #region Message.ImageBinaryContent - - ConsoleExtensions.WriteLine("Message with ImageBinaryContent Test:", ConsoleColor.DarkCyan); - var prompt = "Tell me about this image"; - var filename = "image_edit_mask.png"; + var filename = "image_edit_original.png"; var filePath = $"SampleData/{filename}"; var sampleBytes = await FileExtensions.ReadAllBytesAsync(filePath); - var result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId, new() - { - Role = StaticValues.AssistantsStatics.MessageStatics.Roles.User, - Content = new([ - MessageContent.TextContent(prompt), - MessageContent.ImageBinaryContent( - sampleBytes, - ImageStatics.ImageFileTypes.Png, - ImageStatics.ImageDetailTypes.High - ) - ]), - } - ); - if (result.Successful) - { - CreatedMessageId = result.Id; - ConsoleExtensions.WriteLine($"Message Created Successfully with ID: {result.Id}", ConsoleColor.Green); - } - else - { - ConsoleExtensions.WriteError(result.Error); - } - - #endregion - - #region Upload File - + // Upload File ConsoleExtensions.WriteLine("Upload File Test", ConsoleColor.DarkCyan); ConsoleExtensions.WriteLine($"Uploading file: {filename}", ConsoleColor.DarkCyan); @@ -132,37 +83,22 @@ public static async Task CreateMessageWithImage(IOpenAIService openAI) var uploadFileId = uploadFilesResponse.Id; ConsoleExtensions.WriteLine($"uploadFileId:{uploadFileId}, purpose:{uploadFilesResponse.Purpose}"); - #endregion - - #region Message.ImageFileContent + // Message.ImageFileContent ConsoleExtensions.WriteLine("Message with ImageFileContent Test:", ConsoleColor.DarkCyan); MessageContentOneOfType content = new([ MessageContent.TextContent(prompt), - MessageContent.ImageFileContent( - uploadFileId, - ImageStatics.ImageDetailTypes.High - ) - ]); + MessageContent.ImageFileContent(uploadFileId, ImageStatics.ImageDetailTypes.High) + ]); MessageCreateRequest request = new() { - Role = StaticValues.AssistantsStatics.MessageStatics.Roles.User, - Content = content, - }; - - /* DEBUG - var options = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + Role = AssistantsStatics.MessageStatics.Roles.User, + Content = content }; - var serialized = JsonSerializer.Serialize(request, options); - ConsoleExtensions.WriteLine($"MessageRequest: {serialized}", ConsoleColor.White); - */ - - result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId, request); + var result = await openAI.Beta.Messages.CreateMessage(CreatedThreadId!, request); if (result.Successful) { CreatedMessageId = result.Id; @@ -172,11 +108,6 @@ public static async Task CreateMessageWithImage(IOpenAIService openAI) { ConsoleExtensions.WriteError(result.Error); } - - #endregion - - // TODO: add Run()... - } public static async Task ListMessages(IOpenAIService openAI) @@ -331,6 +262,11 @@ private static async Task Cleanup(IOpenAIService sdk) { await sdk.Beta.Threads.ThreadDelete(CreatedThreadId); } + + if (!string.IsNullOrWhiteSpace(CreatedFileId)) + { + await sdk.Files.DeleteFile(CreatedFileId); + } } } } \ No newline at end of file diff --git a/OpenAI.Playground/TestHelpers/VisionTestHelper.cs b/OpenAI.Playground/TestHelpers/VisionTestHelper.cs index 0659d499..d33d880a 100644 --- a/OpenAI.Playground/TestHelpers/VisionTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/VisionTestHelper.cs @@ -2,8 +2,6 @@ using OpenAI.ObjectModels; using OpenAI.ObjectModels.RequestModels; using OpenAI.Playground.ExtensionsAndHelpers; -using System.Text.Json.Serialization; -using System.Text.Json; using static OpenAI.ObjectModels.StaticValues; namespace OpenAI.Playground.TestHelpers; @@ -12,38 +10,33 @@ internal static class VisionTestHelper { public static async Task RunSimpleVisionTest(IOpenAIService sdk) { - ConsoleExtensions.WriteLine("VIsion Testing is starting:", ConsoleColor.Cyan); + ConsoleExtensions.WriteLine("Vision Testing is starting:", ConsoleColor.Cyan); try { ConsoleExtensions.WriteLine("Vision Test:", ConsoleColor.DarkCyan); - var completionResult = await sdk.ChatCompletion.CreateCompletion( - new ChatCompletionCreateRequest + var completionResult = await sdk.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest + { + Messages = new List { - Messages = new List + ChatMessage.FromSystem("You are an image analyzer assistant."), + ChatMessage.FromUser(new List { - ChatMessage.FromSystem("You are an image analyzer assistant."), - ChatMessage.FromUser( - new List - { - MessageContent.TextContent("What is on the picture in details?"), - MessageContent.ImageUrlContent( - "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", - ImageStatics.ImageDetailTypes.High - ) - } - ), - }, - MaxTokens = 300, - Model = Models.Gpt_4_vision_preview, - N = 1 - } - ); + MessageContent.TextContent("What is on the picture in details?"), + MessageContent.ImageUrlContent("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + ImageStatics.ImageDetailTypes.High) + }), + }, + MaxTokens = 300, + Model = Models.Gpt_4_vision_preview, + N = 1 + }); if (completionResult.Successful) { - Console.WriteLine(completionResult.Choices.First().Message.Content); + Console.WriteLine(completionResult.Choices.First() + .Message.Content); } else { @@ -52,9 +45,7 @@ public static async Task RunSimpleVisionTest(IOpenAIService sdk) throw new Exception("Unknown Error"); } - Console.WriteLine( - $"{completionResult.Error.Code}: {completionResult.Error.Message}" - ); + Console.WriteLine($"{completionResult.Error.Code}: {completionResult.Error.Message}"); } } catch (Exception e) @@ -71,34 +62,29 @@ public static async Task RunSimpleVisionStreamTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Vision Stream Test:", ConsoleColor.DarkCyan); - var completionResult = sdk.ChatCompletion.CreateCompletionAsStream( - new ChatCompletionCreateRequest + var completionResult = sdk.ChatCompletion.CreateCompletionAsStream(new ChatCompletionCreateRequest + { + Messages = new List { - Messages = new List + ChatMessage.FromSystem("You are an image analyzer assistant."), + ChatMessage.FromUser(new List { - ChatMessage.FromSystem("You are an image analyzer assistant."), - ChatMessage.FromUser( - new List - { - MessageContent.TextContent("What’s in this image?"), - MessageContent.ImageUrlContent( - "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", - ImageStatics.ImageDetailTypes.Low - ) - } - ), - }, - MaxTokens = 300, - Model = Models.Gpt_4_vision_preview, - N = 1 - } - ); + MessageContent.TextContent("What’s in this image?"), + MessageContent.ImageUrlContent("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + ImageStatics.ImageDetailTypes.Low) + }), + }, + MaxTokens = 300, + Model = Models.Gpt_4_vision_preview, + N = 1 + }); await foreach (var completion in completionResult) { if (completion.Successful) { - Console.Write(completion.Choices.First().Message.Content); + Console.Write(completion.Choices.First() + .Message.Content); } else { @@ -107,9 +93,7 @@ public static async Task RunSimpleVisionStreamTest(IOpenAIService sdk) throw new Exception("Unknown Error"); } - Console.WriteLine( - $"{completion.Error.Code}: {completion.Error.Message}" - ); + Console.WriteLine($"{completion.Error.Code}: {completion.Error.Message}"); } } @@ -129,58 +113,31 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi try { - - ConsoleExtensions.WriteLine("Vision Test With EncodedImage:", ConsoleColor.DarkCyan); - - ConsoleExtensions.WriteLine( - "Vision with base64 encoded image Test:", - ConsoleColor.DarkCyan - ); + ConsoleExtensions.WriteLine("Vision with base64 encoded image Test:", ConsoleColor.DarkCyan); const string originalFileName = "image_edit_original.png"; - var originalFile = await FileExtensions.ReadAllBytesAsync( - $"SampleData/{originalFileName}" - ); + var originalFile = await FileExtensions.ReadAllBytesAsync($"SampleData/{originalFileName}"); - var messages = new List - { - ChatMessage.FromSystem("You are an image analyzer assistant."), - ChatMessage.FromUser( - new List - { - MessageContent.TextContent("What is on the picture in details?"), - MessageContent.ImageBinaryContent( - originalFile, - ImageStatics.ImageFileTypes.Png, - ImageStatics.ImageDetailTypes.High - ) - } - ), - }; - - /* DEBUG - var options = new JsonSerializerOptions + var completionResult = await sdk.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - - var serialized = JsonSerializer.Serialize(messages, options); - ConsoleExtensions.WriteLine($"MessageRequest: {serialized}", ConsoleColor.White); - */ - - var completionResult = await sdk.ChatCompletion.CreateCompletion( - new ChatCompletionCreateRequest + Messages = new List { - Messages = messages, - MaxTokens = 300, - Model = Models.Gpt_4_vision_preview, - N = 1 - } - ); + ChatMessage.FromSystem("You are an image analyzer assistant."), + ChatMessage.FromUser(new List + { + MessageContent.TextContent("What is on the picture in details?"), + MessageContent.ImageBinaryContent(originalFile, ImageStatics.ImageFileTypes.Png, ImageStatics.ImageDetailTypes.High) + }), + }, + MaxTokens = 300, + Model = Models.Gpt_4_vision_preview, + N = 1 + }); if (completionResult.Successful) { - Console.WriteLine(completionResult.Choices.First().Message.Content); + Console.WriteLine(completionResult.Choices.First() + .Message.Content); } else { @@ -189,9 +146,7 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi throw new Exception("Unknown Error"); } - Console.WriteLine( - $"{completionResult.Error.Code}: {completionResult.Error.Message}" - ); + Console.WriteLine($"{completionResult.Error.Code}: {completionResult.Error.Message}"); } } catch (Exception e) diff --git a/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs index 39a9eb09..05ac169d 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/AssistantCreateRequest.cs @@ -3,7 +3,6 @@ namespace OpenAI.ObjectModels.RequestModels; -// REMOVED: drp052424 - IOpenAiModels.IFileIds property is no longer in the API reference, and will not work if you use it public class AssistantCreateRequest : IOpenAiModels.IModel, IOpenAiModels.IMetaData, IOpenAiModels.ITemperature { /// @@ -66,19 +65,12 @@ public class AssistantCreateRequest : IOpenAiModels.IModel, IOpenAiModels.IMetaD [JsonPropertyName("response_format")] public ResponseFormatOneOfType? ResponseFormat { get; set; } - /// - /// A list of file IDs attached to this assistant. - /// - [JsonPropertyName("file_ids")] - [Obsolete("This field is no longer supported by the API.")] - public List? FileIds { get; set; } - /// /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information /// about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of /// 512 characters long. /// - [JsonPropertyName("metadata")] + [JsonPropertyName("metadata")] public Dictionary? Metadata { get; set; } /// diff --git a/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs index fce95d8a..ac8e4148 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/AudioCreateTranscriptionRequest.cs @@ -42,7 +42,7 @@ public record AudioCreateTranscriptionRequest : IOpenAiModels.IModel, IOpenAiMod public Stream? FileStream { get; set; } /// - /// FileName. Note the API keys off the extension of the FileName to know the format. + /// FileName. /// public string FileName { get; set; } diff --git a/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs index 5c45df69..aad15c49 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/MessageCreateRequest.cs @@ -49,13 +49,13 @@ public MessageCreateRequest(string role, MessageContentOneOfType content, List - /// The ID of the file to attach to. See https://platform.openai.com/docs/assistants/tools/file-search/supported-files for a list of supported file extensions. + /// The ID of the file to attach. See list of supported file extensions . /// [JsonPropertyName("file_id")] public string FileId { get; set; } /// - /// The tools to add this file to. This is required and may contain CodeInterpreter and/or FileSearch + /// The tools to add this file to. /// [JsonPropertyName("tools")] public List Tools { get; set; } diff --git a/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs b/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs index f71a0e6c..41b331d5 100644 --- a/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs +++ b/OpenAI.SDK/ObjectModels/UploadFilePurposes.cs @@ -1,23 +1,31 @@ namespace OpenAI.ObjectModels; +/// +/// The intended purpose of the uploaded file. +/// Use "assistants" for Assistants and Message files, "vision" for Assistants image file inputs, "batch" for Batch +/// API, and "fine-tune" for Fine-tuning. +/// Upload File Purposes +/// Upload File Purpose Responses +/// public static class UploadFilePurposes { public enum UploadFilePurpose { + FineTune, + FineTuneResults, Assistants, + AssistantsOutput, Vision, Batch, - FineTune, - [Obsolete("Not supported by the API")] - FineTuneResults + BatchOutput, } - // REF: https://platform.openai.com/docs/api-reference/files/create public const string Assistants = "assistants"; + public const string AssistantsOutput = "assistants_output"; public const string Vision = "vision"; public const string Batch = "batch"; + public const string BatchOutput = "batch_output"; public const string FineTune = "fine-tune"; - [Obsolete("Not supported by the API")] public const string FineTuneResults = "fine-tune-results"; public static string EnumToString(this UploadFilePurpose uploadFilePurpose) @@ -28,6 +36,9 @@ public static string EnumToString(this UploadFilePurpose uploadFilePurpose) UploadFilePurpose.Vision => Vision, UploadFilePurpose.Batch => Batch, UploadFilePurpose.FineTune => FineTune, + UploadFilePurpose.BatchOutput => BatchOutput, + UploadFilePurpose.AssistantsOutput => AssistantsOutput, + UploadFilePurpose.FineTuneResults => FineTuneResults, _ => throw new ArgumentOutOfRangeException(nameof(uploadFilePurpose), uploadFilePurpose, null) }; } @@ -40,6 +51,9 @@ public static UploadFilePurpose ToEnum(string filePurpose) Vision => UploadFilePurpose.Vision, Batch => UploadFilePurpose.Batch, FineTune => UploadFilePurpose.FineTune, + BatchOutput => UploadFilePurpose.BatchOutput, + AssistantsOutput => UploadFilePurpose.AssistantsOutput, + FineTuneResults => UploadFilePurpose.FineTuneResults, _ => throw new ArgumentOutOfRangeException(nameof(filePurpose), filePurpose, null) }; } From 6baa54baf4f84ea4c35d21447679a8197fe9cf40 Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Sun, 2 Jun 2024 14:21:54 +0100 Subject: [PATCH 06/14] code stylle update --- .../TestHelpers/VisionTestHelper.cs | 29 +++++++++---------- OpenAI.sln | 2 +- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/OpenAI.Playground/TestHelpers/VisionTestHelper.cs b/OpenAI.Playground/TestHelpers/VisionTestHelper.cs index d33d880a..6bd33d12 100644 --- a/OpenAI.Playground/TestHelpers/VisionTestHelper.cs +++ b/OpenAI.Playground/TestHelpers/VisionTestHelper.cs @@ -16,7 +16,7 @@ public static async Task RunSimpleVisionTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Vision Test:", ConsoleColor.DarkCyan); - var completionResult = await sdk.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest + var completionResult = await sdk.ChatCompletion.CreateCompletion(new() { Messages = new List { @@ -26,7 +26,7 @@ public static async Task RunSimpleVisionTest(IOpenAIService sdk) MessageContent.TextContent("What is on the picture in details?"), MessageContent.ImageUrlContent("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", ImageStatics.ImageDetailTypes.High) - }), + }) }, MaxTokens = 300, Model = Models.Gpt_4_vision_preview, @@ -35,14 +35,13 @@ public static async Task RunSimpleVisionTest(IOpenAIService sdk) if (completionResult.Successful) { - Console.WriteLine(completionResult.Choices.First() - .Message.Content); + Console.WriteLine(completionResult.Choices.First().Message.Content); } else { if (completionResult.Error == null) { - throw new Exception("Unknown Error"); + throw new("Unknown Error"); } Console.WriteLine($"{completionResult.Error.Code}: {completionResult.Error.Message}"); @@ -62,7 +61,7 @@ public static async Task RunSimpleVisionStreamTest(IOpenAIService sdk) { ConsoleExtensions.WriteLine("Vision Stream Test:", ConsoleColor.DarkCyan); - var completionResult = sdk.ChatCompletion.CreateCompletionAsStream(new ChatCompletionCreateRequest + var completionResult = sdk.ChatCompletion.CreateCompletionAsStream(new() { Messages = new List { @@ -72,7 +71,7 @@ public static async Task RunSimpleVisionStreamTest(IOpenAIService sdk) MessageContent.TextContent("What’s in this image?"), MessageContent.ImageUrlContent("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", ImageStatics.ImageDetailTypes.Low) - }), + }) }, MaxTokens = 300, Model = Models.Gpt_4_vision_preview, @@ -83,14 +82,13 @@ public static async Task RunSimpleVisionStreamTest(IOpenAIService sdk) { if (completion.Successful) { - Console.Write(completion.Choices.First() - .Message.Content); + Console.Write(completion.Choices.First().Message.Content); } else { if (completion.Error == null) { - throw new Exception("Unknown Error"); + throw new("Unknown Error"); } Console.WriteLine($"{completion.Error.Code}: {completion.Error.Message}"); @@ -118,7 +116,7 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi const string originalFileName = "image_edit_original.png"; var originalFile = await FileExtensions.ReadAllBytesAsync($"SampleData/{originalFileName}"); - var completionResult = await sdk.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest + var completionResult = await sdk.ChatCompletion.CreateCompletion(new() { Messages = new List { @@ -127,7 +125,7 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi { MessageContent.TextContent("What is on the picture in details?"), MessageContent.ImageBinaryContent(originalFile, ImageStatics.ImageFileTypes.Png, ImageStatics.ImageDetailTypes.High) - }), + }) }, MaxTokens = 300, Model = Models.Gpt_4_vision_preview, @@ -136,14 +134,13 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi if (completionResult.Successful) { - Console.WriteLine(completionResult.Choices.First() - .Message.Content); + Console.WriteLine(completionResult.Choices.First().Message.Content); } else { if (completionResult.Error == null) { - throw new Exception("Unknown Error"); + throw new("Unknown Error"); } Console.WriteLine($"{completionResult.Error.Code}: {completionResult.Error.Message}"); @@ -155,4 +152,4 @@ public static async Task RunSimpleVisionTestUsingBase64EncodedImage(IOpenAIServi throw; } } -} +} \ No newline at end of file diff --git a/OpenAI.sln b/OpenAI.sln index 96e37dd2..1a061e10 100644 --- a/OpenAI.sln +++ b/OpenAI.sln @@ -25,7 +25,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI.Utilities", "OpenAI. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI.UtilitiesPlayground", "OpenAI.UtilitiesPlayground\OpenAI.UtilitiesPlayground.csproj", "{A2CEF336-DE84-41A2-880E-84B2871FF929}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI.Utilities.Tests", "OpenAI.Utilities.Tests\OpenAI.Utilities.Tests.csproj", "{8BC7E997-8591-4ED4-BA4A-486B21419A3E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI.Utilities.Tests", "OpenAI.Utilities.Tests\OpenAI.Utilities.Tests.csproj", "{8BC7E997-8591-4ED4-BA4A-486B21419A3E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 6ae07c3d76f3a7fc3c9e5f1dc8cf13dda075213e Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Sun, 2 Jun 2024 14:26:37 +0100 Subject: [PATCH 07/14] Moderation Response Model: The model should not be optional. --- OpenAI.Playground/Program.cs | 6 +++--- .../ObjectModels/ResponseModels/CreateModerationResponse.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs index 914c1673..5d3467a3 100644 --- a/OpenAI.Playground/Program.cs +++ b/OpenAI.Playground/Program.cs @@ -40,8 +40,8 @@ // | / \ / \ | \ /) | ( \ /o\ / ) | (\ / | / \ / \ | // |-----------------------------------------------------------------------| -await ChatCompletionTestHelper.RunSimpleChatCompletionTest(sdk); -await ChatCompletionTestHelper.RunSimpleCompletionStreamTest(sdk); +//await ChatCompletionTestHelper.RunSimpleChatCompletionTest(sdk); +//await ChatCompletionTestHelper.RunSimpleCompletionStreamTest(sdk); //Assistants - BETA //await AssistantTestHelper.BasicsTestHelper.RunTests(sdk); @@ -72,7 +72,7 @@ //await ImageTestHelper.RunSimpleCreateImageTest(sdk); //await ImageTestHelper.RunSimpleCreateImageEditTest(sdk); //await ImageTestHelper.RunSimpleCreateImageVariationTest(sdk); -//await ModerationTestHelper.CreateModerationTest(sdk); +await ModerationTestHelper.CreateModerationTest(sdk); //await CompletionTestHelper.RunSimpleCompletionTest(sdk); //await CompletionTestHelper.RunSimpleCompletionTest2(sdk); //await CompletionTestHelper.RunSimpleCompletionTest3(sdk); diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs index ffd8ce12..d997dca1 100644 --- a/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs +++ b/OpenAI.SDK/ObjectModels/ResponseModels/CreateModerationResponse.cs @@ -9,7 +9,7 @@ public record CreateModerationResponse : BaseResponse, IOpenAiModels.IModel, IOp [JsonPropertyName("id")] public string Id { get; set; } - [JsonPropertyName("model")] public string? Model { get; set; } + [JsonPropertyName("model")] public string Model { get; set; } } public record Result From a61801dd882869ea03620562435c43efe2e0c27b Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Sun, 2 Jun 2024 14:27:04 +0100 Subject: [PATCH 08/14] demo update --- OpenAI.Playground/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs index 5d3467a3..914c1673 100644 --- a/OpenAI.Playground/Program.cs +++ b/OpenAI.Playground/Program.cs @@ -40,8 +40,8 @@ // | / \ / \ | \ /) | ( \ /o\ / ) | (\ / | / \ / \ | // |-----------------------------------------------------------------------| -//await ChatCompletionTestHelper.RunSimpleChatCompletionTest(sdk); -//await ChatCompletionTestHelper.RunSimpleCompletionStreamTest(sdk); +await ChatCompletionTestHelper.RunSimpleChatCompletionTest(sdk); +await ChatCompletionTestHelper.RunSimpleCompletionStreamTest(sdk); //Assistants - BETA //await AssistantTestHelper.BasicsTestHelper.RunTests(sdk); @@ -72,7 +72,7 @@ //await ImageTestHelper.RunSimpleCreateImageTest(sdk); //await ImageTestHelper.RunSimpleCreateImageEditTest(sdk); //await ImageTestHelper.RunSimpleCreateImageVariationTest(sdk); -await ModerationTestHelper.CreateModerationTest(sdk); +//await ModerationTestHelper.CreateModerationTest(sdk); //await CompletionTestHelper.RunSimpleCompletionTest(sdk); //await CompletionTestHelper.RunSimpleCompletionTest2(sdk); //await CompletionTestHelper.RunSimpleCompletionTest3(sdk); From 1fe97035fd62b8a57bd37436f5114a1a88e22f29 Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Mon, 3 Jun 2024 13:12:50 +0100 Subject: [PATCH 09/14] The routes for Azure OpenAI Assistant are fixed. --- .../AzureOpenAiEndpointProvider.cs | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs index c31c756c..c13fa58b 100644 --- a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs +++ b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs @@ -19,7 +19,7 @@ public AzureOpenAiEndpointProvider(string apiVersion, string deploymentId) private string Prefix => $"{ApiPrefix}/{DeploymentsPrefix}/{WebUtility.UrlEncode(_deploymentId)}"; private string AzureVersionQueryString => $"?api-version={_apiVersion}"; - + private string AssistantPrefix => $"{ApiPrefix}/"; public string ModelRetrieve(string model) { return $"{Prefix}/models/{model}{AzureVersionQueryString}"; @@ -185,27 +185,27 @@ public string AudioCreateSpeech() public string AssistantCreate() { - return $"{Prefix}/assistants{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants{AzureVersionQueryString}"; } public string AssistantRetrieve(string assistantId) { - return $"{Prefix}/assistants/{assistantId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants/{assistantId}{AzureVersionQueryString}"; } public string AssistantModify(string assistantId) { - return $"{Prefix}/assistants/{assistantId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants/{assistantId}{AzureVersionQueryString}"; } public string AssistantDelete(string assistantId) { - return $"{Prefix}/assistants/{assistantId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants/{assistantId}{AzureVersionQueryString}"; } public string AssistantList(PaginationRequest? assistantListRequest) { - var url = $"{Prefix}/assistants{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/assistants{AzureVersionQueryString}"; var query = assistantListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -218,22 +218,22 @@ public string AssistantList(PaginationRequest? assistantListRequest) public string AssistantFileCreate(string assistantId) { - return $"{Prefix}/assistants/{assistantId}/files{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants/{assistantId}/files{AzureVersionQueryString}"; } public string AssistantFileRetrieve(string assistantId, string fileId) { - return $"{Prefix}/assistants/{assistantId}/files/{fileId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants/{assistantId}/files/{fileId}{AzureVersionQueryString}"; } public string AssistantFileDelete(string assistantId, string fileId) { - return $"{Prefix}/assistants/{assistantId}/files/{fileId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/assistants/{assistantId}/files/{fileId}{AzureVersionQueryString}"; } public string AssistantFileList(string assistantId, PaginationRequest? assistantFileListRequest) { - var url = $"{Prefix}/assistants/files{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/assistants/files{AzureVersionQueryString}"; var query = assistantFileListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -246,42 +246,42 @@ public string AssistantFileList(string assistantId, PaginationRequest? assistant public string ThreadCreate() { - return $"{Prefix}/threads{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads{AzureVersionQueryString}"; } public string ThreadRetrieve(string threadId) { - return $"{Prefix}/threads/{threadId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}{AzureVersionQueryString}"; } public string ThreadModify(string threadId) { - return $"{Prefix}/threads/{threadId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}{AzureVersionQueryString}"; } public string ThreadDelete(string threadId) { - return $"{Prefix}/threads/{threadId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}{AzureVersionQueryString}"; } public string MessageCreate(string threadId) { - return $"{Prefix}/threads/{threadId}/messages{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/messages{AzureVersionQueryString}"; } public string MessageRetrieve(string threadId, string messageId) { - return $"{Prefix}/threads/{threadId}/messages/{messageId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/messages/{messageId}{AzureVersionQueryString}"; } public string MessageModify(string threadId, string messageId) { - return $"{Prefix}/threads/{threadId}/messages/{messageId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/messages/{messageId}{AzureVersionQueryString}"; } public string MessageList(string threadId, PaginationRequest? messageListRequest) { - var url = $"{Prefix}/threads/{threadId}/messages{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/threads/{threadId}/messages{AzureVersionQueryString}"; var query = messageListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -293,27 +293,27 @@ public string MessageList(string threadId, PaginationRequest? messageListRequest } public string MessageDelete(string threadId, string messageId) { - return $"{Prefix}/threads/{threadId}/messages/{messageId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/messages/{messageId}{AzureVersionQueryString}"; } public string RunCreate(string threadId) { - return $"{Prefix}/threads/{threadId}/runs{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/runs{AzureVersionQueryString}"; } public string RunRetrieve(string threadId, string runId) { - return $"{Prefix}/threads/{threadId}/runs/{runId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/runs/{runId}{AzureVersionQueryString}"; } public string RunModify(string threadId, string runId) { - return $"{Prefix}/threads/{threadId}/runs/{runId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/runs/{runId}{AzureVersionQueryString}"; } public string RunList(string threadId, PaginationRequest? runListRequest) { - var url = $"{Prefix}/threads/{threadId}/runs{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/threads/{threadId}/runs{AzureVersionQueryString}"; var query = runListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -326,27 +326,27 @@ public string RunList(string threadId, PaginationRequest? runListRequest) public string RunSubmitToolOutputs(string threadId, string runId) { - return $"{Prefix}/threads/{threadId}/runs/{runId}/submit_tool_outputs{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/runs/{runId}/submit_tool_outputs{AzureVersionQueryString}"; } public string RunCancel(string threadId, string runId) { - return $"{Prefix}/threads/{threadId}/runs/{runId}/cancel{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/runs/{runId}/cancel{AzureVersionQueryString}"; } public string ThreadAndRunCreate() { - return $"{Prefix}/threads/runs{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/runs{AzureVersionQueryString}"; } public string RunStepRetrieve(string threadId, string runId, string stepId) { - return $"{Prefix}/threads/{threadId}/runs/{runId}/steps/{stepId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/threads/{threadId}/runs/{runId}/steps/{stepId}{AzureVersionQueryString}"; } public string RunStepList(string threadId, string runId, PaginationRequest? runStepListRequest) { - var url = $"{Prefix}/threads/{threadId}/runs/{runId}/steps{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/threads/{threadId}/runs/{runId}/steps{AzureVersionQueryString}"; var query = runStepListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -360,12 +360,12 @@ public string RunStepList(string threadId, string runId, PaginationRequest? runS public string VectorStoreCreate() { - return $"{Prefix}/vector_stores{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores{AzureVersionQueryString}"; } public string VectorStoreList(PaginationRequest baseListRequest) { - var url = $"{Prefix}/vector_stores{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/vector_stores{AzureVersionQueryString}"; var query = baseListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -378,37 +378,37 @@ public string VectorStoreList(PaginationRequest baseListRequest) public string VectorStoreRetrieve(string vectorStoreId) { - return $"{Prefix}/vector_stores/{vectorStoreId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}{AzureVersionQueryString}"; } public string VectorStoreModify(string vectorStoreId) { - return $"{Prefix}/vector_stores/{vectorStoreId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}{AzureVersionQueryString}"; } public string VectorStoreDelete(string vectorStoreId) { - return $"{Prefix}/vector_stores/{vectorStoreId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}{AzureVersionQueryString}"; } public string VectorStoreFileCreate(string vectorStoreId) { - return $"{Prefix}/vector_stores/{vectorStoreId}/files{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files{AzureVersionQueryString}"; } public string VectorStoreFileRetrieve(string vectorStoreId, string fileId) { - return $"{Prefix}/vector_stores/{vectorStoreId}/files/{fileId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files/{fileId}{AzureVersionQueryString}"; } public string VectorStoreFileDelete(string vectorStoreId, string fileId) { - return $"{Prefix}/vector_stores/{vectorStoreId}/files/{fileId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files/{fileId}{AzureVersionQueryString}"; } public string VectorStoreFileList(string vectorStoreId, VectorStoreFileListRequest? baseListRequest) { - var url = $"{Prefix}/vector_stores/{vectorStoreId}/files{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files{AzureVersionQueryString}"; var query = baseListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) @@ -421,22 +421,22 @@ public string VectorStoreFileList(string vectorStoreId, VectorStoreFileListReque public string VectorStoreFileBatchCreate(string vectorStoreId) { - return $"{Prefix}/vector_stores/{vectorStoreId}/files/batches{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files/batches{AzureVersionQueryString}"; } public string VectorStoreFileBatchRetrieve(string vectorStoreId, string batchId) { - return $"{Prefix}/vector_stores/{vectorStoreId}/files/batches/{batchId}{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files/batches/{batchId}{AzureVersionQueryString}"; } public string VectorStoreFileBatchCancel(string vectorStoreId, string batchId) { - return $"{Prefix}/vector_stores/{vectorStoreId}/files/batches/{batchId}/cancel{AzureVersionQueryString}"; + return $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files/batches/{batchId}/cancel{AzureVersionQueryString}"; } public string VectorStoreFileBatchList(string vectorStoreId, string batchId, PaginationRequest? baseListRequest) { - var url = $"{Prefix}/vector_stores/{vectorStoreId}/files/batches{AzureVersionQueryString}"; + var url = $"{AssistantPrefix}/vector_stores/{vectorStoreId}/files/batches{AzureVersionQueryString}"; var query = baseListRequest?.GetQueryParameters(); if (!string.IsNullOrWhiteSpace(query)) From 67ea27b4b7222ec0fa9baff952e920088e7dca9f Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Mon, 3 Jun 2024 19:50:38 +0100 Subject: [PATCH 10/14] Fixed ToString culture problems --- OpenAI.SDK/Managers/OpenAIAudioService.cs | 5 ++--- OpenAI.SDK/Managers/OpenAIImage.cs | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenAI.SDK/Managers/OpenAIAudioService.cs b/OpenAI.SDK/Managers/OpenAIAudioService.cs index 360ca2d6..51f73a78 100644 --- a/OpenAI.SDK/Managers/OpenAIAudioService.cs +++ b/OpenAI.SDK/Managers/OpenAIAudioService.cs @@ -1,5 +1,4 @@ -using System.Text; -using System.Text.Json; +using System.Globalization; using OpenAI.Extensions; using OpenAI.Interfaces; using OpenAI.ObjectModels; @@ -82,7 +81,7 @@ private async Task Create(AudioCreateTranscrip if (audioCreateTranscriptionRequest.Temperature != null) { - multipartContent.Add(new StringContent(audioCreateTranscriptionRequest.Temperature.ToString()!), "temperature"); + multipartContent.Add(new StringContent(audioCreateTranscriptionRequest.Temperature.Value.ToString(CultureInfo.InvariantCulture)), "temperature"); } diff --git a/OpenAI.SDK/Managers/OpenAIImage.cs b/OpenAI.SDK/Managers/OpenAIImage.cs index d7fb2794..9c7cb2a0 100644 --- a/OpenAI.SDK/Managers/OpenAIImage.cs +++ b/OpenAI.SDK/Managers/OpenAIImage.cs @@ -1,4 +1,5 @@ -using OpenAI.Extensions; +using System.Globalization; +using OpenAI.Extensions; using OpenAI.Interfaces; using OpenAI.ObjectModels.RequestModels; using OpenAI.ObjectModels.ResponseModels.ImageResponseModel; @@ -42,7 +43,7 @@ public async Task CreateImageEdit(ImageEditCreateRequest im if (imageEditCreateRequest.N != null) { - multipartContent.Add(new StringContent(imageEditCreateRequest.N.ToString()!), "n"); + multipartContent.Add(new StringContent(imageEditCreateRequest.N.Value.ToString(CultureInfo.InvariantCulture)), "n"); } if (imageEditCreateRequest.Model != null) @@ -86,7 +87,7 @@ public async Task CreateImageVariation(ImageVariationCreate if (imageEditCreateRequest.N != null) { - multipartContent.Add(new StringContent(imageEditCreateRequest.N.ToString()!), "n"); + multipartContent.Add(new StringContent(imageEditCreateRequest.N.Value.ToString(CultureInfo.InvariantCulture)), "n"); } if (imageEditCreateRequest.Model != null) From 2582ed91f859ac06b02385d263be0ce367531c89 Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Mon, 3 Jun 2024 20:26:31 +0100 Subject: [PATCH 11/14] Fixed Audio string response Error handling --- OpenAI.SDK/Extensions/HttpclientExtensions.cs | 16 ++++++++++++++-- OpenAI.SDK/Managers/OpenAIAudioService.cs | 16 ++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/OpenAI.SDK/Extensions/HttpclientExtensions.cs b/OpenAI.SDK/Extensions/HttpclientExtensions.cs index c8ce4535..93075a1c 100644 --- a/OpenAI.SDK/Extensions/HttpclientExtensions.cs +++ b/OpenAI.SDK/Extensions/HttpclientExtensions.cs @@ -111,10 +111,22 @@ private static HttpRequestMessage CreatePostEventStreamRequest(string uri, HttpC return await HandleResponseContent(response, cancellationToken); } - public static async Task PostFileAndReadAsStringAsync(this HttpClient client, string uri, HttpContent content, CancellationToken cancellationToken = default) + public static async Task<(string? stringResponse, TResponse baseResponse)> PostFileAndReadAsStringAsync(this HttpClient client, string uri, HttpContent content, CancellationToken cancellationToken = default) where TResponse : BaseResponse, new() { var response = await client.PostAsync(uri, content, cancellationToken); - return await response.Content.ReadAsStringAsync(cancellationToken) ?? throw new InvalidOperationException(); + if (response.IsSuccessStatusCode) + { + var tResponse = new TResponse + { + HttpStatusCode = response.StatusCode, + HeaderValues = response.ParseHeaders() + }; + return (await response.Content.ReadAsStringAsync(cancellationToken),tResponse ); + } + else + { + return (null, await HandleResponseContent(response, cancellationToken)); + } } public static async Task DeleteAndReadAsAsync(this HttpClient client, string uri, CancellationToken cancellationToken = default) where TResponse : BaseResponse, new() diff --git a/OpenAI.SDK/Managers/OpenAIAudioService.cs b/OpenAI.SDK/Managers/OpenAIAudioService.cs index 360ca2d6..860dd854 100644 --- a/OpenAI.SDK/Managers/OpenAIAudioService.cs +++ b/OpenAI.SDK/Managers/OpenAIAudioService.cs @@ -26,14 +26,14 @@ public async Task CreateTranslation(AudioCreat public async Task> CreateSpeech(AudioCreateSpeechRequest audioCreateSpeechRequest, CancellationToken cancellationToken = default) { - return await _httpClient.PostAndReadAsDataAsync,T>(_endpointProvider.AudioCreateSpeech(), audioCreateSpeechRequest, cancellationToken); + return await _httpClient.PostAndReadAsDataAsync, T>(_endpointProvider.AudioCreateSpeech(), audioCreateSpeechRequest, cancellationToken); } private async Task Create(AudioCreateTranscriptionRequest audioCreateTranscriptionRequest, string uri, CancellationToken cancellationToken = default) { var multipartContent = new MultipartFormDataContent(); - if (audioCreateTranscriptionRequest is {File: not null, FileStream: not null}) + if (audioCreateTranscriptionRequest is { File: not null, FileStream: not null }) { throw new ArgumentException("Either File or FileStream must be set, but not both."); } @@ -56,7 +56,7 @@ private async Task Create(AudioCreateTranscrip } multipartContent.Add(new StringContent(audioCreateTranscriptionRequest.Model), "model"); - + if (audioCreateTranscriptionRequest.TimestampGranularities != null) { foreach (var granularity in audioCreateTranscriptionRequest.TimestampGranularities) @@ -93,9 +93,13 @@ private async Task Create(AudioCreateTranscrip return await _httpClient.PostFileAndReadAsAsync(uri, multipartContent, cancellationToken); } - return new AudioCreateTranscriptionResponse + var response = await _httpClient.PostFileAndReadAsStringAsync(uri, multipartContent, cancellationToken); + if (response.stringResponse != null) { - Text = await _httpClient.PostFileAndReadAsStringAsync(uri, multipartContent, cancellationToken) - }; + response.baseResponse.Text = response.stringResponse; + } + + return response.baseResponse; + } } \ No newline at end of file From bc4649cbc31858bdcbecbc38476b63bd597f9d03 Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Mon, 3 Jun 2024 20:29:54 +0100 Subject: [PATCH 12/14] code Cleanup --- OpenAI.SDK/Managers/OpenAIAudioService.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/OpenAI.SDK/Managers/OpenAIAudioService.cs b/OpenAI.SDK/Managers/OpenAIAudioService.cs index 860dd854..c6855b7f 100644 --- a/OpenAI.SDK/Managers/OpenAIAudioService.cs +++ b/OpenAI.SDK/Managers/OpenAIAudioService.cs @@ -1,6 +1,4 @@ -using System.Text; -using System.Text.Json; -using OpenAI.Extensions; +using OpenAI.Extensions; using OpenAI.Interfaces; using OpenAI.ObjectModels; using OpenAI.ObjectModels.RequestModels; From c7c39e4c568c3f9eeb77e5c704c994ba132b2dae Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Mon, 3 Jun 2024 20:52:28 +0100 Subject: [PATCH 13/14] Added support for chat LogProbs. --- .../ChatCompletionCreateRequest.cs | 13 ++++++++++++ .../SharedModels/ChatChoiceResponse.cs | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/OpenAI.SDK/ObjectModels/RequestModels/ChatCompletionCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/ChatCompletionCreateRequest.cs index 31d2be44..0202d6a3 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/ChatCompletionCreateRequest.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/ChatCompletionCreateRequest.cs @@ -263,4 +263,17 @@ public IEnumerable Validate() /// [JsonPropertyName("user")] public string User { get; set; } + + /// + /// Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the content of message. + /// + [JsonPropertyName("logprobs")] + public bool? LogProbs { get; set; } + + + /// + /// An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. logprobs must be set to true if this parameter is used. + /// + [JsonPropertyName("top_logprobs")] + public int? TopLogprobs { get; set; } } \ No newline at end of file diff --git a/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs b/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs index 630f850e..ad4bf0ac 100644 --- a/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs +++ b/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs @@ -19,6 +19,8 @@ public ChatMessage Delta [JsonPropertyName("finish_reason")] public string FinishReason { get; set; } [JsonPropertyName("finish_details")] public FinishDetailsResponse? FinishDetails { get; set; } + + [JsonPropertyName("logprobs")] public ChatLogProbsResponse LogProbs { get; set; } public class FinishDetailsResponse { [JsonPropertyName("type")] @@ -26,4 +28,22 @@ public class FinishDetailsResponse [JsonPropertyName("stop")] public string Stop { get; set; } } + + public record ChatLogProbsResponse + { + [JsonPropertyName("content")] public List Content { get; set; } + } + + public record ContentItemBase + { + [JsonPropertyName("token")] public string Token { get; set; } + + [JsonPropertyName("logprob")] public double LogProb { get; set; } + + [JsonPropertyName("bytes")] public List Bytes { get; set; } + } + public record ContentItem : ContentItemBase + { + [JsonPropertyName("top_logprobs")] public List TopLogProbs { get; set; } + } } \ No newline at end of file From 7b3f36c4ace2ef503edb7c8ccd1bb854a9da40e6 Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Mon, 3 Jun 2024 21:15:07 +0100 Subject: [PATCH 14/14] Version bump 8.3.0 --- OpenAI.SDK/OpenAI.csproj | 2 +- Readme.md | 23 ++++++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/OpenAI.SDK/OpenAI.csproj b/OpenAI.SDK/OpenAI.csproj index dc86764a..55c75dd9 100644 --- a/OpenAI.SDK/OpenAI.csproj +++ b/OpenAI.SDK/OpenAI.csproj @@ -10,7 +10,7 @@ OpenAI-Betalgo.png true OpenAI SDK by Betalgo - 8.2.2 + 8.3.0 Tolga Kayhan, Betalgo Betalgo Up Ltd. OpenAI ChatGPT, Whisper, GPT-4 and DALL·E dotnet SDK diff --git a/Readme.md b/Readme.md index a7326486..9309f72f 100644 --- a/Readme.md +++ b/Readme.md @@ -117,19 +117,16 @@ Please be aware that future releases may frequently include breaking changes. Co ## Changelog -### 8.2.2 -- Assistant (Beta) feature is now available in the main package. Be aware there might still be bugs due to the beta status of the feature and the SDK itself. Please report any issues you encounter. -- Use `"UseBeta": true` in your config file or `serviceCollection.AddOpenAIService(r => r.UseBeta = true);` or `new OpenAiOptions { UseBeta = true }` in your service registration to enable Assistant features. -- Expect more frequent breaking changes around the assistant API due to its beta nature. -- All Assistant endpoints are implemented except for streaming functionality, which will be added soon. -- The Playground has samples for every endpoint usage, but lacks a complete implementation for the Assistant APIs. Refer to [Assistants overview - OpenAI API](https://platform.openai.com/docs/assistants/overview) for more details. -- Special thanks to all contributors for making this version possible! - -#### Other Changes: -- Fixed a bug with multiple tools calling in stream mode. -- Added error handling for streaming. -- Added usage information for streaming (use `StreamOptions = new(){IncludeUsage = true,}` to get usage information). -- Added **timestamp_granularities[]** for Create transcription to provide the timestamp of every word. +### 8.3.0 +- Updated Assistant tests, added sample for CreateMessageWithImage +- Azure Assistant endpoints are updated since documentation reference still earlier version (Assistant v1). I am not sure if Azure supports all Assistant v2 features. So, feedback is much appreciated. +- Fixed error handling and response parsing for audio transcription result in text mode. +- Fixed Culture issue for number conversions (Audio Temperature and Image N) +- Removed file_ids from Create Assistant +- Added Support for Chat LogProbs +- Fixed File_Id Typo in file VisionImageUrl +- Updated File purpose enum list + ### [More Change Logs](https://github.com/betalgo/openai/wiki/Change-Logs) ---