From 6ddae78e0fed0fdf5247023f6c37a3f1994ccbe3 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Thu, 21 Mar 2024 15:16:23 -0700 Subject: [PATCH 1/7] Initial pass --- .dotnet/src/Custom/Audio/AudioClient.cs | 105 ++----------- .dotnet/src/Custom/Files/FileClient.cs | 55 ++----- .dotnet/src/Custom/Images/GeneratedImage.cs | 11 +- .dotnet/src/Custom/Images/ImageClient.cs | 143 ++---------------- .dotnet/src/Custom/Images/ImageEditOptions.cs | 21 +-- .../Sample01_RetrievalAugmentedGeneration.cs | 8 +- ...ple01_RetrievalAugmentedGenerationAsync.cs | 8 +- .../Samples/Images/Sample01_SimpleImage.cs | 6 +- .../Images/Sample01_SimpleImageAsync.cs | 6 +- .../Images/Sample02_SimpleImageEdit.cs | 12 +- .../Images/Sample02_SimpleImageEditAsync.cs | 14 +- .../Images/Sample03_SimpleImageVariation.cs | 8 +- .../Sample03_SimpleImageVariationAsync.cs | 8 +- .../tests/TestScenarios/FileClientTests.cs | 5 +- .../TestScenarios/ImageGenerationTests.cs | 2 +- .../tests/TestScenarios/TranscriptionTests.cs | 7 +- .../tests/TestScenarios/TranslationTests.cs | 4 +- 17 files changed, 89 insertions(+), 334 deletions(-) diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index 3d85f3686..239355166 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -3,7 +3,6 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.IO; -using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading.Tasks; @@ -86,34 +85,14 @@ public virtual Task> GenerateSpeechFromTextAsync( // convenience method - sync; Stream overload // TODO: add refdoc comment - public virtual ClientResult TranscribeAudio(Stream fileStream, string fileName, AudioTranscriptionOptions options = null) + public virtual ClientResult TranscribeAudio(Stream audio, string fileName, AudioTranscriptionOptions options = null) { - Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(audio, nameof(audio)); Argument.AssertNotNull(fileName, nameof(fileName)); options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model); - - ClientResult result = TranscribeAudio(content, content.ContentType); - - PipelineResponse response = result.GetRawResponse(); - - AudioTranscription value = AudioTranscription.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - sync - // TODO: add refdoc comment - public virtual ClientResult TranscribeAudio(BinaryData audioBytes, string fileName, AudioTranscriptionOptions options = null) - { - Argument.AssertNotNull(audioBytes, nameof(audioBytes)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audio, fileName, _clientConnector.Model); ClientResult result = TranscribeAudio(content, content.ContentType); @@ -126,34 +105,14 @@ public virtual ClientResult TranscribeAudio(BinaryData audio // convenience method - async // TODO: add refdoc comment - public virtual async Task> TranscribeAudioAsync(Stream fileStream, string filename, AudioTranscriptionOptions options = null) + public virtual async Task> TranscribeAudioAsync(Stream audio, string filename, AudioTranscriptionOptions options = null) { - Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(audio, nameof(audio)); Argument.AssertNotNull(filename, nameof(filename)); options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, filename, _clientConnector.Model); - - ClientResult result = await TranscribeAudioAsync(content, content.ContentType).ConfigureAwait(false); - - PipelineResponse response = result.GetRawResponse(); - - AudioTranscription value = AudioTranscription.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - async - // TODO: add refdoc comment - public virtual async Task> TranscribeAudioAsync(BinaryData audioBytes, string fileName, AudioTranscriptionOptions options = null) - { - Argument.AssertNotNull(audioBytes, nameof(audioBytes)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audio, filename, _clientConnector.Model); ClientResult result = await TranscribeAudioAsync(content, content.ContentType).ConfigureAwait(false); @@ -191,34 +150,14 @@ private PipelineMessage CreateCreateTranscriptionRequest(BinaryContent content, // convenience method - sync; Stream overload // TODO: add refdoc comment - public virtual ClientResult TranslateAudio(Stream fileStream, string fileName, AudioTranslationOptions options = null) + public virtual ClientResult TranslateAudio(Stream audio, string fileName, AudioTranslationOptions options = null) { - Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(audio, nameof(audio)); Argument.AssertNotNull(fileName, nameof(fileName)); options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model); - - ClientResult result = TranslateAudio(content, content.ContentType); - - PipelineResponse response = result.GetRawResponse(); - - AudioTranslation value = AudioTranslation.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - sync - // TODO: add refdoc comment - public virtual ClientResult TranslateAudio(BinaryData audioBytes, string fileName, AudioTranslationOptions options = null) - { - Argument.AssertNotNull(audioBytes, nameof(audioBytes)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audio, fileName, _clientConnector.Model); ClientResult result = TranslateAudio(content, content.ContentType); @@ -231,34 +170,14 @@ public virtual ClientResult TranslateAudio(BinaryData audioByt // convenience method - async; Stream overload // TODO: add refdoc comment - public virtual async Task> TranslateAudioAsync(Stream fileStream, string fileName, AudioTranslationOptions options = null) - { - Argument.AssertNotNull(fileStream, nameof(fileStream)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model); - - ClientResult result = await TranslateAudioAsync(content, content.ContentType).ConfigureAwait(false); - - PipelineResponse response = result.GetRawResponse(); - - AudioTranslation value = AudioTranslation.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - async - // TODO: add refdoc comment - public virtual async Task> TranslateAudioAsync(BinaryData audioBytes, string fileName, AudioTranslationOptions options = null) + public virtual async Task> TranslateAudioAsync(Stream audio, string fileName, AudioTranslationOptions options = null) { - Argument.AssertNotNull(audioBytes, nameof(audioBytes)); + Argument.AssertNotNull(audio, nameof(audio)); Argument.AssertNotNull(fileName, nameof(fileName)); options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audio, fileName, _clientConnector.Model); ClientResult result = await TranslateAudioAsync(content, content.ContentType).ConfigureAwait(false); diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index 42ef17eca..576bfc3ba 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -39,26 +39,7 @@ public FileClient(ApiKeyCredential credential = default, OpenAIClientOptions opt // convenience method - sync; Stream overload // TODO: add refdoc comment - public virtual ClientResult UploadFile(Stream fileStream, string fileName, OpenAIFilePurpose purpose) - { - Argument.AssertNotNull(fileStream, nameof(fileStream)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - using MultipartFormDataBinaryContent content = UploadFileOptions.ToMultipartContent(fileStream, fileName, purpose); - - ClientResult result = UploadFile(content, content.ContentType); - - PipelineResponse response = result.GetRawResponse(); - - Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); - OpenAIFileInfo fileInfo = new(internalFile); - - return ClientResult.FromValue(fileInfo, response); - } - - // convenience method - sync - // TODO: add refdoc comment - public virtual ClientResult UploadFile(BinaryData file, string fileName, OpenAIFilePurpose purpose) + public virtual ClientResult UploadFile(Stream file, string fileName, OpenAIFilePurpose purpose) { Argument.AssertNotNull(file, nameof(file)); Argument.AssertNotNull(fileName, nameof(fileName)); @@ -94,25 +75,6 @@ public virtual async Task> UploadFileAsync(Stream f return ClientResult.FromValue(fileInfo, response); } - // convenience method - async - // TODO: add refdoc comment - public virtual async Task> UploadFileAsync(BinaryData file, string fileName, OpenAIFilePurpose purpose) - { - Argument.AssertNotNull(file, nameof(file)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - using MultipartFormDataBinaryContent content = UploadFileOptions.ToMultipartContent(file, fileName, purpose); - - ClientResult result = await UploadFileAsync(content, content.ContentType).ConfigureAwait(false); - - PipelineResponse response = result.GetRawResponse(); - - Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); - OpenAIFileInfo fileInfo = new(internalFile); - - return ClientResult.FromValue(fileInfo, response); - } - public virtual ClientResult GetFileInfo(string fileId) { ClientResult internalResult = Shim.RetrieveFile(fileId); @@ -159,10 +121,11 @@ public virtual async Task> GetFileInfoLis return ClientResult.FromValue(new OpenAIFileInfoCollection(infoItems), result.GetRawResponse()); } - public virtual ClientResult DownloadFile(string fileId) + public virtual ClientResult DownloadFile(string fileId) { - PipelineMessage message = Shim.Pipeline.CreateMessage(); + using PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; + message.BufferResponse = false; PipelineRequest request = message.Request; request.Method = "GET"; UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); @@ -178,12 +141,13 @@ public virtual ClientResult DownloadFile(string fileId) throw new ClientResultException(message.Response); } - return ClientResult.FromValue(message.Response.Content, message.Response); + PipelineResponse response = message.ExtractResponse(); + return ClientResult.FromValue(response.ContentStream, response); } - public virtual async Task> DownloadFileAsync(string fileId) + public virtual async Task> DownloadFileAsync(string fileId) { - PipelineMessage message = Shim.Pipeline.CreateMessage(); + using PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; PipelineRequest request = message.Request; request.Method = "GET"; @@ -201,7 +165,8 @@ public virtual async Task> DownloadFileAsync(string fil throw new ClientResultException(message.Response); } - return ClientResult.FromValue(message.Response.Content, message.Response); + PipelineResponse response = message.ExtractResponse(); + return ClientResult.FromValue(response.ContentStream, response); } public virtual void DeleteFile(string fileId) diff --git a/.dotnet/src/Custom/Images/GeneratedImage.cs b/.dotnet/src/Custom/Images/GeneratedImage.cs index 4643ffc24..91f8c2bf6 100644 --- a/.dotnet/src/Custom/Images/GeneratedImage.cs +++ b/.dotnet/src/Custom/Images/GeneratedImage.cs @@ -1,4 +1,5 @@ using System; +using System.IO; namespace OpenAI.Images; @@ -15,13 +16,13 @@ public class GeneratedImage /// This property is mutually exclusive with and will be null when the other /// is present. /// - public BinaryData ImageBytes { get; } + public Stream Image { get; } /// /// A temporary internet location for an image, provided by default or when /// is set to . /// /// - /// This property is mutually exclusive with and will be null when the other + /// This property is mutually exclusive with and will be null when the other /// is present. /// public Uri ImageUri { get; } @@ -41,7 +42,11 @@ public class GeneratedImage internal GeneratedImage(Internal.Models.ImagesResponse internalResponse, int internalDataIndex) { CreatedAt = internalResponse.Created; - ImageBytes = internalResponse.Data[(int)internalDataIndex].B64Json; + + // TODO: Generator will need to update to make file streams Streams instead of BinaryData + // with this proposal. This is important if these files are going to be large, since + // BinaryData loads the buffers into memory, and this could be problematic for applications. + Image = internalResponse.Data[(int)internalDataIndex].B64Json.ToStream(); RevisedPrompt = internalResponse.Data[(int)internalDataIndex].RevisedPrompt; ImageUri = internalResponse.Data[(int)internalDataIndex].Url; } diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 4f9ca8f92..789fa8aa4 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -4,7 +4,6 @@ using System.ClientModel.Primitives; using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading.Tasks; @@ -42,7 +41,6 @@ public ImageClient(string model, ApiKeyCredential credential = default, OpenAICl /// /// The description and instructions for the image. /// Additional options for the image generation request. - /// The cancellation token for the operation. /// A result for a single image generation. public virtual ClientResult GenerateImage( string prompt, @@ -57,7 +55,6 @@ public virtual ClientResult GenerateImage( /// /// The description and instructions for the image. /// Additional options for the image generation request. - /// The cancellation token for the operation. /// A result for a single image generation. public virtual async Task> GenerateImageAsync( string prompt, @@ -75,7 +72,6 @@ public virtual async Task> GenerateImageAsync( /// The number of alternative images to generate for the prompt. /// /// Additional options for the image generation request. - /// The cancellation token for the operation. /// A result for a single image generation. public virtual ClientResult GenerateImages( string prompt, @@ -102,7 +98,6 @@ public virtual ClientResult GenerateImages( /// The number of alternative images to generate for the prompt. /// /// Additional options for the image generation request. - /// The cancellation token for the operation. /// A result for a single image generation. public virtual async Task> GenerateImagesAsync( string prompt, @@ -124,55 +119,24 @@ public virtual async Task> GenerateImages // convenience method - sync; Stream overload // TODO: add refdoc comment public virtual ClientResult GenerateImageEdits( - Stream fileStream, + Stream image, string fileName, string prompt, int? imageCount = null, ImageEditOptions options = null) { - Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(image, nameof(image)); Argument.AssertNotNull(fileName, nameof(fileName)); Argument.AssertNotNull(prompt, nameof(prompt)); - if (options?.MaskBytes is not null) + if (options?.Mask is not null) { Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); } options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, prompt, _clientConnector.Model, imageCount); - - ClientResult result = GenerateImageEdits(content, content.ContentType); - - PipelineResponse response = result.GetRawResponse(); - - GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - sync - // TODO: add refdoc comment - public virtual ClientResult GenerateImageEdits( - BinaryData imageBytes, - string fileName, - string prompt, - int? imageCount = null, - ImageEditOptions options = null) - { - Argument.AssertNotNull(imageBytes, nameof(imageBytes)); - Argument.AssertNotNull(fileName, nameof(fileName)); - Argument.AssertNotNull(prompt, nameof(prompt)); - - if (options?.MaskBytes is not null) - { - Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); - } - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, prompt, _clientConnector.Model, imageCount); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(image, fileName, prompt, _clientConnector.Model, imageCount); ClientResult result = GenerateImageEdits(content, content.ContentType); @@ -186,55 +150,24 @@ public virtual ClientResult GenerateImageEdits( // convenience method - async; Stream overload // TODO: add refdoc comment public virtual async Task> GenerateImageEditsAsync( - Stream fileStream, - string fileName, - string prompt, - int? imageCount = null, - ImageEditOptions options = null) - { - Argument.AssertNotNull(fileStream, nameof(fileStream)); - Argument.AssertNotNull(fileName, nameof(fileName)); - Argument.AssertNotNull(prompt, nameof(prompt)); - - if (options?.MaskBytes is not null) - { - Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); - } - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, prompt, _clientConnector.Model, imageCount); - - ClientResult result = await GenerateImageEditsAsync(content, content.ContentType).ConfigureAwait(false); - - PipelineResponse response = result.GetRawResponse(); - - GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - async - // TODO: add refdoc comment - public virtual async Task> GenerateImageEditsAsync( - BinaryData imageBytes, + Stream image, string fileName, string prompt, int? imageCount = null, ImageEditOptions options = null) { - Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(image, nameof(image)); Argument.AssertNotNull(fileName, nameof(fileName)); Argument.AssertNotNull(prompt, nameof(prompt)); - if (options?.MaskBytes is not null) + if (options?.Mask is not null) { Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); } options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, prompt, _clientConnector.Model, imageCount); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(image, fileName, prompt, _clientConnector.Model, imageCount); ClientResult result = await GenerateImageEditsAsync(content, content.ContentType).ConfigureAwait(false); @@ -248,41 +181,17 @@ public virtual async Task> GenerateImageE // convenience method - sync // TODO: add refdoc comment public virtual ClientResult GenerateImageVariations( - Stream fileStream, + Stream image, string fileName, int? imageCount = null, ImageVariationOptions options = null) { - Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(image, nameof(image)); Argument.AssertNotNull(fileName, nameof(fileName)); options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model, imageCount); - - ClientResult result = GenerateImageVariations(content, content.ContentType); - - PipelineResponse response = result.GetRawResponse(); - - GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - sync - // TODO: add refdoc comment - public virtual ClientResult GenerateImageVariations( - BinaryData imageBytes, - string fileName, - int? imageCount = null, - ImageVariationOptions options = null) - { - Argument.AssertNotNull(imageBytes, nameof(imageBytes)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, _clientConnector.Model, imageCount); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(image, fileName, _clientConnector.Model, imageCount); ClientResult result = GenerateImageVariations(content, content.ContentType); @@ -296,41 +205,17 @@ public virtual ClientResult GenerateImageVariations( // convenience method - async; Stream overload // TODO: add refdoc comment public virtual async Task> GenerateImageVariationsAsync( - Stream fileStream, - string fileName, - int? imageCount = null, - ImageVariationOptions options = null) - { - Argument.AssertNotNull(fileStream, nameof(fileStream)); - Argument.AssertNotNull(fileName, nameof(fileName)); - - options ??= new(); - - using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model, imageCount); - - ClientResult result = await GenerateImageVariationsAsync(content, content.ContentType).ConfigureAwait(false); - - PipelineResponse response = result.GetRawResponse(); - - GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); - - return ClientResult.FromValue(value, response); - } - - // convenience method - async - // TODO: add refdoc comment - public virtual async Task> GenerateImageVariationsAsync( - BinaryData imageBytes, + Stream image, string fileName, int? imageCount = null, ImageVariationOptions options = null) { - Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(image, nameof(image)); Argument.AssertNotNull(fileName, nameof(fileName)); options ??= new(); - using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, _clientConnector.Model, imageCount); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(image, fileName, _clientConnector.Model, imageCount); ClientResult result = await GenerateImageVariationsAsync(content, content.ContentType).ConfigureAwait(false); diff --git a/.dotnet/src/Custom/Images/ImageEditOptions.cs b/.dotnet/src/Custom/Images/ImageEditOptions.cs index 2a816428f..5eb1830da 100644 --- a/.dotnet/src/Custom/Images/ImageEditOptions.cs +++ b/.dotnet/src/Custom/Images/ImageEditOptions.cs @@ -10,7 +10,7 @@ namespace OpenAI.Images; public partial class ImageEditOptions { /// - public BinaryData MaskBytes { get; set; } + public Stream Mask { get; set; } // The generator will need to add file-name to models for properties that // represent files in order to enable setting the header. @@ -43,29 +43,14 @@ internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, return content; } - internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData imageBytes, - string fileName, - string prompt, - string model, - int? imageCount) - { - MultipartFormDataBinaryContent content = new(); - - content.Add(imageBytes, "image", fileName); - - AddContent(model, prompt, imageCount, content); - - return content; - } - private void AddContent(string model, string prompt, int? imageCount, MultipartFormDataBinaryContent content) { content.Add(prompt, "prompt"); content.Add(model, "model"); - if (MaskBytes is not null) + if (Mask is not null) { - content.Add(MaskBytes.ToArray(), "mask", MaskFileName); + content.Add(Mask, "mask", MaskFileName); } if (imageCount is not null) diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs index 0f7856c2f..557fe5b3d 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs @@ -20,7 +20,7 @@ public void Sample01_RetrievalAugmentedGeneration() AssistantClient assistantClient = openAIClient.GetAssistantClient(); // First, let's contrive a document we'll use retrieval with and upload it. - BinaryData document = BinaryData.FromString(""" + Stream document = BinaryData.FromString(""" { "description": "This document contains the sale history data for Contoso products.", "sales": [ @@ -47,7 +47,7 @@ public void Sample01_RetrievalAugmentedGeneration() } ] } - """); + """).ToStream(); OpenAIFileInfo openAIFileInfo = fileClient.UploadFile(document, "test-rag-file-delete-me.json", OpenAIFilePurpose.Assistants); @@ -125,9 +125,9 @@ public void Sample01_RetrievalAugmentedGeneration() else if (contentItem is MessageImageFileContent imageFileContent) { OpenAIFileInfo imageInfo = fileClient.GetFileInfo(imageFileContent.FileId); - BinaryData imageBytes = fileClient.DownloadFile(imageFileContent.FileId); + using Stream image = fileClient.DownloadFile(imageFileContent.FileId); using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); - imageBytes.ToStream().CopyTo(stream); + image.CopyTo(stream); Console.WriteLine($""); } diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs index 7737114fe..277e75bb2 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs @@ -20,7 +20,7 @@ public async Task Sample01_RetrievalAugmentedGenerationAsync() AssistantClient assistantClient = openAIClient.GetAssistantClient(); // First, let's contrive a document we'll use retrieval with and upload it. - BinaryData document = BinaryData.FromString(""" + Stream document = BinaryData.FromString(""" { "description": "This document contains the sale history data for Contoso products.", "sales": [ @@ -47,7 +47,7 @@ public async Task Sample01_RetrievalAugmentedGenerationAsync() } ] } - """); + """).ToStream(); OpenAIFileInfo openAIFileInfo = await fileClient.UploadFileAsync(document, "test-rag-file-delete-me.json", OpenAIFilePurpose.Assistants); @@ -125,9 +125,9 @@ public async Task Sample01_RetrievalAugmentedGenerationAsync() else if (contentItem is MessageImageFileContent imageFileContent) { OpenAIFileInfo imageInfo = await fileClient.GetFileInfoAsync(imageFileContent.FileId); - BinaryData imageBytes = await fileClient.DownloadFileAsync(imageFileContent.FileId); + using Stream image = await fileClient.DownloadFileAsync(imageFileContent.FileId); using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); - imageBytes.ToStream().CopyTo(stream); + await image.CopyToAsync(stream); Console.WriteLine($""); } diff --git a/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs b/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs index 725e1cab3..25f52cd0d 100644 --- a/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs +++ b/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs @@ -29,11 +29,11 @@ public void Sample01_SimpleImage() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImage image = client.GenerateImage(prompt, options); - BinaryData bytes = image.ImageBytes; + GeneratedImage generatedImage = client.GenerateImage(prompt, options); + using Stream image = generatedImage.Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - bytes.ToStream().CopyTo(stream); + image.CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs b/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs index a3c55901a..aa03d8d53 100644 --- a/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs @@ -30,11 +30,11 @@ public async Task Sample01_SimpleImageAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImage image = await client.GenerateImageAsync(prompt, options); - BinaryData bytes = image.ImageBytes; + GeneratedImage generatedImage = await client.GenerateImageAsync(prompt, options); + using Stream image = generatedImage.Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - bytes.ToStream().CopyTo(stream); + await image.CopyToAsync(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs index 81b0f486c..01c2e21b6 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs @@ -14,26 +14,26 @@ public void Sample02_SimpleImageEdit() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "edit_sample_image.png"); - BinaryData imageBytes = BinaryData.FromBytes(File.ReadAllBytes(imagePath)); + using Stream inputImage = File.OpenRead(imagePath); string prompt = "An inflatable flamingo float in a pool"; string maskPath = Path.Combine("Assets", "edit_sample_mask.png"); - BinaryData maskBytes = BinaryData.FromBytes(File.ReadAllBytes(maskPath)); + using Stream mask = File.OpenRead(maskPath); ImageEditOptions options = new() { - MaskBytes = maskBytes, + Mask = mask, MaskFileName = "edit_sample_mask.png", Size = ImageSize.Size1024x1024, ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = client.GenerateImageEdits(imageBytes, "edit_sample_image.png", prompt, 1, options); - BinaryData bytes = image[0].ImageBytes; + GeneratedImageCollection imageCollection = client.GenerateImageEdits(inputImage, "edit_sample_image.png", prompt, 1, options); + using Stream editedImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - bytes.ToStream().CopyTo(stream); + editedImage.CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index a143ba328..7bb47257a 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -15,26 +15,26 @@ public async Task Sample02_SimpleImageEditAsync() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "edit_sample_image.png"); - BinaryData imageBytes = BinaryData.FromBytes(File.ReadAllBytes(imagePath)); + using Stream inputImage = File.OpenRead(imagePath); string prompt = "An inflatable flamingo float in a pool"; string maskPath = Path.Combine("Assets", "edit_sample_mask.png"); - BinaryData maskBytes = BinaryData.FromBytes(File.ReadAllBytes(maskPath)); - + using Stream mask = File.OpenRead(maskPath); + ImageEditOptions options = new() { - MaskBytes = maskBytes, + Mask = mask, MaskFileName = "edit_sample_mask.png", Size = ImageSize.Size1024x1024, ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = await client.GenerateImageEditsAsync(imageBytes, "edit_sample_image.png", prompt, 1, options); - BinaryData bytes = image[0].ImageBytes; + GeneratedImageCollection imageCollection = await client.GenerateImageEditsAsync(inputImage, "edit_sample_image.png", prompt, 1, options); + using Stream editedImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - bytes.ToStream().CopyTo(stream); + await editedImage.CopyToAsync(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs index 409dd3cef..2b0ebb3ec 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs @@ -14,7 +14,7 @@ public void Sample03_SimpleImageVariation() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "variation_sample_image.png"); - BinaryData imageBytes = BinaryData.FromBytes(File.ReadAllBytes(imagePath)); + using Stream inputImage = File.OpenRead(imagePath); ImageVariationOptions options = new() { @@ -22,11 +22,11 @@ public void Sample03_SimpleImageVariation() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = client.GenerateImageVariations(imageBytes, "variation_sample_image.png", 1, options); - BinaryData bytes = image[0].ImageBytes; + GeneratedImageCollection imageCollection = client.GenerateImageVariations(inputImage, "variation_sample_image.png", 1, options); + using Stream outputImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - bytes.ToStream().CopyTo(stream); + outputImage.CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs index 257abc1fe..e0a0e7c24 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs @@ -15,7 +15,7 @@ public async Task Sample03_SimpleImageVariationAsync() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "variation_sample_image.png"); - BinaryData imageBytes = BinaryData.FromBytes(File.ReadAllBytes(imagePath)); + using Stream inputImage = File.OpenRead(imagePath); ImageVariationOptions options = new() { @@ -23,11 +23,11 @@ public async Task Sample03_SimpleImageVariationAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = await client.GenerateImageVariationsAsync(imageBytes, "variation_sample_image.png", 1, options); - BinaryData bytes = image[0].ImageBytes; + GeneratedImageCollection imageCollection = await client.GenerateImageVariationsAsync(inputImage, "variation_sample_image.png", 1, options); + using Stream outputImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - bytes.ToStream().CopyTo(stream); + outputImage.CopyTo(stream); } } } diff --git a/.dotnet/tests/TestScenarios/FileClientTests.cs b/.dotnet/tests/TestScenarios/FileClientTests.cs index 4a9f6d4cb..5fab6936a 100644 --- a/.dotnet/tests/TestScenarios/FileClientTests.cs +++ b/.dotnet/tests/TestScenarios/FileClientTests.cs @@ -2,6 +2,7 @@ using OpenAI.Files; using System; using System.ClientModel; +using System.IO; using static OpenAI.Tests.TestHelpers; namespace OpenAI.Tests.Files; @@ -25,7 +26,7 @@ public void ListFilesWorks() public void UploadFileWorks() { FileClient client = GetTestClient(); - BinaryData uploadData = BinaryData.FromString("hello, this is a text file, please delete me"); + Stream uploadData = BinaryData.FromString("hello, this is a text file, please delete me").ToStream(); ClientResult uploadResult = client.UploadFile(uploadData, "test-file-delete-me.txt", OpenAIFilePurpose.Assistants); Assert.That(uploadResult.Value, Is.Not.Null); @@ -43,7 +44,7 @@ public void DownloadAndInfoWork() ClientResult fileInfoResult = client.GetFileInfo("file-S7roYWamZqfMK9D979HU4q6m"); Assert.That(fileInfoResult.Value, Is.Not.Null); - ClientResult downloadResult = client.DownloadFile("file-S7roYWamZqfMK9D979HU4q6m"); + ClientResult downloadResult = client.DownloadFile("file-S7roYWamZqfMK9D979HU4q6m"); Assert.That(downloadResult.Value, Is.Not.Null); } diff --git a/.dotnet/tests/TestScenarios/ImageGenerationTests.cs b/.dotnet/tests/TestScenarios/ImageGenerationTests.cs index 1d8d3304c..2a9a5805e 100644 --- a/.dotnet/tests/TestScenarios/ImageGenerationTests.cs +++ b/.dotnet/tests/TestScenarios/ImageGenerationTests.cs @@ -16,7 +16,7 @@ public void BasicGenerationWorks() Assert.That(result, Is.InstanceOf>()); Assert.That(result.Value.ImageUri, Is.Not.Null); Console.WriteLine(result.Value.ImageUri.AbsoluteUri); - Assert.That(result.Value.ImageBytes, Is.Null); + Assert.That(result.Value.Image, Is.Null); Assert.That(result.Value.CreatedAt, Is.GreaterThan(new DateTimeOffset(new DateTime(year: 2020, month: 1, day: 1)))); } diff --git a/.dotnet/tests/TestScenarios/TranscriptionTests.cs b/.dotnet/tests/TestScenarios/TranscriptionTests.cs index 70753d47d..196103acd 100644 --- a/.dotnet/tests/TestScenarios/TranscriptionTests.cs +++ b/.dotnet/tests/TestScenarios/TranscriptionTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using OpenAI.Audio; -using System; using System.ClientModel; using System.IO; using static OpenAI.Tests.TestHelpers; @@ -14,8 +13,7 @@ public void BasicTranscriptionWorks() { AudioClient client = GetTestClient(); using FileStream inputStream = File.OpenRead(Path.Combine("Assets", "hello_world.m4a")); - BinaryData inputData = BinaryData.FromStream(inputStream); - ClientResult transcriptionResult = client.TranscribeAudio(inputData, "hello_world.m4a"); + ClientResult transcriptionResult = client.TranscribeAudio(inputStream, "hello_world.m4a"); Assert.That(transcriptionResult.Value, Is.Not.Null); Assert.That(transcriptionResult.Value.Text.ToLowerInvariant(), Contains.Substring("hello")); } @@ -25,8 +23,7 @@ public void WordTimestampsWork() { AudioClient client = GetTestClient(); using FileStream inputStream = File.OpenRead(Path.Combine("Assets", "hello_world.m4a")); - BinaryData inputData = BinaryData.FromStream(inputStream); - ClientResult transcriptionResult = client.TranscribeAudio(inputData, "hello_world.m4a", new AudioTranscriptionOptions() + ClientResult transcriptionResult = client.TranscribeAudio(inputStream, "hello_world.m4a", new AudioTranscriptionOptions() { EnableWordTimestamps = true, EnableSegmentTimestamps = true, diff --git a/.dotnet/tests/TestScenarios/TranslationTests.cs b/.dotnet/tests/TestScenarios/TranslationTests.cs index be71bb5a2..8d2842dea 100644 --- a/.dotnet/tests/TestScenarios/TranslationTests.cs +++ b/.dotnet/tests/TestScenarios/TranslationTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using OpenAI.Audio; -using System; using System.ClientModel; using System.IO; using static OpenAI.Tests.TestHelpers; @@ -14,8 +13,7 @@ public void BasicTranslationWorks() { AudioClient client = GetTestClient(); using FileStream inputStream = File.OpenRead(Path.Combine("Assets", "multilingual.wav")); - BinaryData inputData = BinaryData.FromStream(inputStream); - ClientResult translationResult = client.TranslateAudio(inputData, "multilingual.wav"); + ClientResult translationResult = client.TranslateAudio(inputStream, "multilingual.wav"); Assert.That(translationResult.Value, Is.Not.Null); // Assert.That(translationResult.Value.Text.ToLowerInvariant(), Contains.Substring("hello")); } From 558454e3f0c0b25b0e4a15889bf48b5c1e7da521 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Thu, 21 Mar 2024 15:35:19 -0700 Subject: [PATCH 2/7] add FileStream overloads --- .dotnet/src/Custom/Audio/AudioClient.cs | 20 ++++++----- .../Custom/Audio/AudioTranscriptionOptions.cs | 25 +++---------- .../Custom/Audio/AudioTranslationOptions.cs | 25 +++---------- .dotnet/src/Custom/Files/FileClient.cs | 10 +++--- .dotnet/src/Custom/Files/UploadFileOptions.cs | 24 +++---------- .dotnet/src/Custom/Images/ImageClient.cs | 35 ++++++++++++++----- .dotnet/src/Custom/Images/ImageEditOptions.cs | 14 +++----- .../Custom/Images/ImageVariationOptions.cs | 25 +++---------- 8 files changed, 65 insertions(+), 113 deletions(-) diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index 239355166..fddee7535 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -83,8 +83,9 @@ public virtual Task> GenerateSpeechFromTextAsync( return Shim.CreateSpeechAsync(request); } - // convenience method - sync; Stream overload - // TODO: add refdoc comment + public virtual ClientResult TranscribeAudio(FileStream audio, AudioTranscriptionOptions options = null) + => TranscribeAudio(audio, Path.GetFileName(audio.Name), options); + public virtual ClientResult TranscribeAudio(Stream audio, string fileName, AudioTranscriptionOptions options = null) { Argument.AssertNotNull(audio, nameof(audio)); @@ -103,8 +104,9 @@ public virtual ClientResult TranscribeAudio(Stream audio, st return ClientResult.FromValue(value, response); } - // convenience method - async - // TODO: add refdoc comment + public virtual async Task> TranscribeAudioAsync(FileStream audio, AudioTranscriptionOptions options = null) + => await TranscribeAudioAsync(audio, Path.GetFileName(audio.Name), options).ConfigureAwait(false); + public virtual async Task> TranscribeAudioAsync(Stream audio, string filename, AudioTranscriptionOptions options = null) { Argument.AssertNotNull(audio, nameof(audio)); @@ -148,8 +150,9 @@ private PipelineMessage CreateCreateTranscriptionRequest(BinaryContent content, return message; } - // convenience method - sync; Stream overload - // TODO: add refdoc comment + public virtual ClientResult TranslateAudio(FileStream audio, AudioTranslationOptions options = null) + => TranslateAudio(audio, Path.GetFileName(audio.Name), options); + public virtual ClientResult TranslateAudio(Stream audio, string fileName, AudioTranslationOptions options = null) { Argument.AssertNotNull(audio, nameof(audio)); @@ -168,8 +171,9 @@ public virtual ClientResult TranslateAudio(Stream audio, strin return ClientResult.FromValue(value, response); } - // convenience method - async; Stream overload - // TODO: add refdoc comment + public virtual async Task> TranslateAudioAsync(FileStream audio, AudioTranslationOptions options = null) + => await TranslateAudioAsync(audio, Path.GetFileName(audio.Name), options).ConfigureAwait(false); + public virtual async Task> TranslateAudioAsync(Stream audio, string fileName, AudioTranslationOptions options = null) { Argument.AssertNotNull(audio, nameof(audio)); diff --git a/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs b/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs index 40318342f..e1a9e033e 100644 --- a/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs +++ b/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs @@ -15,30 +15,11 @@ public partial class AudioTranscriptionOptions public bool? EnableWordTimestamps { get; set; } public bool? EnableSegmentTimestamps { get; set; } - internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, string model) + internal MultipartFormDataBinaryContent ToMultipartContent(Stream file, string fileName, string model) { MultipartFormDataBinaryContent content = new(); - content.Add(fileStream, "file", fileName); - - AddContent(model, content); - - return content; - } - - internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData audioBytes, string fileName, string model) - { - MultipartFormDataBinaryContent content = new(); - - content.Add(audioBytes, "file", fileName); - - AddContent(model, content); - - return content; - } - - private void AddContent(string model, MultipartFormDataBinaryContent content) - { + content.Add(file, "file", fileName); content.Add(model, "model"); if (Language is not null) @@ -85,5 +66,7 @@ private void AddContent(string model, MultipartFormDataBinaryContent content) byte[] data = JsonSerializer.SerializeToUtf8Bytes(granularities); content.Add(data, "timestamp_granularities"); } + + return content; } } diff --git a/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs b/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs index b927043f9..1e9fbbd55 100644 --- a/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs +++ b/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs @@ -10,30 +10,11 @@ public partial class AudioTranslationOptions public AudioTranscriptionFormat? ResponseFormat { get; set; } public float? Temperature { get; set; } - internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, string model) + internal MultipartFormDataBinaryContent ToMultipartContent(Stream file, string fileName, string model) { MultipartFormDataBinaryContent content = new(); - content.Add(fileStream, "file", fileName); - - AddContent(model, content); - - return content; - } - - internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData audioBytes, string fileName, string model) - { - MultipartFormDataBinaryContent content = new(); - - content.Add(audioBytes, "file", fileName); - - AddContent(model, content); - - return content; - } - - private void AddContent(string model, MultipartFormDataBinaryContent content) - { + content.Add(file, "file", fileName); content.Add(model, "model"); if (Prompt is not null) @@ -54,5 +35,7 @@ private void AddContent(string model, MultipartFormDataBinaryContent content) content.Add(value, "response_format"); } + + return content; } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index 576bfc3ba..fa5db0992 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -37,8 +37,9 @@ public FileClient(ApiKeyCredential credential = default, OpenAIClientOptions opt _clientConnector = new(model: null, credential, options); } - // convenience method - sync; Stream overload - // TODO: add refdoc comment + public virtual ClientResult UploadFile(FileStream file, OpenAIFilePurpose purpose) + => UploadFile(file, Path.GetFileName(file.Name), purpose); + public virtual ClientResult UploadFile(Stream file, string fileName, OpenAIFilePurpose purpose) { Argument.AssertNotNull(file, nameof(file)); @@ -56,8 +57,9 @@ public virtual ClientResult UploadFile(Stream file, string fileN return ClientResult.FromValue(fileInfo, response); } - // convenience method - async; Stream overload - // TODO: add refdoc comment + public virtual async Task> UploadFileAsync(FileStream file, OpenAIFilePurpose purpose) + => await UploadFileAsync(file, Path.GetFileName(file.Name), purpose).ConfigureAwait(false); + public virtual async Task> UploadFileAsync(Stream file, string fileName, OpenAIFilePurpose purpose) { Argument.AssertNotNull(file, nameof(file)); diff --git a/.dotnet/src/Custom/Files/UploadFileOptions.cs b/.dotnet/src/Custom/Files/UploadFileOptions.cs index 4b3b6c2d1..bef736831 100644 --- a/.dotnet/src/Custom/Files/UploadFileOptions.cs +++ b/.dotnet/src/Custom/Files/UploadFileOptions.cs @@ -6,30 +6,12 @@ namespace OpenAI.Files; internal class UploadFileOptions { - internal static MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, OpenAIFilePurpose purpose) + internal static MultipartFormDataBinaryContent ToMultipartContent(Stream file, string fileName, OpenAIFilePurpose purpose) { MultipartFormDataBinaryContent content = new(); - content.Add(fileStream, "file", fileName); + content.Add(file, "file", fileName); - AddContent(purpose, content); - - return content; - } - - internal static MultipartFormDataBinaryContent ToMultipartContent(BinaryData fileData, string fileName, OpenAIFilePurpose purpose) - { - MultipartFormDataBinaryContent content = new(); - - content.Add(fileData, "file", fileName); - - AddContent(purpose, content); - - return content; - } - - private static void AddContent(OpenAIFilePurpose purpose, MultipartFormDataBinaryContent content) - { string purposeValue = purpose switch { OpenAIFilePurpose.FineTuning => "fine-tune", @@ -38,5 +20,7 @@ private static void AddContent(OpenAIFilePurpose purpose, MultipartFormDataBinar }; content.Add(purposeValue, "\"purpose\""); + + return content; } } diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 789fa8aa4..974643eac 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -116,8 +116,13 @@ public virtual async Task> GenerateImages return ClientResult.FromValue(new GeneratedImageCollection(images), response.GetRawResponse()); } - // convenience method - sync; Stream overload - // TODO: add refdoc comment + public virtual ClientResult GenerateImageEdits( + FileStream image, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + => GenerateImageEdits(image, Path.GetFileName(image.Name), prompt, imageCount, options); + public virtual ClientResult GenerateImageEdits( Stream image, string fileName, @@ -147,8 +152,13 @@ public virtual ClientResult GenerateImageEdits( return ClientResult.FromValue(value, response); } - // convenience method - async; Stream overload - // TODO: add refdoc comment + public virtual async Task> GenerateImageEditsAsync( + FileStream image, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + => await GenerateImageEditsAsync(image, Path.GetFileName(image.Name), prompt, imageCount, options).ConfigureAwait(false); + public virtual async Task> GenerateImageEditsAsync( Stream image, string fileName, @@ -178,8 +188,12 @@ public virtual async Task> GenerateImageE return ClientResult.FromValue(value, response); } - // convenience method - sync - // TODO: add refdoc comment + public virtual ClientResult GenerateImageVariations( + FileStream image, + int? imageCount = null, + ImageVariationOptions options = null) + => GenerateImageVariations(image, Path.GetFileName(image.Name), imageCount, options); + public virtual ClientResult GenerateImageVariations( Stream image, string fileName, @@ -202,8 +216,13 @@ public virtual ClientResult GenerateImageVariations( return ClientResult.FromValue(value, response); } - // convenience method - async; Stream overload - // TODO: add refdoc comment + + public virtual async Task> GenerateImageVariationsAsync( + FileStream image, + int? imageCount = null, + ImageVariationOptions options = null) + => await GenerateImageVariationsAsync(image, Path.GetFileName(image.Name), imageCount, options).ConfigureAwait(false); + public virtual async Task> GenerateImageVariationsAsync( Stream image, string fileName, diff --git a/.dotnet/src/Custom/Images/ImageEditOptions.cs b/.dotnet/src/Custom/Images/ImageEditOptions.cs index 5eb1830da..36b37c07a 100644 --- a/.dotnet/src/Custom/Images/ImageEditOptions.cs +++ b/.dotnet/src/Custom/Images/ImageEditOptions.cs @@ -28,7 +28,7 @@ public partial class ImageEditOptions /// public string User { get; set; } - internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, + internal MultipartFormDataBinaryContent ToMultipartContent(Stream image, string fileName, string prompt, string model, @@ -36,15 +36,7 @@ internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, { MultipartFormDataBinaryContent content = new(); - content.Add(fileStream, "image", fileName); - - AddContent(model, prompt, imageCount, content); - - return content; - } - - private void AddContent(string model, string prompt, int? imageCount, MultipartFormDataBinaryContent content) - { + content.Add(image, "image", fileName); content.Add(prompt, "prompt"); content.Add(model, "model"); @@ -90,5 +82,7 @@ private void AddContent(string model, string prompt, int? imageCount, MultipartF { content.Add(User, "user"); } + + return content; } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageVariationOptions.cs b/.dotnet/src/Custom/Images/ImageVariationOptions.cs index cb72dfcc7..7a04a9360 100644 --- a/.dotnet/src/Custom/Images/ImageVariationOptions.cs +++ b/.dotnet/src/Custom/Images/ImageVariationOptions.cs @@ -18,30 +18,11 @@ public partial class ImageVariationOptions /// public string User { get; set; } - internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, string model, int? imageCount) + internal MultipartFormDataBinaryContent ToMultipartContent(Stream image, string fileName, string model, int? imageCount) { MultipartFormDataBinaryContent content = new(); - content.Add(fileStream, "image", fileName); - - AddContent(model, imageCount, content); - - return content; - } - - internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData imageBytes, string fileName, string model, int? imageCount) - { - MultipartFormDataBinaryContent content = new(); - - content.Add(imageBytes, "image", fileName); - - AddContent(model, imageCount, content); - - return content; - } - - private void AddContent(string model, int? imageCount, MultipartFormDataBinaryContent content) - { + content.Add(image, "image", fileName); content.Add(model, "model"); if (imageCount is not null) @@ -81,5 +62,7 @@ private void AddContent(string model, int? imageCount, MultipartFormDataBinaryCo { content.Add(User, "user"); } + + return content; } } \ No newline at end of file From 6c0fafa36350c53c7db41d8bfea73f14dc26a8f3 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Thu, 21 Mar 2024 15:57:25 -0700 Subject: [PATCH 3/7] note --- .dotnet/src/Generated/Files.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs index f54d4b2ce..27ceed84d 100644 --- a/.dotnet/src/Generated/Files.cs +++ b/.dotnet/src/Generated/Files.cs @@ -564,6 +564,11 @@ public virtual ClientResult DownloadFile(string fileId, RequestOptions options) try { using PipelineMessage message = CreateDownloadFileRequest(fileId, options); + + // TODO: If we want the end-user to be able to Stream the response, we'll + // need to update this somehow to apply that pattern. Let's sync on the + // best approach for implementing this in this client. + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); } catch (Exception e) From 7e10734773d4000ee3c117b0d69c04dcf025c796 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Thu, 21 Mar 2024 16:10:36 -0700 Subject: [PATCH 4/7] nits --- .../Assistants/Sample01_RetrievalAugmentedGeneration.cs | 2 +- .../Sample01_RetrievalAugmentedGenerationAsync.cs | 2 +- .dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs | 4 ++-- .../tests/Samples/Images/Sample02_SimpleImageEditAsync.cs | 4 ++-- .../tests/Samples/Images/Sample03_SimpleImageVariation.cs | 4 ++-- .../Samples/Images/Sample03_SimpleImageVariationAsync.cs | 6 +++--- .dotnet/tests/TestScenarios/FileClientTests.cs | 5 +++-- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs index 557fe5b3d..c812e6f6f 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs @@ -20,7 +20,7 @@ public void Sample01_RetrievalAugmentedGeneration() AssistantClient assistantClient = openAIClient.GetAssistantClient(); // First, let's contrive a document we'll use retrieval with and upload it. - Stream document = BinaryData.FromString(""" + using Stream document = BinaryData.FromString(""" { "description": "This document contains the sale history data for Contoso products.", "sales": [ diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs index 277e75bb2..6943bf0a6 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs @@ -20,7 +20,7 @@ public async Task Sample01_RetrievalAugmentedGenerationAsync() AssistantClient assistantClient = openAIClient.GetAssistantClient(); // First, let's contrive a document we'll use retrieval with and upload it. - Stream document = BinaryData.FromString(""" + using Stream document = BinaryData.FromString(""" { "description": "This document contains the sale history data for Contoso products.", "sales": [ diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs index 01c2e21b6..89770b75d 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs @@ -14,7 +14,7 @@ public void Sample02_SimpleImageEdit() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "edit_sample_image.png"); - using Stream inputImage = File.OpenRead(imagePath); + using FileStream inputImage = File.OpenRead(imagePath); string prompt = "An inflatable flamingo float in a pool"; @@ -29,7 +29,7 @@ public void Sample02_SimpleImageEdit() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = client.GenerateImageEdits(inputImage, "edit_sample_image.png", prompt, 1, options); + GeneratedImageCollection imageCollection = client.GenerateImageEdits(inputImage, prompt, 1, options); using Stream editedImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index 7bb47257a..4d1b2a2bd 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -15,7 +15,7 @@ public async Task Sample02_SimpleImageEditAsync() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "edit_sample_image.png"); - using Stream inputImage = File.OpenRead(imagePath); + using FileStream inputImage = File.OpenRead(imagePath); string prompt = "An inflatable flamingo float in a pool"; @@ -30,7 +30,7 @@ public async Task Sample02_SimpleImageEditAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = await client.GenerateImageEditsAsync(inputImage, "edit_sample_image.png", prompt, 1, options); + GeneratedImageCollection imageCollection = await client.GenerateImageEditsAsync(inputImage, prompt, 1, options); using Stream editedImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs index 2b0ebb3ec..a05a4ea06 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs @@ -14,7 +14,7 @@ public void Sample03_SimpleImageVariation() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "variation_sample_image.png"); - using Stream inputImage = File.OpenRead(imagePath); + using FileStream inputImage = File.OpenRead(imagePath); ImageVariationOptions options = new() { @@ -22,7 +22,7 @@ public void Sample03_SimpleImageVariation() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = client.GenerateImageVariations(inputImage, "variation_sample_image.png", 1, options); + GeneratedImageCollection imageCollection = client.GenerateImageVariations(inputImage, 1, options); using Stream outputImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs index e0a0e7c24..f3388550c 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs @@ -15,7 +15,7 @@ public async Task Sample03_SimpleImageVariationAsync() ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string imagePath = Path.Combine("Assets", "variation_sample_image.png"); - using Stream inputImage = File.OpenRead(imagePath); + using FileStream inputImage = File.OpenRead(imagePath); ImageVariationOptions options = new() { @@ -23,11 +23,11 @@ public async Task Sample03_SimpleImageVariationAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = await client.GenerateImageVariationsAsync(inputImage, "variation_sample_image.png", 1, options); + GeneratedImageCollection imageCollection = await client.GenerateImageVariationsAsync(inputImage, 1, options); using Stream outputImage = imageCollection[0].Image; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - outputImage.CopyTo(stream); + await outputImage.CopyToAsync(stream); } } } diff --git a/.dotnet/tests/TestScenarios/FileClientTests.cs b/.dotnet/tests/TestScenarios/FileClientTests.cs index 5fab6936a..66ddc3301 100644 --- a/.dotnet/tests/TestScenarios/FileClientTests.cs +++ b/.dotnet/tests/TestScenarios/FileClientTests.cs @@ -26,7 +26,7 @@ public void ListFilesWorks() public void UploadFileWorks() { FileClient client = GetTestClient(); - Stream uploadData = BinaryData.FromString("hello, this is a text file, please delete me").ToStream(); + using Stream uploadData = BinaryData.FromString("hello, this is a text file, please delete me").ToStream(); ClientResult uploadResult = client.UploadFile(uploadData, "test-file-delete-me.txt", OpenAIFilePurpose.Assistants); Assert.That(uploadResult.Value, Is.Not.Null); @@ -45,7 +45,8 @@ public void DownloadAndInfoWork() Assert.That(fileInfoResult.Value, Is.Not.Null); ClientResult downloadResult = client.DownloadFile("file-S7roYWamZqfMK9D979HU4q6m"); - Assert.That(downloadResult.Value, Is.Not.Null); + using Stream value = downloadResult.Value; + Assert.That(value, Is.Not.Null); } private static FileClient GetTestClient() => GetTestClient(TestScenario.Files); From 428ddf208305dee7189e82042c45965fc51297d8 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 25 Mar 2024 09:48:32 -0700 Subject: [PATCH 5/7] nits --- .dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index 4d1b2a2bd..aade1b311 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -21,7 +21,7 @@ public async Task Sample02_SimpleImageEditAsync() string maskPath = Path.Combine("Assets", "edit_sample_mask.png"); using Stream mask = File.OpenRead(maskPath); - + ImageEditOptions options = new() { Mask = mask, From 716bbad998dbc7687c8e455d8d18ba297a3939fa Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 25 Mar 2024 10:16:45 -0700 Subject: [PATCH 6/7] Remove Streams from output APIs --- .dotnet/src/Custom/Files/FileClient.cs | 15 ++++++--------- .dotnet/src/Custom/Images/GeneratedImage.cs | 11 +++-------- .dotnet/src/Generated/Files.cs | 5 ----- .../Sample01_RetrievalAugmentedGeneration.cs | 4 ++-- .../Sample01_RetrievalAugmentedGenerationAsync.cs | 4 ++-- .../tests/Samples/Images/Sample01_SimpleImage.cs | 6 +++--- .../Samples/Images/Sample01_SimpleImageAsync.cs | 6 +++--- .../Samples/Images/Sample02_SimpleImageEdit.cs | 6 +++--- .../Images/Sample02_SimpleImageEditAsync.cs | 6 +++--- .../Images/Sample03_SimpleImageVariation.cs | 6 +++--- .../Images/Sample03_SimpleImageVariationAsync.cs | 6 +++--- .dotnet/tests/TestScenarios/FileClientTests.cs | 5 ++--- .../tests/TestScenarios/ImageGenerationTests.cs | 2 +- 13 files changed, 34 insertions(+), 48 deletions(-) diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index fa5db0992..6dbeb8bf8 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -123,11 +123,10 @@ public virtual async Task> GetFileInfoLis return ClientResult.FromValue(new OpenAIFileInfoCollection(infoItems), result.GetRawResponse()); } - public virtual ClientResult DownloadFile(string fileId) + public virtual ClientResult DownloadFile(string fileId) { - using PipelineMessage message = Shim.Pipeline.CreateMessage(); + PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; - message.BufferResponse = false; PipelineRequest request = message.Request; request.Method = "GET"; UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); @@ -143,13 +142,12 @@ public virtual ClientResult DownloadFile(string fileId) throw new ClientResultException(message.Response); } - PipelineResponse response = message.ExtractResponse(); - return ClientResult.FromValue(response.ContentStream, response); + return ClientResult.FromValue(message.Response.Content, message.Response); } - public virtual async Task> DownloadFileAsync(string fileId) + public virtual async Task> DownloadFileAsync(string fileId) { - using PipelineMessage message = Shim.Pipeline.CreateMessage(); + PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; PipelineRequest request = message.Request; request.Method = "GET"; @@ -167,8 +165,7 @@ public virtual async Task> DownloadFileAsync(string fileId) throw new ClientResultException(message.Response); } - PipelineResponse response = message.ExtractResponse(); - return ClientResult.FromValue(response.ContentStream, response); + return ClientResult.FromValue(message.Response.Content, message.Response); } public virtual void DeleteFile(string fileId) diff --git a/.dotnet/src/Custom/Images/GeneratedImage.cs b/.dotnet/src/Custom/Images/GeneratedImage.cs index 91f8c2bf6..4643ffc24 100644 --- a/.dotnet/src/Custom/Images/GeneratedImage.cs +++ b/.dotnet/src/Custom/Images/GeneratedImage.cs @@ -1,5 +1,4 @@ using System; -using System.IO; namespace OpenAI.Images; @@ -16,13 +15,13 @@ public class GeneratedImage /// This property is mutually exclusive with and will be null when the other /// is present. /// - public Stream Image { get; } + public BinaryData ImageBytes { get; } /// /// A temporary internet location for an image, provided by default or when /// is set to . /// /// - /// This property is mutually exclusive with and will be null when the other + /// This property is mutually exclusive with and will be null when the other /// is present. /// public Uri ImageUri { get; } @@ -42,11 +41,7 @@ public class GeneratedImage internal GeneratedImage(Internal.Models.ImagesResponse internalResponse, int internalDataIndex) { CreatedAt = internalResponse.Created; - - // TODO: Generator will need to update to make file streams Streams instead of BinaryData - // with this proposal. This is important if these files are going to be large, since - // BinaryData loads the buffers into memory, and this could be problematic for applications. - Image = internalResponse.Data[(int)internalDataIndex].B64Json.ToStream(); + ImageBytes = internalResponse.Data[(int)internalDataIndex].B64Json; RevisedPrompt = internalResponse.Data[(int)internalDataIndex].RevisedPrompt; ImageUri = internalResponse.Data[(int)internalDataIndex].Url; } diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs index 27ceed84d..f54d4b2ce 100644 --- a/.dotnet/src/Generated/Files.cs +++ b/.dotnet/src/Generated/Files.cs @@ -564,11 +564,6 @@ public virtual ClientResult DownloadFile(string fileId, RequestOptions options) try { using PipelineMessage message = CreateDownloadFileRequest(fileId, options); - - // TODO: If we want the end-user to be able to Stream the response, we'll - // need to update this somehow to apply that pattern. Let's sync on the - // best approach for implementing this in this client. - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); } catch (Exception e) diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs index c812e6f6f..bb67aed46 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs @@ -125,9 +125,9 @@ public void Sample01_RetrievalAugmentedGeneration() else if (contentItem is MessageImageFileContent imageFileContent) { OpenAIFileInfo imageInfo = fileClient.GetFileInfo(imageFileContent.FileId); - using Stream image = fileClient.DownloadFile(imageFileContent.FileId); + BinaryData imageBytes = fileClient.DownloadFile(imageFileContent.FileId); using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); - image.CopyTo(stream); + imageBytes.ToStream().CopyTo(stream); Console.WriteLine($""); } diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs index 6943bf0a6..061d0b3a1 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs @@ -125,9 +125,9 @@ public async Task Sample01_RetrievalAugmentedGenerationAsync() else if (contentItem is MessageImageFileContent imageFileContent) { OpenAIFileInfo imageInfo = await fileClient.GetFileInfoAsync(imageFileContent.FileId); - using Stream image = await fileClient.DownloadFileAsync(imageFileContent.FileId); + BinaryData imageBytes = await fileClient.DownloadFileAsync(imageFileContent.FileId); using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); - await image.CopyToAsync(stream); + await imageBytes.ToStream().CopyToAsync(stream); Console.WriteLine($""); } diff --git a/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs b/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs index c3dd67482..5a9dcccbb 100644 --- a/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs +++ b/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs @@ -29,11 +29,11 @@ public void Sample01_SimpleImage() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImage generatedImage = client.GenerateImage(prompt, options); - using Stream image = generatedImage.Image; + GeneratedImage image = client.GenerateImage(prompt, options); + BinaryData bytes = image.ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - image.CopyTo(stream); + bytes.ToStream().CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs b/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs index 425719fcb..16af4834a 100644 --- a/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs @@ -30,11 +30,11 @@ public async Task Sample01_SimpleImageAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImage generatedImage = await client.GenerateImageAsync(prompt, options); - using Stream image = generatedImage.Image; + GeneratedImage image = await client.GenerateImageAsync(prompt, options); + BinaryData bytes = image.ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - await image.CopyToAsync(stream); + bytes.ToStream().CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs index cb6c64c33..f91b77173 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs @@ -29,11 +29,11 @@ public void Sample02_SimpleImageEdit() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = client.GenerateImageEdits(inputImage, prompt, 1, options); - using Stream editedImage = imageCollection[0].Image; + GeneratedImageCollection images = client.GenerateImageEdits(inputImage, prompt, 1, options); + BinaryData bytes = images[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - editedImage.CopyTo(stream); + bytes.ToStream().CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index 9e145078b..315e1bf7f 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -30,11 +30,11 @@ public async Task Sample02_SimpleImageEditAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = await client.GenerateImageEditsAsync(inputImage, prompt, 1, options); - using Stream editedImage = imageCollection[0].Image; + GeneratedImageCollection images = await client.GenerateImageEditsAsync(inputImage, prompt, 1, options); + BinaryData bytes = images[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - await editedImage.CopyToAsync(stream); + await bytes.ToStream().CopyToAsync(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs index 203d3ea15..a590123ea 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs @@ -22,11 +22,11 @@ public void Sample03_SimpleImageVariation() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = client.GenerateImageVariations(inputImage, 1, options); - using Stream outputImage = imageCollection[0].Image; + GeneratedImageCollection images = client.GenerateImageVariations(inputImage, 1, options); + BinaryData bytes = images[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - outputImage.CopyTo(stream); + bytes.ToStream().CopyTo(stream); } } } diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs index 567d7eadb..58f708dde 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs @@ -23,11 +23,11 @@ public async Task Sample03_SimpleImageVariationAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection imageCollection = await client.GenerateImageVariationsAsync(inputImage, 1, options); - using Stream outputImage = imageCollection[0].Image; + GeneratedImageCollection images = await client.GenerateImageVariationsAsync(inputImage, 1, options); + BinaryData bytes = images[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); - await outputImage.CopyToAsync(stream); + bytes.ToStream().CopyTo(stream); } } } diff --git a/.dotnet/tests/TestScenarios/FileClientTests.cs b/.dotnet/tests/TestScenarios/FileClientTests.cs index 66ddc3301..c7c3875ae 100644 --- a/.dotnet/tests/TestScenarios/FileClientTests.cs +++ b/.dotnet/tests/TestScenarios/FileClientTests.cs @@ -44,9 +44,8 @@ public void DownloadAndInfoWork() ClientResult fileInfoResult = client.GetFileInfo("file-S7roYWamZqfMK9D979HU4q6m"); Assert.That(fileInfoResult.Value, Is.Not.Null); - ClientResult downloadResult = client.DownloadFile("file-S7roYWamZqfMK9D979HU4q6m"); - using Stream value = downloadResult.Value; - Assert.That(value, Is.Not.Null); + ClientResult downloadResult = client.DownloadFile("file-S7roYWamZqfMK9D979HU4q6m"); + Assert.That(downloadResult.Value, Is.Not.Null); } private static FileClient GetTestClient() => GetTestClient(TestScenario.Files); diff --git a/.dotnet/tests/TestScenarios/ImageGenerationTests.cs b/.dotnet/tests/TestScenarios/ImageGenerationTests.cs index 2a9a5805e..1d8d3304c 100644 --- a/.dotnet/tests/TestScenarios/ImageGenerationTests.cs +++ b/.dotnet/tests/TestScenarios/ImageGenerationTests.cs @@ -16,7 +16,7 @@ public void BasicGenerationWorks() Assert.That(result, Is.InstanceOf>()); Assert.That(result.Value.ImageUri, Is.Not.Null); Console.WriteLine(result.Value.ImageUri.AbsoluteUri); - Assert.That(result.Value.Image, Is.Null); + Assert.That(result.Value.ImageBytes, Is.Null); Assert.That(result.Value.CreatedAt, Is.GreaterThan(new DateTimeOffset(new DateTime(year: 2020, month: 1, day: 1)))); } From a55a3fdecfa933b9aa3d6be4e5f49a44e5a59b2b Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Thu, 28 Mar 2024 08:47:09 -0700 Subject: [PATCH 7/7] pr feedback --- .../tests/Samples/Images/Sample02_SimpleImageEdit.cs | 12 +++++++----- .../Samples/Images/Sample02_SimpleImageEditAsync.cs | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs index f91b77173..570e44829 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs @@ -13,23 +13,25 @@ public void Sample02_SimpleImageEdit() { ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - string imagePath = Path.Combine("Assets", "edit_sample_image.png"); - using FileStream inputImage = File.OpenRead(imagePath); + string imageFileName = "edit_sample_image.png"; + string imagePath = Path.Combine("Assets", imageFileName); + using Stream inputImage = File.OpenRead(imagePath); string prompt = "An inflatable flamingo float in a pool"; - string maskPath = Path.Combine("Assets", "edit_sample_mask.png"); + string maskFileName = "edit_sample_mask.png"; + string maskPath = Path.Combine("Assets", maskFileName); using Stream mask = File.OpenRead(maskPath); ImageEditOptions options = new() { Mask = mask, - MaskFileName = "edit_sample_mask.png", + MaskFileName = maskFileName, Size = GeneratedImageSize.W1024xH1024, ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection images = client.GenerateImageEdits(inputImage, prompt, 1, options); + GeneratedImageCollection images = client.GenerateImageEdits(inputImage, imageFileName, prompt, 1, options); BinaryData bytes = images[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index 315e1bf7f..e389c339a 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -14,23 +14,25 @@ public async Task Sample02_SimpleImageEditAsync() { ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - string imagePath = Path.Combine("Assets", "edit_sample_image.png"); - using FileStream inputImage = File.OpenRead(imagePath); + string imageFileName = "edit_sample_image.png"; + string imagePath = Path.Combine("Assets", imageFileName); + using Stream inputImage = File.OpenRead(imagePath); string prompt = "An inflatable flamingo float in a pool"; - string maskPath = Path.Combine("Assets", "edit_sample_mask.png"); + string maskFileName = "edit_sample_mask.png"; + string maskPath = Path.Combine("Assets", maskFileName); using Stream mask = File.OpenRead(maskPath); ImageEditOptions options = new() { Mask = mask, - MaskFileName = "edit_sample_mask.png", + MaskFileName = maskFileName, Size = GeneratedImageSize.W1024xH1024, ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection images = await client.GenerateImageEditsAsync(inputImage, prompt, 1, options); + GeneratedImageCollection images = await client.GenerateImageEditsAsync(inputImage, imageFileName, prompt, 1, options); BinaryData bytes = images[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png");