Skip to content

Commit

Permalink
Merge pull request #537 from betalgo/feature/Batch-api
Browse files Browse the repository at this point in the history
Batch API
  • Loading branch information
kayhantolga authored Apr 16, 2024
2 parents 6d0f4e0 + a2a63ee commit 9295517
Show file tree
Hide file tree
Showing 17 changed files with 363 additions and 3 deletions.
3 changes: 3 additions & 0 deletions OpenAI.Playground/OpenAI.Playground.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
<None Update="ApiSettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="SampleData\BatchDataSampleFile.jsonl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="SampleData\FineTuningSample1.jsonl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
4 changes: 2 additions & 2 deletions OpenAI.Playground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@

// Tools
//await ChatCompletionTestHelper.RunChatFunctionCallTest(sdk);
await ChatCompletionTestHelper.RunChatFunctionCallTestAsStream(sdk);

//await ChatCompletionTestHelper.RunChatFunctionCallTestAsStream(sdk);
await BatchTestHelper.RunBatchOperationsTest(sdk);
// Whisper
//await AudioTestHelper.RunSimpleAudioCreateTranscriptionTest(sdk);
//await AudioTestHelper.RunSimpleAudioCreateTranslationTest(sdk);
Expand Down
1 change: 1 addition & 0 deletions OpenAI.Playground/SampleData/BatchDataSampleFile.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"custom_id": "request-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-3.5-turbo", "messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What is 2+2?"}]}}
77 changes: 77 additions & 0 deletions OpenAI.Playground/TestHelpers/BatchTestHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using OpenAI.Interfaces;
using OpenAI.ObjectModels.RequestModels;

namespace OpenAI.Playground.TestHelpers;

