Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move service methods for paginated endpoints to use SCM based pagination pattern #188

Merged
merged 4 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Release History

## 2.0.0-beta.11 (Unreleased)

### Features Added

### Breaking Changes

- Updated fine-tuning pagination methods `GetJobs`, `GetEvents`, and `GetJobCheckpoints` to return `IEnumerable<ClientResult>` instead of `ClientResult`. (commit_hash)
- Updated batching pagination method `GetBatches` to return `IEnumerable<ClientResult>` instead of `ClientResult`. (commit_hash)

### Bugs Fixed

### Other Changes

## 2.0.0-beta.10 (2024-08-26)

### Breaking Changes
Expand Down
16 changes: 8 additions & 8 deletions api/OpenAI.netstandard2.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,8 +1170,8 @@ public class BatchClient {
public virtual Task<ClientResult> CreateBatchAsync(BinaryContent content, RequestOptions options = null);
public virtual ClientResult GetBatch(string batchId, RequestOptions options);
public virtual Task<ClientResult> GetBatchAsync(string batchId, RequestOptions options);
public virtual ClientResult GetBatches(string after, int? limit, RequestOptions options);
public virtual Task<ClientResult> GetBatchesAsync(string after, int? limit, RequestOptions options);
public virtual IEnumerable<ClientResult> GetBatches(string after, int? limit, RequestOptions options);
public virtual IAsyncEnumerable<ClientResult> GetBatchesAsync(string after, int? limit, RequestOptions options);
}
}
namespace OpenAI.Chat {
Expand Down Expand Up @@ -1792,12 +1792,12 @@ public class FineTuningClient {
public virtual Task<ClientResult> CreateJobAsync(BinaryContent content, RequestOptions options = null);
public virtual ClientResult GetJob(string jobId, RequestOptions options);
public virtual Task<ClientResult> GetJobAsync(string jobId, RequestOptions options);
public virtual ClientResult GetJobCheckpoints(string fineTuningJobId, string after, int? limit, RequestOptions options);
public virtual Task<ClientResult> GetJobCheckpointsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options);
public virtual ClientResult GetJobEvents(string jobId, string after, int? limit, RequestOptions options);
public virtual Task<ClientResult> GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options);
public virtual ClientResult GetJobs(string after, int? limit, RequestOptions options);
public virtual Task<ClientResult> GetJobsAsync(string after, int? limit, RequestOptions options);
public virtual IEnumerable<ClientResult> GetJobCheckpoints(string jobId, string after, int? limit, RequestOptions options);
public virtual IAsyncEnumerable<ClientResult> GetJobCheckpointsAsync(string jobId, string after, int? limit, RequestOptions options);
public virtual IEnumerable<ClientResult> GetJobEvents(string jobId, string after, int? limit, RequestOptions options);
public virtual IAsyncEnumerable<ClientResult> GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options);
public virtual IEnumerable<ClientResult> GetJobs(string after, int? limit, RequestOptions options);
public virtual IAsyncEnumerable<ClientResult> GetJobsAsync(string after, int? limit, RequestOptions options);
}
}
namespace OpenAI.Images {
Expand Down
13 changes: 7 additions & 6 deletions src/Custom/Batch/BatchClient.Protocol.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace OpenAI.Batch;
Expand Down Expand Up @@ -49,10 +50,10 @@ public virtual ClientResult CreateBatch(BinaryContent content, RequestOptions op
/// <param name="options"> The request options, which can override default behaviors of the client pipeline on a per-call basis. </param>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual async Task<ClientResult> GetBatchesAsync(string after, int? limit, RequestOptions options)
public virtual IAsyncEnumerable<ClientResult> 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);
}

/// <summary>
Expand All @@ -63,10 +64,10 @@ public virtual async Task<ClientResult> GetBatchesAsync(string after, int? limit
/// <param name="options"> The request options, which can override default behaviors of the client pipeline on a per-call basis. </param>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual ClientResult GetBatches(string after, int? limit, RequestOptions options)
public virtual IEnumerable<ClientResult> 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);
}

/// <summary>
Expand Down
109 changes: 109 additions & 0 deletions src/Custom/Batch/Internal/Pagination/BatchesPageEnumerator.cs
Original file line number Diff line number Diff line change
@@ -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<ClientResult> GetFirstAsync()
=> await GetBatchesAsync(_after, _limit, _options).ConfigureAwait(false);

public override ClientResult GetFirst()
=> GetBatches(_after, _limit, _options);

