From 26acfdc3a85c556e6a4fc6f52e46ce1cced55a51 Mon Sep 17 00:00:00 2001 From: ShivangiReja Date: Mon, 26 Aug 2024 12:34:14 -0700 Subject: [PATCH 1/3] Move service methods for paginated endpoints to use SCM based pagination pattern --- CHANGELOG.md | 24 ++++ api/OpenAI.netstandard2.0.cs | 28 ++--- .../Audio/Example01_SimpleTextToSpeech.cs | 2 +- .../Example01_SimpleTextToSpeechAsync.cs | 2 +- examples/CombinationExamples.cs | 6 +- .../Pagination/AssistantsPageEnumerator.cs | 2 +- .../Pagination/MessagesPageEnumerator.cs | 2 +- .../Pagination/RunStepsPageEnumerator.cs | 2 +- .../Internal/Pagination/RunsPageEnumerator.cs | 2 +- src/Custom/Audio/AudioClient.Protocol.cs | 4 +- src/Custom/Audio/AudioClient.cs | 8 +- src/Custom/Batch/BatchClient.Protocol.cs | 13 +- .../Pagination/BatchesPageEnumerator.cs | 109 ++++++++++++++++ src/Custom/Files/OpenAIFileInfo.cs | 2 +- src/Custom/Files/OpenAIFilesModelFactory.cs | 2 +- .../FineTuning/FineTuningClient.Protocol.cs | 53 ++++---- .../FineTuningJobCheckpointsPageEnumerator.cs | 116 +++++++++++++++++ .../FineTuningJobEventsPageEnumerator.cs | 117 ++++++++++++++++++ .../FineTuningJobsPageEnumerator.cs | 109 ++++++++++++++++ src/Custom/OpenAIClient.cs | 3 +- src/Custom/OpenAIClientOptions.cs | 64 ++++++++-- .../VectorStoreFileBatchesPageEnumerator.cs | 2 +- .../VectorStoreFilesPageEnumerator.cs | 2 +- .../Pagination/VectorStoresPageEnumerator.cs | 2 +- src/Generated/AssistantClient.cs | 10 +- src/Generated/AudioClient.cs | 6 +- src/Generated/BatchClient.cs | 8 +- src/Generated/ChatClient.cs | 2 +- src/Generated/EmbeddingClient.cs | 2 +- src/Generated/FileClient.cs | 10 +- src/Generated/FineTuningClient.cs | 12 +- src/Generated/ImageClient.cs | 6 +- .../InternalAssistantMessageClient.cs | 10 +- src/Generated/InternalAssistantRunClient.cs | 18 +-- .../InternalAssistantThreadClient.cs | 8 +- src/Generated/InternalUploadsClient.cs | 8 +- src/Generated/LegacyCompletionClient.cs | 2 +- src/Generated/ModelClient.cs | 6 +- .../Models/OpenAIFileInfo.Serialization.cs | 4 +- src/Generated/Models/OpenAIFileInfo.cs | 4 +- src/Generated/ModerationClient.cs | 2 +- src/Generated/VectorStoreClient.cs | 26 ++-- src/Utility/PageCollectionHelpers.cs | 16 +++ tests/Assistants/VectorStoreTests.cs | 4 +- tests/Audio/TextToSpeechTests.cs | 8 +- tests/Batch/BatchTests.cs | 72 ++++++++--- tests/Chat/ChatSmokeTests.cs | 25 ++++ 47 files changed, 773 insertions(+), 172 deletions(-) create mode 100644 src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs create mode 100644 src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs create mode 100644 src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs create mode 100644 src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index d8777eb6..498b3113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Release History +## 2.0.0-beta.10 (Unreleased) + +### Features Added + +### Breaking Changes + +- Removed client constructors that do not explicitly take an API key parameter or an endpoint via an `OpenAIClientOptions` parameter, making it clearer how to appropriately instantiate a client. (commit_hash) +- Removed the endpoint parameter from all client constructors, making it clearer that an alternative endpoint must be specified via the `OpenAIClientOptions` parameter. (commit_hash) +- Removed `OpenAIClient`'s `Endpoint` `protected` property. (commit_hash) +- Made `OpenAIClient`'s constructor that takes a `ClientPipeline` parameter `protected internal` instead of just `protected`. (commit_hash) +- Renamed the `User` property in applicable Options classes to `EndUserId`, making its purpose clearer. (commit_hash) +- Updated fine-tuning pagination methods `GetJobs`, `GetEvents`, and `GetJobCheckpoints` to return `IEnumerable` instead of `ClientResult`. (commit_hash) +- Updated the batching pagination method `GetBatches` to return `IEnumerable` instead of `ClientResult`. (commit_hash) +- Renamed `AudioClient`'s `GenerateSpeechFromText` methods to simply `GenerateSpeech`. (commit_hash) +- Changed the type of `OpenAIFileInfo`'s `SizeInBytes` property from `long?` to `int?`. (commit_hash) + +### Bugs Fixed + +- Fixed a newly introduced bug ([#185](https://github.com/openai/openai-dotnet/pull/185)) where providing `OpenAIClientOptions` to a top-level `OpenAIClient` did not carry over to scenario clients (e.g. `ChatClient`) created via that top-level client + +### Other Changes + +- Removed the version path parameter "v1" from the default endpoint URL. (commit_hash) + ## 2.0.0-beta.9 (2024-08-23) ### Features Added diff --git a/api/OpenAI.netstandard2.0.cs b/api/OpenAI.netstandard2.0.cs index a67971fb..9db98764 100644 --- a/api/OpenAI.netstandard2.0.cs +++ b/api/OpenAI.netstandard2.0.cs @@ -999,11 +999,11 @@ public class AudioClient { public AudioClient(string model, ApiKeyCredential credential); public virtual ClientPipeline Pipeline { get; } [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GenerateSpeechFromText(BinaryContent content, RequestOptions options = null); - public virtual ClientResult GenerateSpeechFromText(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default); + public virtual ClientResult GenerateSpeech(BinaryContent content, RequestOptions options = null); + public virtual ClientResult GenerateSpeech(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default); [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GenerateSpeechFromTextAsync(BinaryContent content, RequestOptions options = null); - public virtual Task> GenerateSpeechFromTextAsync(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default); + public virtual Task GenerateSpeechAsync(BinaryContent content, RequestOptions options = null); + public virtual Task> GenerateSpeechAsync(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default); [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult TranscribeAudio(BinaryContent content, string contentType, RequestOptions options = null); public virtual ClientResult TranscribeAudio(Stream audio, string audioFilename, AudioTranscriptionOptions options = null, CancellationToken cancellationToken = default); @@ -1170,8 +1170,8 @@ public class BatchClient { public virtual Task CreateBatchAsync(BinaryContent content, RequestOptions options = null); public virtual ClientResult GetBatch(string batchId, RequestOptions options); public virtual Task GetBatchAsync(string batchId, RequestOptions options); - public virtual ClientResult GetBatches(string after, int? limit, RequestOptions options); - public virtual Task GetBatchesAsync(string after, int? limit, RequestOptions options); + public virtual IEnumerable GetBatches(string after, int? limit, RequestOptions options); + public virtual IAsyncEnumerable GetBatchesAsync(string after, int? limit, RequestOptions options); } } namespace OpenAI.Chat { @@ -1720,7 +1720,7 @@ public class OpenAIFileInfo : IJsonModel, IPersistableModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); @@ -1758,7 +1758,7 @@ public class OpenAIFileInfoCollection : ObjectModel.ReadOnlyCollection items = null); } public readonly partial struct OpenAIFileStatus : IEquatable { @@ -1792,12 +1792,12 @@ public class FineTuningClient { public virtual Task CreateJobAsync(BinaryContent content, RequestOptions options = null); public virtual ClientResult GetJob(string jobId, RequestOptions options); public virtual Task GetJobAsync(string jobId, RequestOptions options); - public virtual ClientResult GetJobCheckpoints(string fineTuningJobId, string after, int? limit, RequestOptions options); - public virtual Task GetJobCheckpointsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options); - public virtual ClientResult GetJobEvents(string jobId, string after, int? limit, RequestOptions options); - public virtual Task GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options); - public virtual ClientResult GetJobs(string after, int? limit, RequestOptions options); - public virtual Task GetJobsAsync(string after, int? limit, RequestOptions options); + public virtual IEnumerable GetJobCheckpoints(string jobId, string after, int? limit, RequestOptions options); + public virtual IAsyncEnumerable GetJobCheckpointsAsync(string jobId, string after, int? limit, RequestOptions options); + public virtual IEnumerable GetJobEvents(string jobId, string after, int? limit, RequestOptions options); + public virtual IAsyncEnumerable GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options); + public virtual IEnumerable GetJobs(string after, int? limit, RequestOptions options); + public virtual IAsyncEnumerable GetJobsAsync(string after, int? limit, RequestOptions options); } } namespace OpenAI.Images { diff --git a/examples/Audio/Example01_SimpleTextToSpeech.cs b/examples/Audio/Example01_SimpleTextToSpeech.cs index 79b8ac12..8573152f 100644 --- a/examples/Audio/Example01_SimpleTextToSpeech.cs +++ b/examples/Audio/Example01_SimpleTextToSpeech.cs @@ -18,7 +18,7 @@ public void Example01_SimpleTextToSpeech() + " moisture, it is wise to postpone watering for a couple more days. When in doubt, it is often safer" + " to water sparingly and maintain a less-is-more approach."; - BinaryData speech = client.GenerateSpeechFromText(input, GeneratedSpeechVoice.Alloy); + BinaryData speech = client.GenerateSpeech(input, GeneratedSpeechVoice.Alloy); using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.mp3"); speech.ToStream().CopyTo(stream); diff --git a/examples/Audio/Example01_SimpleTextToSpeechAsync.cs b/examples/Audio/Example01_SimpleTextToSpeechAsync.cs index ae8432eb..7226ae73 100644 --- a/examples/Audio/Example01_SimpleTextToSpeechAsync.cs +++ b/examples/Audio/Example01_SimpleTextToSpeechAsync.cs @@ -19,7 +19,7 @@ public async Task Example01_SimpleTextToSpeechAsync() + " moisture, it is wise to postpone watering for a couple more days. When in doubt, it is often safer" + " to water sparingly and maintain a less-is-more approach."; - BinaryData speech = await client.GenerateSpeechFromTextAsync(input, GeneratedSpeechVoice.Alloy); + BinaryData speech = await client.GenerateSpeechAsync(input, GeneratedSpeechVoice.Alloy); using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.mp3"); speech.ToStream().CopyTo(stream); diff --git a/examples/CombinationExamples.cs b/examples/CombinationExamples.cs index c4b460b1..7987d81f 100644 --- a/examples/CombinationExamples.cs +++ b/examples/CombinationExamples.cs @@ -48,7 +48,7 @@ public void AlpacaArtAssessor() // Finally, we'll get some text-to-speech for that critical evaluation using tts-1-hd: AudioClient audioClient = new("tts-1-hd", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); - ClientResult ttsResult = audioClient.GenerateSpeechFromText( + ClientResult ttsResult = audioClient.GenerateSpeech( text: chatResponseText, GeneratedSpeechVoice.Fable, new SpeechGenerationOptions() @@ -84,7 +84,7 @@ public async Task CuriousCreatureCreator() // Asynchronously, in parallel to the next steps, we'll get the creative description in the voice of Onyx AudioClient ttsClient = new("tts-1-hd", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); - Task> imageDescriptionAudioTask = ttsClient.GenerateSpeechFromTextAsync( + Task> imageDescriptionAudioTask = ttsClient.GenerateSpeechAsync( description, GeneratedSpeechVoice.Onyx, new SpeechGenerationOptions() @@ -131,7 +131,7 @@ public async Task CuriousCreatureCreator() Console.WriteLine($"Critic's appraisal:\n{appraisal}"); // Finally, we'll get that art expert's laudations in the voice of Fable - ClientResult appraisalAudioResult = await ttsClient.GenerateSpeechFromTextAsync( + ClientResult appraisalAudioResult = await ttsClient.GenerateSpeechAsync( appraisal, GeneratedSpeechVoice.Fable, new SpeechGenerationOptions() diff --git a/src/Custom/Assistants/Internal/Pagination/AssistantsPageEnumerator.cs b/src/Custom/Assistants/Internal/Pagination/AssistantsPageEnumerator.cs index 66019bbb..7f970fec 100644 --- a/src/Custom/Assistants/Internal/Pagination/AssistantsPageEnumerator.cs +++ b/src/Custom/Assistants/Internal/Pagination/AssistantsPageEnumerator.cs @@ -107,7 +107,7 @@ private PipelineMessage CreateGetAssistantsRequest(int? limit, string order, str request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/assistants", false); + uri.AppendPath("/v1/assistants", false); if (limit != null) { uri.AppendQuery("limit", limit.Value, true); diff --git a/src/Custom/Assistants/Internal/Pagination/MessagesPageEnumerator.cs b/src/Custom/Assistants/Internal/Pagination/MessagesPageEnumerator.cs index 53e09fec..860bfbe0 100644 --- a/src/Custom/Assistants/Internal/Pagination/MessagesPageEnumerator.cs +++ b/src/Custom/Assistants/Internal/Pagination/MessagesPageEnumerator.cs @@ -115,7 +115,7 @@ private PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, st request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/messages", false); if (limit != null) diff --git a/src/Custom/Assistants/Internal/Pagination/RunStepsPageEnumerator.cs b/src/Custom/Assistants/Internal/Pagination/RunStepsPageEnumerator.cs index b5992ce7..1245c476 100644 --- a/src/Custom/Assistants/Internal/Pagination/RunStepsPageEnumerator.cs +++ b/src/Custom/Assistants/Internal/Pagination/RunStepsPageEnumerator.cs @@ -119,7 +119,7 @@ private PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); diff --git a/src/Custom/Assistants/Internal/Pagination/RunsPageEnumerator.cs b/src/Custom/Assistants/Internal/Pagination/RunsPageEnumerator.cs index f48ceb3c..879f389b 100644 --- a/src/Custom/Assistants/Internal/Pagination/RunsPageEnumerator.cs +++ b/src/Custom/Assistants/Internal/Pagination/RunsPageEnumerator.cs @@ -113,7 +113,7 @@ private PipelineMessage CreateGetRunsRequest(string threadId, int? limit, string request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs", false); if (limit != null) diff --git a/src/Custom/Audio/AudioClient.Protocol.cs b/src/Custom/Audio/AudioClient.Protocol.cs index ba000162..0fd68c69 100644 --- a/src/Custom/Audio/AudioClient.Protocol.cs +++ b/src/Custom/Audio/AudioClient.Protocol.cs @@ -27,7 +27,7 @@ public partial class AudioClient /// Service returned a non-success status code. /// The response returned from the service. [EditorBrowsable(EditorBrowsableState.Never)] - public virtual async Task GenerateSpeechFromTextAsync(BinaryContent content, RequestOptions options = null) + public virtual async Task GenerateSpeechAsync(BinaryContent content, RequestOptions options = null) { Argument.AssertNotNull(content, nameof(content)); @@ -48,7 +48,7 @@ public virtual async Task GenerateSpeechFromTextAsync(BinaryConten /// Service returned a non-success status code. /// The response returned from the service. [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GenerateSpeechFromText(BinaryContent content, RequestOptions options = null) + public virtual ClientResult GenerateSpeech(BinaryContent content, RequestOptions options = null) { Argument.AssertNotNull(content, nameof(content)); diff --git a/src/Custom/Audio/AudioClient.cs b/src/Custom/Audio/AudioClient.cs index fff3bc7d..58c0e49a 100644 --- a/src/Custom/Audio/AudioClient.cs +++ b/src/Custom/Audio/AudioClient.cs @@ -93,7 +93,7 @@ protected internal AudioClient(ClientPipeline pipeline, string model, OpenAIClie /// 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) + public virtual async Task> GenerateSpeechAsync(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(text, nameof(text)); @@ -101,7 +101,7 @@ public virtual async Task> GenerateSpeechFromTextAsync( CreateSpeechGenerationOptions(text, voice, ref options); using BinaryContent content = options.ToBinaryContent(); - ClientResult result = await GenerateSpeechFromTextAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false); + ClientResult result = await GenerateSpeechAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false); return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } @@ -116,7 +116,7 @@ public virtual async Task> GenerateSpeechFromTextAsync( /// 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) + public virtual ClientResult GenerateSpeech(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, CancellationToken cancellationToken = default) { Argument.AssertNotNull(text, nameof(text)); @@ -124,7 +124,7 @@ public virtual ClientResult GenerateSpeechFromText(string text, Gene CreateSpeechGenerationOptions(text, voice, ref options); using BinaryContent content = options.ToBinaryContent(); - ClientResult result = GenerateSpeechFromText(content, cancellationToken.ToRequestOptions()); ; + ClientResult result = GenerateSpeech(content, cancellationToken.ToRequestOptions()); ; return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } diff --git a/src/Custom/Batch/BatchClient.Protocol.cs b/src/Custom/Batch/BatchClient.Protocol.cs index 525dce1a..1505718a 100644 --- a/src/Custom/Batch/BatchClient.Protocol.cs +++ b/src/Custom/Batch/BatchClient.Protocol.cs @@ -1,6 +1,7 @@ using System; using System.ClientModel; using System.ClientModel.Primitives; +using System.Collections.Generic; using System.Threading.Tasks; namespace OpenAI.Batch; @@ -49,10 +50,10 @@ public virtual ClientResult CreateBatch(BinaryContent content, RequestOptions op /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetBatchesAsync(string after, int? limit, RequestOptions options) + public virtual IAsyncEnumerable GetBatchesAsync(string after, int? limit, RequestOptions options) { - using PipelineMessage message = CreateGetBatchesRequest(after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + BatchesPageEnumerator enumerator = new BatchesPageEnumerator(_pipeline, _endpoint, after, limit, options); + return PageCollectionHelpers.CreateAsync(enumerator); } /// @@ -63,10 +64,10 @@ public virtual async Task GetBatchesAsync(string after, int? limit /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. - public virtual ClientResult GetBatches(string after, int? limit, RequestOptions options) + public virtual IEnumerable GetBatches(string after, int? limit, RequestOptions options) { - using PipelineMessage message = CreateGetBatchesRequest(after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + BatchesPageEnumerator enumerator = new BatchesPageEnumerator(_pipeline, _endpoint, after, limit, options); + return PageCollectionHelpers.Create(enumerator); } /// diff --git a/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs b/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs new file mode 100644 index 00000000..6f23fb8a --- /dev/null +++ b/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs @@ -0,0 +1,109 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; + +#nullable enable + +namespace OpenAI.Batch; + +internal partial class BatchesPageEnumerator : PageResultEnumerator +{ + private readonly ClientPipeline _pipeline; + private readonly Uri _endpoint; + + private readonly int? _limit; + private readonly RequestOptions _options; + + private string _after; + + public BatchesPageEnumerator( + ClientPipeline pipeline, + Uri endpoint, + string after, int? limit, + RequestOptions options) + { + _pipeline = pipeline; + _endpoint = endpoint; + + _after = after; + _limit = limit; + _options = options; + } + + public override async Task GetFirstAsync() + => await GetBatchesAsync(_after, _limit, _options).ConfigureAwait(false); + + public override ClientResult GetFirst() + => GetBatches(_after, _limit, _options); + + public override async Task GetNextAsync(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return await GetBatchesAsync(_after, _limit, _options).ConfigureAwait(false); + } + + public override ClientResult GetNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return GetBatches(_after, _limit, _options); + } + + public override bool HasNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + bool hasMore = doc.RootElement.GetProperty("has_more"u8).GetBoolean(); + + return hasMore; + } + + internal virtual async Task GetBatchesAsync(string after, int? limit, RequestOptions options) + { + using PipelineMessage message = CreateGetBatchesRequest(after, limit, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + + internal virtual ClientResult GetBatches(string after, int? limit, RequestOptions options) + { + using PipelineMessage message = CreateGetBatchesRequest(after, limit, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + + internal PipelineMessage CreateGetBatchesRequest(string after, int? limit, RequestOptions options) + { + var message = _pipeline.CreateMessage(); + message.ResponseClassifier = PipelineMessageClassifier200; + var request = message.Request; + request.Method = "GET"; + var uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/batches", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.Headers.Set("Accept", "application/json"); + message.Apply(options); + return message; + } + + private static PipelineMessageClassifier? _pipelineMessageClassifier200; + private static PipelineMessageClassifier PipelineMessageClassifier200 => _pipelineMessageClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); +} diff --git a/src/Custom/Files/OpenAIFileInfo.cs b/src/Custom/Files/OpenAIFileInfo.cs index 0067c479..17f0d479 100644 --- a/src/Custom/Files/OpenAIFileInfo.cs +++ b/src/Custom/Files/OpenAIFileInfo.cs @@ -10,5 +10,5 @@ public partial class OpenAIFileInfo // CUSTOM: Renamed. /// The size of the file, in bytes. [CodeGenMember("Bytes")] - public long? SizeInBytes { get; } + public int? SizeInBytes { get; } } diff --git a/src/Custom/Files/OpenAIFilesModelFactory.cs b/src/Custom/Files/OpenAIFilesModelFactory.cs index 0d79b520..41c13090 100644 --- a/src/Custom/Files/OpenAIFilesModelFactory.cs +++ b/src/Custom/Files/OpenAIFilesModelFactory.cs @@ -9,7 +9,7 @@ public static partial class OpenAIFilesModelFactory { /// Initializes a new instance of . /// A new instance for mocking. - public static OpenAIFileInfo OpenAIFileInfo(string id = null, long? sizeInBytes = null, DateTimeOffset createdAt = default, string filename = null, OpenAIFilePurpose purpose = default, OpenAIFileStatus status = default, string statusDetails = null) + public static OpenAIFileInfo OpenAIFileInfo(string id = null, int? sizeInBytes = null, DateTimeOffset createdAt = default, string filename = null, OpenAIFilePurpose purpose = default, OpenAIFileStatus status = default, string statusDetails = null) { return new OpenAIFileInfo( id, diff --git a/src/Custom/FineTuning/FineTuningClient.Protocol.cs b/src/Custom/FineTuning/FineTuningClient.Protocol.cs index 2483478d..bccc9516 100644 --- a/src/Custom/FineTuning/FineTuningClient.Protocol.cs +++ b/src/Custom/FineTuning/FineTuningClient.Protocol.cs @@ -1,6 +1,7 @@ using System; using System.ClientModel; using System.ClientModel.Primitives; +using System.Collections.Generic; using System.Threading.Tasks; namespace OpenAI.FineTuning; @@ -76,10 +77,10 @@ public virtual ClientResult CreateJob(BinaryContent content, RequestOptions opti /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetJobsAsync(string after, int? limit, RequestOptions options) + public virtual IAsyncEnumerable GetJobsAsync(string after, int? limit, RequestOptions options) { - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + FineTuningJobsPageEnumerator enumerator = new FineTuningJobsPageEnumerator(_pipeline, _endpoint, after, limit, options); + return PageCollectionHelpers.CreateAsync(enumerator); } // CUSTOM: @@ -93,10 +94,10 @@ public virtual async Task GetJobsAsync(string after, int? limit, R /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. - public virtual ClientResult GetJobs(string after, int? limit, RequestOptions options) + public virtual IEnumerable GetJobs(string after, int? limit, RequestOptions options) { - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + FineTuningJobsPageEnumerator enumerator = new FineTuningJobsPageEnumerator(_pipeline, _endpoint, after, limit, options); + return PageCollectionHelpers.Create(enumerator); } // CUSTOM: @@ -197,12 +198,12 @@ public virtual ClientResult CancelJob(string jobId, RequestOptions options) /// is an empty string, and was expected to be non-empty. /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options) + public virtual IAsyncEnumerable GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options) { Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - using PipelineMessage message = CreateGetFineTuningEventsRequest(jobId, after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + FineTuningJobEventsPageEnumerator enumerator = new FineTuningJobEventsPageEnumerator(_pipeline, _endpoint, jobId, after, limit, options); + return PageCollectionHelpers.CreateAsync(enumerator); } // CUSTOM: @@ -219,49 +220,49 @@ public virtual async Task GetJobEventsAsync(string jobId, string a /// is an empty string, and was expected to be non-empty. /// Service returned a non-success status code. /// The response returned from the service. - public virtual ClientResult GetJobEvents(string jobId, string after, int? limit, RequestOptions options) + public virtual IEnumerable GetJobEvents(string jobId, string after, int? limit, RequestOptions options) { Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - using PipelineMessage message = CreateGetFineTuningEventsRequest(jobId, after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + FineTuningJobEventsPageEnumerator enumerator = new FineTuningJobEventsPageEnumerator(_pipeline, _endpoint, jobId, after, limit, options); + return PageCollectionHelpers.Create(enumerator); } /// /// [Protocol Method] List the checkpoints for a fine-tuning job. /// - /// The ID of the fine-tuning job to get checkpoints for. + /// The ID of the fine-tuning job to get checkpoints for. /// Identifier for the last checkpoint ID from the previous pagination request. /// Number of checkpoints to retrieve. /// The request options, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. + /// is null. + /// is an empty string, and was expected to be non-empty. /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetJobCheckpointsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) + public virtual IAsyncEnumerable GetJobCheckpointsAsync(string jobId, string after, int? limit, RequestOptions options) { - Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - using PipelineMessage message = CreateGetFineTuningJobCheckpointsRequest(fineTuningJobId, after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + FineTuningJobCheckpointsPageEnumerator enumerator = new FineTuningJobCheckpointsPageEnumerator(_pipeline, _endpoint, jobId, after, limit, options); + return PageCollectionHelpers.CreateAsync(enumerator); } /// /// [Protocol Method] List the checkpoints for a fine-tuning job. /// - /// The ID of the fine-tuning job to get checkpoints for. + /// The ID of the fine-tuning job to get checkpoints for. /// Identifier for the last checkpoint ID from the previous pagination request. /// Number of checkpoints to retrieve. /// The request options, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. + /// is null. + /// is an empty string, and was expected to be non-empty. /// Service returned a non-success status code. /// The response returned from the service. - public virtual ClientResult GetJobCheckpoints(string fineTuningJobId, string after, int? limit, RequestOptions options) + public virtual IEnumerable GetJobCheckpoints(string jobId, string after, int? limit, RequestOptions options) { - Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - using PipelineMessage message = CreateGetFineTuningJobCheckpointsRequest(fineTuningJobId, after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + FineTuningJobCheckpointsPageEnumerator enumerator = new FineTuningJobCheckpointsPageEnumerator(_pipeline, _endpoint, jobId, after, limit, options); + return PageCollectionHelpers.Create(enumerator); } } diff --git a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs new file mode 100644 index 00000000..0422a2a5 --- /dev/null +++ b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs @@ -0,0 +1,116 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; +using System.Threading.Tasks; + +#nullable enable + +namespace OpenAI.FineTuning; + +internal partial class FineTuningJobCheckpointsPageEnumerator : PageResultEnumerator +{ + private readonly ClientPipeline _pipeline; + private readonly Uri _endpoint; + + private readonly string _jobId; + private readonly int? _limit; + private readonly RequestOptions _options; + + private string _after; + + public FineTuningJobCheckpointsPageEnumerator( + ClientPipeline pipeline, + Uri endpoint, + string jobId, string after, int? limit, + RequestOptions options) + { + _pipeline = pipeline; + _endpoint = endpoint; + + _jobId = jobId; + _after = after; + _limit = limit; + _options = options; + } + + public override async Task GetFirstAsync() + => await GetJobCheckpointsAsync(_jobId, _after, _limit, _options).ConfigureAwait(false); + + public override ClientResult GetFirst() + => GetJobCheckpoints(_jobId, _after, _limit, _options); + + public override async Task GetNextAsync(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return await GetJobCheckpointsAsync(_jobId, _after, _limit, _options).ConfigureAwait(false); + } + + public override ClientResult GetNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return GetJobCheckpoints(_jobId, _after, _limit, _options); + } + + public override bool HasNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + bool hasMore = doc.RootElement.GetProperty("has_more"u8).GetBoolean(); + + return hasMore; + } + + internal virtual async Task GetJobCheckpointsAsync(string jobId, string after, int? limit, RequestOptions options) + { + Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); + + using PipelineMessage message = CreateGetFineTuningJobCheckpointsRequest(jobId, after, limit, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + + internal virtual ClientResult GetJobCheckpoints(string jobId, string after, int? limit, RequestOptions options) + { + Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); + + using PipelineMessage message = CreateGetFineTuningJobCheckpointsRequest(jobId, after, limit, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + + internal PipelineMessage CreateGetFineTuningJobCheckpointsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) + { + var message = _pipeline.CreateMessage(); + message.ResponseClassifier = PipelineMessageClassifier200; + var request = message.Request; + request.Method = "GET"; + var uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + uri.AppendPath("/checkpoints", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.Headers.Set("Accept", "application/json"); + message.Apply(options); + return message; + } + + private static PipelineMessageClassifier? _pipelineMessageClassifier200; + private static PipelineMessageClassifier PipelineMessageClassifier200 => _pipelineMessageClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); +} diff --git a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs new file mode 100644 index 00000000..a8bfc3b6 --- /dev/null +++ b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs @@ -0,0 +1,117 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; + +#nullable enable + +namespace OpenAI.FineTuning; + +internal partial class FineTuningJobEventsPageEnumerator : PageResultEnumerator +{ + private readonly ClientPipeline _pipeline; + private readonly Uri _endpoint; + + private readonly string _jobId; + private readonly int? _limit; + private readonly RequestOptions _options; + + private string _after; + + public FineTuningJobEventsPageEnumerator( + ClientPipeline pipeline, + Uri endpoint, + string jobId, string after, int? limit, + RequestOptions options) + { + _pipeline = pipeline; + _endpoint = endpoint; + + _jobId = jobId; + _after = after; + _limit = limit; + _options = options; + } + + public override async Task GetFirstAsync() + => await GetJobEventsAsync(_jobId, _after, _limit, _options).ConfigureAwait(false); + + public override ClientResult GetFirst() + => GetJobEvents(_jobId, _after, _limit, _options); + + public override async Task GetNextAsync(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return await GetJobEventsAsync(_jobId, _after, _limit, _options).ConfigureAwait(false); + } + + public override ClientResult GetNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return GetJobEvents(_jobId, _after, _limit, _options); + } + + public override bool HasNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + bool hasMore = doc.RootElement.GetProperty("has_more"u8).GetBoolean(); + + return hasMore; + } + + internal virtual async Task GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options) + { + Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); + + using PipelineMessage message = CreateGetFineTuningEventsRequest(jobId, after, limit, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + + internal virtual ClientResult GetJobEvents(string jobId, string after, int? limit, RequestOptions options) + { + Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); + + using PipelineMessage message = CreateGetFineTuningEventsRequest(jobId, after, limit, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + + internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) + { + var message = _pipeline.CreateMessage(); + message.ResponseClassifier = PipelineMessageClassifier200; + var request = message.Request; + request.Method = "GET"; + var uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + uri.AppendPath("/events", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.Headers.Set("Accept", "application/json"); + message.Apply(options); + return message; + } + + private static PipelineMessageClassifier? _pipelineMessageClassifier200; + private static PipelineMessageClassifier PipelineMessageClassifier200 => _pipelineMessageClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); +} diff --git a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs new file mode 100644 index 00000000..3c7c8b30 --- /dev/null +++ b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs @@ -0,0 +1,109 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; + +#nullable enable + +namespace OpenAI.FineTuning; + +internal partial class FineTuningJobsPageEnumerator : PageResultEnumerator +{ + private readonly ClientPipeline _pipeline; + private readonly Uri _endpoint; + + private readonly int? _limit; + private readonly RequestOptions _options; + + private string _after; + + public FineTuningJobsPageEnumerator( + ClientPipeline pipeline, + Uri endpoint, + string after, int? limit, + RequestOptions options) + { + _pipeline = pipeline; + _endpoint = endpoint; + + _after = after; + _limit = limit; + _options = options; + } + + public override async Task GetFirstAsync() + => await GetJobsAsync(_after, _limit, _options).ConfigureAwait(false); + + public override ClientResult GetFirst() + => GetJobs(_after, _limit, _options); + + public override async Task GetNextAsync(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return await GetJobsAsync(_after, _limit, _options).ConfigureAwait(false); + } + + public override ClientResult GetNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + _after = doc.RootElement.GetProperty("last_id"u8).GetString()!; + + return GetJobs(_after, _limit, _options); + } + + public override bool HasNext(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + + using JsonDocument doc = JsonDocument.Parse(response.Content); + bool hasMore = doc.RootElement.GetProperty("has_more"u8).GetBoolean(); + + return hasMore; + } + + internal virtual async Task GetJobsAsync(string after, int? limit, RequestOptions options) + { + using PipelineMessage message = CreateGetFineTuningJobsRequest(after, limit, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + + internal virtual ClientResult GetJobs(string after, int? limit, RequestOptions options) + { + using PipelineMessage message = CreateGetFineTuningJobsRequest(after, limit, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + + internal PipelineMessage CreateGetFineTuningJobsRequest(string after, int? limit, RequestOptions options) + { + var message = _pipeline.CreateMessage(); + message.ResponseClassifier = PipelineMessageClassifier200; + var request = message.Request; + request.Method = "GET"; + var uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.Headers.Set("Accept", "application/json"); + message.Apply(options); + return message; + } + + private static PipelineMessageClassifier? _pipelineMessageClassifier200; + private static PipelineMessageClassifier PipelineMessageClassifier200 => _pipelineMessageClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); +} diff --git a/src/Custom/OpenAIClient.cs b/src/Custom/OpenAIClient.cs index 3518a18e..45e4e275 100644 --- a/src/Custom/OpenAIClient.cs +++ b/src/Custom/OpenAIClient.cs @@ -61,7 +61,7 @@ namespace OpenAI; [CodeGenSuppress("GetVectorStoreClientClient")] public partial class OpenAIClient { - private const string OpenAIV1Endpoint = "https://api.openai.com/v1"; + private const string OpenAIV1Endpoint = "https://api.openai.com"; private const string OpenAIBetaHeaderValue = "assistants=v2"; private static class KnownHeaderNames @@ -98,6 +98,7 @@ public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions options) _pipeline = OpenAIClient.CreatePipeline(credential, options); _endpoint = OpenAIClient.GetEndpoint(options); + _options = options; } // CUSTOM: Added protected internal constructor that takes a ClientPipeline. diff --git a/src/Custom/OpenAIClientOptions.cs b/src/Custom/OpenAIClientOptions.cs index 81efabbd..396cbf0b 100644 --- a/src/Custom/OpenAIClientOptions.cs +++ b/src/Custom/OpenAIClientOptions.cs @@ -3,29 +3,71 @@ namespace OpenAI; -/// -/// Client-level options for the OpenAI service. -/// +/// The options to configure the client. [CodeGenModel("OpenAIClientOptions")] public partial class OpenAIClientOptions : ClientPipelineOptions { + private Uri _endpoint; + private string _organizationId; + private string _projectId; + private string _applicationId; + /// - /// A non-default base endpoint that clients should use when connecting. + /// The service endpoint that the client will send requests to. If not set, the default endpoint will be used. /// - public Uri Endpoint { get; set; } + public Uri Endpoint + { + get => _endpoint; + set + { + AssertNotFrozen(); + _endpoint = value; + } + } /// - /// An optional application ID to use as part of the request User-Agent header. + /// The value to use for the OpenAI-Organization request header. Users who belong to multiple organizations + /// can set this value to specify which organization is used for an API request. Usage from these API requests will + /// count against the specified organization's quota. If not set, the header will be omitted, and the default + /// organization will be billed. You can change your default organization in your user settings. + /// Learn more. /// - public string ApplicationId { get; set; } + public string OrganizationId + { + get => _organizationId; + set + { + AssertNotFrozen(); + _organizationId = value; + } + } /// - /// An optional ID added to OpenAI-Organization header + /// The value to use for the OpenAI-Project request header. Users who are accessing their projects through + /// their legacy user API key can set this value to specify which project is used for an API request. Usage from + /// these API requests will count as usage for the specified project. If not set, the header will be omitted, and + /// the default project will be accessed. /// - public string OrganizationId { get; set; } + public string ProjectId + { + get => _projectId; + set + { + AssertNotFrozen(); + _projectId = value; + } + } /// - /// An optional ID added to OpenAI-Project header + /// An optional application ID to use as part of the request User-Agent header. /// - public string ProjectId { get; set; } + public string ApplicationId + { + get => _applicationId; + set + { + AssertNotFrozen(); + _applicationId = value; + } + } } diff --git a/src/Custom/VectorStores/Internal/Pagination/VectorStoreFileBatchesPageEnumerator.cs b/src/Custom/VectorStores/Internal/Pagination/VectorStoreFileBatchesPageEnumerator.cs index 1445485d..3212db4d 100644 --- a/src/Custom/VectorStores/Internal/Pagination/VectorStoreFileBatchesPageEnumerator.cs +++ b/src/Custom/VectorStores/Internal/Pagination/VectorStoreFileBatchesPageEnumerator.cs @@ -121,7 +121,7 @@ internal PipelineMessage CreateGetFilesInVectorStoreBatchesRequest(string vector request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/file_batches/", false); uri.AppendPath(batchId, true); diff --git a/src/Custom/VectorStores/Internal/Pagination/VectorStoreFilesPageEnumerator.cs b/src/Custom/VectorStores/Internal/Pagination/VectorStoreFilesPageEnumerator.cs index 9a5e9bec..81506b05 100644 --- a/src/Custom/VectorStores/Internal/Pagination/VectorStoreFilesPageEnumerator.cs +++ b/src/Custom/VectorStores/Internal/Pagination/VectorStoreFilesPageEnumerator.cs @@ -116,7 +116,7 @@ internal PipelineMessage CreateGetVectorStoreFilesRequest(string vectorStoreId, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/files", false); if (limit != null) diff --git a/src/Custom/VectorStores/Internal/Pagination/VectorStoresPageEnumerator.cs b/src/Custom/VectorStores/Internal/Pagination/VectorStoresPageEnumerator.cs index 311a8837..d3416a3b 100644 --- a/src/Custom/VectorStores/Internal/Pagination/VectorStoresPageEnumerator.cs +++ b/src/Custom/VectorStores/Internal/Pagination/VectorStoresPageEnumerator.cs @@ -106,7 +106,7 @@ internal PipelineMessage CreateGetVectorStoresRequest(int? limit, string order, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores", false); + uri.AppendPath("/v1/vector_stores", false); if (limit != null) { uri.AppendQuery("limit", limit.Value, true); diff --git a/src/Generated/AssistantClient.cs b/src/Generated/AssistantClient.cs index 14c304e8..3e5a40f5 100644 --- a/src/Generated/AssistantClient.cs +++ b/src/Generated/AssistantClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateAssistantRequest(BinaryContent content, Req request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/assistants", false); + uri.AppendPath("/v1/assistants", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -49,7 +49,7 @@ internal PipelineMessage CreateGetAssistantsRequest(int? limit, string order, st request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/assistants", false); + uri.AppendPath("/v1/assistants", false); if (limit != null) { uri.AppendQuery("limit", limit.Value, true); @@ -80,7 +80,7 @@ internal PipelineMessage CreateGetAssistantRequest(string assistantId, RequestOp request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); + uri.AppendPath("/v1/assistants/", false); uri.AppendPath(assistantId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -96,7 +96,7 @@ internal PipelineMessage CreateModifyAssistantRequest(string assistantId, Binary request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); + uri.AppendPath("/v1/assistants/", false); uri.AppendPath(assistantId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -114,7 +114,7 @@ internal PipelineMessage CreateDeleteAssistantRequest(string assistantId, Reques request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); + uri.AppendPath("/v1/assistants/", false); uri.AppendPath(assistantId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); diff --git a/src/Generated/AudioClient.cs b/src/Generated/AudioClient.cs index 8b5a4f1d..6022edc5 100644 --- a/src/Generated/AudioClient.cs +++ b/src/Generated/AudioClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateSpeechRequest(BinaryContent content, Reques request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/audio/speech", false); + uri.AppendPath("/v1/audio/speech", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/octet-stream"); request.Headers.Set("Content-Type", "application/json"); @@ -49,7 +49,7 @@ internal PipelineMessage CreateCreateTranscriptionRequest(BinaryContent content, request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/audio/transcriptions", false); + uri.AppendPath("/v1/audio/transcriptions", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", contentType); @@ -66,7 +66,7 @@ internal PipelineMessage CreateCreateTranslationRequest(BinaryContent content, s request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/audio/translations", false); + uri.AppendPath("/v1/audio/translations", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", contentType); diff --git a/src/Generated/BatchClient.cs b/src/Generated/BatchClient.cs index 3ccd2f90..2b43e1b0 100644 --- a/src/Generated/BatchClient.cs +++ b/src/Generated/BatchClient.cs @@ -33,7 +33,7 @@ internal PipelineMessage CreateCreateBatchRequest(BinaryContent content, Request request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/batches", false); + uri.AppendPath("/v1/batches", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -50,7 +50,7 @@ internal PipelineMessage CreateGetBatchesRequest(string after, int? limit, Reque request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/batches", false); + uri.AppendPath("/v1/batches", false); if (after != null) { uri.AppendQuery("after", after, true); @@ -73,7 +73,7 @@ internal PipelineMessage CreateRetrieveBatchRequest(string batchId, RequestOptio request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/batches/", false); + uri.AppendPath("/v1/batches/", false); uri.AppendPath(batchId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -89,7 +89,7 @@ internal PipelineMessage CreateCancelBatchRequest(string batchId, RequestOptions request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/batches/", false); + uri.AppendPath("/v1/batches/", false); uri.AppendPath(batchId, true); uri.AppendPath("/cancel", false); request.Uri = uri.ToUri(); diff --git a/src/Generated/ChatClient.cs b/src/Generated/ChatClient.cs index 6db94d5e..b27f0ede 100644 --- a/src/Generated/ChatClient.cs +++ b/src/Generated/ChatClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateChatCompletionRequest(BinaryContent content request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/chat/completions", false); + uri.AppendPath("/v1/chat/completions", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); diff --git a/src/Generated/EmbeddingClient.cs b/src/Generated/EmbeddingClient.cs index e93cade4..00352b85 100644 --- a/src/Generated/EmbeddingClient.cs +++ b/src/Generated/EmbeddingClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateEmbeddingRequest(BinaryContent content, Req request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/embeddings", false); + uri.AppendPath("/v1/embeddings", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); diff --git a/src/Generated/FileClient.cs b/src/Generated/FileClient.cs index 131f6ba5..bfb518a3 100644 --- a/src/Generated/FileClient.cs +++ b/src/Generated/FileClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateFileRequest(BinaryContent content, string c request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/files", false); + uri.AppendPath("/v1/files", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", contentType); @@ -49,7 +49,7 @@ internal PipelineMessage CreateGetFilesRequest(string purpose, RequestOptions op request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/files", false); + uri.AppendPath("/v1/files", false); if (purpose != null) { uri.AppendQuery("purpose", purpose, true); @@ -68,7 +68,7 @@ internal PipelineMessage CreateRetrieveFileRequest(string fileId, RequestOptions request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/files/", false); + uri.AppendPath("/v1/files/", false); uri.AppendPath(fileId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -84,7 +84,7 @@ internal PipelineMessage CreateDeleteFileRequest(string fileId, RequestOptions o request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/files/", false); + uri.AppendPath("/v1/files/", false); uri.AppendPath(fileId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -100,7 +100,7 @@ internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/files/", false); + uri.AppendPath("/v1/files/", false); uri.AppendPath(fileId, true); uri.AppendPath("/content", false); request.Uri = uri.ToUri(); diff --git a/src/Generated/FineTuningClient.cs b/src/Generated/FineTuningClient.cs index c4446699..fe4998f4 100644 --- a/src/Generated/FineTuningClient.cs +++ b/src/Generated/FineTuningClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateFineTuningJobRequest(BinaryContent content, request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); + uri.AppendPath("/v1/fine_tuning/jobs", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -49,7 +49,7 @@ internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, i request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); + uri.AppendPath("/v1/fine_tuning/jobs", false); if (after != null) { uri.AppendQuery("after", after, true); @@ -72,7 +72,7 @@ internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJob request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath("/v1/fine_tuning/jobs/", false); uri.AppendPath(fineTuningJobId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -88,7 +88,7 @@ internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath("/v1/fine_tuning/jobs/", false); uri.AppendPath(fineTuningJobId, true); uri.AppendPath("/cancel", false); request.Uri = uri.ToUri(); @@ -105,7 +105,7 @@ internal PipelineMessage CreateGetFineTuningJobCheckpointsRequest(string fineTun request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath("/v1/fine_tuning/jobs/", false); uri.AppendPath(fineTuningJobId, true); uri.AppendPath("/checkpoints", false); if (after != null) @@ -130,7 +130,7 @@ internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath("/v1/fine_tuning/jobs/", false); uri.AppendPath(fineTuningJobId, true); uri.AppendPath("/events", false); if (after != null) diff --git a/src/Generated/ImageClient.cs b/src/Generated/ImageClient.cs index 6e0558f0..cab97e7f 100644 --- a/src/Generated/ImageClient.cs +++ b/src/Generated/ImageClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateImageRequest(BinaryContent content, Request request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/images/generations", false); + uri.AppendPath("/v1/images/generations", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -49,7 +49,7 @@ internal PipelineMessage CreateCreateImageEditRequest(BinaryContent content, str request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/images/edits", false); + uri.AppendPath("/v1/images/edits", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", contentType); @@ -66,7 +66,7 @@ internal PipelineMessage CreateCreateImageVariationRequest(BinaryContent content request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/images/variations", false); + uri.AppendPath("/v1/images/variations", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", contentType); diff --git a/src/Generated/InternalAssistantMessageClient.cs b/src/Generated/InternalAssistantMessageClient.cs index 5ad0ce02..5b211af7 100644 --- a/src/Generated/InternalAssistantMessageClient.cs +++ b/src/Generated/InternalAssistantMessageClient.cs @@ -48,7 +48,7 @@ internal PipelineMessage CreateCreateMessageRequest(string threadId, BinaryConte request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/messages", false); request.Uri = uri.ToUri(); @@ -67,7 +67,7 @@ internal PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, s request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/messages", false); if (limit != null) @@ -100,7 +100,7 @@ internal PipelineMessage CreateGetMessageRequest(string threadId, string message request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/messages/", false); uri.AppendPath(messageId, true); @@ -118,7 +118,7 @@ internal PipelineMessage CreateModifyMessageRequest(string threadId, string mess request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/messages/", false); uri.AppendPath(messageId, true); @@ -138,7 +138,7 @@ internal PipelineMessage CreateDeleteMessageRequest(string threadId, string mess request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/messages/", false); uri.AppendPath(messageId, true); diff --git a/src/Generated/InternalAssistantRunClient.cs b/src/Generated/InternalAssistantRunClient.cs index b079a8a5..2a6b2de9 100644 --- a/src/Generated/InternalAssistantRunClient.cs +++ b/src/Generated/InternalAssistantRunClient.cs @@ -66,7 +66,7 @@ internal PipelineMessage CreateCreateThreadAndRunRequest(BinaryContent content, request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/runs", false); + uri.AppendPath("/v1/threads/runs", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -83,7 +83,7 @@ internal PipelineMessage CreateCreateRunRequest(string threadId, BinaryContent c request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs", false); request.Uri = uri.ToUri(); @@ -102,7 +102,7 @@ internal PipelineMessage CreateGetRunsRequest(string threadId, int? limit, strin request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs", false); if (limit != null) @@ -135,7 +135,7 @@ internal PipelineMessage CreateGetRunRequest(string threadId, string runId, Requ request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); @@ -153,7 +153,7 @@ internal PipelineMessage CreateModifyRunRequest(string threadId, string runId, B request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); @@ -173,7 +173,7 @@ internal PipelineMessage CreateCancelRunRequest(string threadId, string runId, R request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); @@ -192,7 +192,7 @@ internal PipelineMessage CreateSubmitToolOutputsToRunRequest(string threadId, st request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); @@ -213,7 +213,7 @@ internal PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); @@ -248,7 +248,7 @@ internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); uri.AppendPath("/runs/", false); uri.AppendPath(runId, true); diff --git a/src/Generated/InternalAssistantThreadClient.cs b/src/Generated/InternalAssistantThreadClient.cs index 347ef4bd..9bba60ad 100644 --- a/src/Generated/InternalAssistantThreadClient.cs +++ b/src/Generated/InternalAssistantThreadClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateThreadRequest(BinaryContent content, Reques request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads", false); + uri.AppendPath("/v1/threads", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -49,7 +49,7 @@ internal PipelineMessage CreateGetThreadRequest(string threadId, RequestOptions request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -65,7 +65,7 @@ internal PipelineMessage CreateModifyThreadRequest(string threadId, BinaryConten request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -83,7 +83,7 @@ internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptio request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); + uri.AppendPath("/v1/threads/", false); uri.AppendPath(threadId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); diff --git a/src/Generated/InternalUploadsClient.cs b/src/Generated/InternalUploadsClient.cs index 4c6d033a..0e30e2f4 100644 --- a/src/Generated/InternalUploadsClient.cs +++ b/src/Generated/InternalUploadsClient.cs @@ -174,7 +174,7 @@ internal PipelineMessage CreateCreateUploadRequest(BinaryContent content, Reques request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/uploads", false); + uri.AppendPath("/v1/uploads", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -191,7 +191,7 @@ internal PipelineMessage CreateAddUploadPartRequest(string uploadId, BinaryConte request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/uploads/", false); + uri.AppendPath("/v1/uploads/", false); uri.AppendPath(uploadId, true); uri.AppendPath("/parts", false); request.Uri = uri.ToUri(); @@ -210,7 +210,7 @@ internal PipelineMessage CreateCompleteUploadRequest(string uploadId, BinaryCont request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/uploads/", false); + uri.AppendPath("/v1/uploads/", false); uri.AppendPath(uploadId, true); uri.AppendPath("/complete", false); request.Uri = uri.ToUri(); @@ -229,7 +229,7 @@ internal PipelineMessage CreateCancelUploadRequest(string uploadId, RequestOptio request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/uploads/", false); + uri.AppendPath("/v1/uploads/", false); uri.AppendPath(uploadId, true); uri.AppendPath("/cancel", false); request.Uri = uri.ToUri(); diff --git a/src/Generated/LegacyCompletionClient.cs b/src/Generated/LegacyCompletionClient.cs index efb44faa..4a0ad7e2 100644 --- a/src/Generated/LegacyCompletionClient.cs +++ b/src/Generated/LegacyCompletionClient.cs @@ -66,7 +66,7 @@ internal PipelineMessage CreateCreateCompletionRequest(BinaryContent content, Re request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/completions", false); + uri.AppendPath("/v1/completions", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); diff --git a/src/Generated/ModelClient.cs b/src/Generated/ModelClient.cs index 86aef48f..62db6d53 100644 --- a/src/Generated/ModelClient.cs +++ b/src/Generated/ModelClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateGetModelsRequest(RequestOptions options) request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/models", false); + uri.AppendPath("/v1/models", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); message.Apply(options); @@ -47,7 +47,7 @@ internal PipelineMessage CreateRetrieveRequest(string model, RequestOptions opti request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/models/", false); + uri.AppendPath("/v1/models/", false); uri.AppendPath(model, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -63,7 +63,7 @@ internal PipelineMessage CreateDeleteRequest(string model, RequestOptions option request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/models/", false); + uri.AppendPath("/v1/models/", false); uri.AppendPath(model, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); diff --git a/src/Generated/Models/OpenAIFileInfo.Serialization.cs b/src/Generated/Models/OpenAIFileInfo.Serialization.cs index 18fbf44d..fcd6544a 100644 --- a/src/Generated/Models/OpenAIFileInfo.Serialization.cs +++ b/src/Generated/Models/OpenAIFileInfo.Serialization.cs @@ -111,7 +111,7 @@ internal static OpenAIFileInfo DeserializeOpenAIFileInfo(JsonElement element, Mo return null; } string id = default; - long? bytes = default; + int? bytes = default; DateTimeOffset createdAt = default; string filename = default; InternalOpenAIFileObject @object = default; @@ -134,7 +134,7 @@ internal static OpenAIFileInfo DeserializeOpenAIFileInfo(JsonElement element, Mo bytes = null; continue; } - bytes = property.Value.GetInt64(); + bytes = property.Value.GetInt32(); continue; } if (property.NameEquals("created_at"u8)) diff --git a/src/Generated/Models/OpenAIFileInfo.cs b/src/Generated/Models/OpenAIFileInfo.cs index 240c8589..6643d5ab 100644 --- a/src/Generated/Models/OpenAIFileInfo.cs +++ b/src/Generated/Models/OpenAIFileInfo.cs @@ -10,7 +10,7 @@ namespace OpenAI.Files public partial class OpenAIFileInfo { internal IDictionary SerializedAdditionalRawData { get; set; } - internal OpenAIFileInfo(string id, long? sizeInBytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) + internal OpenAIFileInfo(string id, int? sizeInBytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) { Argument.AssertNotNull(id, nameof(id)); Argument.AssertNotNull(filename, nameof(filename)); @@ -23,7 +23,7 @@ internal OpenAIFileInfo(string id, long? sizeInBytes, DateTimeOffset createdAt, Status = status; } - internal OpenAIFileInfo(string id, long? sizeInBytes, DateTimeOffset createdAt, string filename, InternalOpenAIFileObject @object, OpenAIFilePurpose purpose, OpenAIFileStatus status, string statusDetails, IDictionary serializedAdditionalRawData) + internal OpenAIFileInfo(string id, int? sizeInBytes, DateTimeOffset createdAt, string filename, InternalOpenAIFileObject @object, OpenAIFilePurpose purpose, OpenAIFileStatus status, string statusDetails, IDictionary serializedAdditionalRawData) { Id = id; SizeInBytes = sizeInBytes; diff --git a/src/Generated/ModerationClient.cs b/src/Generated/ModerationClient.cs index 9eac7994..73c07013 100644 --- a/src/Generated/ModerationClient.cs +++ b/src/Generated/ModerationClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateCreateModerationRequest(BinaryContent content, Re request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/moderations", false); + uri.AppendPath("/v1/moderations", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); diff --git a/src/Generated/VectorStoreClient.cs b/src/Generated/VectorStoreClient.cs index 5e44c7ab..14b48e96 100644 --- a/src/Generated/VectorStoreClient.cs +++ b/src/Generated/VectorStoreClient.cs @@ -32,7 +32,7 @@ internal PipelineMessage CreateGetVectorStoresRequest(int? limit, string order, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores", false); + uri.AppendPath("/v1/vector_stores", false); if (limit != null) { uri.AppendQuery("limit", limit.Value, true); @@ -63,7 +63,7 @@ internal PipelineMessage CreateCreateVectorStoreRequest(BinaryContent content, R request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores", false); + uri.AppendPath("/v1/vector_stores", false); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); request.Headers.Set("Content-Type", "application/json"); @@ -80,7 +80,7 @@ internal PipelineMessage CreateGetVectorStoreRequest(string vectorStoreId, Reque request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -96,7 +96,7 @@ internal PipelineMessage CreateModifyVectorStoreRequest(string vectorStoreId, Bi request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -114,7 +114,7 @@ internal PipelineMessage CreateDeleteVectorStoreRequest(string vectorStoreId, Re request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); request.Uri = uri.ToUri(); request.Headers.Set("Accept", "application/json"); @@ -130,7 +130,7 @@ internal PipelineMessage CreateGetVectorStoreFilesRequest(string vectorStoreId, request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/files", false); if (limit != null) @@ -167,7 +167,7 @@ internal PipelineMessage CreateCreateVectorStoreFileRequest(string vectorStoreId request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/files", false); request.Uri = uri.ToUri(); @@ -186,7 +186,7 @@ internal PipelineMessage CreateGetVectorStoreFileRequest(string vectorStoreId, s request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/files/", false); uri.AppendPath(fileId, true); @@ -204,7 +204,7 @@ internal PipelineMessage CreateDeleteVectorStoreFileRequest(string vectorStoreId request.Method = "DELETE"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/files/", false); uri.AppendPath(fileId, true); @@ -222,7 +222,7 @@ internal PipelineMessage CreateCreateVectorStoreFileBatchRequest(string vectorSt request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/file_batches", false); request.Uri = uri.ToUri(); @@ -241,7 +241,7 @@ internal PipelineMessage CreateGetVectorStoreFileBatchRequest(string vectorStore request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/file_batches/", false); uri.AppendPath(batchId, true); @@ -259,7 +259,7 @@ internal PipelineMessage CreateCancelVectorStoreFileBatchRequest(string vectorSt request.Method = "POST"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/file_batches/", false); uri.AppendPath(batchId, true); @@ -278,7 +278,7 @@ internal PipelineMessage CreateGetFilesInVectorStoreBatchesRequest(string vector request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/vector_stores/", false); + uri.AppendPath("/v1/vector_stores/", false); uri.AppendPath(vectorStoreId, true); uri.AppendPath("/file_batches/", false); uri.AppendPath(batchId, true); diff --git a/src/Utility/PageCollectionHelpers.cs b/src/Utility/PageCollectionHelpers.cs index f7863ce2..b5be39a6 100644 --- a/src/Utility/PageCollectionHelpers.cs +++ b/src/Utility/PageCollectionHelpers.cs @@ -15,6 +15,22 @@ public static PageCollection Create(PageEnumerator enumerator) public static AsyncPageCollection CreateAsync(PageEnumerator enumerator) => new AsyncEnumeratorPageCollection(enumerator); + public static IEnumerable Create(PageResultEnumerator enumerator) + { + while (enumerator.MoveNext()) + { + yield return enumerator.Current; + } + } + + public static async IAsyncEnumerable CreateAsync(PageResultEnumerator enumerator) + { + while (await enumerator.MoveNextAsync().ConfigureAwait(false)) + { + yield return enumerator.Current; + } + } + private class EnumeratorPageCollection : PageCollection { private readonly PageEnumerator _enumerator; diff --git a/tests/Assistants/VectorStoreTests.cs b/tests/Assistants/VectorStoreTests.cs index ed4426f3..d13b1b08 100644 --- a/tests/Assistants/VectorStoreTests.cs +++ b/tests/Assistants/VectorStoreTests.cs @@ -187,7 +187,7 @@ public void CanAssociateFiles() _associationsToRemove.RemoveAt(0); // Errata: removals aren't immediately reflected when requesting the list - Thread.Sleep(1000); + Thread.Sleep(2000); int count = 0; foreach (VectorStoreFileAssociation association in client.GetFileAssociations(vectorStore).GetAllValues()) @@ -227,7 +227,7 @@ public void Pagination_CanRehydrateFileAssociationCollection() _associationsToRemove.RemoveAt(0); // Errata: removals aren't immediately reflected when requesting the list - Thread.Sleep(1000); + Thread.Sleep(2000); PageCollection pages = client.GetFileAssociations(vectorStore); IEnumerator> pageEnumerator = ((IEnumerable>)pages).GetEnumerator(); diff --git a/tests/Audio/TextToSpeechTests.cs b/tests/Audio/TextToSpeechTests.cs index c3753e14..cbbd748d 100644 --- a/tests/Audio/TextToSpeechTests.cs +++ b/tests/Audio/TextToSpeechTests.cs @@ -23,8 +23,8 @@ public async Task BasicTextToSpeechWorks() AudioClient client = GetTestClient(TestScenario.Audio_TTS); BinaryData audio = IsAsync - ? await client.GenerateSpeechFromTextAsync("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer) - : client.GenerateSpeechFromText("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer); + ? await client.GenerateSpeechAsync("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer) + : client.GenerateSpeech("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer); Assert.That(audio, Is.Not.Null); ValidateGeneratedAudio(audio, "hello"); @@ -47,8 +47,8 @@ public async Task OutputFormatWorks(GeneratedSpeechFormat? responseFormat) : new() { ResponseFormat = responseFormat }; BinaryData audio = IsAsync - ? await client.GenerateSpeechFromTextAsync("Hello, world!", GeneratedSpeechVoice.Alloy, options) - : client.GenerateSpeechFromText("Hello, world!", GeneratedSpeechVoice.Alloy, options); + ? await client.GenerateSpeechAsync("Hello, world!", GeneratedSpeechVoice.Alloy, options) + : client.GenerateSpeech("Hello, world!", GeneratedSpeechVoice.Alloy, options); Assert.That(audio, Is.Not.Null); } diff --git a/tests/Batch/BatchTests.cs b/tests/Batch/BatchTests.cs index 65be9eaa..8e51201a 100644 --- a/tests/Batch/BatchTests.cs +++ b/tests/Batch/BatchTests.cs @@ -4,6 +4,7 @@ using OpenAI.Tests.Utility; using System; using System.ClientModel; +using System.Collections.Generic; using System.IO; using System.Text.Json; using System.Threading.Tasks; @@ -22,32 +23,71 @@ public BatchTests(bool isAsync) : base(isAsync) } [Test] - public async Task ListBatchesProtocol() + public void ListBatchesProtocol() { BatchClient client = GetTestClient(); - ClientResult result = IsAsync - ? await client.GetBatchesAsync(after: null, limit: null, options: null) - : client.GetBatches(after: null, limit: null, options: null); + IEnumerable pageResults = client.GetBatches(after: null, limit: null, options: null); - BinaryData response = result.GetRawResponse().Content; - JsonDocument jsonDocument = JsonDocument.Parse(response); - JsonElement dataElement = jsonDocument.RootElement.GetProperty("data"); + int pageCount = 0; + foreach (ClientResult pageResult in pageResults) + { + BinaryData response = pageResult.GetRawResponse().Content; + using JsonDocument jsonDocument = JsonDocument.Parse(response); + JsonElement dataElement = jsonDocument.RootElement.GetProperty("data"); - Assert.That(dataElement.GetArrayLength(), Is.GreaterThan(0)); + Assert.That(dataElement.GetArrayLength(), Is.GreaterThan(0)); - long unixTime2024 = (new DateTimeOffset(2024, 01, 01, 0, 0, 0, TimeSpan.Zero)).ToUnixTimeSeconds(); + long unixTime2024 = (new DateTimeOffset(2024, 01, 01, 0, 0, 0, TimeSpan.Zero)).ToUnixTimeSeconds(); + + foreach (JsonElement batchElement in dataElement.EnumerateArray()) + { + JsonElement createdAtElement = batchElement.GetProperty("created_at"); + long createdAt = createdAtElement.GetInt64(); + + Assert.That(createdAt, Is.GreaterThan(unixTime2024)); + } + pageCount++; + + //var dynamicResult = result.GetRawResponse().Content.ToDynamicFromJson(); + //Assert.That(dynamicResult.data.Count, Is.GreaterThan(0)); + //Assert.That(dynamicResult.data[0].createdAt, Is.GreaterThan(new DateTimeOffset(2024, 01, 01, 0, 0, 0, TimeSpan.Zero))); + } + + Assert.GreaterOrEqual(pageCount, 1); + } - foreach (JsonElement batchElement in dataElement.EnumerateArray()) + [Test] + public async Task ListBatchesProtocolAsync() + { + BatchClient client = GetTestClient(); + IAsyncEnumerable pageResults = client.GetBatchesAsync(after: null, limit: null, options: null); + + int pageCount = 0; + await foreach (ClientResult pageResult in pageResults) { - JsonElement createdAtElement = batchElement.GetProperty("created_at"); - long createdAt = createdAtElement.GetInt64(); + BinaryData response = pageResult.GetRawResponse().Content; + using JsonDocument jsonDocument = JsonDocument.Parse(response); + JsonElement dataElement = jsonDocument.RootElement.GetProperty("data"); + + Assert.That(dataElement.GetArrayLength(), Is.GreaterThan(0)); + + long unixTime2024 = (new DateTimeOffset(2024, 01, 01, 0, 0, 0, TimeSpan.Zero)).ToUnixTimeSeconds(); + + foreach (JsonElement batchElement in dataElement.EnumerateArray()) + { + JsonElement createdAtElement = batchElement.GetProperty("created_at"); + long createdAt = createdAtElement.GetInt64(); + + Assert.That(createdAt, Is.GreaterThan(unixTime2024)); + } + pageCount++; - Assert.That(createdAt, Is.GreaterThan(unixTime2024)); + //var dynamicResult = result.GetRawResponse().Content.ToDynamicFromJson(); + //Assert.That(dynamicResult.data.Count, Is.GreaterThan(0)); + //Assert.That(dynamicResult.data[0].createdAt, Is.GreaterThan(new DateTimeOffset(2024, 01, 01, 0, 0, 0, TimeSpan.Zero))); } - //var dynamicResult = result.GetRawResponse().Content.ToDynamicFromJson(); - //Assert.That(dynamicResult.data.Count, Is.GreaterThan(0)); - //Assert.That(dynamicResult.data[0].createdAt, Is.GreaterThan(new DateTimeOffset(2024, 01, 01, 0, 0, 0, TimeSpan.Zero))); + Assert.GreaterOrEqual(pageCount, 1); } [Test] diff --git a/tests/Chat/ChatSmokeTests.cs b/tests/Chat/ChatSmokeTests.cs index e9c172bc..309b2ae5 100644 --- a/tests/Chat/ChatSmokeTests.cs +++ b/tests/Chat/ChatSmokeTests.cs @@ -585,4 +585,29 @@ public void SerializeMessagesWithNullProperties() FunctionChatMessage deserializedMessage = ModelReaderWriter.Read(serializedMessage); #pragma warning restore } + + [Test] + public void TopLevelClientOptionsPersistence() + { + MockPipelineTransport mockTransport = new(BinaryData.FromString("{}"), BinaryData.FromString("{}")); + OpenAIClientOptions options = new() + { + Transport = mockTransport, + Endpoint = new Uri("https://api.openai.com/expected/test/endpoint"), + }; + Uri observedEndpoint = null; + options.AddPolicy(new TestPipelinePolicy(message => + { + observedEndpoint = message?.Request?.Uri; + Console.WriteLine($"foo: {message.Request.Uri.AbsoluteUri}"); + }), + PipelinePosition.PerCall); + + OpenAIClient topLevelClient = new(new("mock-credential"), options); + ChatClient firstClient = topLevelClient.GetChatClient("mock-model"); + ClientResult first = firstClient.CompleteChat("Hello, world"); + + Assert.That(observedEndpoint, Is.Not.Null); + Assert.That(observedEndpoint.AbsoluteUri, Does.Contain("expected/test/endpoint")); + } } From 20e6d5b14665c55c87c6b0333202643814cfb7c7 Mon Sep 17 00:00:00 2001 From: ShivangiReja Date: Mon, 26 Aug 2024 14:33:36 -0700 Subject: [PATCH 2/3] Update --- CHANGELOG.md | 24 ++++++++++++++---------- src/OpenAI.csproj | 2 +- tests/Chat/ChatSmokeTests.cs | 6 +++--- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 498b3113..2697eb9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,28 +1,32 @@ # Release History -## 2.0.0-beta.10 (Unreleased) +## 2.0.0-beta.11 (Unreleased) ### Features Added ### Breaking Changes -- Removed client constructors that do not explicitly take an API key parameter or an endpoint via an `OpenAIClientOptions` parameter, making it clearer how to appropriately instantiate a client. (commit_hash) -- Removed the endpoint parameter from all client constructors, making it clearer that an alternative endpoint must be specified via the `OpenAIClientOptions` parameter. (commit_hash) -- Removed `OpenAIClient`'s `Endpoint` `protected` property. (commit_hash) -- Made `OpenAIClient`'s constructor that takes a `ClientPipeline` parameter `protected internal` instead of just `protected`. (commit_hash) -- Renamed the `User` property in applicable Options classes to `EndUserId`, making its purpose clearer. (commit_hash) - Updated fine-tuning pagination methods `GetJobs`, `GetEvents`, and `GetJobCheckpoints` to return `IEnumerable` instead of `ClientResult`. (commit_hash) - Updated the batching pagination method `GetBatches` to return `IEnumerable` instead of `ClientResult`. (commit_hash) -- Renamed `AudioClient`'s `GenerateSpeechFromText` methods to simply `GenerateSpeech`. (commit_hash) -- Changed the type of `OpenAIFileInfo`'s `SizeInBytes` property from `long?` to `int?`. (commit_hash) ### Bugs Fixed -- Fixed a newly introduced bug ([#185](https://github.com/openai/openai-dotnet/pull/185)) where providing `OpenAIClientOptions` to a top-level `OpenAIClient` did not carry over to scenario clients (e.g. `ChatClient`) created via that top-level client +### Other Changes + +## 2.0.0-beta.10 (2024-08-26) + +### Breaking Changes + +- Renamed `AudioClient`'s `GenerateSpeechFromText` methods to simply `GenerateSpeech`. ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7)) +- Changed the type of `OpenAIFileInfo`'s `SizeInBytes` property from `long?` to `int?`. ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7)) + +### Bugs Fixed + +- Fixed a newly introduced bug ([#185](https://github.com/openai/openai-dotnet/pull/185)) where providing `OpenAIClientOptions` to a top-level `OpenAIClient` did not carry over to scenario clients (e.g. `ChatClient`) created via that top-level client ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7)) ### Other Changes -- Removed the version path parameter "v1" from the default endpoint URL. (commit_hash) +- Removed the version path parameter "v1" from the default endpoint URL. ([d84bf54](https://github.com/openai/openai-dotnet/commit/d84bf54df14ddac4c49f6efd61467b600d34ecd7)) ## 2.0.0-beta.9 (2024-08-23) diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index ccedc487..2a1dd21b 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -5,7 +5,7 @@ OpenAI 2.0.0 - beta.9 + beta.10 netstandard2.0;net6.0 latest diff --git a/tests/Chat/ChatSmokeTests.cs b/tests/Chat/ChatSmokeTests.cs index 309b2ae5..f06d97a9 100644 --- a/tests/Chat/ChatSmokeTests.cs +++ b/tests/Chat/ChatSmokeTests.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using static OpenAI.Tests.Telemetry.TestMeterListener; using static OpenAI.Tests.TestHelpers; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace OpenAI.Tests.Chat; @@ -593,13 +594,12 @@ public void TopLevelClientOptionsPersistence() OpenAIClientOptions options = new() { Transport = mockTransport, - Endpoint = new Uri("https://api.openai.com/expected/test/endpoint"), + Endpoint = new Uri("https://my.custom.com/expected/test/endpoint"), }; Uri observedEndpoint = null; options.AddPolicy(new TestPipelinePolicy(message => { observedEndpoint = message?.Request?.Uri; - Console.WriteLine($"foo: {message.Request.Uri.AbsoluteUri}"); }), PipelinePosition.PerCall); @@ -608,6 +608,6 @@ public void TopLevelClientOptionsPersistence() ClientResult first = firstClient.CompleteChat("Hello, world"); Assert.That(observedEndpoint, Is.Not.Null); - Assert.That(observedEndpoint.AbsoluteUri, Does.Contain("expected/test/endpoint")); + Assert.That(observedEndpoint.AbsoluteUri, Does.Contain("my.custom.com/expected/test/endpoint")); } } From 19d9ed9b71b8561716080914109c4197a050d261 Mon Sep 17 00:00:00 2001 From: ShivangiReja Date: Mon, 26 Aug 2024 16:42:23 -0700 Subject: [PATCH 3/3] Fix batching operations URI --- CHANGELOG.md | 2 +- src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs | 3 +-- .../Pagination/FineTuningJobCheckpointsPageEnumerator.cs | 2 +- .../Internal/Pagination/FineTuningJobEventsPageEnumerator.cs | 3 +-- .../Internal/Pagination/FineTuningJobsPageEnumerator.cs | 3 +-- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc0ef7d9..2697eb9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ### Breaking Changes - Updated fine-tuning pagination methods `GetJobs`, `GetEvents`, and `GetJobCheckpoints` to return `IEnumerable` instead of `ClientResult`. (commit_hash) -- Updated batching pagination method `GetBatches` to return `IEnumerable` instead of `ClientResult`. (commit_hash) +- Updated the batching pagination method `GetBatches` to return `IEnumerable` instead of `ClientResult`. (commit_hash) ### Bugs Fixed diff --git a/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs b/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs index 6f23fb8a..f8055d3a 100644 --- a/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs +++ b/src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs @@ -1,7 +1,6 @@ using System; using System.ClientModel; using System.ClientModel.Primitives; -using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; @@ -89,7 +88,7 @@ internal PipelineMessage CreateGetBatchesRequest(string after, int? limit, Reque request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/batches", false); + uri.AppendPath("/v1/batches", false); if (after != null) { uri.AppendQuery("after", after, true); diff --git a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs index 0422a2a5..f404409d 100644 --- a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs +++ b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobCheckpointsPageEnumerator.cs @@ -94,7 +94,7 @@ internal PipelineMessage CreateGetFineTuningJobCheckpointsRequest(string fineTun request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath("/v1/fine_tuning/jobs/", false); uri.AppendPath(fineTuningJobId, true); uri.AppendPath("/checkpoints", false); if (after != null) diff --git a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs index a8bfc3b6..095bedfa 100644 --- a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs +++ b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobEventsPageEnumerator.cs @@ -1,7 +1,6 @@ using System; using System.ClientModel; using System.ClientModel.Primitives; -using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; @@ -95,7 +94,7 @@ internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath("/v1/fine_tuning/jobs/", false); uri.AppendPath(fineTuningJobId, true); uri.AppendPath("/events", false); if (after != null) diff --git a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs index 3c7c8b30..d9ad21b9 100644 --- a/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs +++ b/src/Custom/FineTuning/Internal/Pagination/FineTuningJobsPageEnumerator.cs @@ -1,7 +1,6 @@ using System; using System.ClientModel; using System.ClientModel.Primitives; -using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; @@ -89,7 +88,7 @@ internal PipelineMessage CreateGetFineTuningJobsRequest(string after, int? limit request.Method = "GET"; var uri = new ClientUriBuilder(); uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); + uri.AppendPath("/v1/fine_tuning/jobs", false); if (after != null) { uri.AppendQuery("after", after, true);