internal static class BatchTestHelper
{
public static async Task RunBatchOperationsTest(IOpenAIService sdk)
{
ConsoleExtensions.WriteLine("Batch Operations Testing is starting:", ConsoleColor.Cyan);

try
{
ConsoleExtensions.WriteLine("Batch Create Test:", ConsoleColor.DarkCyan);

const string fileName = "BatchDataSampleFile.jsonl";
var sampleFile = await FileExtensions.ReadAllBytesAsync($"SampleData/{fileName}");
ConsoleExtensions.WriteLine($"Uploading file {fileName}", ConsoleColor.DarkCyan);

var fileUploadResult = await sdk.Files.UploadFile("batch", sampleFile, fileName);

if (!fileUploadResult.Successful)
{
throw new Exception("File upload failed");
}

var batchCreateResult = await sdk.Batch.BatchCreate(new BatchCreateRequest
{
InputFileId = fileUploadResult.Id,
Endpoint = "/v1/chat/completions",
CompletionWindow = "24h"
});

if (!batchCreateResult.Successful)
{
throw new Exception("Batch creation failed");
}

ConsoleExtensions.WriteLine($"Batch ID: {batchCreateResult.Id}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($"Batch Status: {batchCreateResult.Status}", ConsoleColor.Green);

ConsoleExtensions.WriteLine("Batch Retrieve Test:", ConsoleColor.DarkCyan);

var batchRetrieveResult = await sdk.Batch.BatchRetrieve(batchCreateResult.Id);

if (!batchRetrieveResult.Successful)
{
throw new Exception("Batch retrieval failed");
}

ConsoleExtensions.WriteLine($"Batch ID: {batchRetrieveResult.Id}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($"Batch Status: {batchRetrieveResult.Status}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($"Request Counts:", ConsoleColor.Green);
ConsoleExtensions.WriteLine($" Total: {batchRetrieveResult.RequestCounts.Total}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($" Completed: {batchRetrieveResult.RequestCounts.Completed}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($" Failed: {batchRetrieveResult.RequestCounts.Failed}", ConsoleColor.Green);

ConsoleExtensions.WriteLine("Batch Cancel Test:", ConsoleColor.DarkCyan);

var batchCancelResult = await sdk.Batch.BatchCancel(batchCreateResult.Id);

if (!batchCancelResult.Successful)
{
throw new Exception("Batch cancellation failed");
}

ConsoleExtensions.WriteLine($"Batch ID: {batchCancelResult.Id}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($"Batch Status: {batchCancelResult.Status}", ConsoleColor.Green);
ConsoleExtensions.WriteLine($"Cancelling At: {batchCancelResult.CancellingAt}", ConsoleColor.Green);
}
catch (Exception e)
{
ConsoleExtensions.WriteLine($"Error: {e.Message}", ConsoleColor.Red);
throw;
}
}
}
15 changes: 15 additions & 0 deletions OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,21 @@ public string AudioCreateSpeech()
return $"{Prefix}/audio/speech{QueryString}";
}

public string BatchCreate()
{
return $"{Prefix}/batches{QueryString}";
}

public string BatchRetrieve(string batchId)
{
return $"{Prefix}/batches/{batchId}{QueryString}";
}

public string BatchCancel(string batchId)
{
return $"{Prefix}/batches/{batchId}/cancel{QueryString}";
}

private string Files()
{
return $"{Prefix}/files{QueryString}";
Expand Down
3 changes: 3 additions & 0 deletions OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ internal interface IOpenAiEndpointProvider
string AudioCreateTranscription();
string AudioCreateTranslation();
string AudioCreateSpeech();
string BatchCreate();
string BatchRetrieve(string batchId);
string BatchCancel(string batchId);
}
15 changes: 15 additions & 0 deletions OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ public string AudioCreateSpeech()
return $"{_apiVersion}/audio/speech";
}

public string BatchCreate()
{
return $"{_apiVersion}/batches";
}

public string BatchRetrieve(string batchId)
{
return $"{_apiVersion}/batches/{batchId}";
}

public string BatchCancel(string batchId)
{
return $"{_apiVersion}/batches/{batchId}/cancel";
}

public string EditCreate()
{
return $"{_apiVersion}/edits";
Expand Down
32 changes: 32 additions & 0 deletions OpenAI.SDK/Interfaces/IBatchService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels.BatchResponseModel;

namespace OpenAI.Interfaces;

public interface IBatchService
{
/// <summary>
/// Creates and executes a batch from an uploaded file of requests.
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns>The created Batch object.</returns>
Task<BatchResponse> BatchCreate(BatchCreateRequest request, CancellationToken cancellationToken = default);

/// <summary>
/// Retrieves a batch.
/// </summary>
/// <param name="batchId">The ID of the batch to retrieve.</param>
/// <param name="cancellationToken"></param>
/// <returns>The Batch object matching the specified ID.</returns>
Task<BatchResponse?> BatchRetrieve(string batchId, CancellationToken cancellationToken = default);

/// <summary>
/// Cancels an in-progress batch.
/// </summary>
/// <param name="batchId">The ID of the batch to cancel.</param>
/// <param name="cancellationToken"></param>
/// <returns>The Batch object matching the specified ID.</returns>
Task<BatchResponse> BatchCancel(string batchId, CancellationToken cancellationToken = default);

}
4 changes: 4 additions & 0 deletions OpenAI.SDK/Interfaces/IOpenAIService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public interface IOpenAIService
/// Given an audio file, the model will return a transcription of the audio.
/// </summary>
public IAudioService Audio { get; }
/// <summary>
/// Create large batches of API requests to run asynchronously.
/// </summary>
public IBatchService Batch{ get; }


/// <summary>
Expand Down
28 changes: 28 additions & 0 deletions OpenAI.SDK/Managers/OpenAIBatchService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using OpenAI.Extensions;
using OpenAI.Interfaces;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels.BatchResponseModel;
using System.Net.Http.Json;

namespace OpenAI.Managers;

public partial class OpenAIService : IBatchService
{
/// <inheritdoc />
public async Task<BatchResponse> BatchCreate(BatchCreateRequest request, CancellationToken cancellationToken = default)
{
return await _httpClient.PostAndReadAsAsync<BatchResponse>(_endpointProvider.BatchCreate(), request, cancellationToken);
}

/// <inheritdoc />
public async Task<BatchResponse?> BatchRetrieve(string batchId, CancellationToken cancellationToken = default)
{
return await _httpClient.GetFromJsonAsync<BatchResponse>(_endpointProvider.BatchRetrieve(batchId), cancellationToken);
}

/// <inheritdoc />
public async Task<BatchResponse> BatchCancel(string batchId, CancellationToken cancellationToken = default)
{
return await _httpClient.PostAndReadAsAsync<BatchResponse>(_endpointProvider.BatchCancel(batchId),null, cancellationToken);
}
}
3 changes: 3 additions & 0 deletions OpenAI.SDK/Managers/OpenAIService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ public void Dispose()

/// <inheritdoc />
public IAudioService Audio => this;

/// <inheritdoc />
public IBatchService Batch => this;

/// <summary>
/// Sets default Model Id
Expand Down
32 changes: 32 additions & 0 deletions OpenAI.SDK/ObjectModels/RequestModels/BatchCreateRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Text.Json.Serialization;

namespace OpenAI.ObjectModels.RequestModels;

public record BatchCreateRequest
{
/// <summary>
/// The ID of an uploaded file that contains requests for the new batch.
/// See [upload file](/docs/api-reference/files/create) for how to upload a file.
/// Your input file must be formatted as a JSONL file, and must be uploaded with the purpose `batch`.
/// </summary>
[JsonPropertyName("input_file_id")]
public string InputFileId { get; set; }

/// <summary>
/// The endpoint to be used for all requests in the batch. Currently only `/v1/chat/completions` is supported.
/// </summary>
[JsonPropertyName("endpoint")]
public string Endpoint { get; set; }

/// <summary>
/// The time frame within which the batch should be processed. Currently only `24h` is supported.
/// </summary>
[JsonPropertyName("completion_window")]
public string CompletionWindow { get; set; }

/// <summary>
/// Optional custom metadata for the batch.
/// </summary>
[JsonPropertyName("metadata")]
public Dictionary<string, string>? MetaData { get; set; }
}
2 changes: 2 additions & 0 deletions OpenAI.SDK/ObjectModels/ResponseModels/BaseResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public class Error

[JsonPropertyName("type")] public string? Type { get; set; }

[JsonPropertyName("line")]
public int? Line { get; set; }
[JsonIgnore] public string? Message { get; private set; }

[JsonIgnore] public List<string?> Messages { get; private set; }
Expand Down
Loading

0 comments on commit 9295517

Please sign in to comment.