diff --git a/OpenAI-DotNet-Tests/TestFixture_05_Images.cs b/OpenAI-DotNet-Tests/TestFixture_05_Images.cs index 2b316abd..49100810 100644 --- a/OpenAI-DotNet-Tests/TestFixture_05_Images.cs +++ b/OpenAI-DotNet-Tests/TestFixture_05_Images.cs @@ -13,7 +13,8 @@ public async Task Test_1_GenerateImages() { Assert.IsNotNull(OpenAIClient.ImagesEndPoint); - var results = await OpenAIClient.ImagesEndPoint.GenerateImageAsync("A house riding a velociraptor", 1, ImageSize.Small); + var request = new ImageGenerationRequest("A house riding a velociraptor", Models.Model.DallE_2); + var results = await OpenAIClient.ImagesEndPoint.GenerateImageAsync(request); Assert.IsNotNull(results); Assert.NotZero(results.Count); @@ -30,7 +31,8 @@ public async Task Test_2_GenerateImages_B64_Json() { Assert.IsNotNull(OpenAIClient.ImagesEndPoint); - var results = await OpenAIClient.ImagesEndPoint.GenerateImageAsync("A house riding a velociraptor", 1, ImageSize.Small, responseFormat: ResponseFormat.B64_Json); + var request = new ImageGenerationRequest("A house riding a velociraptor", Models.Model.DallE_2, responseFormat: ResponseFormat.B64_Json); + var results = await OpenAIClient.ImagesEndPoint.GenerateImageAsync(request); Assert.IsNotNull(results); Assert.NotZero(results.Count); @@ -47,10 +49,11 @@ public async Task Test_3_GenerateImageEdits() { Assert.IsNotNull(OpenAIClient.ImagesEndPoint); - var imageAssetPath = Path.GetFullPath("..\\..\\..\\Assets\\image_edit_original.png"); - var maskAssetPath = Path.GetFullPath("..\\..\\..\\Assets\\image_edit_mask.png"); + var imageAssetPath = Path.GetFullPath(@"..\..\..\Assets\image_edit_original.png"); + var maskAssetPath = Path.GetFullPath(@"..\..\..\Assets\image_edit_mask.png"); - var results = await OpenAIClient.ImagesEndPoint.CreateImageEditAsync(imageAssetPath, maskAssetPath, "A sunlit indoor lounge area with a pool containing a flamingo", 1, ImageSize.Small); + var request = new ImageEditRequest(imageAssetPath, maskAssetPath, "A sunlit indoor lounge area with a pool containing a flamingo", size: ImageSize.Small); + var results = await OpenAIClient.ImagesEndPoint.CreateImageEditAsync(request); Assert.IsNotNull(results); Assert.NotZero(results.Count); @@ -66,10 +69,11 @@ public async Task Test_4_GenerateImageEdits_B64_Json() { Assert.IsNotNull(OpenAIClient.ImagesEndPoint); - var imageAssetPath = Path.GetFullPath("..\\..\\..\\Assets\\image_edit_original.png"); - var maskAssetPath = Path.GetFullPath("..\\..\\..\\Assets\\image_edit_mask.png"); + var imageAssetPath = Path.GetFullPath(@"..\..\..\Assets\image_edit_original.png"); + var maskAssetPath = Path.GetFullPath(@"..\..\..\Assets\image_edit_mask.png"); - var results = await OpenAIClient.ImagesEndPoint.CreateImageEditAsync(imageAssetPath, maskAssetPath, "A sunlit indoor lounge area with a pool containing a flamingo", 1, ImageSize.Small); + var request = new ImageEditRequest(imageAssetPath, maskAssetPath, "A sunlit indoor lounge area with a pool containing a flamingo", size: ImageSize.Small, responseFormat: ResponseFormat.B64_Json); + var results = await OpenAIClient.ImagesEndPoint.CreateImageEditAsync(request); Assert.IsNotNull(results); Assert.NotZero(results.Count); @@ -85,9 +89,9 @@ public async Task Test_5_GenerateImageVariations() { Assert.IsNotNull(OpenAIClient.ImagesEndPoint); - var imageAssetPath = Path.GetFullPath("..\\..\\..\\Assets\\image_edit_original.png"); - - var results = await OpenAIClient.ImagesEndPoint.CreateImageVariationAsync(imageAssetPath, 1, ImageSize.Small); + var imageAssetPath = Path.GetFullPath(@"..\..\..\Assets\image_edit_original.png"); + var request = new ImageVariationRequest(imageAssetPath, size: ImageSize.Small); + var results = await OpenAIClient.ImagesEndPoint.CreateImageVariationAsync(request); Assert.IsNotNull(results); Assert.NotZero(results.Count); @@ -103,9 +107,9 @@ public async Task Test_6_GenerateImageVariations_B64_Json() { Assert.IsNotNull(OpenAIClient.ImagesEndPoint); - var imageAssetPath = Path.GetFullPath("..\\..\\..\\Assets\\image_edit_original.png"); - - var results = await OpenAIClient.ImagesEndPoint.CreateImageVariationAsync(imageAssetPath, 1, ImageSize.Small, responseFormat: ResponseFormat.B64_Json); + var imageAssetPath = Path.GetFullPath(@"..\..\..\Assets\image_edit_original.png"); + var request = new ImageVariationRequest(imageAssetPath, size: ImageSize.Small, responseFormat: ResponseFormat.B64_Json); + var results = await OpenAIClient.ImagesEndPoint.CreateImageVariationAsync(request); Assert.IsNotNull(results); Assert.NotZero(results.Count); diff --git a/OpenAI-DotNet/Images/AbstractBaseImageRequest.cs b/OpenAI-DotNet/Images/AbstractBaseImageRequest.cs index e6601b19..d30ba7b0 100644 --- a/OpenAI-DotNet/Images/AbstractBaseImageRequest.cs +++ b/OpenAI-DotNet/Images/AbstractBaseImageRequest.cs @@ -1,4 +1,5 @@ -using System; +using OpenAI.Extensions; +using System; using System.Text.Json.Serialization; namespace OpenAI.Images @@ -23,10 +24,10 @@ public abstract class AbstractBaseImageRequest /// /// The format in which the generated images are returned. /// Must be one of url or b64_json. - /// Defaults to + /// Defaults to /// /// - protected AbstractBaseImageRequest(int numberOfResults = 1, ImageSize size = ImageSize.Large, ResponseFormat responseFormat = Images.ResponseFormat.Url, string user = null) + protected AbstractBaseImageRequest(int numberOfResults = 1, ImageSize size = ImageSize.Large, ResponseFormat responseFormat = ResponseFormat.Url, string user = null) { Number = numberOfResults; @@ -39,12 +40,7 @@ protected AbstractBaseImageRequest(int numberOfResults = 1, ImageSize size = Ima }; User = user; - ResponseFormat = responseFormat switch - { - Images.ResponseFormat.Url => "url", - Images.ResponseFormat.B64_Json => "b64_json", - _ => throw new ArgumentOutOfRangeException(nameof(responseFormat), responseFormat, null) - }; + ResponseFormat = responseFormat; } /// @@ -56,10 +52,11 @@ protected AbstractBaseImageRequest(int numberOfResults = 1, ImageSize size = Ima /// /// The format in which the generated images are returned. /// Must be one of url or b64_json. - /// Defaults to + /// Defaults to /// [JsonPropertyName("response_format")] - public string ResponseFormat { get; } + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResponseFormat ResponseFormat { get; } /// /// The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024. diff --git a/OpenAI-DotNet/Images/ImageEditRequest.cs b/OpenAI-DotNet/Images/ImageEditRequest.cs index 0cd79254..2fc813c1 100644 --- a/OpenAI-DotNet/Images/ImageEditRequest.cs +++ b/OpenAI-DotNet/Images/ImageEditRequest.cs @@ -27,14 +27,15 @@ public sealed class ImageEditRequest : AbstractBaseImageRequest, IDisposable /// /// The format in which the generated images are returned. /// Must be one of url or b64_json. - /// Defaults to + /// Defaults to /// public ImageEditRequest( string imagePath, string prompt, int numberOfResults = 1, ImageSize size = ImageSize.Large, - string user = null, ResponseFormat responseFormat = Images.ResponseFormat.Url) + string user = null, + ResponseFormat responseFormat = ResponseFormat.Url) : this(imagePath, null, prompt, numberOfResults, size, user, responseFormat) { } @@ -74,7 +75,7 @@ public ImageEditRequest( int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, - ResponseFormat responseFormat = Images.ResponseFormat.Url) + ResponseFormat responseFormat = ResponseFormat.Url) : this( File.OpenRead(imagePath), Path.GetFileName(imagePath), @@ -120,7 +121,7 @@ public ImageEditRequest( int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, - ResponseFormat responseFormat = Images.ResponseFormat.Url) + ResponseFormat responseFormat = ResponseFormat.Url) : this(image, imageName, null, null, prompt, numberOfResults, size, user, responseFormat) { } @@ -164,7 +165,7 @@ public ImageEditRequest( int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, - ResponseFormat responseFormat = Images.ResponseFormat.Url) + ResponseFormat responseFormat = ResponseFormat.Url) : base(numberOfResults, size, responseFormat, user) { Image = image; diff --git a/OpenAI-DotNet/Images/ImageGenerationRequest.cs b/OpenAI-DotNet/Images/ImageGenerationRequest.cs index e61ab971..797281e1 100644 --- a/OpenAI-DotNet/Images/ImageGenerationRequest.cs +++ b/OpenAI-DotNet/Images/ImageGenerationRequest.cs @@ -1,53 +1,136 @@ -using System; +using OpenAI.Models; +using System; using System.Text.Json.Serialization; +using OpenAI.Extensions; namespace OpenAI.Images { /// /// Creates an image given a prompt. /// - public sealed class ImageGenerationRequest : AbstractBaseImageRequest + public sealed class ImageGenerationRequest { + [Obsolete("Use new constructor")] + public ImageGenerationRequest(string prompt, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = ResponseFormat.Url) + { + throw new NotSupportedException(); + } + /// /// Constructor. /// /// - /// A text description of the desired image(s). The maximum length is 1000 characters. + /// A text description of the desired image(s). + /// The maximum length is 1000 characters for dall-e-2 and 4000 characters for dall-e-3. + /// + /// + /// The model to use for image generation. /// /// - /// The number of images to generate. Must be between 1 and 10. + /// The number of images to generate. + /// Must be between 1 and 10. For dall-e-3, only n=1 is supported. + /// + /// + /// The quality of the image that will be generated. + /// hd creates images with finer details and greater consistency across the image. + /// This param is only supported for dall-e-3. + /// + /// + /// The format in which the generated images are returned. + /// Must be one of url or b64_json. + /// Defaults to /// /// - /// The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024. + /// The size of the generated images. + /// Must be one of 256x256, 512x512, or 1024x1024 for dall-e-2. + /// Must be one of 1024x1024, 1792x1024, or 1024x1792 for dall-e-3 models. + /// + /// + /// The style of the generated images. + /// Must be one of vivid or natural. + /// Vivid causes the model to lean towards generating hyper-real and dramatic images. + /// Natural causes the model to produce more natural, less hyper-real looking images. + /// This param is only supported for dall-e-3. /// /// /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. /// - /// - /// - /// The format in which the generated images are returned. Must be one of url or b64_json. - /// Defaults to - /// - public ImageGenerationRequest(string prompt, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = Images.ResponseFormat.Url) - : base(numberOfResults, size, responseFormat, user) + public ImageGenerationRequest( + string prompt, + Model model = null, + int numberOfResults = 1, + string quality = null, + ResponseFormat responseFormat = ResponseFormat.Url, + string size = null, + string style = null, + string user = null) { - if (prompt.Length > 1000) - { - throw new ArgumentOutOfRangeException(nameof(prompt), "The maximum character length for the prompt is 1000 characters."); - } - Prompt = prompt; - - if (numberOfResults is > 10 or < 1) - { - throw new ArgumentOutOfRangeException(nameof(numberOfResults), "The number of results must be between 1 and 10"); - } + Model = string.IsNullOrWhiteSpace(model?.Id) ? Models.Model.DallE_2 : model; + Number = numberOfResults; + Quality = quality; + ResponseFormat = responseFormat; + Size = size; + Style = style; + User = user; } + [JsonPropertyName("model")] + public string Model { get; } + /// - /// A text description of the desired image(s). The maximum length is 1000 characters. + /// A text description of the desired image(s). + /// The maximum length is 1000 characters for dall-e-2 and 4000 characters for dall-e-3. /// [JsonPropertyName("prompt")] public string Prompt { get; } + + /// + /// The number of images to generate. + /// Must be between 1 and 10. For dall-e-3, only n=1 is supported. + /// + [JsonPropertyName("n")] + public int Number { get; } + + /// + /// The quality of the image that will be generated. + /// hd creates images with finer details and greater consistency across the image. + /// This param is only supported for dall-e-3. + /// + [JsonPropertyName("quality")] + public string Quality { get; } + + /// + /// The format in which the generated images are returned. + /// Must be one of url or b64_json. + /// Defaults to + /// + [JsonPropertyName("response_format")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public ResponseFormat ResponseFormat { get; } + + /// + /// The size of the generated images. + /// Must be one of 256x256, 512x512, or 1024x1024 for dall-e-2. + /// Must be one of 1024x1024, 1792x1024, or 1024x1792 for dall-e-3 models. + /// + [JsonPropertyName("size")] + public string Size { get; } + + /// + /// The style of the generated images. + /// Must be one of vivid or natural. + /// Vivid causes the model to lean towards generating hyper-real and dramatic images. + /// Natural causes the model to produce more natural, less hyper-real looking images. + /// This param is only supported for dall-e-3. + /// + [JsonPropertyName("style")] + public string Style { get; } + + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. + /// + [JsonPropertyName("user")] + public string User { get; } } } diff --git a/OpenAI-DotNet/Images/ImageVariationRequest.cs b/OpenAI-DotNet/Images/ImageVariationRequest.cs index a5eab476..24cb53b4 100644 --- a/OpenAI-DotNet/Images/ImageVariationRequest.cs +++ b/OpenAI-DotNet/Images/ImageVariationRequest.cs @@ -25,7 +25,7 @@ public sealed class ImageVariationRequest : AbstractBaseImageRequest, IDisposabl /// Must be one of url or b64_json. /// Defaults to /// - public ImageVariationRequest(string imagePath, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = Images.ResponseFormat.Url) + public ImageVariationRequest(string imagePath, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = ResponseFormat.Url) : this(File.OpenRead(imagePath), Path.GetFileName(imagePath), numberOfResults, size, user, responseFormat) { } @@ -53,7 +53,7 @@ public ImageVariationRequest(string imagePath, int numberOfResults = 1, ImageSiz /// Must be one of url or b64_json. /// Defaults to /// - public ImageVariationRequest(Stream image, string imageName, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = Images.ResponseFormat.Url) + public ImageVariationRequest(Stream image, string imageName, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = ResponseFormat.Url) : base(numberOfResults, size, responseFormat, user) { Image = image; diff --git a/OpenAI-DotNet/Images/ImagesEndpoint.cs b/OpenAI-DotNet/Images/ImagesEndpoint.cs index 9ab04338..85d3c396 100644 --- a/OpenAI-DotNet/Images/ImagesEndpoint.cs +++ b/OpenAI-DotNet/Images/ImagesEndpoint.cs @@ -1,4 +1,5 @@ using OpenAI.Extensions; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -44,6 +45,7 @@ internal ImagesEndpoint(OpenAIClient api) : base(api) { } /// Optional, . /// /// A list of generated texture urls to download. + [Obsolete] public async Task> GenerateImageAsync( string prompt, int numberOfResults = 1, @@ -97,6 +99,7 @@ public async Task> GenerateImageAsync(ImageGenerationReque /// Optional, . /// A list of generated texture urls to download. /// + [Obsolete] public async Task> CreateImageEditAsync( string image, string mask, @@ -132,7 +135,7 @@ public async Task> CreateImageEditAsync(ImageEditRequest r content.Add(new StringContent(request.Prompt), "prompt"); content.Add(new StringContent(request.Number.ToString()), "n"); content.Add(new StringContent(request.Size), "size"); - content.Add(new StringContent(request.ResponseFormat), "response_format"); + content.Add(new StringContent(request.ResponseFormat.ToString().ToLower()), "response_format"); if (!string.IsNullOrWhiteSpace(request.User)) { @@ -167,6 +170,7 @@ public async Task> CreateImageEditAsync(ImageEditRequest r /// Optional, . /// A list of generated texture urls to download. /// + [Obsolete] public async Task> CreateImageVariationAsync( string imagePath, int numberOfResults = 1, @@ -191,7 +195,7 @@ public async Task> CreateImageVariationAsync(ImageVariatio content.Add(new ByteArrayContent(imageData.ToArray()), "image", request.ImageName); content.Add(new StringContent(request.Number.ToString()), "n"); content.Add(new StringContent(request.Size), "size"); - content.Add(new StringContent(request.ResponseFormat), "response_format"); + content.Add(new StringContent(request.ResponseFormat.ToString().ToLower()), "response_format"); if (!string.IsNullOrWhiteSpace(request.User)) { diff --git a/OpenAI-DotNet/Images/ResponseFormat.cs b/OpenAI-DotNet/Images/ResponseFormat.cs index 1af7faaa..180d07d1 100644 --- a/OpenAI-DotNet/Images/ResponseFormat.cs +++ b/OpenAI-DotNet/Images/ResponseFormat.cs @@ -1,8 +1,12 @@ -namespace OpenAI.Images +using System.Runtime.Serialization; + +namespace OpenAI.Images { public enum ResponseFormat { + [EnumMember(Value = "url")] Url, + [EnumMember(Value = "b64_json")] B64_Json } } \ No newline at end of file