public override async Task<ClientResult> 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<ClientResult> 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);
ShivangiReja marked this conversation as resolved.
Show resolved Hide resolved
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 });
}
53 changes: 27 additions & 26 deletions src/Custom/FineTuning/FineTuningClient.Protocol.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace OpenAI.FineTuning;
Expand Down Expand Up @@ -76,10 +77,10 @@ public virtual ClientResult CreateJob(BinaryContent content, RequestOptions opti
/// <param name="options"> The request options, which can override default behaviors of the client pipeline on a per-call basis. </param>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual async Task<ClientResult> GetJobsAsync(string after, int? limit, RequestOptions options)
public virtual IAsyncEnumerable<ClientResult> 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:
Expand All @@ -93,10 +94,10 @@ public virtual async Task<ClientResult> GetJobsAsync(string after, int? limit, R
/// <param name="options"> The request options, which can override default behaviors of the client pipeline on a per-call basis. </param>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual ClientResult GetJobs(string after, int? limit, RequestOptions options)
public virtual IEnumerable<ClientResult> 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:
Expand Down Expand Up @@ -197,12 +198,12 @@ public virtual ClientResult CancelJob(string jobId, RequestOptions options)
/// <exception cref="ArgumentException"> <paramref name="jobId"/> is an empty string, and was expected to be non-empty. </exception>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual async Task<ClientResult> GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options)
public virtual IAsyncEnumerable<ClientResult> 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:
Expand All @@ -219,49 +220,49 @@ public virtual async Task<ClientResult> GetJobEventsAsync(string jobId, string a
/// <exception cref="ArgumentException"> <paramref name="jobId"/> is an empty string, and was expected to be non-empty. </exception>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual ClientResult GetJobEvents(string jobId, string after, int? limit, RequestOptions options)
public virtual IEnumerable<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));
FineTuningJobEventsPageEnumerator enumerator = new FineTuningJobEventsPageEnumerator(_pipeline, _endpoint, jobId, after, limit, options);
return PageCollectionHelpers.Create(enumerator);
}

/// <summary>
/// [Protocol Method] List the checkpoints for a fine-tuning job.
/// </summary>
/// <param name="fineTuningJobId"> The ID of the fine-tuning job to get checkpoints for. </param>
/// <param name="jobId"> The ID of the fine-tuning job to get checkpoints for. </param>
/// <param name="after"> Identifier for the last checkpoint ID from the previous pagination request. </param>
/// <param name="limit"> Number of checkpoints to retrieve. </param>
/// <param name="options"> The request options, which can override default behaviors of the client pipeline on a per-call basis. </param>
/// <exception cref="ArgumentNullException"> <paramref name="fineTuningJobId"/> is null. </exception>
/// <exception cref="ArgumentException"> <paramref name="fineTuningJobId"/> is an empty string, and was expected to be non-empty. </exception>
/// <exception cref="ArgumentNullException"> <paramref name="jobId"/> is null. </exception>
/// <exception cref="ArgumentException"> <paramref name="jobId"/> is an empty string, and was expected to be non-empty. </exception>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual async Task<ClientResult> GetJobCheckpointsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options)
public virtual IAsyncEnumerable<ClientResult> 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);
}

/// <summary>
/// [Protocol Method] List the checkpoints for a fine-tuning job.
/// </summary>
/// <param name="fineTuningJobId"> The ID of the fine-tuning job to get checkpoints for. </param>
/// <param name="jobId"> The ID of the fine-tuning job to get checkpoints for. </param>
/// <param name="after"> Identifier for the last checkpoint ID from the previous pagination request. </param>
/// <param name="limit"> Number of checkpoints to retrieve. </param>
/// <param name="options"> The request options, which can override default behaviors of the client pipeline on a per-call basis. </param>
/// <exception cref="ArgumentNullException"> <paramref name="fineTuningJobId"/> is null. </exception>
/// <exception cref="ArgumentException"> <paramref name="fineTuningJobId"/> is an empty string, and was expected to be non-empty. </exception>
/// <exception cref="ArgumentNullException"> <paramref name="jobId"/> is null. </exception>
/// <exception cref="ArgumentException"> <paramref name="jobId"/> is an empty string, and was expected to be non-empty. </exception>
/// <exception cref="ClientResultException"> Service returned a non-success status code. </exception>
/// <returns> The response returned from the service. </returns>
public virtual ClientResult GetJobCheckpoints(string fineTuningJobId, string after, int? limit, RequestOptions options)
public virtual IEnumerable<ClientResult> 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);
}
}
Loading