diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e7098ba..1c3c7b898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,21 @@ ### Features Added - Added the following model factories (static classes that can be used to instantiate OpenAI models for mocking in non-live test scenarios): - - `OpenAIAudioModelFactory` in the `OpenAI.Audio` namespace - - `OpenAIEmbeddingsModelFactory` in the `OpenAI.Embeddings` namespace - - `OpenAIFilesModelFactory` in the `OpenAI.Files` namespace - - `OpenAIImagesModelFactory` in the `OpenAI.Images` namespace - - `OpenAIModelsModelFactory` in the `OpenAI.Models` namespace - - `OpenAIModerationsModelFactory` in the `OpenAI.Moderations` namespace + - `OpenAIAudioModelFactory` in the `OpenAI.Audio` namespace (commit_hash) + - `OpenAIEmbeddingsModelFactory` in the `OpenAI.Embeddings` namespace (commit_hash) + - `OpenAIFilesModelFactory` in the `OpenAI.Files` namespace (commit_hash) + - `OpenAIImagesModelFactory` in the `OpenAI.Images` namespace (commit_hash) + - `OpenAIModelsModelFactory` in the `OpenAI.Models` namespace (commit_hash) + - `OpenAIModerationsModelFactory` in the `OpenAI.Moderations` namespace (commit_hash) ### Breaking Changes +- Removed client constructors that do not explicitly take an API key parameter or an endpoint via an `OpenAIClientOptions` parameter, making it clearer how to appropriately instantiate a client. (commit_hash) +- Removed the endpoint parameter from all client constructors, making it clearer that an alternative endpoint must be specified via the `OpenAIClientOptions` parameter. (commit_hash) +- Removed `OpenAIClient`'s `Endpoint` `protected` property. (commit_hash) +- Made `OpenAIClient`'s constructor that takes a `ClientPipeline` parameter `protected internal` instead of just `protected`. (commit_hash) +- Renamed the `User` property in applicable Options classes to `EndUserId`, making its purpose clearer. (commit_hash) + ### Bugs Fixed ### Other Changes diff --git a/api/OpenAI.netstandard2.0.cs b/api/OpenAI.netstandard2.0.cs index 9937bf300..2b3b9d35f 100644 --- a/api/OpenAI.netstandard2.0.cs +++ b/api/OpenAI.netstandard2.0.cs @@ -17,10 +17,9 @@ namespace OpenAI { } public class OpenAIClient { protected OpenAIClient(); - public OpenAIClient(OpenAIClientOptions options = null); - public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); - protected Uri Endpoint { get; } + public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions options); + public OpenAIClient(ApiKeyCredential credential); + protected internal OpenAIClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } public virtual AssistantClient GetAssistantClient(); public virtual AudioClient GetAudioClient(string model); @@ -63,9 +62,9 @@ public class Assistant : IJsonModel, IPersistableModel { } public class AssistantClient { protected AssistantClient(); - public AssistantClient(OpenAIClientOptions options = null); - public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected internal AssistantClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); + public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options); + public AssistantClient(ApiKeyCredential credential); + protected internal AssistantClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult CancelRun(ThreadRun run); [EditorBrowsable(EditorBrowsableState.Never)] @@ -982,9 +981,9 @@ public class VectorStoreCreationHelper : IJsonModel, namespace OpenAI.Audio { public class AudioClient { protected AudioClient(); - protected internal AudioClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options); - public AudioClient(string model, OpenAIClientOptions options = null); - public AudioClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null); + protected internal AudioClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); + public AudioClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); + public AudioClient(string model, ApiKeyCredential credential); public virtual ClientPipeline Pipeline { get; } [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GenerateSpeechFromText(BinaryContent content, RequestOptions options = null); @@ -1148,9 +1147,9 @@ public class SpeechGenerationOptions : IJsonModel, IPer namespace OpenAI.Batch { public class BatchClient { protected BatchClient(); - public BatchClient(OpenAIClientOptions options = null); - public BatchClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected internal BatchClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); + public BatchClient(ApiKeyCredential credential, OpenAIClientOptions options); + public BatchClient(ApiKeyCredential credential); + protected internal BatchClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult CancelBatch(string batchId, RequestOptions options); public virtual Task CancelBatchAsync(string batchId, RequestOptions options); @@ -1180,9 +1179,9 @@ public class AssistantChatMessage : ChatMessage, IJsonModel CompleteChat(params ChatMessage[] messages); [EditorBrowsable(EditorBrowsableState.Never)] @@ -1217,6 +1216,7 @@ public class ChatCompletion : IJsonModel, IPersistableModel, IPersistableModel { + public string EndUserId { get; set; } public float? FrequencyPenalty { get; set; } public ChatFunctionChoice FunctionChoice { get; set; } public IList Functions { get; } @@ -1233,7 +1233,6 @@ public class ChatCompletionOptions : IJsonModel, IPersist public IList Tools { get; } public int? TopLogProbabilityCount { get; set; } public float? TopP { get; set; } - public string User { get; set; } ChatCompletionOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); ChatCompletionOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); @@ -1557,9 +1556,9 @@ public class Embedding : IJsonModel, IPersistableModel { } public class EmbeddingClient { protected EmbeddingClient(); - protected internal EmbeddingClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options); - public EmbeddingClient(string model, OpenAIClientOptions options = null); - public EmbeddingClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null); + protected internal EmbeddingClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); + public EmbeddingClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); + public EmbeddingClient(string model, ApiKeyCredential credential); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult GenerateEmbedding(string input, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default); public virtual Task> GenerateEmbeddingAsync(string input, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default); @@ -1583,7 +1582,7 @@ public class EmbeddingCollection : ObjectModel.ReadOnlyCollection, IJ } public class EmbeddingGenerationOptions : IJsonModel, IPersistableModel { public int? Dimensions { get; set; } - public string User { get; set; } + public string EndUserId { get; set; } EmbeddingGenerationOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); EmbeddingGenerationOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); @@ -1608,23 +1607,19 @@ public static class OpenAIEmbeddingsModelFactory { namespace OpenAI.Files { public class FileClient { protected FileClient(); - public FileClient(OpenAIClientOptions options = null); - public FileClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected internal FileClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); + public FileClient(ApiKeyCredential credential, OpenAIClientOptions options); + public FileClient(ApiKeyCredential credential); + protected internal FileClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } - public virtual ClientResult DeleteFile(OpenAIFileInfo file); [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult DeleteFile(string fileId, RequestOptions options); public virtual ClientResult DeleteFile(string fileId, CancellationToken cancellationToken = default); - public virtual Task> DeleteFileAsync(OpenAIFileInfo file); [EditorBrowsable(EditorBrowsableState.Never)] public virtual Task DeleteFileAsync(string fileId, RequestOptions options); public virtual Task> DeleteFileAsync(string fileId, CancellationToken cancellationToken = default); - public virtual ClientResult DownloadFile(OpenAIFileInfo file); [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult DownloadFile(string fileId, RequestOptions options); public virtual ClientResult DownloadFile(string fileId, CancellationToken cancellationToken = default); - public virtual Task> DownloadFileAsync(OpenAIFileInfo file); [EditorBrowsable(EditorBrowsableState.Never)] public virtual Task DownloadFileAsync(string fileId, RequestOptions options); public virtual Task> DownloadFileAsync(string fileId, CancellationToken cancellationToken = default); @@ -1736,9 +1731,9 @@ public static class OpenAIFilesModelFactory { namespace OpenAI.FineTuning { public class FineTuningClient { protected FineTuningClient(); - public FineTuningClient(OpenAIClientOptions options = null); - public FineTuningClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected internal FineTuningClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); + public FineTuningClient(ApiKeyCredential credential, OpenAIClientOptions options); + public FineTuningClient(ApiKeyCredential credential); + protected internal FineTuningClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult CancelJob(string jobId, RequestOptions options); public virtual Task CancelJobAsync(string jobId, RequestOptions options); @@ -1806,9 +1801,9 @@ public enum GeneratedImageStyle { } public class ImageClient { protected ImageClient(); - protected internal ImageClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options); - public ImageClient(string model, OpenAIClientOptions options = null); - public ImageClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null); + protected internal ImageClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); + public ImageClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); + public ImageClient(string model, ApiKeyCredential credential); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult GenerateImage(string prompt, ImageGenerationOptions options = null, CancellationToken cancellationToken = default); public virtual Task> GenerateImageAsync(string prompt, ImageGenerationOptions options = null, CancellationToken cancellationToken = default); @@ -1852,9 +1847,9 @@ public class ImageClient { public virtual Task> GenerateImageVariationsAsync(string imageFilePath, int imageCount, ImageVariationOptions options = null); } public class ImageEditOptions : IJsonModel, IPersistableModel { + public string EndUserId { get; set; } public GeneratedImageFormat? ResponseFormat { get; set; } public GeneratedImageSize? Size { get; set; } - public string User { get; set; } ImageEditOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); ImageEditOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); @@ -1862,11 +1857,11 @@ public class ImageEditOptions : IJsonModel, IPersistableModel< BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); } public class ImageGenerationOptions : IJsonModel, IPersistableModel { + public string EndUserId { get; set; } public GeneratedImageQuality? Quality { get; set; } public GeneratedImageFormat? ResponseFormat { get; set; } public GeneratedImageSize? Size { get; set; } public GeneratedImageStyle? Style { get; set; } - public string User { get; set; } ImageGenerationOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); ImageGenerationOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); @@ -1874,9 +1869,9 @@ public class ImageGenerationOptions : IJsonModel, IPersi BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); } public class ImageVariationOptions : IJsonModel, IPersistableModel { + public string EndUserId { get; set; } public GeneratedImageFormat? ResponseFormat { get; set; } public GeneratedImageSize? Size { get; set; } - public string User { get; set; } ImageVariationOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); ImageVariationOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); @@ -1891,9 +1886,9 @@ public static class OpenAIImagesModelFactory { namespace OpenAI.Models { public class ModelClient { protected ModelClient(); - public ModelClient(OpenAIClientOptions options = null); - public ModelClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected internal ModelClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); + public ModelClient(ApiKeyCredential credential, OpenAIClientOptions options); + public ModelClient(ApiKeyCredential credential); + protected internal ModelClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult DeleteModel(string model, RequestOptions options); @@ -1975,9 +1970,9 @@ public class ModerationCategoryScores : IJsonModel, IP } public class ModerationClient { protected ModerationClient(); - protected internal ModerationClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options); - public ModerationClient(string model, OpenAIClientOptions options = null); - public ModerationClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null); + protected internal ModerationClient(ClientPipeline pipeline, string model, OpenAIClientOptions options); + public ModerationClient(string model, ApiKeyCredential credential, OpenAIClientOptions options); + public ModerationClient(string model, ApiKeyCredential credential); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult ClassifyTextInput(string input, CancellationToken cancellationToken = default); public virtual Task> ClassifyTextInputAsync(string input, CancellationToken cancellationToken = default); @@ -2084,9 +2079,9 @@ public class VectorStoreBatchFileJob : IJsonModel, IPer } public class VectorStoreClient { protected VectorStoreClient(); - public VectorStoreClient(OpenAIClientOptions options = null); - public VectorStoreClient(ApiKeyCredential credential, OpenAIClientOptions options = null); - protected internal VectorStoreClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options); + public VectorStoreClient(ApiKeyCredential credential, OpenAIClientOptions options); + public VectorStoreClient(ApiKeyCredential credential); + protected internal VectorStoreClient(ClientPipeline pipeline, OpenAIClientOptions options); public virtual ClientPipeline Pipeline { get; } public virtual ClientResult AddFileToVectorStore(VectorStore vectorStore, OpenAIFileInfo file); [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs b/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs index 549ea3db0..6d9117e9c 100644 --- a/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs +++ b/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs @@ -145,6 +145,6 @@ PageCollection messagePages // Optionally, delete any persistent resources you no longer need. _ = assistantClient.DeleteThread(threadRun.ThreadId); _ = assistantClient.DeleteAssistant(assistant); - _ = fileClient.DeleteFile(salesFile); + _ = fileClient.DeleteFile(salesFile.Id); } } diff --git a/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs b/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs index 83b95fb0e..13b49145a 100644 --- a/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs +++ b/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs @@ -146,6 +146,6 @@ AsyncPageCollection messagePages // Optionally, delete any persistent resources you no longer need. _ = await assistantClient.DeleteThreadAsync(threadRun.ThreadId); _ = await assistantClient.DeleteAssistantAsync(assistant); - _ = await fileClient.DeleteFileAsync(salesFile); + _ = await fileClient.DeleteFileAsync(salesFile.Id); } } diff --git a/examples/Assistants/Example04_AllTheTools.cs b/examples/Assistants/Example04_AllTheTools.cs index 3d55253d0..5a8943052 100644 --- a/examples/Assistants/Example04_AllTheTools.cs +++ b/examples/Assistants/Example04_AllTheTools.cs @@ -45,7 +45,7 @@ static string GetNameOfFamilyMember(string relation) }; #region Upload a mock file for use with file search - FileClient fileClient = new(); + FileClient fileClient = new(Environment.GetEnvironmentVariable("OPENAI_API_KEY")); OpenAIFileInfo favoriteNumberFile = fileClient.UploadFile( BinaryData.FromString(""" This file contains the favorite numbers for individuals. @@ -59,7 +59,7 @@ static string GetNameOfFamilyMember(string relation) #endregion #region Create an assistant with functions, file search, and code interpreter all enabled - AssistantClient client = new(); + AssistantClient client = new(Environment.GetEnvironmentVariable("OPENAI_API_KEY")); Assistant assistant = client.CreateAssistant("gpt-4-turbo", new AssistantCreationOptions() { Instructions = "Use functions to resolve family relations into the names of people. Use file search to " diff --git a/examples/Assistants/Example05_AssistantsWithVision.cs b/examples/Assistants/Example05_AssistantsWithVision.cs index 4d10c84cf..99315cdfb 100644 --- a/examples/Assistants/Example05_AssistantsWithVision.cs +++ b/examples/Assistants/Example05_AssistantsWithVision.cs @@ -65,7 +65,7 @@ public void Example05_AssistantsWithVision() } // Delete temporary resources, if desired - _ = fileClient.DeleteFile(pictureOfAppleFile); + _ = fileClient.DeleteFile(pictureOfAppleFile.Id); _ = assistantClient.DeleteThread(thread); _ = assistantClient.DeleteAssistant(assistant); } diff --git a/examples/Assistants/Example05_AssistantsWithVisionAsync.cs b/examples/Assistants/Example05_AssistantsWithVisionAsync.cs index 3f79137e8..db23818dd 100644 --- a/examples/Assistants/Example05_AssistantsWithVisionAsync.cs +++ b/examples/Assistants/Example05_AssistantsWithVisionAsync.cs @@ -65,7 +65,7 @@ public async Task Example05_AssistantsWithVisionAsync() } } - _ = await fileClient.DeleteFileAsync(pictureOfAppleFile); + _ = await fileClient.DeleteFileAsync(pictureOfAppleFile.Id); _ = await assistantClient.DeleteThreadAsync(thread); _ = await assistantClient.DeleteAssistantAsync(assistant); } diff --git a/examples/CombinationExamples.cs b/examples/CombinationExamples.cs index 31d5ef4cd..c4b460b1c 100644 --- a/examples/CombinationExamples.cs +++ b/examples/CombinationExamples.cs @@ -15,7 +15,7 @@ public partial class CombinationExamples public void AlpacaArtAssessor() { // First, we create an image using dall-e-3: - ImageClient imageClient = new("dall-e-3"); + ImageClient imageClient = new("dall-e-3", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); ClientResult imageResult = imageClient.GenerateImage( "a majestic alpaca on a mountain ridge, backed by an expansive blue sky accented with sparse clouds", new() @@ -28,7 +28,7 @@ public void AlpacaArtAssessor() Console.WriteLine($"Majestic alpaca available at:\n{imageGeneration.ImageUri.AbsoluteUri}"); // Now, we'll ask a cranky art critic to evaluate the image using gpt-4-vision-preview: - ChatClient chatClient = new("gpt-4-vision-preview"); + ChatClient chatClient = new("gpt-4o-mini", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); ChatCompletion chatCompletion = chatClient.CompleteChat( [ new SystemChatMessage("Assume the role of a cranky art critic. When asked to describe or " @@ -47,7 +47,7 @@ public void AlpacaArtAssessor() Console.WriteLine($"Art critique of majestic alpaca:\n{chatResponseText}"); // Finally, we'll get some text-to-speech for that critical evaluation using tts-1-hd: - AudioClient audioClient = new("tts-1-hd"); + AudioClient audioClient = new("tts-1-hd", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); ClientResult ttsResult = audioClient.GenerateSpeechFromText( text: chatResponseText, GeneratedSpeechVoice.Fable, @@ -69,7 +69,7 @@ public void AlpacaArtAssessor() public async Task CuriousCreatureCreator() { // First, we'll use gpt-4 to have a creative helper imagine a twist on a household pet - ChatClient creativeWriterClient = new("gpt-4"); + ChatClient creativeWriterClient = new("gpt-4o-mini", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); ClientResult creativeWriterResult = creativeWriterClient.CompleteChat( [ new SystemChatMessage("You're a creative helper that specializes in brainstorming designs for concepts that fuse ordinary, mundane items with a fantastical touch. In particular, you can provide good one-paragraph descriptions of concept images."), @@ -83,7 +83,7 @@ public async Task CuriousCreatureCreator() Console.WriteLine($"Creative helper's creature description:\n{description}"); // Asynchronously, in parallel to the next steps, we'll get the creative description in the voice of Onyx - AudioClient ttsClient = new("tts-1-hd"); + AudioClient ttsClient = new("tts-1-hd", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); Task> imageDescriptionAudioTask = ttsClient.GenerateSpeechFromTextAsync( description, GeneratedSpeechVoice.Onyx, @@ -103,7 +103,7 @@ public async Task CuriousCreatureCreator() }); // Meanwhile, we'll use dall-e-3 to generate a rendition of our LLM artist's vision - ImageClient imageGenerationClient = new("dall-e-3"); + ImageClient imageGenerationClient = new("dall-e-3", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); ClientResult imageGenerationResult = await imageGenerationClient.GenerateImageAsync( description, new ImageGenerationOptions() @@ -115,7 +115,7 @@ public async Task CuriousCreatureCreator() Console.WriteLine($"Creature image available at:\n{imageLocation.AbsoluteUri}"); // Now, we'll use gpt-4-vision-preview to get a hopelessly taken assessment from a usually exigent art connoisseur - ChatClient imageCriticClient = new("gpt-4-vision-preview"); + ChatClient imageCriticClient = new("gpt-4o-mini", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); ClientResult criticalAppraisalResult = await imageCriticClient.CompleteChatAsync( [ new SystemChatMessage("Assume the role of an art critic. Although usually cranky and occasionally even referred to as a 'curmudgeon', you're somehow entirely smitten with the subject presented to you and, despite your best efforts, can't help but lavish praise when you're asked to appraise a provided image."), diff --git a/src/Custom/Assistants/AssistantClient.cs b/src/Custom/Assistants/AssistantClient.cs index 3ca8be2f8..036f71be6 100644 --- a/src/Custom/Assistants/AssistantClient.cs +++ b/src/Custom/Assistants/AssistantClient.cs @@ -10,9 +10,7 @@ namespace OpenAI.Assistants; -/// -/// The service client for OpenAI assistants. -/// +/// The service client for OpenAI assistants operations. [Experimental("OPENAI001")] [CodeGenClient("Assistants")] [CodeGenSuppress("AssistantClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] @@ -32,47 +30,53 @@ public partial class AssistantClient private readonly InternalAssistantRunClient _runSubClient; private readonly InternalAssistantThreadClient _threadSubClient; - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public AssistantClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public AssistantClient(OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - { } - - /// Initializes a new instance of . - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - /// Client-wide options to propagate settings from. - protected internal AssistantClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options) { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + _messageSubClient = new(_pipeline, options); + _runSubClient = new(_pipeline, options); + _threadSubClient = new(_pipeline, options); + } + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal AssistantClient(ClientPipeline pipeline, OpenAIClientOptions options) + { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; - _messageSubClient = new(_pipeline, _endpoint, options); - _runSubClient = new(_pipeline, _endpoint, options); - _threadSubClient = new(_pipeline, _endpoint, options); + _endpoint = OpenAIClient.GetEndpoint(options); + _messageSubClient = new(_pipeline, options); + _runSubClient = new(_pipeline, options); + _threadSubClient = new(_pipeline, options); } /// Creates a new assistant. diff --git a/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs b/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs index baaf1a3af..625f36158 100644 --- a/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs +++ b/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs @@ -18,42 +18,46 @@ namespace OpenAI.Assistants; [CodeGenSuppress("DeleteMessage", typeof(string), typeof(string))] internal partial class InternalAssistantMessageClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public InternalAssistantMessageClient(ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public InternalAssistantMessageClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public InternalAssistantMessageClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public InternalAssistantMessageClient(OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - { } + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } - /// Initializes a new instance of . - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal InternalAssistantMessageClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal InternalAssistantMessageClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } } diff --git a/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs b/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs index 675133fa1..8b6474cfe 100644 --- a/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs +++ b/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs @@ -26,43 +26,46 @@ namespace OpenAI.Assistants; [CodeGenSuppress("GetRunStep", typeof(string), typeof(string), typeof(string))] internal partial class InternalAssistantRunClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public InternalAssistantRunClient(ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public InternalAssistantRunClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public InternalAssistantRunClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public InternalAssistantRunClient(OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - { } + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } - /// Initializes a new instance of . - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - /// Client-wide options to propagate settings from. - protected internal InternalAssistantRunClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal InternalAssistantRunClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } } diff --git a/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs b/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs index e99afc049..295a8a492 100644 --- a/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs +++ b/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs @@ -16,43 +16,46 @@ namespace OpenAI.Assistants; [CodeGenSuppress("DeleteThread", typeof(string))] internal partial class InternalAssistantThreadClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public InternalAssistantThreadClient(ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public InternalAssistantThreadClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public InternalAssistantThreadClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public InternalAssistantThreadClient(OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - { } + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } - /// Initializes a new instance of . - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - /// Client-wide options to propagate settings from. - protected internal InternalAssistantThreadClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal InternalAssistantThreadClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } } diff --git a/src/Custom/Audio/AudioClient.cs b/src/Custom/Audio/AudioClient.cs index bf5ab688b..fff3bc7db 100644 --- a/src/Custom/Audio/AudioClient.cs +++ b/src/Custom/Audio/AudioClient.cs @@ -7,6 +7,10 @@ namespace OpenAI.Audio; +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed methods that only take the options parameter. /// The service client for OpenAI audio operations. [CodeGenClient("Audio")] [CodeGenSuppress("AudioClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] @@ -22,71 +26,72 @@ public partial class AudioClient // CUSTOM: // - Added `model` parameter. - // - Added support for retrieving credential and endpoint from environment variables. - - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The model name to use for audio operations. - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public AudioClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - model, - OpenAIClient.GetEndpoint(options), - options) - { } - - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// The model name to use for audio operations. - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public AudioClient(string model, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - model, - OpenAIClient.GetEndpoint(options), - options) - { } + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public AudioClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions()) + { + } // CUSTOM: // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public AudioClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNullOrEmpty(model, nameof(model)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// Initializes a new instance of EmbeddingClient. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal AudioClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options) + _model = model; + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + protected internal AudioClient(ClientPipeline pipeline, string model, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); Argument.AssertNotNullOrEmpty(model, nameof(model)); + options ??= new OpenAIClientOptions(); - _pipeline = pipeline; _model = model; - _endpoint = endpoint; + _pipeline = pipeline; + _endpoint = OpenAIClient.GetEndpoint(options); } #region GenerateSpeech - /// - /// Generates text-to-speech audio using the specified voice speaking the provided input text. - /// + /// Generates a life-like, spoken audio recording of the input text. /// - /// The default format of the generated audio is unless otherwise specified - /// via . + /// The default format of the generated audio is unless otherwise specified + /// via . /// - /// The text for the voice to speak. - /// The voice to use. - /// Additional options to tailor the text-to-speech request. - /// A token that can be used to cancel this method call. + /// The text to generate audio for. + /// The voice to use in the generated audio. + /// The options to configure the audio generation. + /// A token that can be used to cancel this method call. + /// is null. /// The generated audio in the specified output format. public virtual async Task> GenerateSpeechFromTextAsync(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default) { @@ -100,17 +105,16 @@ public virtual async Task> GenerateSpeechFromTextAsync( return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } - /// - /// Generates text-to-speech audio using the specified voice speaking the provided input text. - /// + /// Generates a life-like, spoken audio recording of the input text. /// - /// The default format of the generated audio is unless otherwise specified - /// via . + /// The default format of the generated audio is unless otherwise specified + /// via . /// - /// The text for the voice to speak. - /// The voice to use. - /// Additional options to tailor the text-to-speech request. - /// A token that can be used to cancel this method call. + /// The text to generate audio for. + /// The voice to use in the generated audio. + /// The options to configure the audio generation. + /// A token that can be used to cancel this method call. + /// is null. /// The generated audio in the specified output format. public virtual ClientResult GenerateSpeechFromText(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default) { @@ -128,20 +132,17 @@ public virtual ClientResult GenerateSpeechFromText(string text, Gene #region TranscribeAudio - /// - /// Transcribes audio from a stream. - /// - /// The audio to transcribe. + /// Transcribes the input audio. + /// The audio stream to transcribe. /// - /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to - /// validate the format of the input audio. The request may fail if the file extension and input audio format do - /// not match. + /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to + /// validate the format of the input audio. The request may fail if the filename's extension and the actual + /// format of the input audio do not match. /// - /// Additional options to tailor the audio transcription request. - /// A token that can be used to cancel this method call. + /// The options to configure the audio transcription. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The audio transcription. public virtual async Task> TranscribeAudioAsync(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(audio, nameof(audio)); @@ -155,20 +156,17 @@ public virtual async Task> TranscribeAudioAsync return ClientResult.FromValue(AudioTranscription.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Transcribes audio from a stream. - /// - /// The audio to transcribe. + /// Transcribes the input audio. + /// The audio stream to transcribe. /// - /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to - /// validate the format of the input audio. The request may fail if the file extension and input audio format do - /// not match. + /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to + /// validate the format of the input audio. The request may fail if the filename's extension and the actual + /// format of the input audio do not match. /// - /// Additional options to tailor the audio transcription request. - /// A token that can be used to cancel this method call. + /// The options to configure the audio transcription. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The audio transcription. public virtual ClientResult TranscribeAudio(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(audio, nameof(audio)); @@ -182,18 +180,15 @@ public virtual ClientResult TranscribeAudio(Stream audio, st return ClientResult.FromValue(AudioTranscription.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Transcribes audio from a file with a known path. - /// + /// Transcribes the input audio. /// - /// The path of the audio file to transcribe. The provided file path's extension (for example: .mp3) will be used - /// to validate the format of the input audio. The request may fail if the file extension and input audio format - /// do not match. + /// The path of the audio file to transcribe. The provided file path's extension (for example: .mp3) will be + /// used to validate the format of the input audio. The request may fail if the file path's extension and the + /// actual format of the input audio do not match. /// - /// Additional options to tailor the audio transcription request. + /// The options to configure the audio transcription. /// is null. /// is an empty string, and was expected to be non-empty. - /// The audio transcription. public virtual async Task> TranscribeAudioAsync(string audioFilePath, AudioTranscriptionOptions options = null) { Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath)); @@ -202,18 +197,15 @@ public virtual async Task> TranscribeAudioAsync return await TranscribeAudioAsync(audioStream, audioFilePath, options).ConfigureAwait(false); } - /// - /// Transcribes audio from a file with a known path. - /// + /// Transcribes the input audio. /// - /// The path of the audio file to transcribe. The provided file path's extension (for example: .mp3) will be used - /// to validate the format of the input audio. The request may fail if the file extension and input audio format - /// do not match. + /// The path of the audio file to transcribe. The provided file path's extension (for example: .mp3) will be + /// used to validate the format of the input audio. The request may fail if the file path's extension and the + /// actual format of the input audio do not match. /// - /// Additional options to tailor the audio transcription request. + /// The options to configure the audio transcription. /// is null. /// is an empty string, and was expected to be non-empty. - /// The audio transcription. public virtual ClientResult TranscribeAudio(string audioFilePath, AudioTranscriptionOptions options = null) { Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath)); @@ -226,18 +218,17 @@ public virtual ClientResult TranscribeAudio(string audioFile #region TranslateAudio - /// Translates audio from a stream into English. - /// The audio to translate. + /// Translates the input audio into English. + /// The audio stream to translate. /// - /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to - /// validate the format of the input audio. The request may fail if the file extension and input audio format do - /// not match. + /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to + /// validate the format of the input audio. The request may fail if the filename's extension and the actual + /// format of the input audio do not match. /// - /// Additional options to tailor the audio translation request. - /// A token that can be used to cancel this method call. + /// The options to configure the audio translation. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The audio translation. public virtual async Task> TranslateAudioAsync(Stream audio, string audioFilename, AudioTranslationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(audio, nameof(audio)); @@ -251,18 +242,17 @@ public virtual async Task> TranslateAudioAsync(St return ClientResult.FromValue(AudioTranslation.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Translates audio from a stream into English. - /// The audio to translate. + /// Translates the input audio into English. + /// The audio stream to translate. /// - /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to - /// validate the format of the input audio. The request may fail if the file extension and input audio format do - /// not match. + /// The filename associated with the audio stream. The filename's extension (for example: .mp3) will be used to + /// validate the format of the input audio. The request may fail if the filename's extension and the actual + /// format of the input audio do not match. /// - /// Additional options to tailor the audio translation request. - /// A token that can be used to cancel this method call. + /// The options to configure the audio translation. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The audio translation. public virtual ClientResult TranslateAudio(Stream audio, string audioFilename, AudioTranslationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(audio, nameof(audio)); @@ -276,18 +266,15 @@ public virtual ClientResult TranslateAudio(Stream audio, strin return ClientResult.FromValue(AudioTranslation.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Translates audio from a file with a known path into English. - /// + /// Translates the input audio into English. /// - /// The path of the audio file to translate. The provided file path's extension (for example: .mp3) will be used - /// to validate the format of the input audio. The request may fail if the file extension and input audio format - /// do not match. + /// The path of the audio file to translate. The provided file path's extension (for example: .mp3) will be + /// used to validate the format of the input audio. The request may fail if the file path's extension and the + /// actual format of the input audio do not match. /// - /// Additional options to tailor the audio translation request. + /// The options to configure the audio translation. /// was null. /// is an empty string, and was expected to be non-empty. - /// The audio translation. public virtual ClientResult TranslateAudio(string audioFilePath, AudioTranslationOptions options = null) { Argument.AssertNotNullOrEmpty(audioFilePath, nameof(audioFilePath)); @@ -296,18 +283,15 @@ public virtual ClientResult TranslateAudio(string audioFilePat return TranslateAudio(audioStream, audioFilePath, options); } - /// - /// Translates audio from a file with a known path into English. - /// + /// Translates the input audio into English. /// - /// The path of the audio file to translate. The provided file path's extension (for example: .mp3) will be used - /// to validate the format of the input audio. The request may fail if the file extension and input audio format - /// do not match. + /// The path of the audio file to translate. The provided file path's extension (for example: .mp3) will be + /// used to validate the format of the input audio. The request may fail if the file path's extension and the + /// actual format of the input audio do not match. /// - /// Additional options to tailor the audio translation request. + /// The options to configure the audio translation. /// was null. /// is an empty string, and was expected to be non-empty. - /// The audio translation. public virtual async Task> TranslateAudioAsync(string audioFilePath, AudioTranslationOptions options = null) { Argument.AssertNotNull(audioFilePath, nameof(audioFilePath)); diff --git a/src/Custom/Batch/BatchClient.Protocol.cs b/src/Custom/Batch/BatchClient.Protocol.cs index 11cc1097c..525dce1ae 100644 --- a/src/Custom/Batch/BatchClient.Protocol.cs +++ b/src/Custom/Batch/BatchClient.Protocol.cs @@ -5,6 +5,8 @@ namespace OpenAI.Batch; +[CodeGenSuppress("RetrieveBatch", typeof(string), typeof(RequestOptions))] +[CodeGenSuppress("RetrieveBatchAsync", typeof(string), typeof(RequestOptions))] public partial class BatchClient { /// diff --git a/src/Custom/Batch/BatchClient.cs b/src/Custom/Batch/BatchClient.cs index adce1b0d1..f84fa5b74 100644 --- a/src/Custom/Batch/BatchClient.cs +++ b/src/Custom/Batch/BatchClient.cs @@ -2,62 +2,66 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; -using System.Threading.Tasks; namespace OpenAI.Batch; +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed convenience methods for now. +/// The service client for OpenAI batch operations. [CodeGenClient("Batches")] [CodeGenSuppress("BatchClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateBatch", typeof(string), typeof(InternalCreateBatchRequestEndpoint), typeof(InternalBatchCompletionTimeframe), typeof(IDictionary))] [CodeGenSuppress("CreateBatchAsync", typeof(string), typeof(InternalCreateBatchRequestEndpoint), typeof(InternalBatchCompletionTimeframe), typeof(IDictionary))] [CodeGenSuppress("RetrieveBatch", typeof(string))] [CodeGenSuppress("RetrieveBatchAsync", typeof(string))] -[CodeGenSuppress("RetrieveBatch", typeof(string), typeof(RequestOptions))] -[CodeGenSuppress("RetrieveBatchAsync", typeof(string), typeof(RequestOptions))] [CodeGenSuppress("CancelBatch", typeof(string))] [CodeGenSuppress("CancelBatchAsync", typeof(string))] [CodeGenSuppress("GetBatches", typeof(string), typeof(int?))] [CodeGenSuppress("GetBatchesAsync", typeof(string), typeof(int?))] public partial class BatchClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public BatchClient(ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public BatchClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public BatchClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public BatchClient(OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - { } + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } - /// - /// Initializes a new instance of . - /// - /// The client pipeline to use. - /// The endpoint to use. - protected internal BatchClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal BatchClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } } diff --git a/src/Custom/Chat/ChatClient.cs b/src/Custom/Chat/ChatClient.cs index 2f366b9a1..1eb1c0e1a 100644 --- a/src/Custom/Chat/ChatClient.cs +++ b/src/Custom/Chat/ChatClient.cs @@ -9,7 +9,13 @@ namespace OpenAI.Chat; +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed methods that only take the options parameter. +/// The service client for OpenAI chat operations. [CodeGenClient("Chat")] +[CodeGenSuppress("ChatClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateChatCompletionAsync", typeof(ChatCompletionOptions))] [CodeGenSuppress("CreateChatCompletion", typeof(ChatCompletionOptions))] public partial class ChatClient @@ -17,63 +23,72 @@ public partial class ChatClient private readonly string _model; private readonly OpenTelemetrySource _telemetry; - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The model name for chat completions that the client should use. - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - model, - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ChatClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions()) + { + } - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// The model name for chat completions that the client should use. - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public ChatClient(string model, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - model, - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Added telemetry support. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNullOrEmpty(model, nameof(model)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Initializes a new instance of . - /// - /// The instance to use. - /// The model name to use. - /// The endpoint to use. - protected internal ChatClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options) + _model = model; + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + _telemetry = new OpenTelemetrySource(model, _endpoint); + } + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Added telemetry support. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + protected internal ChatClient(ClientPipeline pipeline, string model, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); Argument.AssertNotNullOrEmpty(model, nameof(model)); + options ??= new OpenAIClientOptions(); _model = model; _pipeline = pipeline; - _endpoint = endpoint; - _telemetry = new OpenTelemetrySource(model, endpoint); + _endpoint = OpenAIClient.GetEndpoint(options); + _telemetry = new OpenTelemetrySource(model, _endpoint); } - /// - /// Generates a single chat completion result for a provided set of input chat messages. - /// - /// The messages to provide as input and history for chat completion. - /// Additional options for the chat completion request. - /// A token that can be used to cancel this method call. - /// A result for a single chat completion. + /// Generates a completion for the given chat. + /// The messages comprising the chat so far. + /// The options to configure the chat completion. + /// A token that can be used to cancel this method call. + /// is null. + /// is an empty collection, and was expected to be non-empty. public virtual async Task> CompleteChatAsync(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(messages, nameof(messages)); @@ -98,21 +113,12 @@ public virtual async Task> CompleteChatAsync(IEnume } } - /// - /// Generates a single chat completion result for a provided set of input chat messages. - /// - /// The messages to provide as input and history for chat completion. - /// A result for a single chat completion. - public virtual async Task> CompleteChatAsync(params ChatMessage[] messages) - => await CompleteChatAsync(messages, default(ChatCompletionOptions)).ConfigureAwait(false); - - /// - /// Generates a single chat completion result for a provided set of input chat messages. - /// - /// The messages to provide as input and history for chat completion. - /// Additional options for the chat completion request. - /// A token that can be used to cancel this method call. - /// A result for a single chat completion. + /// Generates a completion for the given chat. + /// The messages comprising the chat so far. + /// The options to configure the chat completion. + /// A token that can be used to cancel this method call. + /// is null. + /// is an empty collection, and was expected to be non-empty. public virtual ClientResult CompleteChat(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(messages, nameof(messages)); @@ -137,26 +143,33 @@ public virtual ClientResult CompleteChat(IEnumerable - /// Generates a single chat completion result for a provided set of input chat messages. - /// - /// The messages to provide as input and history for chat completion. - /// A result for a single chat completion. + /// Generates a completion for the given chat. + /// The messages comprising the chat so far. + /// is null. + /// is an empty collection, and was expected to be non-empty. + public virtual async Task> CompleteChatAsync(params ChatMessage[] messages) + => await CompleteChatAsync(messages, default(ChatCompletionOptions)).ConfigureAwait(false); + + /// Generates a completion for the given chat. + /// The messages comprising the chat so far. + /// is null. + /// is an empty collection, and was expected to be non-empty. public virtual ClientResult CompleteChat(params ChatMessage[] messages) => CompleteChat(messages, default(ChatCompletionOptions)); /// - /// Begins a streaming response for a chat completion request using the provided chat messages as input and - /// history. + /// Generates a completion for the given chat. The completion is streamed back token by token as it is being + /// generated by the model instead of waiting for it to be finished first. /// /// - /// can be enumerated over using the await foreach pattern using the - /// interface. + /// implements the interface and can be + /// enumerated over using the await foreach pattern. /// - /// The messages to provide as input for chat completion. - /// Additional options for the chat completion request. - /// A token that can be used to cancel this method call. - /// A streaming result with incremental chat completion updates. + /// The messages comprising the chat so far. + /// The options to configure the chat completion. + /// A token that can be used to cancel this method call. + /// is null. + /// is an empty collection, and was expected to be non-empty. public virtual AsyncCollectionResult CompleteChatStreamingAsync(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(messages, nameof(messages)); @@ -172,30 +185,18 @@ async Task getResultAsync() => } /// - /// Begins a streaming response for a chat completion request using the provided chat messages as input and - /// history. + /// Generates a completion for the given chat. The completion is streamed back token by token as it is being + /// generated by the model instead of waiting for it to be finished first. /// /// - /// can be enumerated over using the await foreach pattern using the - /// interface. + /// implements the interface and can be + /// enumerated over using the await foreach pattern. /// - /// The messages to provide as input for chat completion. - /// A streaming result with incremental chat completion updates. - public virtual AsyncCollectionResult CompleteChatStreamingAsync(params ChatMessage[] messages) - => CompleteChatStreamingAsync(messages, default(ChatCompletionOptions)); - - /// - /// Begins a streaming response for a chat completion request using the provided chat messages as input and - /// history. - /// - /// - /// can be enumerated over using the foreach pattern using the - /// interface. - /// - /// The messages to provide as input for chat completion. - /// Additional options for the chat completion request. - /// A token that can be used to cancel this method call. - /// A streaming result with incremental chat completion updates. + /// The messages comprising the chat so far. + /// The options to configure the chat completion. + /// A token that can be used to cancel this method call. + /// is null. + /// is an empty collection, and was expected to be non-empty. public virtual CollectionResult CompleteChatStreaming(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(messages, nameof(messages)); @@ -209,15 +210,30 @@ public virtual CollectionResult CompleteChatStrea } /// - /// Begins a streaming response for a chat completion request using the provided chat messages as input and - /// history. + /// Generates a completion for the given chat. The completion is streamed back token by token as it is being + /// generated by the model instead of waiting for it to be finished first. + /// + /// + /// implements the interface and can be + /// enumerated over using the await foreach pattern. + /// + /// The messages comprising the chat so far. + /// is null. + /// is an empty collection, and was expected to be non-empty. + public virtual AsyncCollectionResult CompleteChatStreamingAsync(params ChatMessage[] messages) + => CompleteChatStreamingAsync(messages, default(ChatCompletionOptions)); + + /// + /// Generates a completion for the given chat. The completion is streamed back token by token as it is being + /// generated by the model instead of waiting for it to be finished first. /// /// - /// can be enumerated over using the foreach pattern using the - /// interface. + /// implements the interface and can be + /// enumerated over using the await foreach pattern. /// - /// The messages to provide as input for chat completion. - /// A streaming result with incremental chat completion updates. + /// The messages comprising the chat so far. + /// is null. + /// is an empty collection, and was expected to be non-empty. public virtual CollectionResult CompleteChatStreaming(params ChatMessage[] messages) => CompleteChatStreaming(messages, default(ChatCompletionOptions)); diff --git a/src/Custom/Chat/ChatCompletionOptions.cs b/src/Custom/Chat/ChatCompletionOptions.cs index 77ef66507..e1d152936 100644 --- a/src/Custom/Chat/ChatCompletionOptions.cs +++ b/src/Custom/Chat/ChatCompletionOptions.cs @@ -102,6 +102,7 @@ public ChatCompletionOptions() [CodeGenMember("FunctionCall")] public ChatFunctionChoice FunctionChoice { get; set; } + // CUSTOM: Renamed. /// /// Whether to enable parallel function calling during tool use. /// @@ -110,4 +111,12 @@ public ChatCompletionOptions() /// [CodeGenMember("ParallelToolCalls")] public bool? ParallelToolCallsEnabled { get; set; } + + // CUSTOM: Renamed. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. + /// Learn more. + /// + [CodeGenMember("User")] + public string EndUserId { get; set; } } \ No newline at end of file diff --git a/src/Custom/Embeddings/EmbeddingClient.cs b/src/Custom/Embeddings/EmbeddingClient.cs index 2280c9b54..eae8dad2c 100644 --- a/src/Custom/Embeddings/EmbeddingClient.cs +++ b/src/Custom/Embeddings/EmbeddingClient.cs @@ -8,7 +8,11 @@ namespace OpenAI.Embeddings; -/// The service client for the OpenAI Embeddings endpoint. +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed methods that only take the options parameter. +/// The service client for OpenAI embedding operations. [CodeGenClient("Embeddings")] [CodeGenSuppress("EmbeddingClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateEmbeddingAsync", typeof(EmbeddingGenerationOptions))] @@ -19,63 +23,65 @@ public partial class EmbeddingClient // CUSTOM: // - Added `model` parameter. - // - Added support for retrieving credential and endpoint from environment variables. - - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The model name to use for audio operations. - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public EmbeddingClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - model, - OpenAIClient.GetEndpoint(options), - options) - {} - - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// The model name to use for audio operations. - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public EmbeddingClient(string model, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - model, - OpenAIClient.GetEndpoint(options), - options) - {} + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public EmbeddingClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions()) + { + } // CUSTOM: // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public EmbeddingClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNullOrEmpty(model, nameof(model)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// Initializes a new instance of EmbeddingClient. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal EmbeddingClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options) + _model = model; + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + protected internal EmbeddingClient(ClientPipeline pipeline, string model, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); Argument.AssertNotNullOrEmpty(model, nameof(model)); + options ??= new OpenAIClientOptions(); - _pipeline = pipeline; _model = model; - _endpoint = endpoint; + _pipeline = pipeline; + _endpoint = OpenAIClient.GetEndpoint(options); } // CUSTOM: Added to simplify generating a single embedding from a string input. - /// Creates an embedding vector representing the input text. - /// The string that will be turned into an embedding. - /// The to use. - /// A token that can be used to cancel this method call. + /// Generates an embedding representing the text input. + /// The text input to generate an embedding for. + /// The options to configure the embedding generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. public virtual async Task> GenerateEmbeddingAsync(string input, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default) @@ -91,10 +97,10 @@ public virtual async Task> GenerateEmbeddingAsync(string } // CUSTOM: Added to simplify generating a single embedding from a string input. - /// Creates an embedding vector representing the input text. - /// The string that will be turned into an embedding. - /// The to use. - /// A token that can be used to cancel this method call. + /// Generates an embedding representing the text input. + /// The text input to generate an embedding for. + /// The options to configure the embedding generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. public virtual ClientResult GenerateEmbedding(string input, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default) @@ -110,10 +116,10 @@ public virtual ClientResult GenerateEmbedding(string input, Embedding } // CUSTOM: Added to simplify passing the input as a collection of strings instead of BinaryData. - /// Creates an embedding vector representing the input text. - /// The strings that will be turned into embeddings. - /// The to use. - /// A token that can be used to cancel this method call. + /// Generates embeddings representing the text inputs. + /// The text inputs to generate embeddings for. + /// The options to configure the embedding generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty collection, and was expected to be non-empty. public virtual async Task> GenerateEmbeddingsAsync(IEnumerable inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default) @@ -130,10 +136,10 @@ public virtual async Task> GenerateEmbeddingsA } // CUSTOM: Added to simplify passing the input as a collection of strings instead of BinaryData. - /// Creates an embedding vector representing the input text. - /// The strings that will be turned into embeddings. - /// The to use. - /// A token that can be used to cancel this method call. + /// Generates embeddings representing the text inputs. + /// The text inputs to generate embeddings for. + /// The options to configure the embedding generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty collection, and was expected to be non-empty. public virtual ClientResult GenerateEmbeddings(IEnumerable inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default) @@ -149,10 +155,10 @@ public virtual ClientResult GenerateEmbeddings(IEnumerable< } // CUSTOM: Added to simplify passing the input as a collection of a collection of tokens instead of BinaryData. - /// Creates an embedding vector representing the input text. - /// The strings that will be turned into embeddings. - /// The to use. - /// A token that can be used to cancel this method call. + /// Generates embeddings representing the text inputs. + /// The text inputs to generate embeddings for. + /// The options to configure the embedding generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty collection, and was expected to be non-empty. public virtual async Task> GenerateEmbeddingsAsync(IEnumerable> inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default) @@ -168,10 +174,10 @@ public virtual async Task> GenerateEmbeddingsA } // CUSTOM: Added to simplify passing the input as a collection of a collection of tokens instead of BinaryData. - /// Creates an embedding vector representing the input text. - /// The strings that will be turned into embeddings. - /// The to use. - /// A token that can be used to cancel this method call. + /// Generates embeddings representing the text inputs. + /// The text inputs to generate embeddings for. + /// The options to configure the embedding generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty collection, and was expected to be non-empty. public virtual ClientResult GenerateEmbeddings(IEnumerable> inputs, EmbeddingGenerationOptions options = null, CancellationToken cancellationToken = default) diff --git a/src/Custom/Embeddings/EmbeddingGenerationOptions.cs b/src/Custom/Embeddings/EmbeddingGenerationOptions.cs index 0d3e807e6..0c3760797 100644 --- a/src/Custom/Embeddings/EmbeddingGenerationOptions.cs +++ b/src/Custom/Embeddings/EmbeddingGenerationOptions.cs @@ -86,4 +86,12 @@ public partial class EmbeddingGenerationOptions public EmbeddingGenerationOptions() { } + + // CUSTOM: Renamed. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. + /// Learn more. + /// + [CodeGenMember("User")] + public string EndUserId { get; set; } } \ No newline at end of file diff --git a/src/Custom/Files/FileClient.cs b/src/Custom/Files/FileClient.cs index 3b8f7c338..c18d8c713 100644 --- a/src/Custom/Files/FileClient.cs +++ b/src/Custom/Files/FileClient.cs @@ -7,9 +7,10 @@ namespace OpenAI.Files; -/// -/// The service client for OpenAI file operations. -/// +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +/// The service client for OpenAI file operations. [CodeGenClient("Files")] [CodeGenSuppress("FileClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateFileAsync", typeof(InternalFileUploadOptions))] @@ -24,70 +25,61 @@ namespace OpenAI.Files; [CodeGenSuppress("DownloadFile", typeof(string))] public partial class FileClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public FileClient(ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public FileClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) { } - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public FileClient(OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public FileClient(ApiKeyCredential credential, OpenAIClientOptions options) { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); } - /// - /// Initializes a new instance of . - /// - /// The client pipeline to use. - /// The endpoint to use. - protected internal FileClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal FileClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } - /// - /// Upload a file that can be used across various endpoints. The size of all the files uploaded by - /// one organization can be up to 100 GB. - /// - /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - /// the Assistants Tools guide to - /// learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. - /// - /// Please contact us if you need to increase these - /// storage limits. - /// - /// The file to upload. + /// Uploads a file that can be used across various operations. + /// Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. + /// The file stream to upload. /// - /// The filename associated with the file stream. The filename's extension (for example: .json) will be used to - /// validate the file format. The request may fail if the file extension and file format do not match. + /// The filename associated with the file stream. The filename's extension (for example: .json) will be used to + /// validate the file format. The request may fail if the filename's extension and the actual file format do + /// not match. /// /// The intended purpose of the uploaded file. - /// A token that can be used to cancel this method call. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Information about the uploaded file. public virtual async Task> UploadFileAsync(Stream file, string filename, FileUploadPurpose purpose, CancellationToken cancellationToken = default) { Argument.AssertNotNull(file, nameof(file)); @@ -103,27 +95,18 @@ public virtual async Task> UploadFileAsync(Stream f return ClientResult.FromValue(OpenAIFileInfo.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Upload a file that can be used across various endpoints. The size of all the files uploaded by - /// one organization can be up to 100 GB. - /// - /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - /// the Assistants Tools guide to - /// learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. - /// - /// Please contact us if you need to increase these - /// storage limits. - /// - /// The file to upload. + /// Uploads a file that can be used across various operations. + /// Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. + /// The file stream to upload. /// - /// The filename associated with the file stream. The filename's extension (for example: .json) will be used to - /// validate the file format. The request may fail if the file extension and file format do not match. + /// The filename associated with the file stream. The filename's extension (for example: .json) will be used to + /// validate the file format. The request may fail if the filename's extension and the actual file format do + /// not match. /// /// The intended purpose of the uploaded file. - /// A token that can be used to cancel this method call. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Information about the uploaded file. public virtual ClientResult UploadFile(Stream file, string filename, FileUploadPurpose purpose, CancellationToken cancellationToken = default) { Argument.AssertNotNull(file, nameof(file)); @@ -139,26 +122,17 @@ public virtual ClientResult UploadFile(Stream file, string filen return ClientResult.FromValue(OpenAIFileInfo.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Upload a file that can be used across various endpoints. The size of all the files uploaded by - /// one organization can be up to 100 GB. - /// - /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - /// the Assistants Tools guide to - /// learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. - /// - /// Please contact us if you need to increase these - /// storage limits. - /// - /// The file to upload. + /// Uploads a file that can be used across various operations. + /// Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. + /// The file bytes to upload. /// - /// The filename associated with the file binary data. The filename's extension (for example: .json) will be used to - /// validate the file format. The request may fail if the file extension and file format do not match. + /// The filename associated with the file bytes. The filename's extension (for example: .json) will be used to + /// validate the file format. The request may fail if the filename's extension and the actual file format do + /// not match. /// /// The intended purpose of the uploaded file. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Information about the uploaded file. public virtual Task> UploadFileAsync(BinaryData file, string filename, FileUploadPurpose purpose) { Argument.AssertNotNull(file, nameof(file)); @@ -167,26 +141,17 @@ public virtual Task> UploadFileAsync(BinaryData fil return UploadFileAsync(file?.ToStream(), filename, purpose); } - /// - /// Upload a file that can be used across various endpoints. The size of all the files uploaded by - /// one organization can be up to 100 GB. - /// - /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - /// the Assistants Tools guide to - /// learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. - /// - /// Please contact us if you need to increase these - /// storage limits. - /// - /// The file to upload. + /// Uploads a file that can be used across various operations. + /// Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. + /// The file bytes to upload. /// - /// The filename associated with the file binary data. The filename's extension (for example: .json) will be used to - /// validate the file format. The request may fail if the file extension and file format do not match. + /// The filename associated with the file bytes. The filename's extension (for example: .json) will be used to + /// validate the file format. The request may fail if the filename's extension and the actual file format do + /// not match. /// /// The intended purpose of the uploaded file. /// or is null. /// is an empty string, and was expected to be non-empty. - /// public virtual ClientResult UploadFile(BinaryData file, string filename, FileUploadPurpose purpose) { Argument.AssertNotNull(file, nameof(file)); @@ -195,25 +160,16 @@ public virtual ClientResult UploadFile(BinaryData file, string f return UploadFile(file?.ToStream(), filename, purpose); } - /// - /// Upload a file that can be used across various endpoints. The size of all the files uploaded by - /// one organization can be up to 100 GB. - /// - /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - /// the Assistants Tools guide to - /// learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. - /// - /// Please contact us if you need to increase these - /// storage limits. - /// + /// Uploads a file that can be used across various operations. + /// Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. /// - /// The path of the file to upload. The provided file path's extension (for example: .json) will be used - /// to validate the file format. The request may fail if the file extension and file format do not match. + /// The path of the file to upload. The provided file path's extension (for example: .json) will be used to + /// validate the file format. The request may fail if the file path's extension and the actual file format do + /// not match. /// /// The intended purpose of the uploaded file. /// was null. /// is an empty string, and was expected to be non-empty. - /// Information about the uploaded file. public virtual async Task> UploadFileAsync(string filePath, FileUploadPurpose purpose) { Argument.AssertNotNullOrEmpty(filePath, nameof(filePath)); @@ -222,25 +178,16 @@ public virtual async Task> UploadFileAsync(string f return await UploadFileAsync(stream, filePath, purpose).ConfigureAwait(false); } - /// - /// Upload a file that can be used across various endpoints. The size of all the files uploaded by - /// one organization can be up to 100 GB. - /// - /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - /// the Assistants Tools guide to - /// learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. - /// - /// Please contact us if you need to increase these - /// storage limits. - /// + /// Uploads a file that can be used across various operations. + /// Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. /// - /// The path of the file to upload. The provided file path's extension (for example: .json) will be used - /// to validate the file format. The request may fail if the file extension and file format do not match. + /// The path of the file to upload. The provided file path's extension (for example: .json) will be used to + /// validate the file format. The request may fail if the file path's extension and the actual file format do + /// not match. /// /// The intended purpose of the uploaded file. /// was null. /// is an empty string, and was expected to be non-empty. - /// Information about the uploaded file. public virtual ClientResult UploadFile(string filePath, FileUploadPurpose purpose) { Argument.AssertNotNullOrEmpty(filePath, nameof(filePath)); @@ -249,32 +196,29 @@ public virtual ClientResult UploadFile(string filePath, FileUplo return UploadFile(stream, filePath, purpose); } - /// Retrieves a list of files that belong to the user's organization. + /// Gets basic information about each of the files belonging to the user's organization. /// Only return files with the given purpose. - /// A token that can be used to cancel this method call. - /// Information about the files in the user's organization. + /// A token that can be used to cancel this method call. public virtual async Task> GetFilesAsync(OpenAIFilePurpose? purpose = null, CancellationToken cancellationToken = default) { ClientResult result = await GetFilesAsync(purpose?.ToString(), cancellationToken.ToRequestOptions()).ConfigureAwait(false); return ClientResult.FromValue(OpenAIFileInfoCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Retrieves a list of files that belong to the user's organization. + /// Gets basic information about each of the files belonging to the user's organization. /// Only return files with the given purpose. - /// A token that can be used to cancel this method call. - /// Information about the files in the user's organization. + /// A token that can be used to cancel this method call. public virtual ClientResult GetFiles(OpenAIFilePurpose? purpose = null, CancellationToken cancellationToken = default) { ClientResult result = GetFiles(purpose?.ToString(), cancellationToken.ToRequestOptions()); return ClientResult.FromValue(OpenAIFileInfoCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Retrieves information about a specified file. - /// The ID of the file to retrieve. - /// A token that can be used to cancel this method call. + /// Gets basic information about the specified file. + /// The ID of the desired file. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// Information about the specified file. public virtual async Task> GetFileAsync(string fileId, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); @@ -283,12 +227,11 @@ public virtual async Task> GetFileAsync(string file return ClientResult.FromValue(OpenAIFileInfo.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Retrieves information about a specified file. - /// The ID of the file to retrieve. - /// A token that can be used to cancel this method call. + /// Gets basic information about the specified file. + /// The ID of the desired file. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// Information about the specified file. public virtual ClientResult GetFile(string fileId, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); @@ -297,12 +240,11 @@ public virtual ClientResult GetFile(string fileId, CancellationT return ClientResult.FromValue(OpenAIFileInfo.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Deletes a previously uploaded file. + /// Deletes the specified file. /// The ID of the file to delete. - /// A token that can be used to cancel this method call. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// A boolean value indicating whether the deletion request was successful. public virtual async Task> DeleteFileAsync(string fileId, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); @@ -312,12 +254,11 @@ public virtual async Task> DeleteFileAsync(string fileId, Can return ClientResult.FromValue(internalDeletion.Deleted, result.GetRawResponse()); } - /// Deletes a previously uploaded file. + /// Deletes the specified file. /// The ID of the file to delete. - /// A token that can be used to cancel this method call. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// A boolean value indicating whether the deletion request was successful. public virtual ClientResult DeleteFile(string fileId, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); @@ -327,32 +268,11 @@ public virtual ClientResult DeleteFile(string fileId, CancellationToken ca return ClientResult.FromValue(internalDeletion.Deleted, result.GetRawResponse()); } - /// Deletes a previously uploaded file. - /// The file to delete. - /// is null. - /// A boolean value indicating whether the deletion request was successful. - public virtual Task> DeleteFileAsync(OpenAIFileInfo file) - { - Argument.AssertNotNull(file, nameof(file)); - return DeleteFileAsync(file.Id); - } - - /// Deletes a previously uploaded file. - /// The file to delete. - /// is null. - /// A boolean value indicating whether the deletion request was successful. - public virtual ClientResult DeleteFile(OpenAIFileInfo file) - { - Argument.AssertNotNull(file.Id, nameof(file)); - return DeleteFile(file.Id); - } - - /// Downloads the binary content of the specified file. + /// Downloads the content of the specified file. /// The ID of the file to download. - /// A token that can be used to cancel this method call. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// The contents of the specified file. public virtual async Task> DownloadFileAsync(string fileId, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); @@ -361,12 +281,11 @@ public virtual async Task> DownloadFileAsync(string fil return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } - /// Downloads the binary content of the specified file. + /// Downloads the content of the specified file. /// The ID of the file to download. - /// A token that can be used to cancel this method call. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// The bionary content of the specified file. public virtual ClientResult DownloadFile(string fileId, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); @@ -374,24 +293,4 @@ public virtual ClientResult DownloadFile(string fileId, Cancellation ClientResult result = DownloadFile(fileId, cancellationToken.ToRequestOptions()); return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } - - /// Downloads the binary content of the specified file. - /// The file to download. - /// is null. - /// The binary content of the uploaded file. - public virtual Task> DownloadFileAsync(OpenAIFileInfo file) - { - Argument.AssertNotNull(file, nameof(file)); - return DownloadFileAsync(file.Id); - } - - /// Downloads the binary content of the specified file. - /// The file to download. - /// is null. - /// The binary content of the uploaded file. - public virtual ClientResult DownloadFile(OpenAIFileInfo file) - { - Argument.AssertNotNull(file, nameof(file)); - return DownloadFile(file.Id); - } } diff --git a/src/Custom/FineTuning/FineTuningClient.cs b/src/Custom/FineTuning/FineTuningClient.cs index 6313c783f..0d4ff991f 100644 --- a/src/Custom/FineTuning/FineTuningClient.cs +++ b/src/Custom/FineTuning/FineTuningClient.cs @@ -4,10 +4,13 @@ namespace OpenAI.FineTuning; -/// -/// The service client for OpenAI fine-tuning operations. -/// +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed convenience methods for now. +/// The service client for OpenAI fine-tuning operations. [CodeGenClient("FineTuning")] +[CodeGenSuppress("FineTuningClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateFineTuningJobAsync", typeof(InternalCreateFineTuningJobRequest))] [CodeGenSuppress("CreateFineTuningJob", typeof(InternalCreateFineTuningJobRequest))] [CodeGenSuppress("GetPaginatedFineTuningJobsAsync", typeof(string), typeof(int?))] @@ -22,44 +25,46 @@ namespace OpenAI.FineTuning; [CodeGenSuppress("GetFineTuningJobCheckpoints", typeof(string), typeof(string), typeof(int?))] public partial class FineTuningClient { - // Customization: documented constructors, apply protected visibility + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public FineTuningClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public FineTuningClient(ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public FineTuningClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public FineTuningClient(OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - {} + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } - /// Initializes a new instance of FineTuningClient. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal FineTuningClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal FineTuningClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } } diff --git a/src/Custom/Images/ImageClient.cs b/src/Custom/Images/ImageClient.cs index 7f57dd889..b7efdd384 100644 --- a/src/Custom/Images/ImageClient.cs +++ b/src/Custom/Images/ImageClient.cs @@ -8,6 +8,10 @@ namespace OpenAI.Images; +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed methods that only take the options parameter. /// The service client for OpenAI image operations. [CodeGenClient("Images")] [CodeGenSuppress("ImageClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] @@ -23,69 +27,68 @@ public partial class ImageClient // CUSTOM: // - Added `model` parameter. - // - Added support for retrieving credential and endpoint from environment variables. - - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The model name to use for image operations. - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public ImageClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - model, - OpenAIClient.GetEndpoint(options), - options) - { } - - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// The model name to use for image operations. - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public ImageClient(string model, OpenAIClientOptions options = default) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - model, - OpenAIClient.GetEndpoint(options), - options) - { } + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ImageClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions()) + { + } // CUSTOM: // - Added `model` parameter. - - /// Initializes a new instance of EmbeddingClient. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal ImageClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options) + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ImageClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) { Argument.AssertNotNullOrEmpty(model, nameof(model)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - _pipeline = pipeline; _model = model; - _endpoint = endpoint; + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + protected internal ImageClient(ClientPipeline pipeline, string model, OpenAIClientOptions options) + { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); + options ??= new OpenAIClientOptions(); + + _model = model; + _pipeline = pipeline; + _endpoint = OpenAIClient.GetEndpoint(options); } #region GenerateImages - /// - /// Generates an image based on a given prompt. - /// + /// Generates an image based on a prompt. /// A text description of the desired image. - /// Additional options to tailor the image generation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// The generated image. public virtual async Task> GenerateImageAsync(string prompt, ImageGenerationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(prompt, nameof(prompt)); @@ -98,15 +101,12 @@ public virtual async Task> GenerateImageAsync(strin return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// - /// Generates an image based on a given prompt. - /// + /// Generates an image based on a prompt. /// A text description of the desired image. - /// Additional options to tailor the image generation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// The generated image. public virtual ClientResult GenerateImage(string prompt, ImageGenerationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(prompt, nameof(prompt)); @@ -119,16 +119,13 @@ public virtual ClientResult GenerateImage(string prompt, ImageGe return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// - /// Generates images based on a given prompt. - /// + /// Generates images based on a prompt. /// A text description of the desired images. /// The number of images to generate. - /// Additional options to tailor the image generation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// The generated images. public virtual async Task> GenerateImagesAsync(string prompt, int imageCount, ImageGenerationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(prompt, nameof(prompt)); @@ -141,16 +138,13 @@ public virtual async Task> GenerateImages return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Generates images based on a given prompt. - /// + /// Generates images based on a prompt. /// A text description of the desired images. /// The number of images to generate. - /// Additional options to tailor the image generation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image generation. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. - /// The generated images. public virtual ClientResult GenerateImages(string prompt, int imageCount, ImageGenerationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(prompt, nameof(prompt)); @@ -167,22 +161,21 @@ public virtual ClientResult GenerateImages(string prom #region GenerateImageEdits - /// Generates an edited or extended image given an original image and a prompt. + /// Generates an edited or extended image based on an original image and a prompt. /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which - /// will be used as the mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which + /// will be used as the mask. /// /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual async Task> GenerateImageEditAsync(Stream image, string imageFilename, string prompt, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -197,22 +190,21 @@ public virtual async Task> GenerateImageEditAsync(S return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// Generates an edited or extended image given an original image and a prompt. + /// Generates an edited or extended image based on an original image and a prompt. /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which - /// will be used as the mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which + /// will be used as the mask. /// /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual ClientResult GenerateImageEdit(Stream image, string imageFilename, string prompt, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -227,18 +219,17 @@ public virtual ClientResult GenerateImageEdit(Stream image, stri return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// Generates an edited or extended image given an original image and a prompt. + /// Generates an edited or extended image based on an original image and a prompt. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must have - /// transparency, which will be used as the mask. The provided file path's extension (for example: .png) will be - /// used to validate the format of the input image. The request may fail if the file extension and input image - /// format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must + /// have transparency, which will be used as the mask. The provided file path's extension (for example: .png) + /// will be used to validate the format of the input image. The request may fail if the file path's extension + /// and the actual format of the input image do not match. /// /// A text description of the desired image. - /// Additional options to tailor the image edit request. + /// The options to configure the image edit. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual async Task> GenerateImageEditAsync(string imageFilePath, string prompt, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -248,18 +239,17 @@ public virtual async Task> GenerateImageEditAsync(s return await GenerateImageEditAsync(imageStream, imageFilePath, prompt, options).ConfigureAwait(false); } - /// Generates an edited or extended image given an original image and a prompt. + /// Generates an edited or extended image based on an original image and a prompt. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must have - /// transparency, which will be used as the mask. The provided file path's extension (for example: .png) will be - /// used to validate the format of the input image. The request may fail if the file extension and input image - /// format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must + /// have transparency, which will be used as the mask. The provided file path's extension (for example: .png) + /// will be used to validate the format of the input image. The request may fail if the file path's extension + /// and the actual format of the input image do not match. /// /// A text description of the desired image. - /// Additional options to tailor the image edit request. + /// The options to configure the image edit. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual ClientResult GenerateImageEdit(string imageFilePath, string prompt, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -269,30 +259,27 @@ public virtual ClientResult GenerateImageEdit(string imageFilePa return GenerateImageEdit(imageStream, imageFilePath, prompt,options); } - /// Generates an edited or extended image given an original image, a prompt, and a mask. - /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. - /// + /// Generates an edited or extended image based on an original image, a prompt, and a mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. /// - /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where the original image - /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. + /// An additional image whose fully transparent areas (i.e., where alpha is zero) indicate where the original image + /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. /// /// - /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the mask image. The request may fail if the file extension and mask image format - /// do not match. + /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be + /// used to validate the format of the mask image. The request may fail if the filename's extension and the + /// actual format of the mask image do not match. /// - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , , , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual async Task> GenerateImageEditAsync(Stream image, string imageFilename, string prompt, Stream mask, string maskFilename, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -309,30 +296,27 @@ public virtual async Task> GenerateImageEditAsync(S return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// Generates an edited or extended image given an original image, a prompt, and a mask. - /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. - /// + /// Generates an edited or extended image based on an original image, a prompt, and a mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. /// - /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where the original image - /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. + /// An additional image whose fully transparent areas (i.e., where alpha is zero) indicate where the original image + /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. /// /// - /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the mask image. The request may fail if the file extension and mask image format - /// do not match. + /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be + /// used to validate the format of the mask image. The request may fail if the filename's extension and the + /// actual format of the mask image do not match. /// - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , , , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual ClientResult GenerateImageEdit(Stream image, string imageFilename, string prompt, Stream mask, string maskFilename, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -349,23 +333,23 @@ public virtual ClientResult GenerateImageEdit(Stream image, stri return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// Generates an edited or extended image given an original image, a prompt, and a mask. + /// Generates an edited or extended image based on an original image, a prompt, and a mask. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file - /// path's extension (for example: .png) will be used to validate the format of the input image. The request may - /// fail if the file extension and input image format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file + /// path's extension (for example: .png) will be used to validate the format of the input image. The request + /// may fail if the file path's extension and the actual format of the input image do not match. /// /// A text description of the desired image. /// - /// The path of the mask image file whose fully transparent areas (e.g. where alpha is zero) indicate where the - /// original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as the - /// original image. The provided file path's extension (for example: .png) will be used to validate the format of - /// the input image. The request may fail if the file extension and mask image format do not match. + /// The path of the mask image file whose fully transparent areas (i.e., where alpha is zero) indicate where + /// the original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as the original image. The provided file path's extension (for example: .png) will be used to validate the + /// format of the mask image. The request may fail if the file path's extension and the actual format of the + /// mask image do not match. /// - /// Additional options to tailor the image edit request. + /// The options to configure the image edit. /// , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual async Task> GenerateImageEditAsync(string imageFilePath, string prompt, string maskFilePath, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -377,23 +361,23 @@ public virtual async Task> GenerateImageEditAsync(s return await GenerateImageEditAsync(imageStream, imageFilePath, prompt, maskStream, maskFilePath, options).ConfigureAwait(false); } - /// Generates an edited or extended image given an original image, a prompt, and a mask. + /// Generates an edited or extended image based on an original image, a prompt, and a mask. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file - /// path's extension (for example: .png) will be used to validate the format of the input image. The request may - /// fail if the file extension and input image format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file + /// path's extension (for example: .png) will be used to validate the format of the input image. The request + /// may fail if the file path's extension and the actual format of the input image do not match. /// /// A text description of the desired image. /// - /// The path of the mask image file whose fully transparent areas (e.g. where alpha is zero) indicate where the - /// original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as the - /// original image. The provided file path's extension (for example: .png) will be used to validate the format of - /// the input image. The request may fail if the file extension and mask image format do not match. + /// The path of the mask image file whose fully transparent areas (i.e., where alpha is zero) indicate where + /// the original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as the original image. The provided file path's extension (for example: .png) will be used to validate the + /// format of the mask image. The request may fail if the file path's extension and the actual format of the + /// mask image do not match. /// - /// Additional options to tailor the image edit request. + /// The options to configure the image edit. /// , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended image. public virtual ClientResult GenerateImageEdit(string imageFilePath, string prompt, string maskFilePath, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -405,23 +389,22 @@ public virtual ClientResult GenerateImageEdit(string imageFilePa return GenerateImageEdit(imageStream, imageFilePath, prompt, maskStream, maskFilePath, options); } - /// Generates edited or extended images given an original image and a prompt. + /// Generates edited or extended images based on an original image and a prompt. /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which - /// will be used as the mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which + /// will be used as the mask. /// /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The number of edited or extended images to generate. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual async Task> GenerateImageEditsAsync(Stream image, string imageFilename, string prompt, int imageCount, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -436,23 +419,22 @@ public virtual async Task> GenerateImageE return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Generates edited or extended images given an original image and a prompt. + /// Generates edited or extended images based on an original image and a prompt. /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which - /// will be used as the mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. The image must have transparency, which + /// will be used as the mask. /// /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The number of edited or extended images to generate. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual ClientResult GenerateImageEdits(Stream image, string imageFilename, string prompt, int imageCount, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -467,19 +449,18 @@ public virtual ClientResult GenerateImageEdits(Stream return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Generates edited or extended images given an original image and a prompt. + /// Generates edited or extended images based on an original image and a prompt. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must have - /// transparency, which will be used as the mask. The provided file path's extension (for example: .png) will be - /// used to validate the format of the input image. The request may fail if the file extension and input image - /// format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must + /// have transparency, which will be used as the mask. The provided file path's extension (for example: .png) + /// will be used to validate the format of the input image. The request may fail if the file path's extension + /// and the actual format of the input image do not match. /// /// A text description of the desired image. - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. + /// The number of edited or extended images to generate. + /// The options to configure the image edit. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual async Task> GenerateImageEditsAsync(string imageFilePath, string prompt, int imageCount, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -489,19 +470,18 @@ public virtual async Task> GenerateImageE return await GenerateImageEditsAsync(imageStream, imageFilePath, prompt, imageCount, options).ConfigureAwait(false); } - /// Generates edited or extended images given an original image and a prompt. + /// Generates edited or extended images based on an original image and a prompt. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must have - /// transparency, which will be used as the mask. The provided file path's extension (for example: .png) will be - /// used to validate the format of the input image. The request may fail if the file extension and input image - /// format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The image must + /// have transparency, which will be used as the mask. The provided file path's extension (for example: .png) + /// will be used to validate the format of the input image. The request may fail if the file path's extension + /// and the actual format of the input image do not match. /// /// A text description of the desired image. - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. + /// The number of edited or extended images to generate. + /// The options to configure the image edit. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual ClientResult GenerateImageEdits(string imageFilePath, string prompt, int imageCount, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -511,31 +491,28 @@ public virtual ClientResult GenerateImageEdits(string return GenerateImageEdits(imageStream, imageFilePath, prompt, imageCount, options); } - /// Generates edited or extended images given an original image, a prompt, and a mask. - /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. - /// + /// Generates edited or extended images based on an original image, a prompt, and a mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. /// - /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where the original image - /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. + /// An additional image whose fully transparent areas (i.e., where alpha is zero) indicate where the original image + /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. /// /// - /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the mask image. The request may fail if the file extension and mask image format - /// do not match. + /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be + /// used to validate the format of the mask image. The request may fail if the filename's extension and the + /// actual format of the mask image do not match. /// - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The number of edited or extended images to generate. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , , , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual async Task> GenerateImageEditsAsync(Stream image, string imageFilename, string prompt, Stream mask, string maskFilename, int imageCount, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -552,31 +529,28 @@ public virtual async Task> GenerateImageE return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Generates edited or extended images given an original image, a prompt, and a mask. - /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. - /// + /// Generates edited or extended images based on an original image, a prompt, and a mask. + /// The image stream to edit. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// A text description of the desired image. /// - /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where the original image - /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. + /// An additional image whose fully transparent areas (i.e., where alpha is zero) indicate where the original image + /// should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. /// /// - /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the mask image. The request may fail if the file extension and mask image format - /// do not match. + /// The filename associated with the mask image stream. The filename's extension (for example: .png) will be + /// used to validate the format of the mask image. The request may fail if the filename's extension and the + /// actual format of the mask image do not match. /// - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. - /// A token that can be used to cancel this method call. + /// The number of edited or extended images to generate. + /// The options to configure the image edit. + /// A token that can be used to cancel this method call. /// , , , , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual ClientResult GenerateImageEdits(Stream image, string imageFilename, string prompt, Stream mask, string maskFilename, int imageCount, ImageEditOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -593,24 +567,24 @@ public virtual ClientResult GenerateImageEdits(Stream return ClientResult.FromValue(GeneratedImageCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Generates edited or extended images given an original image, a prompt, and a mask. + /// Generates edited or extended images based on an original image, a prompt, and a mask. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file - /// path's extension (for example: .png) will be used to validate the format of the input image. The request may - /// fail if the file extension and input image format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file + /// path's extension (for example: .png) will be used to validate the format of the input image. The request + /// may fail if the file path's extension and the actual format of the input image do not match. /// /// A text description of the desired image. /// - /// The path of the mask image file whose fully transparent areas (e.g. where alpha is zero) indicate where the - /// original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as the - /// original image. The provided file path's extension (for example: .png) will be used to validate the format of - /// the input image. The request may fail if the file extension and mask image format do not match. - /// - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. + /// The path of the mask image file whose fully transparent areas (i.e., where alpha is zero) indicate where + /// the original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as the original image. The provided file path's extension (for example: .png) will be used to validate the + /// format of the mask image. The request may fail if the file path's extension and the actual format of the + /// mask image do not match. + /// + /// The number of edited or extended images to generate. + /// The options to configure the image edit. /// , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual async Task> GenerateImageEditsAsync(string imageFilePath, string prompt, string maskFilePath, int imageCount, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -622,24 +596,24 @@ public virtual async Task> GenerateImageE return await GenerateImageEditsAsync(imageStream, imageFilePath, prompt, maskStream, maskFilePath, imageCount, options).ConfigureAwait(false); } - /// Generates edited or extended images given an original image, a prompt, and a mask. + /// Generates edited or extended images based on an original image, a prompt, and a mask. /// - /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file - /// path's extension (for example: .png) will be used to validate the format of the input image. The request may - /// fail if the file extension and input image format do not match. + /// The path of the image file to edit. Must be a valid PNG file, less than 4MB, and square. The provided file + /// path's extension (for example: .png) will be used to validate the format of the input image. The request + /// may fail if the file path's extension and the actual format of the input image do not match. /// /// A text description of the desired image. /// - /// The path of the mask image file whose fully transparent areas (e.g. where alpha is zero) indicate where the - /// original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as the - /// original image. The provided file path's extension (for example: .png) will be used to validate the format of - /// the input image. The request may fail if the file extension and mask image format do not match. - /// - /// The number of edit or extended images to generate. - /// Additional options to tailor the image edit request. + /// The path of the mask image file whose fully transparent areas (i.e., where alpha is zero) indicate where + /// the original image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as the original image. The provided file path's extension (for example: .png) will be used to validate the + /// format of the mask image. The request may fail if the file path's extension and the actual format of the + /// mask image do not match. + /// + /// The number of edited or extended images to generate. + /// The options to configure the image edit. /// , or is null. /// , , or is an empty string, and was expected to be non-empty. - /// The edited or extended images. public virtual ClientResult GenerateImageEdits(string imageFilePath, string prompt, string maskFilePath, int imageCount, ImageEditOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -656,19 +630,16 @@ public virtual ClientResult GenerateImageEdits(string #region GenerateImageVariations /// Generates a variation of a given image. - /// - /// The image to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. - /// + /// The image stream to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// - /// Additional options to tailor the image variation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image variation. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The generated image variation. public virtual async Task> GenerateImageVariationAsync(Stream image, string imageFilename, ImageVariationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -683,19 +654,16 @@ public virtual async Task> GenerateImageVariationAs } /// Generates a variation of a given image. - /// - /// The image to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. - /// + /// The image stream to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// - /// Additional options to tailor the image variation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image variation. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The generated image variation. public virtual ClientResult GenerateImageVariation(Stream image, string imageFilename, ImageVariationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -711,14 +679,14 @@ public virtual ClientResult GenerateImageVariation(Stream image, /// Generates a variation of a given image. /// - /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and - /// square. The provided file path's extension (for example: .png) will be used to validate the format of the input - /// image. The request may fail if the file extension and input image format do not match. + /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, + /// and square. The provided file path's extension (for example: .png) will be used to validate the format of + /// the input image. The request may fail if the file path's extension and the actual format of the input image + /// do not match. /// - /// Additional options to tailor the image variation request. + /// The options to configure the image variation. /// is null. /// is an empty string, and was expected to be non-empty. - /// The generated image variation. public virtual async Task> GenerateImageVariationAsync(string imageFilePath, ImageVariationOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -729,14 +697,14 @@ public virtual async Task> GenerateImageVariationAs /// Generates a variation of a given image. /// - /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and - /// square. The provided file path's extension (for example: .png) will be used to validate the format of the input - /// image. The request may fail if the file extension and input image format do not match. + /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, + /// and square. The provided file path's extension (for example: .png) will be used to validate the format of + /// the input image. The request may fail if the file path's extension and the actual format of the input image + /// do not match. /// - /// Additional options to tailor the image variation request. + /// The options to configure the image variation. /// is null. /// is an empty string, and was expected to be non-empty. - /// The generated image variation. public virtual ClientResult GenerateImageVariation(string imageFilePath, ImageVariationOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -746,20 +714,17 @@ public virtual ClientResult GenerateImageVariation(string imageF } /// Generates variations of a given image. - /// - /// The image to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. - /// + /// The image stream to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// The number of image variations to generate. - /// Additional options to tailor the image variation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image variation. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The generated image variations. public virtual async Task> GenerateImageVariationsAsync(Stream image, string imageFilename, int imageCount, ImageVariationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -774,20 +739,17 @@ public virtual async Task> GenerateImageV } /// Generates variations of a given image. - /// - /// The image to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. - /// + /// The image stream to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and square. /// - /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to - /// validate the format of the input image. The request may fail if the file extension and input image format do - /// not match. + /// The filename associated with the image stream. The filename's extension (for example: .png) will be used to + /// validate the format of the input image. The request may fail if the filename's extension and the actual + /// format of the input image do not match. /// /// The number of image variations to generate. - /// Additional options to tailor the image variation request. - /// A token that can be used to cancel this method call. + /// The options to configure the image variation. + /// A token that can be used to cancel this method call. /// or is null. /// is an empty string, and was expected to be non-empty. - /// The generated image variations. public virtual ClientResult GenerateImageVariations(Stream image, string imageFilename, int imageCount, ImageVariationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(image, nameof(image)); @@ -803,15 +765,15 @@ public virtual ClientResult GenerateImageVariations(St /// Generates variations of a given image. /// - /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and - /// square. The provided file path's extension (for example: .png) will be used to validate the format of the input - /// image. The request may fail if the file extension and input image format do not match. + /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, + /// and square. The provided file path's extension (for example: .png) will be used to validate the format of + /// the input image. The request may fail if the file path's extension and the actual format of the input image + /// do not match. /// /// The number of image variations to generate. - /// Additional options to tailor the image variation request. + /// The options to configure the image variation. /// was null. /// is an empty string, and was expected to be non-empty. - /// The generated image variations. public virtual async Task> GenerateImageVariationsAsync(string imageFilePath, int imageCount, ImageVariationOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); @@ -822,15 +784,15 @@ public virtual async Task> GenerateImageV /// Generates variations of a given image. /// - /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, and - /// square. The provided file path's extension (for example: .png) will be used to validate the format of the input - /// image. The request may fail if the file extension and input image format do not match. + /// The path of the image file to use as the basis for the variation. Must be a valid PNG file, less than 4MB, + /// and square. The provided file path's extension (for example: .png) will be used to validate the format of + /// the input image. The request may fail if the file path's extension and the actual format of the input image + /// do not match. /// /// The number of image variations to generate. - /// Additional options to tailor the image variation request. + /// The options to configure the image variation. /// was null. /// is an empty string, and was expected to be non-empty. - /// The generated image variations. public virtual ClientResult GenerateImageVariations(string imageFilePath, int imageCount, ImageVariationOptions options = null) { Argument.AssertNotNullOrEmpty(imageFilePath, nameof(imageFilePath)); diff --git a/src/Custom/Images/ImageEditOptions.cs b/src/Custom/Images/ImageEditOptions.cs index 5ed8a92cd..b8681a3de 100644 --- a/src/Custom/Images/ImageEditOptions.cs +++ b/src/Custom/Images/ImageEditOptions.cs @@ -75,12 +75,22 @@ public ImageEditOptions() // CUSTOM: Changed property type. /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + [CodeGenMember("Size")] public GeneratedImageSize? Size { get; set; } // CUSTOM: Changed property type. /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + [CodeGenMember("ResponseFormat")] public GeneratedImageFormat? ResponseFormat { get; set; } + // CUSTOM: Renamed. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. + /// Learn more. + /// + [CodeGenMember("User")] + public string EndUserId { get; set; } + internal MultipartFormDataBinaryContent ToMultipartContent(Stream image, string imageFilename, Stream mask, string maskFilename) { MultipartFormDataBinaryContent content = new(); @@ -116,9 +126,9 @@ internal MultipartFormDataBinaryContent ToMultipartContent(Stream image, string content.Add(Size.ToString(), "size"); } - if (User is not null) + if (EndUserId is not null) { - content.Add(User, "user"); + content.Add(EndUserId, "user"); } return content; diff --git a/src/Custom/Images/ImageGenerationOptions.cs b/src/Custom/Images/ImageGenerationOptions.cs index f22988e0b..688e7e701 100644 --- a/src/Custom/Images/ImageGenerationOptions.cs +++ b/src/Custom/Images/ImageGenerationOptions.cs @@ -32,4 +32,12 @@ public partial class ImageGenerationOptions public ImageGenerationOptions() { } + + // CUSTOM: Renamed. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. + /// Learn more. + /// + [CodeGenMember("User")] + public string EndUserId { get; set; } } \ No newline at end of file diff --git a/src/Custom/Images/ImageVariationOptions.cs b/src/Custom/Images/ImageVariationOptions.cs index f36e2ef47..0f71b265b 100644 --- a/src/Custom/Images/ImageVariationOptions.cs +++ b/src/Custom/Images/ImageVariationOptions.cs @@ -48,12 +48,22 @@ public ImageVariationOptions() // CUSTOM: Changed property type. /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + [CodeGenMember("Size")] public GeneratedImageSize? Size { get; set; } // CUSTOM: Changed property type. /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + [CodeGenMember("ResponseFormat")] public GeneratedImageFormat? ResponseFormat { get; set; } + // CUSTOM: Renamed. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. + /// Learn more. + /// + [CodeGenMember("User")] + public string EndUserId { get; set; } + internal MultipartFormDataBinaryContent ToMultipartContent(Stream image, string imageFilename) { MultipartFormDataBinaryContent content = new(); @@ -83,9 +93,9 @@ internal MultipartFormDataBinaryContent ToMultipartContent(Stream image, string content.Add(Size.ToString(), "size"); } - if (User is not null) + if (EndUserId is not null) { - content.Add(User, "user"); + content.Add(EndUserId, "user"); } return content; diff --git a/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs b/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs index 074625f2e..7d50115ce 100644 --- a/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs +++ b/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs @@ -1,13 +1,73 @@ +using System; +using System.ClientModel.Primitives; +using System.ClientModel; + namespace OpenAI.LegacyCompletions; -/// -/// The basic, protocol-level service client for OpenAI legacy completion operations. -/// -/// Note: pre-chat completions are a legacy feature. New solutions should consider the use of chat -/// completions or assistants, instead. -/// -/// +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed methods that only take the options parameter. +/// The service client for OpenAI legacy completion operations. [CodeGenClient("Completions")] +[CodeGenSuppress("LegacyCompletionClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] internal partial class LegacyCompletionClient { + private readonly string _model; + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public LegacyCompletionClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions()) + { + } + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public LegacyCompletionClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNullOrEmpty(model, nameof(model)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + _model = model; + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } + + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + protected internal LegacyCompletionClient(ClientPipeline pipeline, string model, OpenAIClientOptions options) + { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); + options ??= new OpenAIClientOptions(); + + _model = model; + _pipeline = pipeline; + _endpoint = OpenAIClient.GetEndpoint(options); + } } diff --git a/src/Custom/Models/ModelClient.cs b/src/Custom/Models/ModelClient.cs index 56e20876a..efbadd6d7 100644 --- a/src/Custom/Models/ModelClient.cs +++ b/src/Custom/Models/ModelClient.cs @@ -5,90 +5,80 @@ namespace OpenAI.Models; -/// -/// The service client for OpenAI model operations. -/// +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Renamed convenience methods. +/// The service client for OpenAI model operations. [CodeGenClient("ModelsOps")] [CodeGenSuppress("ModelClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] -[CodeGenSuppress("GetModelsAsync")] -[CodeGenSuppress("GetModels")] [CodeGenSuppress("RetrieveAsync", typeof(string))] [CodeGenSuppress("Retrieve", typeof(string))] [CodeGenSuppress("DeleteAsync", typeof(string))] [CodeGenSuppress("Delete", typeof(string))] public partial class ModelClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public ModelClient(ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public ModelClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) { } - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public ModelClient(OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public ModelClient(ApiKeyCredential credential, OpenAIClientOptions options) { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); } - /// Initializes a new instance of . - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal ModelClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal ModelClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } - /// - /// Lists the currently available models, and provides basic information about each one such as the - /// owner and availability. - /// - /// List models. + /// Gets basic information about each of the models that are currently available, such as their corresponding owner and availability. public virtual async Task> GetModelsAsync() { ClientResult result = await GetModelsAsync(null).ConfigureAwait(false); return ClientResult.FromValue(OpenAIModelInfoCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Lists the currently available models, and provides basic information about each one such as the - /// owner and availability. - /// - /// List models. + /// Gets basic information about each of the models that are currently available, such as their corresponding owner and availability. public virtual ClientResult GetModels() { ClientResult result = GetModels(null); return ClientResult.FromValue(OpenAIModelInfoCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Retrieves a model instance, providing basic information about the model such as the owner and - /// permissioning. - /// - /// The ID of the model to use for this request. + /// Gets basic information about the specified model, such as its owner and availability. + /// The name of the desired model. /// is null. /// is an empty string, and was expected to be non-empty. - /// Retrieve. public virtual async Task> GetModelAsync(string model) { Argument.AssertNotNullOrEmpty(model, nameof(model)); @@ -97,14 +87,10 @@ public virtual async Task> GetModelAsync(string mo return ClientResult.FromValue(OpenAIModelInfo.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// - /// Retrieves a model instance, providing basic information about the model such as the owner and - /// permissioning. - /// - /// The ID of the model to use for this request. + /// Gets basic information about the specified model, such as its owner and availability. + /// The name of the desired model. /// is null. /// is an empty string, and was expected to be non-empty. - /// Retrieve. public virtual ClientResult GetModel(string model) { Argument.AssertNotNullOrEmpty(model, nameof(model)); @@ -113,11 +99,11 @@ public virtual ClientResult GetModel(string model) return ClientResult.FromValue(OpenAIModelInfo.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. - /// The model to delete. + /// Deletes the specified fine-tuned model. + /// You must have the role of "owner" within your organization in order to be able to delete a model. + /// The name of the model to delete. /// is null. /// is an empty string, and was expected to be non-empty. - /// A value indicating whether the deletion operation was successful. public virtual async Task> DeleteModelAsync(string model) { Argument.AssertNotNullOrEmpty(model, nameof(model)); @@ -128,11 +114,11 @@ public virtual async Task> DeleteModelAsync(string model) return ClientResult.FromValue(value.Deleted, response); } - /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. - /// The model to delete. + /// Deletes the specified fine-tuned model. + /// You must have the role of "owner" within your organization in order to be able to delete a model. + /// The name of the model to delete. /// is null. /// is an empty string, and was expected to be non-empty. - /// A value indicating whether the deletion operation was successful. public virtual ClientResult DeleteModel(string model) { Argument.AssertNotNullOrEmpty(model, nameof(model)); diff --git a/src/Custom/Moderations/ModerationClient.cs b/src/Custom/Moderations/ModerationClient.cs index 44cfde541..d425f1ad9 100644 --- a/src/Custom/Moderations/ModerationClient.cs +++ b/src/Custom/Moderations/ModerationClient.cs @@ -8,9 +8,11 @@ namespace OpenAI.Moderations; -/// -/// The service client for OpenAI moderation operations. -/// +// CUSTOM: +// - Renamed. +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. +// - Suppressed methods that only take the options parameter. +/// The service client for OpenAI moderation operations. [CodeGenClient("Moderations")] [CodeGenSuppress("ModerationClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateModerationAsync", typeof(ModerationOptions))] @@ -19,56 +21,65 @@ public partial class ModerationClient { private readonly string _model; - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The model name to use for moderation operations. - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public ModerationClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - model, - OpenAIClient.GetEndpoint(options), - options) + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ModerationClient(string model, ApiKeyCredential credential) : this(model, credential, new OpenAIClientOptions()) { } - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// The model name to use for moderation operations. - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public ModerationClient(string model, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - model, - OpenAIClient.GetEndpoint(options), - options) + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public ModerationClient(string model, ApiKeyCredential credential, OpenAIClientOptions options) { + Argument.AssertNotNullOrEmpty(model, nameof(model)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + _model = model; + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); } - /// Initializes a new instance of . - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The model name to use for moderation operations. - /// OpenAI Endpoint. - protected internal ModerationClient(ClientPipeline pipeline, string model, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Added `model` parameter. + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The name of the model to use in requests sent to the service. To learn more about the available models, see . + /// The options to configure the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + protected internal ModerationClient(ClientPipeline pipeline, string model, OpenAIClientOptions options) { - _pipeline = pipeline; + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); + options ??= new OpenAIClientOptions(); + _model = model; - _endpoint = endpoint; + _pipeline = pipeline; + _endpoint = OpenAIClient.GetEndpoint(options); } - /// Classifies if text is potentially harmful. - /// The text to classify. - /// A token that can be used to cancel this method call. + /// Classifies if the text input is potentially harmful across several categories. + /// The text input to classify. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. public virtual async Task> ClassifyTextInputAsync(string input, CancellationToken cancellationToken = default) @@ -83,9 +94,9 @@ public virtual async Task> ClassifyTextInputAsync return ClientResult.FromValue(ModerationCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - /// Classifies if text is potentially harmful. - /// The text to classify. - /// A token that can be used to cancel this method call. + /// Classifies if the text input is potentially harmful across several categories. + /// The text input to classify. + /// A token that can be used to cancel this method call. /// is null. /// is an empty string, and was expected to be non-empty. public virtual ClientResult ClassifyTextInput(string input, CancellationToken cancellationToken = default) @@ -100,10 +111,9 @@ public virtual ClientResult ClassifyTextInput(string input, Ca return ClientResult.FromValue(ModerationCollection.FromResponse(result.GetRawResponse()).FirstOrDefault(), result.GetRawResponse()); } - - /// Classifies if text is potentially harmful. - /// The text to classify. - /// A token that can be used to cancel this method call. + /// Classifies if the text inputs are potentially harmful across several categories. + /// The text inputs to classify. + /// A token that can be used to cancel this method call. /// is null. /// is an empty collection, and was expected to be non-empty. public virtual async Task> ClassifyTextInputsAsync(IEnumerable inputs, CancellationToken cancellationToken = default) @@ -118,9 +128,9 @@ public virtual async Task> ClassifyTextInputs return ClientResult.FromValue(ModerationCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } - /// Classifies if text is potentially harmful. - /// The text to classify. - /// A token that can be used to cancel this method call. + /// Classifies if the text inputs are potentially harmful across several categories. + /// The text inputs to classify. + /// A token that can be used to cancel this method call. /// is null. /// is an empty collection, and was expected to be non-empty. public virtual ClientResult ClassifyTextInputs(IEnumerable inputs, CancellationToken cancellationToken = default) diff --git a/src/Custom/OpenAIClient.cs b/src/Custom/OpenAIClient.cs index bcd29ef93..fa1e8973f 100644 --- a/src/Custom/OpenAIClient.cs +++ b/src/Custom/OpenAIClient.cs @@ -17,6 +17,7 @@ namespace OpenAI; // CUSTOM: +// - Suppressed constructor that takes endpoint parameter; endpoint is now a property in the options class. // - Suppressed cached clients. Clients are not singletons, and users can create multiple clients of the same type // if needed (e.g., to target different OpenAI models). The Get*Client methods return new client instances. /// @@ -58,52 +59,57 @@ namespace OpenAI; [CodeGenSuppress("GetVectorStoreClientClient")] public partial class OpenAIClient { - private readonly OpenAIClientOptions _options; + private const string OpenAIV1Endpoint = "https://api.openai.com/v1"; + private const string OpenAIBetaHeaderValue = "assistants=v2"; - /// - /// The configured connection endpoint. - /// - protected Uri Endpoint => _endpoint; + private static class KnownHeaderNames + { + public const string OpenAIBeta = "OpenAI-Beta"; + public const string OpenAIOrganization = "OpenAI-Organization"; + public const string OpenAIProject = "OpenAI-Project"; + public const string UserAgent = "User-Agent"; + } - /// - /// Creates a new instance of . This type is used to share common - /// and client configuration details across scenario client instances created via - /// methods like . - /// - /// The API key to use when authenticating the client. - /// A common client options definition that all clients created by this should use. - /// The provided is null. - public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions options = null) - : this(CreatePipeline(GetApiKey(credential, requireExplicitCredential: true), options), GetEndpoint(options), options) + private readonly OpenAIClientOptions _options; + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public OpenAIClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) { - _keyCredential = credential; } - /// - /// Creates a new instance of . This type is used to share common - /// and client configuration details across scenario client instances created via - /// methods like . - /// - /// This constructor overload will use the value of the OPENAI_API_KEY environment variable as its - /// authentication mechanism. To provide an explicit credential, use an alternate constructor like - /// . - /// - /// - /// A common client options definition that all clients created by this should use. - public OpenAIClient(OpenAIClientOptions options = default) - : this(CreatePipeline(GetApiKey(), options), GetEndpoint(options), options) - {} + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); - /// - /// Creates a new instance of . - /// - /// The common client pipeline that should be used for all created scenario clients. - /// The HTTP endpoint to use. - /// The common client options that should be used for all created scenario clients. - protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } + + // CUSTOM: Added protected internal constructor that takes a ClientPipeline. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal OpenAIClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); _options = options; } @@ -117,7 +123,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// /// A new . [Experimental("OPENAI001")] - public virtual AssistantClient GetAssistantClient() => new(_pipeline, _endpoint, _options); + public virtual AssistantClient GetAssistantClient() => new(_pipeline, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -128,7 +134,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual AudioClient GetAudioClient(string model) => new(_pipeline, model, _endpoint, _options); + public virtual AudioClient GetAudioClient(string model) => new(_pipeline, model, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -139,7 +145,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual BatchClient GetBatchClient() => new(_pipeline, _endpoint, _options); + public virtual BatchClient GetBatchClient() => new(_pipeline, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -150,7 +156,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual ChatClient GetChatClient(string model) => new(_pipeline, model, _endpoint, _options); + public virtual ChatClient GetChatClient(string model) => new(_pipeline, model, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -161,7 +167,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual EmbeddingClient GetEmbeddingClient(string model) => new(_pipeline, model, _endpoint, _options); + public virtual EmbeddingClient GetEmbeddingClient(string model) => new(_pipeline, model, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -172,7 +178,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual FileClient GetFileClient() => new(_pipeline, _endpoint, _options); + public virtual FileClient GetFileClient() => new(_pipeline, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -183,7 +189,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual FineTuningClient GetFineTuningClient() => new(_pipeline, _endpoint, _options); + public virtual FineTuningClient GetFineTuningClient() => new(_pipeline, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -194,7 +200,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual ImageClient GetImageClient(string model) => new(_pipeline, model, _endpoint, _options); + public virtual ImageClient GetImageClient(string model) => new(_pipeline, model, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -205,7 +211,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual ModelClient GetModelClient() => new(_pipeline, _endpoint, _options); + public virtual ModelClient GetModelClient() => new(_pipeline, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -216,7 +222,7 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// the same configuration details. /// /// A new . - public virtual ModerationClient GetModerationClient(string model) => new(_pipeline, model, _endpoint, _options); + public virtual ModerationClient GetModerationClient(string model) => new(_pipeline, model, _options); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -228,59 +234,35 @@ protected OpenAIClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOption /// /// A new . [Experimental("OPENAI001")] - public virtual VectorStoreClient GetVectorStoreClient() => new(_pipeline, _endpoint, _options); + public virtual VectorStoreClient GetVectorStoreClient() => new(_pipeline, _options); - internal static ClientPipeline CreatePipeline(ApiKeyCredential credential, OpenAIClientOptions options = null) + internal static ClientPipeline CreatePipeline(ApiKeyCredential credential, OpenAIClientOptions options) { return ClientPipeline.Create( - options ?? new(), + options, perCallPolicies: [ CreateAddBetaFeatureHeaderPolicy(), CreateAddCustomHeadersPolicy(options), ], - perTryPolicies: - [ + perTryPolicies: [ ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy(credential, AuthorizationHeader, AuthorizationApiKeyPrefix) ], - beforeTransportPolicies: []); + beforeTransportPolicies: [ + ]); } - internal static Uri GetEndpoint(OpenAIClientOptions options) + internal static Uri GetEndpoint(OpenAIClientOptions options = null) { - return options?.Endpoint ?? new(Environment.GetEnvironmentVariable(OpenAIEndpointEnvironmentVariable) ?? OpenAIV1Endpoint); - } - - internal static ApiKeyCredential GetApiKey(ApiKeyCredential explicitCredential = null, bool requireExplicitCredential = false) - { - if (explicitCredential is not null) - { - return explicitCredential; - } - else if (requireExplicitCredential) - { - throw new ArgumentNullException(nameof(explicitCredential), $"A non-null credential value is required."); - } - else - { - string environmentApiKey = Environment.GetEnvironmentVariable(OpenAIApiKeyEnvironmentVariable); - if (string.IsNullOrEmpty(environmentApiKey)) - { - throw new InvalidOperationException( - $"No environment variable value was found for {OpenAIApiKeyEnvironmentVariable}. " - + "Please either populate this environment variable or provide authentication information directly " - + "to the client constructor."); - } - return new(environmentApiKey); - } + return options?.Endpoint ?? new(OpenAIV1Endpoint); } private static PipelinePolicy CreateAddBetaFeatureHeaderPolicy() { return new GenericActionPipelinePolicy((message) => { - if (message?.Request?.Headers?.TryGetValue(OpenAIBetaFeatureHeaderName, out string _) == false) + if (message?.Request?.Headers?.TryGetValue(KnownHeaderNames.OpenAIBeta, out string _) == false) { - message.Request.Headers.Set(OpenAIBetaFeatureHeaderName, OpenAIBetaAssistantsV1HeaderValue); + message.Request.Headers.Set(KnownHeaderNames.OpenAIBeta, OpenAIBetaHeaderValue); } }); } @@ -290,28 +272,20 @@ private static PipelinePolicy CreateAddCustomHeadersPolicy(OpenAIClientOptions o TelemetryDetails telemetryDetails = new(typeof(OpenAIClientOptions).Assembly, options?.ApplicationId); return new GenericActionPipelinePolicy((message) => { - if (message?.Request?.Headers?.TryGetValue(UserAgentHeaderName, out string _) == false) + if (message?.Request?.Headers?.TryGetValue(KnownHeaderNames.UserAgent, out string _) == false) { - message.Request.Headers.Set(UserAgentHeaderName, telemetryDetails.ToString()); + message.Request.Headers.Set(KnownHeaderNames.UserAgent, telemetryDetails.ToString()); } if (!string.IsNullOrEmpty(options?.OrganizationId)) { - message.Request.Headers.Set(OpenAIOrganizationHeaderName, options.OrganizationId); + message.Request.Headers.Set(KnownHeaderNames.OpenAIOrganization, options.OrganizationId); } + if (!string.IsNullOrEmpty(options?.ProjectId)) { - message.Request.Headers.Set(OpenAIProjectHeaderName, options.ProjectId); + message.Request.Headers.Set(KnownHeaderNames.OpenAIProject, options.ProjectId); } }); } - - private const string OpenAIBetaFeatureHeaderName = "OpenAI-Beta"; - private const string OpenAIOrganizationHeaderName = "OpenAI-Organization"; - private const string OpenAIProjectHeaderName = "OpenAI-Project"; - private const string OpenAIBetaAssistantsV1HeaderValue = "assistants=v2"; - private const string OpenAIEndpointEnvironmentVariable = "OPENAI_ENDPOINT"; - private const string OpenAIApiKeyEnvironmentVariable = "OPENAI_API_KEY"; - private const string OpenAIV1Endpoint = "https://api.openai.com/v1"; - private const string UserAgentHeaderName = "User-Agent"; } diff --git a/src/Custom/VectorStores/VectorStoreClient.cs b/src/Custom/VectorStores/VectorStoreClient.cs index 1d5947894..5edeb0dfb 100644 --- a/src/Custom/VectorStores/VectorStoreClient.cs +++ b/src/Custom/VectorStores/VectorStoreClient.cs @@ -13,6 +13,7 @@ namespace OpenAI.VectorStores; /// The service client for OpenAI vector store operations. /// [CodeGenClient("VectorStores")] +[CodeGenSuppress("VectorStoreClient", typeof(ClientPipeline), typeof(ApiKeyCredential), typeof(Uri))] [CodeGenSuppress("CreateVectorStoreAsync", typeof(VectorStoreCreationOptions))] [CodeGenSuppress("CreateVectorStore", typeof(VectorStoreCreationOptions))] [CodeGenSuppress("GetVectorStoreAsync", typeof(string))] @@ -42,43 +43,47 @@ namespace OpenAI.VectorStores; [Experimental("OPENAI001")] public partial class VectorStoreClient { - /// - /// Initializes a new instance of that will use an API key when authenticating. - /// - /// The API key used to authenticate with the service endpoint. - /// Additional options to customize the client. - /// The provided was null. - public VectorStoreClient(ApiKeyCredential credential, OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(credential, requireExplicitCredential: true), options), - OpenAIClient.GetEndpoint(options), - options) - { } + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// is null. + public VectorStoreClient(ApiKeyCredential credential) : this(credential, new OpenAIClientOptions()) + { + } - /// - /// Initializes a new instance of that will use an API key from the OPENAI_API_KEY - /// environment variable when authenticating. - /// - /// - /// To provide an explicit credential instead of using the environment variable, use an alternate constructor like - /// . - /// - /// Additional options to customize the client. - /// The OPENAI_API_KEY environment variable was not found. - public VectorStoreClient(OpenAIClientOptions options = null) - : this( - OpenAIClient.CreatePipeline(OpenAIClient.GetApiKey(), options), - OpenAIClient.GetEndpoint(options), - options) - { } - - /// Initializes a new instance of VectorStoreClient. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// OpenAI Endpoint. - protected internal VectorStoreClient(ClientPipeline pipeline, Uri endpoint, OpenAIClientOptions options) + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + /// Initializes a new instance of . + /// The API key to authenticate with the service. + /// The options to configure the client. + /// is null. + public VectorStoreClient(ApiKeyCredential credential, OpenAIClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + _pipeline = OpenAIClient.CreatePipeline(credential, options); + _endpoint = OpenAIClient.GetEndpoint(options); + } + + // CUSTOM: + // - Used a custom pipeline. + // - Demoted the endpoint parameter to be a property in the options class. + // - Made protected. + /// Initializes a new instance of . + /// The HTTP pipeline to send and receive REST requests and responses. + /// The options to configure the client. + /// is null. + protected internal VectorStoreClient(ClientPipeline pipeline, OpenAIClientOptions options) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + options ??= new OpenAIClientOptions(); + _pipeline = pipeline; - _endpoint = endpoint; + _endpoint = OpenAIClient.GetEndpoint(options); } /// Creates a vector store. diff --git a/src/Generated/ChatClient.cs b/src/Generated/ChatClient.cs index 681019cf2..6db94d5ea 100644 --- a/src/Generated/ChatClient.cs +++ b/src/Generated/ChatClient.cs @@ -24,13 +24,6 @@ protected ChatClient() { } - internal ChatClient(ClientPipeline pipeline, ApiKeyCredential keyCredential, Uri endpoint) - { - _pipeline = pipeline; - _keyCredential = keyCredential; - _endpoint = endpoint; - } - internal PipelineMessage CreateCreateChatCompletionRequest(BinaryContent content, RequestOptions options) { var message = _pipeline.CreateMessage(); diff --git a/src/Generated/FineTuningClient.cs b/src/Generated/FineTuningClient.cs index 7424e0331..c4446699d 100644 --- a/src/Generated/FineTuningClient.cs +++ b/src/Generated/FineTuningClient.cs @@ -24,13 +24,6 @@ protected FineTuningClient() { } - internal FineTuningClient(ClientPipeline pipeline, ApiKeyCredential keyCredential, Uri endpoint) - { - _pipeline = pipeline; - _keyCredential = keyCredential; - _endpoint = endpoint; - } - internal PipelineMessage CreateCreateFineTuningJobRequest(BinaryContent content, RequestOptions options) { var message = _pipeline.CreateMessage(); diff --git a/src/Generated/LegacyCompletionClient.cs b/src/Generated/LegacyCompletionClient.cs index 84402ded2..efb44faac 100644 --- a/src/Generated/LegacyCompletionClient.cs +++ b/src/Generated/LegacyCompletionClient.cs @@ -24,13 +24,6 @@ protected LegacyCompletionClient() { } - internal LegacyCompletionClient(ClientPipeline pipeline, ApiKeyCredential keyCredential, Uri endpoint) - { - _pipeline = pipeline; - _keyCredential = keyCredential; - _endpoint = endpoint; - } - public virtual async Task> CreateCompletionAsync(InternalCreateCompletionRequest requestBody) { Argument.AssertNotNull(requestBody, nameof(requestBody)); diff --git a/src/Generated/Models/ChatCompletionOptions.Serialization.cs b/src/Generated/Models/ChatCompletionOptions.Serialization.cs index 23a61e573..3a571fe7a 100644 --- a/src/Generated/Models/ChatCompletionOptions.Serialization.cs +++ b/src/Generated/Models/ChatCompletionOptions.Serialization.cs @@ -217,10 +217,10 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderW writer.WritePropertyName("parallel_tool_calls"u8); writer.WriteBooleanValue(ParallelToolCallsEnabled.Value); } - if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(User)) + if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(EndUserId)) { writer.WritePropertyName("user"u8); - writer.WriteStringValue(User); + writer.WriteStringValue(EndUserId); } if (SerializedAdditionalRawData?.ContainsKey("function_call") != true && Optional.IsDefined(FunctionChoice)) { diff --git a/src/Generated/Models/ChatCompletionOptions.cs b/src/Generated/Models/ChatCompletionOptions.cs index 9588a63d4..4ca6247be 100644 --- a/src/Generated/Models/ChatCompletionOptions.cs +++ b/src/Generated/Models/ChatCompletionOptions.cs @@ -12,7 +12,7 @@ public partial class ChatCompletionOptions { internal IDictionary SerializedAdditionalRawData { get; set; } - internal ChatCompletionOptions(IList messages, InternalCreateChatCompletionRequestModel model, float? frequencyPenalty, IDictionary logitBiases, bool? includeLogProbabilities, int? topLogProbabilityCount, int? maxTokens, int? n, float? presencePenalty, ChatResponseFormat responseFormat, long? seed, IList stopSequences, bool? stream, InternalChatCompletionStreamOptions streamOptions, float? temperature, float? topP, IList tools, ChatToolChoice toolChoice, bool? parallelToolCallsEnabled, string user, ChatFunctionChoice functionChoice, IList functions, IDictionary serializedAdditionalRawData) + internal ChatCompletionOptions(IList messages, InternalCreateChatCompletionRequestModel model, float? frequencyPenalty, IDictionary logitBiases, bool? includeLogProbabilities, int? topLogProbabilityCount, int? maxTokens, int? n, float? presencePenalty, ChatResponseFormat responseFormat, long? seed, IList stopSequences, bool? stream, InternalChatCompletionStreamOptions streamOptions, float? temperature, float? topP, IList tools, ChatToolChoice toolChoice, bool? parallelToolCallsEnabled, string endUserId, ChatFunctionChoice functionChoice, IList functions, IDictionary serializedAdditionalRawData) { Messages = messages; Model = model; @@ -33,7 +33,7 @@ internal ChatCompletionOptions(IList messages, InternalCreateChatCo Tools = tools; ToolChoice = toolChoice; ParallelToolCallsEnabled = parallelToolCallsEnabled; - User = user; + EndUserId = endUserId; FunctionChoice = functionChoice; Functions = functions; SerializedAdditionalRawData = serializedAdditionalRawData; @@ -46,7 +46,6 @@ internal ChatCompletionOptions(IList messages, InternalCreateChatCo public float? Temperature { get; set; } public float? TopP { get; set; } public IList Tools { get; } - public string User { get; set; } public IList Functions { get; } } } diff --git a/src/Generated/Models/EmbeddingGenerationOptions.Serialization.cs b/src/Generated/Models/EmbeddingGenerationOptions.Serialization.cs index 8b8c90264..5a2ee5c11 100644 --- a/src/Generated/Models/EmbeddingGenerationOptions.Serialization.cs +++ b/src/Generated/Models/EmbeddingGenerationOptions.Serialization.cs @@ -48,10 +48,10 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WritePropertyName("dimensions"u8); writer.WriteNumberValue(Dimensions.Value); } - if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(User)) + if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(EndUserId)) { writer.WritePropertyName("user"u8); - writer.WriteStringValue(User); + writer.WriteStringValue(EndUserId); } if (SerializedAdditionalRawData != null) { diff --git a/src/Generated/Models/EmbeddingGenerationOptions.cs b/src/Generated/Models/EmbeddingGenerationOptions.cs index b9845d838..92ffbca28 100644 --- a/src/Generated/Models/EmbeddingGenerationOptions.cs +++ b/src/Generated/Models/EmbeddingGenerationOptions.cs @@ -11,16 +11,15 @@ public partial class EmbeddingGenerationOptions { internal IDictionary SerializedAdditionalRawData { get; set; } - internal EmbeddingGenerationOptions(BinaryData input, InternalCreateEmbeddingRequestModel model, InternalCreateEmbeddingRequestEncodingFormat? encodingFormat, int? dimensions, string user, IDictionary serializedAdditionalRawData) + internal EmbeddingGenerationOptions(BinaryData input, InternalCreateEmbeddingRequestModel model, InternalCreateEmbeddingRequestEncodingFormat? encodingFormat, int? dimensions, string endUserId, IDictionary serializedAdditionalRawData) { Input = input; Model = model; EncodingFormat = encodingFormat; Dimensions = dimensions; - User = user; + EndUserId = endUserId; SerializedAdditionalRawData = serializedAdditionalRawData; } public int? Dimensions { get; set; } - public string User { get; set; } } } diff --git a/src/Generated/Models/ImageEditOptions.Serialization.cs b/src/Generated/Models/ImageEditOptions.Serialization.cs index 2a36f0792..45e614018 100644 --- a/src/Generated/Models/ImageEditOptions.Serialization.cs +++ b/src/Generated/Models/ImageEditOptions.Serialization.cs @@ -99,10 +99,10 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter writer.WriteNull("response_format"); } } - if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(User)) + if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(EndUserId)) { writer.WritePropertyName("user"u8); - writer.WriteStringValue(User); + writer.WriteStringValue(EndUserId); } if (SerializedAdditionalRawData != null) { @@ -293,9 +293,9 @@ internal virtual MultipartFormDataBinaryContent ToMultipartBinaryBody() content.Add(ResponseFormat.Value.ToSerialString(), "response_format"); } } - if (Optional.IsDefined(User)) + if (Optional.IsDefined(EndUserId)) { - content.Add(User, "user"); + content.Add(EndUserId, "user"); } return content; } diff --git a/src/Generated/Models/ImageEditOptions.cs b/src/Generated/Models/ImageEditOptions.cs index bae4472ef..c46d7879c 100644 --- a/src/Generated/Models/ImageEditOptions.cs +++ b/src/Generated/Models/ImageEditOptions.cs @@ -11,7 +11,7 @@ public partial class ImageEditOptions { internal IDictionary SerializedAdditionalRawData { get; set; } - internal ImageEditOptions(BinaryData image, string prompt, BinaryData mask, InternalCreateImageEditRequestModel? model, long? n, GeneratedImageSize? size, GeneratedImageFormat? responseFormat, string user, IDictionary serializedAdditionalRawData) + internal ImageEditOptions(BinaryData image, string prompt, BinaryData mask, InternalCreateImageEditRequestModel? model, long? n, GeneratedImageSize? size, GeneratedImageFormat? responseFormat, string endUserId, IDictionary serializedAdditionalRawData) { Image = image; Prompt = prompt; @@ -20,9 +20,8 @@ internal ImageEditOptions(BinaryData image, string prompt, BinaryData mask, Inte N = n; Size = size; ResponseFormat = responseFormat; - User = user; + EndUserId = endUserId; SerializedAdditionalRawData = serializedAdditionalRawData; } - public string User { get; set; } } } diff --git a/src/Generated/Models/ImageGenerationOptions.Serialization.cs b/src/Generated/Models/ImageGenerationOptions.Serialization.cs index 44a19bd2c..a007fd04a 100644 --- a/src/Generated/Models/ImageGenerationOptions.Serialization.cs +++ b/src/Generated/Models/ImageGenerationOptions.Serialization.cs @@ -91,10 +91,10 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("style"); } } - if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(User)) + if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(EndUserId)) { writer.WritePropertyName("user"u8); - writer.WriteStringValue(User); + writer.WriteStringValue(EndUserId); } if (SerializedAdditionalRawData != null) { diff --git a/src/Generated/Models/ImageGenerationOptions.cs b/src/Generated/Models/ImageGenerationOptions.cs index e5f92429f..e7d9311dc 100644 --- a/src/Generated/Models/ImageGenerationOptions.cs +++ b/src/Generated/Models/ImageGenerationOptions.cs @@ -11,7 +11,7 @@ public partial class ImageGenerationOptions { internal IDictionary SerializedAdditionalRawData { get; set; } - internal ImageGenerationOptions(string prompt, InternalCreateImageRequestModel? model, long? n, GeneratedImageQuality? quality, GeneratedImageFormat? responseFormat, GeneratedImageSize? size, GeneratedImageStyle? style, string user, IDictionary serializedAdditionalRawData) + internal ImageGenerationOptions(string prompt, InternalCreateImageRequestModel? model, long? n, GeneratedImageQuality? quality, GeneratedImageFormat? responseFormat, GeneratedImageSize? size, GeneratedImageStyle? style, string endUserId, IDictionary serializedAdditionalRawData) { Prompt = prompt; Model = model; @@ -20,13 +20,12 @@ internal ImageGenerationOptions(string prompt, InternalCreateImageRequestModel? ResponseFormat = responseFormat; Size = size; Style = style; - User = user; + EndUserId = endUserId; SerializedAdditionalRawData = serializedAdditionalRawData; } public GeneratedImageQuality? Quality { get; set; } public GeneratedImageFormat? ResponseFormat { get; set; } public GeneratedImageSize? Size { get; set; } public GeneratedImageStyle? Style { get; set; } - public string User { get; set; } } } diff --git a/src/Generated/Models/ImageVariationOptions.Serialization.cs b/src/Generated/Models/ImageVariationOptions.Serialization.cs index 1ba8f7a15..aea32c3d6 100644 --- a/src/Generated/Models/ImageVariationOptions.Serialization.cs +++ b/src/Generated/Models/ImageVariationOptions.Serialization.cs @@ -82,10 +82,10 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderW writer.WriteNull("size"); } } - if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(User)) + if (SerializedAdditionalRawData?.ContainsKey("user") != true && Optional.IsDefined(EndUserId)) { writer.WritePropertyName("user"u8); - writer.WriteStringValue(User); + writer.WriteStringValue(EndUserId); } if (SerializedAdditionalRawData != null) { @@ -253,9 +253,9 @@ internal virtual MultipartFormDataBinaryContent ToMultipartBinaryBody() content.Add(Size.Value.ToString(), "size"); } } - if (Optional.IsDefined(User)) + if (Optional.IsDefined(EndUserId)) { - content.Add(User, "user"); + content.Add(EndUserId, "user"); } return content; } diff --git a/src/Generated/Models/ImageVariationOptions.cs b/src/Generated/Models/ImageVariationOptions.cs index d4b9a8cf2..6fac2f976 100644 --- a/src/Generated/Models/ImageVariationOptions.cs +++ b/src/Generated/Models/ImageVariationOptions.cs @@ -11,16 +11,15 @@ public partial class ImageVariationOptions { internal IDictionary SerializedAdditionalRawData { get; set; } - internal ImageVariationOptions(BinaryData image, InternalCreateImageVariationRequestModel? model, long? n, GeneratedImageFormat? responseFormat, GeneratedImageSize? size, string user, IDictionary serializedAdditionalRawData) + internal ImageVariationOptions(BinaryData image, InternalCreateImageVariationRequestModel? model, long? n, GeneratedImageFormat? responseFormat, GeneratedImageSize? size, string endUserId, IDictionary serializedAdditionalRawData) { Image = image; Model = model; N = n; ResponseFormat = responseFormat; Size = size; - User = user; + EndUserId = endUserId; SerializedAdditionalRawData = serializedAdditionalRawData; } - public string User { get; set; } } } diff --git a/src/Generated/VectorStoreClient.cs b/src/Generated/VectorStoreClient.cs index 6f2be46a8..5e44c7abe 100644 --- a/src/Generated/VectorStoreClient.cs +++ b/src/Generated/VectorStoreClient.cs @@ -24,13 +24,6 @@ protected VectorStoreClient() { } - internal VectorStoreClient(ClientPipeline pipeline, ApiKeyCredential keyCredential, Uri endpoint) - { - _pipeline = pipeline; - _keyCredential = keyCredential; - _endpoint = endpoint; - } - internal PipelineMessage CreateGetVectorStoresRequest(int? limit, string order, string after, string before, RequestOptions options) { var message = _pipeline.CreateMessage(); diff --git a/tests/Assistants/AssistantTests.cs b/tests/Assistants/AssistantTests.cs index b38e4e5cf..263480681 100644 --- a/tests/Assistants/AssistantTests.cs +++ b/tests/Assistants/AssistantTests.cs @@ -29,9 +29,9 @@ protected void Cleanup() return; } - AssistantClient client = new(); - FileClient fileClient = new(); - VectorStoreClient vectorStoreClient = new(); + AssistantClient client = GetTestClient(TestScenario.Assistants); + FileClient fileClient = GetTestClient(TestScenario.Files); + VectorStoreClient vectorStoreClient = GetTestClient(TestScenario.VectorStores); RequestOptions requestOptions = new() { ErrorOptions = ClientErrorBehaviors.NoThrow, @@ -273,7 +273,7 @@ public void BasicRunStepFunctionalityWorks() }); Validate(assistant); - FileClient fileClient = new(); + FileClient fileClient = GetTestClient(TestScenario.Files); OpenAIFileInfo equationFile = fileClient.UploadFile( BinaryData.FromString(""" x,y @@ -450,7 +450,7 @@ public void FunctionToolsWork() [Test] public async Task StreamingRunWorks() { - AssistantClient client = new(); + AssistantClient client = GetTestClient(); Assistant assistant = await client.CreateAssistantAsync("gpt-4o-mini"); Validate(assistant); @@ -557,7 +557,7 @@ public async Task StreamingToolCall() public void BasicFileSearchWorks() { // First, we need to upload a simple test file. - FileClient fileClient = new(); + FileClient fileClient = GetTestClient(TestScenario.Files); OpenAIFileInfo testFile = fileClient.UploadFile( BinaryData.FromString(""" This file describes the favorite foods of several people. @@ -944,7 +944,7 @@ public void Pagination_CanRehydrateRunStepPageCollectionFromBytes() }); Validate(assistant); - FileClient fileClient = new(); + FileClient fileClient = GetTestClient(TestScenario.Files); OpenAIFileInfo equationFile = fileClient.UploadFile( BinaryData.FromString(""" x,y diff --git a/tests/Assistants/VectorStoreTests.cs b/tests/Assistants/VectorStoreTests.cs index ea1d2b7ae..ed4426f30 100644 --- a/tests/Assistants/VectorStoreTests.cs +++ b/tests/Assistants/VectorStoreTests.cs @@ -359,7 +359,7 @@ private IReadOnlyList GetNewTestFiles(int count) { List files = []; - FileClient client = new(); + FileClient client = GetTestClient(TestScenario.Files); for (int i = 0; i < count; i++) { OpenAIFileInfo file = client.UploadFile( @@ -376,8 +376,8 @@ private IReadOnlyList GetNewTestFiles(int count) [TearDown] protected void Cleanup() { - FileClient fileClient = new(); - VectorStoreClient vectorStoreClient = new(); + FileClient fileClient = GetTestClient(TestScenario.Files); + VectorStoreClient vectorStoreClient = GetTestClient(TestScenario.VectorStores); RequestOptions requestOptions = new() { ErrorOptions = ClientErrorBehaviors.NoThrow, diff --git a/tests/Batch/BatchTests.cs b/tests/Batch/BatchTests.cs index 16b7c5b4c..65be9eaa5 100644 --- a/tests/Batch/BatchTests.cs +++ b/tests/Batch/BatchTests.cs @@ -60,7 +60,7 @@ public async Task CreateGetAndCancelBatchProtocol() streamWriter.Flush(); testFileStream.Position = 0; - FileClient fileClient = new(); + FileClient fileClient = GetTestClient(TestScenario.Files); OpenAIFileInfo inputFile = await fileClient.UploadFileAsync(testFileStream, "test-batch-file", FileUploadPurpose.Batch); Assert.That(inputFile.Id, Is.Not.Null.And.Not.Empty); diff --git a/tests/Embeddings/EmbeddingTests.cs b/tests/Embeddings/EmbeddingTests.cs index a20f6b9b2..94ebfe8b5 100644 --- a/tests/Embeddings/EmbeddingTests.cs +++ b/tests/Embeddings/EmbeddingTests.cs @@ -28,7 +28,7 @@ public enum EmbeddingsInputKind [Test] public async Task GenerateSingleEmbedding() { - EmbeddingClient client = new("text-embedding-3-small"); + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); string input = "Hello, world!"; @@ -49,7 +49,7 @@ public async Task GenerateSingleEmbedding() [TestCase(EmbeddingsInputKind.UsingIntegers)] public async Task GenerateMultipleEmbeddings(EmbeddingsInputKind embeddingsInputKind) { - EmbeddingClient client = new("text-embedding-3-small"); + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); const int Dimensions = 456; diff --git a/tests/Models/ModelTests.cs b/tests/Models/ModelTests.cs index 92bbaf887..aa5078490 100644 --- a/tests/Models/ModelTests.cs +++ b/tests/Models/ModelTests.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using static OpenAI.Tests.TestHelpers; namespace OpenAI.Tests.Models; @@ -20,7 +21,7 @@ public ModelTests(bool isAsync) : base(isAsync) [Test] public async Task ListModels() { - ModelClient client = new(); + ModelClient client = GetTestClient(TestScenario.Models); OpenAIModelInfoCollection allModels = IsAsync ? await client.GetModelsAsync() @@ -33,7 +34,7 @@ public async Task ListModels() [Test] public async Task GetModelInfo() { - ModelClient client = new(); + ModelClient client = GetTestClient(TestScenario.Models); string modelName = "gpt-4o-mini"; diff --git a/tests/Moderations/ModerationTests.cs b/tests/Moderations/ModerationTests.cs index 3c10fbfab..bb5b0e25c 100644 --- a/tests/Moderations/ModerationTests.cs +++ b/tests/Moderations/ModerationTests.cs @@ -3,6 +3,7 @@ using OpenAI.Tests.Utility; using System.Collections.Generic; using System.Threading.Tasks; +using static OpenAI.Tests.TestHelpers; namespace OpenAI.Tests.Moderations; @@ -19,7 +20,7 @@ public ModerationTests(bool isAsync) : base(isAsync) [Test] public async Task ClassifySingleInput() { - ModerationClient client = new("text-moderation-stable"); + ModerationClient client = GetTestClient(TestScenario.Moderations); const string input = "I am killing all my houseplants!"; @@ -35,7 +36,7 @@ public async Task ClassifySingleInput() [Test] public async Task ClassifyMultipleInputs() { - ModerationClient client = new("text-moderation-stable"); + ModerationClient client = GetTestClient(TestScenario.Moderations); List inputs = [ diff --git a/tests/UserAgentTests.cs b/tests/UserAgentTests.cs index 3af362178..31b74e11d 100644 --- a/tests/UserAgentTests.cs +++ b/tests/UserAgentTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using OpenAI.Chat; +using System; using System.ClientModel; using System.ClientModel.Primitives; using System.IO; @@ -29,7 +30,7 @@ private void UserAgentStringWorks(bool useApplicationId) } : new(); options.AddPolicy(policy, PipelinePosition.BeforeTransport); - ChatClient client = new("no-real-model-needed", options); + ChatClient client = new("no-real-model-needed", Environment.GetEnvironmentVariable("OPENAI_API_KEY"), options); RequestOptions noThrowOptions = new() { ErrorOptions = ClientErrorBehaviors.NoThrow, }; using BinaryContent emptyContent = BinaryContent.Create(new MemoryStream()); _ = client.CompleteChat(emptyContent, noThrowOptions); diff --git a/tests/Utility/TestHelpers.cs b/tests/Utility/TestHelpers.cs index 9231231e5..9fb30f472 100644 --- a/tests/Utility/TestHelpers.cs +++ b/tests/Utility/TestHelpers.cs @@ -6,8 +6,11 @@ using OpenAI.Embeddings; using OpenAI.Files; using OpenAI.Images; +using OpenAI.Models; +using OpenAI.Moderations; using OpenAI.VectorStores; using System; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.IO; @@ -42,23 +45,26 @@ public enum TestScenario public static T GetTestClient(TestScenario scenario, string overrideModel = null) { OpenAIClientOptions options = new(); + ApiKeyCredential credential = Environment.GetEnvironmentVariable("OPENAI_API_KEY"); options.AddPolicy(GetDumpPolicy(), PipelinePosition.PerTry); object clientObject = scenario switch { #pragma warning disable OPENAI001 - TestScenario.Assistants => new AssistantClient(options), + TestScenario.Assistants => new AssistantClient(credential, options), #pragma warning restore OPENAI001 - TestScenario.Audio_TTS => new AudioClient(overrideModel ?? "tts-1", options), - TestScenario.Audio_Whisper => new AudioClient(overrideModel ?? "whisper-1", options), - TestScenario.Batch => new BatchClient(options), - TestScenario.Chat => new ChatClient(overrideModel ?? "gpt-4o-mini", options), - TestScenario.Embeddings => new EmbeddingClient(overrideModel ?? "text-embedding-3-small", options), - TestScenario.Files => new FileClient(options), - TestScenario.Images => new ImageClient(overrideModel ?? "dall-e-3", options), + TestScenario.Audio_TTS => new AudioClient(overrideModel ?? "tts-1", credential, options), + TestScenario.Audio_Whisper => new AudioClient(overrideModel ?? "whisper-1", credential, options), + TestScenario.Batch => new BatchClient(credential, options), + TestScenario.Chat => new ChatClient(overrideModel ?? "gpt-4o-mini", credential, options), + TestScenario.Embeddings => new EmbeddingClient(overrideModel ?? "text-embedding-3-small", credential, options), + TestScenario.Files => new FileClient(credential,options), + TestScenario.Images => new ImageClient(overrideModel ?? "dall-e-3", credential, options), + TestScenario.Models => new ModelClient(credential, options), + TestScenario.Moderations => new ModerationClient(overrideModel ?? "text-moderation-stable", credential, options), #pragma warning disable OPENAI001 - TestScenario.VectorStores => new VectorStoreClient(options), + TestScenario.VectorStores => new VectorStoreClient(credential, options), #pragma warning restore OPENAI001 - TestScenario.TopLevel => new OpenAIClient(options), + TestScenario.TopLevel => new OpenAIClient(credential, options), _ => throw new NotImplementedException(), }; return (T)clientObject;