diff --git a/.dotnet.azure/src/Custom/Assistants/AzureAssistantClient.cs b/.dotnet.azure/src/Custom/Assistants/AzureAssistantClient.cs index aa35d2bc6..cd623fdab 100644 --- a/.dotnet.azure/src/Custom/Assistants/AzureAssistantClient.cs +++ b/.dotnet.azure/src/Custom/Assistants/AzureAssistantClient.cs @@ -17,17 +17,18 @@ internal partial class AzureAssistantClient : AssistantClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureAssistantClient( - ClientPipeline pipeline, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, endpoint, options) + internal AzureAssistantClient(ClientPipeline pipeline, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _endpoint = endpoint; _apiVersion = options.Version; } protected AzureAssistantClient() - { } + { + } } diff --git a/.dotnet.azure/src/Custom/Audio/AzureAudioClient.cs b/.dotnet.azure/src/Custom/Audio/AzureAudioClient.cs index 1ad255b9b..40c40b1cf 100644 --- a/.dotnet.azure/src/Custom/Audio/AzureAudioClient.cs +++ b/.dotnet.azure/src/Custom/Audio/AzureAudioClient.cs @@ -18,19 +18,20 @@ internal partial class AzureAudioClient : AudioClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureAudioClient( - ClientPipeline pipeline, - string deploymentName, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, model: deploymentName, endpoint, options) + internal AzureAudioClient(ClientPipeline pipeline, string deploymentName, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, model: deploymentName, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(deploymentName, nameof(deploymentName)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _deploymentName = deploymentName; _endpoint = endpoint; _apiVersion = options.Version; } protected AzureAudioClient() - { } + { + } } diff --git a/.dotnet.azure/src/Custom/AzureOpenAIClient.cs b/.dotnet.azure/src/Custom/AzureOpenAIClient.cs index 62f5a86b0..6bdbdea55 100644 --- a/.dotnet.azure/src/Custom/AzureOpenAIClient.cs +++ b/.dotnet.azure/src/Custom/AzureOpenAIClient.cs @@ -41,6 +41,7 @@ namespace Azure.AI.OpenAI; /// public partial class AzureOpenAIClient : OpenAIClient { + private readonly Uri _endpoint; private readonly AzureOpenAIClientOptions _options; /// @@ -53,64 +54,78 @@ public partial class AzureOpenAIClient : OpenAIClient /// /// /// - /// - /// - /// The Azure OpenAI resource endpoint to use. This should not include model deployment or operation information. - /// + /// The Azure OpenAI resource endpoint to use. This should not include model deployment or operation information. For example: https://my-resource.openai.azure.com. + /// The API key to authenticate with the service. + public AzureOpenAIClient(Uri endpoint, ApiKeyCredential credential) : this(endpoint, credential, new AzureOpenAIClientOptions()) + { + } + + /// + /// Creates a new instance of that will connect to a specified Azure OpenAI + /// service resource endpoint using an API key. + /// + /// /// - /// Example: https://my-resource.openai.azure.com + /// For token-based authentication, including the use of managed identity, please use the alternate constructor: + /// /// - /// - /// The API key to use when authenticating with the specified endpoint. - /// Additional options for the client. - public AzureOpenAIClient(Uri endpoint, ApiKeyCredential credential, AzureOpenAIClientOptions options = null) - : this( - CreatePipeline(GetApiKey(credential, requireExplicitCredential: true), options), - GetEndpoint(endpoint, requireExplicitEndpoint: true), - options) - {} - - /// - public AzureOpenAIClient(Uri endpoint, AzureKeyCredential credential, AzureOpenAIClientOptions options = null) - : this( - CreatePipeline(GetApiKey(new ApiKeyCredential(credential?.Key), requireExplicitCredential: true), options), - GetEndpoint(endpoint, requireExplicitEndpoint: true), - options) - {} + /// + /// The Azure OpenAI resource endpoint to use. This should not include model deployment or operation information. For example: https://my-resource.openai.azure.com. + /// The API key to authenticate with the service. + /// The options to configure the client. + public AzureOpenAIClient(Uri endpoint, AzureKeyCredential credential) : this(endpoint, credential, new AzureOpenAIClientOptions()) + { + } /// /// Creates a new instance of that will connect to an Azure OpenAI service resource - /// using endpoint and authentication settings from available configuration information. + /// using token authentication, including for tokens issued via managed identity. + /// + /// + /// For API-key-based authentication, please use the alternate constructor: + /// + /// + /// The Azure OpenAI resource endpoint to use. This should not include model deployment or operation information. For example: https://my-resource.openai.azure.com. + /// The token credential to authenticate with the service. + public AzureOpenAIClient(Uri endpoint, TokenCredential credential) : this(endpoint, credential, new AzureOpenAIClientOptions()) + { + } + + /// + /// Creates a new instance of that will connect to a specified Azure OpenAI + /// service resource endpoint using an API key. /// /// /// /// For token-based authentication, including the use of managed identity, please use the alternate constructor: /// /// + /// + /// The Azure OpenAI resource endpoint to use. This should not include model deployment or operation information. For example: https://my-resource.openai.azure.com. + /// The API key to authenticate with the service. + /// The options to configure the client. + public AzureOpenAIClient(Uri endpoint, ApiKeyCredential credential, AzureOpenAIClientOptions options) + : this(CreatePipeline(credential, options), endpoint, options) + { + } + + /// + /// Creates a new instance of that will connect to a specified Azure OpenAI + /// service resource endpoint using an API key. + /// + /// /// - /// The client selects its resource endpoint in the following order of precedence: - /// - /// The property on , if available - /// The setting in an applicable IConfiguration instance, if available - /// The value of the AZURE_OPENAI_ENDPOINT environment variable, if present - /// - /// - /// The client selects its API key credential in the following order of precedence: - /// - /// The setting in an applicable IConfiguration instance, if available - /// The value of the AZURE_OPENAI_API_KEY environment variable, if present - /// - /// - /// Note: resource endpoints should not include model deployment or operation information. - /// - /// - /// Example: https://my-resource.openai.azure.com + /// For token-based authentication, including the use of managed identity, please use the alternate constructor: + /// /// /// - /// Additional options for the client. - public AzureOpenAIClient(AzureOpenAIClientOptions options = null) - : this(CreatePipeline(GetApiKey(), options), GetEndpoint(), options) - {} + /// The Azure OpenAI resource endpoint to use. This should not include model deployment or operation information. For example: https://my-resource.openai.azure.com. + /// The API key to authenticate with the service. + /// The options to configure the client. + public AzureOpenAIClient(Uri endpoint, AzureKeyCredential credential, AzureOpenAIClientOptions options) + : this(CreatePipeline(credential?.Key, options), endpoint, options) + { + } /// /// Creates a new instance of that will connect to an Azure OpenAI service resource @@ -128,15 +143,11 @@ public AzureOpenAIClient(AzureOpenAIClientOptions options = null) /// Example: https://my-resource.openai.azure.com /// /// - /// - /// - /// The API key to use when authenticating with the provided endpoint. - /// - /// + /// The API key to use when authenticating with the provided endpoint. /// The scenario-independent options to use. public AzureOpenAIClient(Uri endpoint, TokenCredential credential, AzureOpenAIClientOptions options = null) - : this(CreatePipeline(credential, options), GetEndpoint(endpoint, requireExplicitEndpoint: true), options) - {} + : this(CreatePipeline(credential, options), endpoint, options) + { } /// /// Creates a new instance of . @@ -145,8 +156,13 @@ public AzureOpenAIClient(Uri endpoint, TokenCredential credential, AzureOpenAICl /// The endpoint to use. /// The additional client options to use. protected AzureOpenAIClient(ClientPipeline pipeline, Uri endpoint, AzureOpenAIClientOptions options) - : base(pipeline, endpoint, options) + : base(pipeline, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); + options ??= new(); + + _endpoint = endpoint; _options = options; } @@ -162,7 +178,7 @@ protected AzureOpenAIClient() /// A new instance. [Experimental("OPENAI001")] public override AssistantClient GetAssistantClient() - => new AzureAssistantClient(Pipeline, Endpoint, _options); + => new AzureAssistantClient(Pipeline, _endpoint, _options); /// /// Gets a new instance configured for audio operation use with the Azure OpenAI service. @@ -170,7 +186,7 @@ public override AssistantClient GetAssistantClient() /// The model deployment name to use for the new client's audio operations. /// A new instance. public override AudioClient GetAudioClient(string deploymentName) - => new AzureAudioClient(Pipeline, deploymentName, Endpoint, _options); + => new AzureAudioClient(Pipeline, deploymentName, _endpoint, _options); /// /// Gets a new instance configured for batch operation use with the Azure OpenAI service. @@ -178,7 +194,7 @@ public override AudioClient GetAudioClient(string deploymentName) /// The model deployment name to use for the new client's audio operations. /// A new instance. public BatchClient GetBatchClient(string deploymentName) - => new AzureBatchClient(Pipeline, deploymentName, Endpoint, _options); + => new AzureBatchClient(Pipeline, deploymentName, _endpoint, _options); /// /// This method is unsupported for Azure OpenAI. Please use the alternate @@ -193,7 +209,7 @@ public BatchClient GetBatchClient(string deploymentName) /// The model deployment name to use for the new client's chat completion operations. /// A new instance. public override ChatClient GetChatClient(string deploymentName) - => new AzureChatClient(Pipeline, deploymentName, Endpoint, _options); + => new AzureChatClient(Pipeline, deploymentName, _endpoint, _options); /// /// Gets a new instance configured for embedding operation use with the Azure OpenAI service. @@ -201,21 +217,21 @@ public override ChatClient GetChatClient(string deploymentName) /// The model deployment name to use for the new client's embedding operations. /// A new instance. public override EmbeddingClient GetEmbeddingClient(string deploymentName) - => new AzureEmbeddingClient(Pipeline, deploymentName, Endpoint, _options); + => new AzureEmbeddingClient(Pipeline, deploymentName, _endpoint, _options); /// /// Gets a new instance configured for file operation use with the Azure OpenAI service. /// /// A new instance. public override FileClient GetFileClient() - => new AzureFileClient(Pipeline, Endpoint, _options); + => new AzureFileClient(Pipeline, _endpoint, _options); /// /// Gets a new instance configured for fine-tuning operation use with the Azure OpenAI service. /// /// A new instance. public override FineTuningClient GetFineTuningClient() - => new AzureFineTuningClient(Pipeline, Endpoint, _options); + => new AzureFineTuningClient(Pipeline, _endpoint, _options); /// /// Gets a new instance configured for image operation use with the Azure OpenAI service. @@ -223,7 +239,7 @@ public override FineTuningClient GetFineTuningClient() /// The model deployment name to use for the new client's image operations. /// A new instance. public override ImageClient GetImageClient(string deploymentName) - => new AzureImageClient(Pipeline, deploymentName, Endpoint, _options); + => new AzureImageClient(Pipeline, deploymentName, _endpoint, _options); /// /// Model management operations are not supported with Azure OpenAI. @@ -249,18 +265,21 @@ public override ModerationClient GetModerationClient(string _) /// A new instance. [Experimental("OPENAI001")] public override VectorStoreClient GetVectorStoreClient() - => new AzureVectorStoreClient(Pipeline, Endpoint, _options); + => new AzureVectorStoreClient(Pipeline, _endpoint, _options); private static ClientPipeline CreatePipeline(PipelinePolicy authenticationPolicy, AzureOpenAIClientOptions options) - => ClientPipeline.Create( + { + return ClientPipeline.Create( options ?? new(), - perCallPolicies: [], - perTryPolicies: - [ + perCallPolicies: [ + ], + perTryPolicies: [ authenticationPolicy, CreateAddUserAgentHeaderPolicy(options), ], - beforeTransportPolicies: []); + beforeTransportPolicies: [ + ]); + } internal static ClientPipeline CreatePipeline(ApiKeyCredential credential, AzureOpenAIClientOptions options = null) { @@ -274,60 +293,6 @@ internal static ClientPipeline CreatePipeline(TokenCredential credential, AzureO return CreatePipeline(new AzureTokenAuthenticationPolicy(credential), options); } - internal static new ApiKeyCredential GetApiKey(ApiKeyCredential explicitCredential = null, bool requireExplicitCredential = false) - { - if (explicitCredential is not null) - { - return explicitCredential; - } - // To do: IConfiguration support - else if (requireExplicitCredential) - { - throw new ArgumentNullException(nameof(explicitCredential), $"A non-null credential value is required."); - } - else - { - string environmentApiKey = Environment.GetEnvironmentVariable(s_aoaiApiKeyEnvironmentVariable); - if (string.IsNullOrEmpty(environmentApiKey)) - { - throw new InvalidOperationException( - $"No environment variable value was found for AZURE_OPENAI_API_KEY. " - + "Please either populate this environment variable or provide authentication information directly " - + "to the client constructor."); - } - return new(environmentApiKey); - } - } - - internal static Uri GetEndpoint(Uri explicitEndpoint = null, bool requireExplicitEndpoint = false, AzureOpenAIClientOptions options = null) - { - if (explicitEndpoint is not null) - { - return explicitEndpoint; - } - else if (options?.Endpoint is not null) - { - return options.Endpoint; - } - // To do: IConfiguration support - else if (requireExplicitEndpoint) - { - throw new ArgumentNullException(nameof(explicitEndpoint), $"A non-null endpoint value is required."); - } - else - { - string environmentApiKey = Environment.GetEnvironmentVariable(s_aoaiEndpointEnvironmentVariable); - if (string.IsNullOrEmpty(environmentApiKey)) - { - throw new InvalidOperationException( - $"No environment variable value was found for AZURE_OPENAI_ENDPOINT. " - + "Please either populate this environment variable or provide endpoint information directly " - + "to the client constructor."); - } - return new(environmentApiKey); - } - } - private static PipelinePolicy CreateAddUserAgentHeaderPolicy(AzureOpenAIClientOptions options = null) { Core.TelemetryDetails telemetryDetails = new(typeof(AzureOpenAIClient).Assembly); @@ -341,8 +306,6 @@ private static PipelinePolicy CreateAddUserAgentHeaderPolicy(AzureOpenAIClientOp }); } - private static readonly string s_aoaiEndpointEnvironmentVariable = "AZURE_OPENAI_ENDPOINT"; - private static readonly string s_aoaiApiKeyEnvironmentVariable = "AZURE_OPENAI_API_KEY"; private static readonly string s_userAgentHeaderKey = "User-Agent"; private static PipelineMessageClassifier _pipelineMessageClassifier; internal static PipelineMessageClassifier PipelineMessageClassifier diff --git a/.dotnet.azure/src/Custom/Batch/AzureBatchClient.cs b/.dotnet.azure/src/Custom/Batch/AzureBatchClient.cs index 56058a27e..74c15b8e4 100644 --- a/.dotnet.azure/src/Custom/Batch/AzureBatchClient.cs +++ b/.dotnet.azure/src/Custom/Batch/AzureBatchClient.cs @@ -18,20 +18,20 @@ internal partial class AzureBatchClient : BatchClient private readonly string _deploymentName; private readonly string _apiVersion; - internal AzureBatchClient( - ClientPipeline pipeline, - string deploymentName, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, endpoint, options) + internal AzureBatchClient(ClientPipeline pipeline, string deploymentName, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, new OpenAIClientOptions() { Endpoint = endpoint }) { - options ??= new(); + Argument.AssertNotNull(pipeline, nameof(pipeline)); Argument.AssertNotNullOrEmpty(deploymentName, nameof(deploymentName)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); + options ??= new(); + _deploymentName = deploymentName; _endpoint = endpoint; _apiVersion = options.Version; } protected AzureBatchClient() - { } + { + } } diff --git a/.dotnet.azure/src/Custom/Chat/AzureChatClient.cs b/.dotnet.azure/src/Custom/Chat/AzureChatClient.cs index 89949a52d..75e131b08 100644 --- a/.dotnet.azure/src/Custom/Chat/AzureChatClient.cs +++ b/.dotnet.azure/src/Custom/Chat/AzureChatClient.cs @@ -21,21 +21,21 @@ internal partial class AzureChatClient : ChatClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureChatClient( - ClientPipeline pipeline, - string deploymentName, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, model: deploymentName, endpoint, options) + internal AzureChatClient(ClientPipeline pipeline, string deploymentName, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, model: deploymentName, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(deploymentName, nameof(deploymentName)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _deploymentName = deploymentName; - _endpoint = endpoint; _apiVersion = options.Version; } protected AzureChatClient() - { } + { + } /// public override AsyncCollectionResult CompleteChatStreamingAsync(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) diff --git a/.dotnet.azure/src/Custom/Embeddings/AzureEmbeddingClient.cs b/.dotnet.azure/src/Custom/Embeddings/AzureEmbeddingClient.cs index cc35248ac..cb986e80e 100644 --- a/.dotnet.azure/src/Custom/Embeddings/AzureEmbeddingClient.cs +++ b/.dotnet.azure/src/Custom/Embeddings/AzureEmbeddingClient.cs @@ -18,19 +18,20 @@ internal partial class AzureEmbeddingClient : EmbeddingClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureEmbeddingClient( - ClientPipeline pipeline, - string deploymentName, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, model: deploymentName, endpoint, options) + internal AzureEmbeddingClient(ClientPipeline pipeline, string deploymentName, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, model: deploymentName, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(deploymentName, nameof(deploymentName)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _deploymentName = deploymentName; _endpoint = endpoint; _apiVersion = options.Version; } protected AzureEmbeddingClient() - { } + { + } } diff --git a/.dotnet.azure/src/Custom/Files/AzureFileClient.cs b/.dotnet.azure/src/Custom/Files/AzureFileClient.cs index e48e989f3..699219c66 100644 --- a/.dotnet.azure/src/Custom/Files/AzureFileClient.cs +++ b/.dotnet.azure/src/Custom/Files/AzureFileClient.cs @@ -18,19 +18,20 @@ internal partial class AzureFileClient : FileClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureFileClient( - ClientPipeline pipeline, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, endpoint, options) + internal AzureFileClient(ClientPipeline pipeline, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _endpoint = endpoint; _apiVersion = options.Version; } protected AzureFileClient() - { } + { + } /// public override ClientResult UploadFile(Stream file, string filename, FileUploadPurpose purpose, CancellationToken cancellationToken = default) diff --git a/.dotnet.azure/src/Custom/FineTuning/AzureFineTuningClient.cs b/.dotnet.azure/src/Custom/FineTuning/AzureFineTuningClient.cs index 2b3c0f1d6..afca340b4 100644 --- a/.dotnet.azure/src/Custom/FineTuning/AzureFineTuningClient.cs +++ b/.dotnet.azure/src/Custom/FineTuning/AzureFineTuningClient.cs @@ -17,17 +17,18 @@ internal partial class AzureFineTuningClient : FineTuningClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureFineTuningClient( - ClientPipeline pipeline, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, endpoint, options) + internal AzureFineTuningClient(ClientPipeline pipeline, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _endpoint = endpoint; _apiVersion = options.Version; } protected AzureFineTuningClient() - { } + { + } } diff --git a/.dotnet.azure/src/Custom/Images/AzureImageClient.cs b/.dotnet.azure/src/Custom/Images/AzureImageClient.cs index f6e35676f..5ddabe8f3 100644 --- a/.dotnet.azure/src/Custom/Images/AzureImageClient.cs +++ b/.dotnet.azure/src/Custom/Images/AzureImageClient.cs @@ -18,19 +18,20 @@ internal partial class AzureImageClient : ImageClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureImageClient( - ClientPipeline pipeline, - string deploymentName, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, model: deploymentName, endpoint, options) + internal AzureImageClient(ClientPipeline pipeline, string deploymentName, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, model: deploymentName, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNullOrEmpty(deploymentName, nameof(deploymentName)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _deploymentName = deploymentName; _endpoint = endpoint; _apiVersion = options.Version; } protected AzureImageClient() - {} + { + } } diff --git a/.dotnet.azure/src/Custom/VectorStores/AzureVectorStoreClient.cs b/.dotnet.azure/src/Custom/VectorStores/AzureVectorStoreClient.cs index 5d6bcd29a..4b46bcde3 100644 --- a/.dotnet.azure/src/Custom/VectorStores/AzureVectorStoreClient.cs +++ b/.dotnet.azure/src/Custom/VectorStores/AzureVectorStoreClient.cs @@ -19,17 +19,18 @@ internal partial class AzureVectorStoreClient : VectorStoreClient private readonly Uri _endpoint; private readonly string _apiVersion; - internal AzureVectorStoreClient( - ClientPipeline pipeline, - Uri endpoint, - AzureOpenAIClientOptions options) - : base(pipeline, endpoint, options) + internal AzureVectorStoreClient(ClientPipeline pipeline, Uri endpoint, AzureOpenAIClientOptions options) + : base(pipeline, new OpenAIClientOptions() { Endpoint = endpoint }) { + Argument.AssertNotNull(pipeline, nameof(pipeline)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); options ??= new(); + _endpoint = endpoint; _apiVersion = options.Version; } protected AzureVectorStoreClient() - { } + { + } } diff --git a/.dotnet/CHANGELOG.md b/.dotnet/CHANGELOG.md index 60e7098ba..b3ef5c92f 100644 --- a/.dotnet/CHANGELOG.md +++ b/.dotnet/CHANGELOG.md @@ -5,15 +5,20 @@ ### 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) + ### Bugs Fixed ### Other Changes diff --git a/.dotnet/api/OpenAI.netstandard2.0.cs b/.dotnet/api/OpenAI.netstandard2.0.cs index 9937bf300..108bfa76c 100644 --- a/.dotnet/api/OpenAI.netstandard2.0.cs +++ b/.dotnet/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)] @@ -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); @@ -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); @@ -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/.dotnet/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs b/.dotnet/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs index 549ea3db0..6d9117e9c 100644 --- a/.dotnet/examples/Assistants/Example01_RetrievalAugmentedGeneration.cs +++ b/.dotnet/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/.dotnet/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs b/.dotnet/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs index 83b95fb0e..13b49145a 100644 --- a/.dotnet/examples/Assistants/Example01_RetrievalAugmentedGenerationAsync.cs +++ b/.dotnet/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/.dotnet/examples/Assistants/Example04_AllTheTools.cs b/.dotnet/examples/Assistants/Example04_AllTheTools.cs index 3d55253d0..5a8943052 100644 --- a/.dotnet/examples/Assistants/Example04_AllTheTools.cs +++ b/.dotnet/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/.dotnet/examples/Assistants/Example05_AssistantsWithVision.cs b/.dotnet/examples/Assistants/Example05_AssistantsWithVision.cs index 4d10c84cf..99315cdfb 100644 --- a/.dotnet/examples/Assistants/Example05_AssistantsWithVision.cs +++ b/.dotnet/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/.dotnet/examples/Assistants/Example05_AssistantsWithVisionAsync.cs b/.dotnet/examples/Assistants/Example05_AssistantsWithVisionAsync.cs index 3f79137e8..db23818dd 100644 --- a/.dotnet/examples/Assistants/Example05_AssistantsWithVisionAsync.cs +++ b/.dotnet/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/.dotnet/examples/CombinationExamples.cs b/.dotnet/examples/CombinationExamples.cs index 31d5ef4cd..c4b460b1c 100644 --- a/.dotnet/examples/CombinationExamples.cs +++ b/.dotnet/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/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index 3ca8be2f8..036f71be6 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs b/.dotnet/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs index baaf1a3af..625f36158 100644 --- a/.dotnet/src/Custom/Assistants/Internal/InternalAssistantMessageClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs b/.dotnet/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs index 675133fa1..8b6474cfe 100644 --- a/.dotnet/src/Custom/Assistants/Internal/InternalAssistantRunClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs b/.dotnet/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs index e99afc049..295a8a492 100644 --- a/.dotnet/src/Custom/Assistants/Internal/InternalAssistantThreadClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index bf5ab688b..fff3bc7db 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Batch/BatchClient.Protocol.cs b/.dotnet/src/Custom/Batch/BatchClient.Protocol.cs index 11cc1097c..525dce1ae 100644 --- a/.dotnet/src/Custom/Batch/BatchClient.Protocol.cs +++ b/.dotnet/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/.dotnet/src/Custom/Batch/BatchClient.cs b/.dotnet/src/Custom/Batch/BatchClient.cs index adce1b0d1..f84fa5b74 100644 --- a/.dotnet/src/Custom/Batch/BatchClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Chat/ChatClient.cs b/.dotnet/src/Custom/Chat/ChatClient.cs index 2f366b9a1..1eb1c0e1a 100644 --- a/.dotnet/src/Custom/Chat/ChatClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs b/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs index 2280c9b54..eae8dad2c 100644 --- a/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index 3b8f7c338..c18d8c713 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/FineTuning/FineTuningClient.cs b/.dotnet/src/Custom/FineTuning/FineTuningClient.cs index 6313c783f..0d4ff991f 100644 --- a/.dotnet/src/Custom/FineTuning/FineTuningClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 7f57dd889..b7efdd384 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs b/.dotnet/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs index 074625f2e..7d50115ce 100644 --- a/.dotnet/src/Custom/LegacyCompletions/Internal/LegacyCompletionClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Models/ModelClient.cs b/.dotnet/src/Custom/Models/ModelClient.cs index 56e20876a..efbadd6d7 100644 --- a/.dotnet/src/Custom/Models/ModelClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/Moderations/ModerationClient.cs b/.dotnet/src/Custom/Moderations/ModerationClient.cs index 44cfde541..d425f1ad9 100644 --- a/.dotnet/src/Custom/Moderations/ModerationClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/OpenAIClient.cs b/.dotnet/src/Custom/OpenAIClient.cs index 287c4ca81..08005f934 100644 --- a/.dotnet/src/Custom/OpenAIClient.cs +++ b/.dotnet/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/.dotnet/src/Custom/VectorStores/VectorStoreClient.cs b/.dotnet/src/Custom/VectorStores/VectorStoreClient.cs index 1d5947894..5edeb0dfb 100644 --- a/.dotnet/src/Custom/VectorStores/VectorStoreClient.cs +++ b/.dotnet/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/.dotnet/src/Generated/ChatClient.cs b/.dotnet/src/Generated/ChatClient.cs index 681019cf2..6db94d5ea 100644 --- a/.dotnet/src/Generated/ChatClient.cs +++ b/.dotnet/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/.dotnet/src/Generated/FineTuningClient.cs b/.dotnet/src/Generated/FineTuningClient.cs index 7424e0331..c4446699d 100644 --- a/.dotnet/src/Generated/FineTuningClient.cs +++ b/.dotnet/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/.dotnet/src/Generated/LegacyCompletionClient.cs b/.dotnet/src/Generated/LegacyCompletionClient.cs index 84402ded2..efb44faac 100644 --- a/.dotnet/src/Generated/LegacyCompletionClient.cs +++ b/.dotnet/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/.dotnet/src/Generated/VectorStoreClient.cs b/.dotnet/src/Generated/VectorStoreClient.cs index 6f2be46a8..5e44c7abe 100644 --- a/.dotnet/src/Generated/VectorStoreClient.cs +++ b/.dotnet/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/.dotnet/tests/Assistants/AssistantTests.cs b/.dotnet/tests/Assistants/AssistantTests.cs index b38e4e5cf..263480681 100644 --- a/.dotnet/tests/Assistants/AssistantTests.cs +++ b/.dotnet/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/.dotnet/tests/Assistants/VectorStoreTests.cs b/.dotnet/tests/Assistants/VectorStoreTests.cs index ea1d2b7ae..ed4426f30 100644 --- a/.dotnet/tests/Assistants/VectorStoreTests.cs +++ b/.dotnet/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/.dotnet/tests/Batch/BatchTests.cs b/.dotnet/tests/Batch/BatchTests.cs index 16b7c5b4c..65be9eaa5 100644 --- a/.dotnet/tests/Batch/BatchTests.cs +++ b/.dotnet/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/.dotnet/tests/Embeddings/EmbeddingTests.cs b/.dotnet/tests/Embeddings/EmbeddingTests.cs index a20f6b9b2..94ebfe8b5 100644 --- a/.dotnet/tests/Embeddings/EmbeddingTests.cs +++ b/.dotnet/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/.dotnet/tests/Models/ModelTests.cs b/.dotnet/tests/Models/ModelTests.cs index 92bbaf887..aa5078490 100644 --- a/.dotnet/tests/Models/ModelTests.cs +++ b/.dotnet/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/.dotnet/tests/Moderations/ModerationTests.cs b/.dotnet/tests/Moderations/ModerationTests.cs index 3c10fbfab..bb5b0e25c 100644 --- a/.dotnet/tests/Moderations/ModerationTests.cs +++ b/.dotnet/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/.dotnet/tests/UserAgentTests.cs b/.dotnet/tests/UserAgentTests.cs index 3af362178..31b74e11d 100644 --- a/.dotnet/tests/UserAgentTests.cs +++ b/.dotnet/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/.dotnet/tests/Utility/TestHelpers.cs b/.dotnet/tests/Utility/TestHelpers.cs index 9231231e5..9fb30f472 100644 --- a/.dotnet/tests/Utility/TestHelpers.cs +++ b/.dotnet/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;