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

7.2.0 #382

Merged
merged 15 commits into from
Oct 6, 2023
Merged

7.2.0 #382

Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions OpenAI.Playground/OpenAI.Playground.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
<None Update="SampleData\FineTuningSample1.jsonl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="SampleData\FineTuningJobSample2.jsonl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="SampleData\image_edit_mask.png">
<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 @@ -44,8 +44,8 @@

//await ChatCompletionTestHelper.RunSimpleChatCompletionTest(sdk);
//await ChatCompletionTestHelper.RunSimpleCompletionStreamTest(sdk);
await ChatCompletionTestHelper.RunChatFunctionCallTest(sdk);

//await ChatCompletionTestHelper.RunChatFunctionCallTest(sdk);
await FineTuningJobTestHelper.RunCaseStudyIsTheModelMakingUntrueStatements(sdk);
// Whisper
//await AudioTestHelper.RunSimpleAudioCreateTranscriptionTest(sdk);
//await AudioTestHelper.RunSimpleAudioCreateTranslationTest(sdk);
Expand Down
10 changes: 10 additions & 0 deletions OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"What's the capital of France?"},{"role":"assistant","content":"Paris, as if everyone doesn't know that already."}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"Who wrote 'Romeo and Juliet'?"},{"role":"assistant","content":"Oh, just some guy named William Shakespeare. Ever heard of him?"}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"How far is the Moon from Earth?"},{"role":"assistant","content":"Around 384,400 kilometers. Give or take a few, like that really matters."}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"What is the boiling point of water?"},{"role":"assistant","content":"100 degrees Celsius. Groundbreaking information, right?"}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"Who discovered gravity?"},{"role":"assistant","content":"Isaac Newton. You know, the apple guy?"}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"How many continents are there?"},{"role":"assistant","content":"Seven. Did you just skip geography class or what?"}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"What's the largest planet in the solar system?"},{"role":"assistant","content":"Jupiter, as if it wasn't obvious enough."}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"What's the speed of light?"},{"role":"assistant","content":"Approximately 299,792,458 meters per second. But who's counting?"}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"Who is the current U.S. President?"},{"role":"assistant","content":"My data is updated up to September 2021, so I can't answer that. But you've got the internet, don't you?"}]}
{"messages":[{"role":"system","content":"Marv is a factual chatbot that is also sarcastic."},{"role":"user","content":"What's the formula for water?"},{"role":"assistant","content":"H2O. Even a toddler knows that."}]}
108 changes: 108 additions & 0 deletions OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using OpenAI.Interfaces;
using OpenAI.ObjectModels;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;

namespace OpenAI.Playground.TestHelpers;

internal static class FineTuningJobTestHelper
{
public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAIService sdk)
{
ConsoleExtensions.WriteLine("Run Case Study Is The Model Making Untrue Statements:", ConsoleColor.Cyan);

var jobs = await sdk.FineTuningJob.ListFineTuningJobs();
//print all jobs
foreach (var job in jobs.Data)
{
Console.WriteLine(job.FineTunedModel);
}

try
{
const string fileName = "FineTuningJobSample2.jsonl";
var sampleFile = await FileExtensions.ReadAllBytesAsync($"SampleData/{fileName}");

ConsoleExtensions.WriteLine($"Uploading file {fileName}", ConsoleColor.DarkCyan);
var uploadFilesResponse = await sdk.Files.FileUpload(UploadFilePurposes.UploadFilePurpose.FineTune, sampleFile, fileName);
if (uploadFilesResponse.Successful)
{
ConsoleExtensions.WriteLine($"{fileName} uploaded", ConsoleColor.DarkGreen);
}
else
{
ConsoleExtensions.WriteLine($"{fileName} failed", ConsoleColor.DarkRed);
}

ConsoleExtensions.WriteLine($"Wait 5 seconds for the file to be ready", ConsoleColor.DarkYellow);
await Task.Delay(5_000);

var createFineTuningJobResponse = await sdk.FineTuningJob.CreateFineTuningJob(new FineTuningJobCreateRequest
{
TrainingFile = uploadFilesResponse.Id,
Model = Models.Gpt_3_5_Turbo
});

var listFineTuningJobEventsStream = await sdk.FineTuningJob.ListFineTuningJobEvents(new FineTuningJobListEventsRequest
{
FineTuningJobId = createFineTuningJobResponse.Id
}, true);

using var streamReader = new StreamReader(listFineTuningJobEventsStream);
while (!streamReader.EndOfStream)
{
Console.WriteLine(await streamReader.ReadLineAsync());
}

FineTuningJobResponse retrieveFineTuningJobResponse;
do
{
retrieveFineTuningJobResponse = await sdk.FineTuningJob.RetrieveFineTuningJob(createFineTuningJobResponse.Id);
if (retrieveFineTuningJobResponse.Status == "succeeded" || retrieveFineTuningJobResponse.Status == "cancelled" || retrieveFineTuningJobResponse.Status == "failed")
{
ConsoleExtensions.WriteLine($"Fine-tune Status for {createFineTuningJobResponse.Id}: {retrieveFineTuningJobResponse.Status}.", ConsoleColor.Yellow);
break;
}

ConsoleExtensions.WriteLine($"Fine-tune Status for {createFineTuningJobResponse.Id}: {retrieveFineTuningJobResponse.Status}. Wait 10 more seconds", ConsoleColor.DarkYellow);
await Task.Delay(10_000);
} while (true);

do
{
var completionResult = await sdk.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem("You are Marv, a chatbot that reluctantly answers questions with sarcastic responses."),
ChatMessage.FromUser("How many pounds are in a kilogram?"),
},
MaxTokens = 50,
Model = retrieveFineTuningJobResponse.FineTunedModel
});

if (completionResult.Successful)
{
Console.WriteLine(completionResult.Choices.FirstOrDefault());
break;
}

ConsoleExtensions.WriteLine($"failed{completionResult.Error?.Message}", ConsoleColor.DarkRed);
} while (true);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}

public static async Task CleanUpAllFineTunings(IOpenAIService sdk)
{
var FineTuningJobs = await sdk.FineTuningJob.ListFineTuningJobs();
foreach (var datum in FineTuningJobs.Data)
{
await sdk.Models.DeleteModel(datum.FineTunedModel);
}
}
}
52 changes: 50 additions & 2 deletions OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using OpenAI.ObjectModels.RequestModels;

namespace OpenAI.EndpointProviders;

Expand Down Expand Up @@ -95,6 +96,53 @@ public string FineTuneDelete(string fineTuneId)
return $"{Prefix}/models/{fineTuneId}{QueryString}";
}

public string FineTuningJobCreate()
{
return $"{Prefix}/fine_tuning/jobs{QueryString}";
}

public string FineTuningJobList(FineTuningJobListRequest? fineTuningJobListRequest)
{
var url = $"/{Prefix}/fine_tuning/jobs";
if (fineTuningJobListRequest != null)
{
var queryParams = new List<string>();
if (fineTuningJobListRequest.After != null)
queryParams.Add($"after={WebUtility.UrlEncode(fineTuningJobListRequest.After)}");
if (fineTuningJobListRequest.Limit.HasValue)
queryParams.Add($"limit={fineTuningJobListRequest.Limit.Value}");

if (queryParams.Any())
url = $"{url}{QueryString}&{string.Join("&", queryParams)}";
}
return url;
}

public string FineTuningJobList()
{
return $"{Prefix}/fine_tuning/jobs{QueryString}";
}

public string FineTuningJobRetrieve(string fineTuningJobId)
{
return $"{Prefix}/fine_tuning/jobs/{fineTuningJobId}{QueryString}";
}

public string FineTuningJobCancel(string fineTuningJobId)
{
return $"{Prefix}/fine_tuning/jobs/{fineTuningJobId}/cancel{QueryString}";
}

public string FineTuningJobListEvents(string fineTuningJobId)
{
return $"{Prefix}/fine_tuning/jobs/{fineTuningJobId}/events{QueryString}";
}

public string ModelsDelete(string modelId)
{
return $"{Prefix}/models/{modelId}{QueryString}";
}

public string EmbeddingCreate()
{
return $"{Prefix}/embeddings{QueryString}";
Expand Down Expand Up @@ -127,12 +175,12 @@ public string ChatCompletionCreate()

public string AudioCreateTranscription()
{
return $"/{Prefix}/audio/transcriptions{QueryString}";
return $"{Prefix}/audio/transcriptions{QueryString}";
}

public string AudioCreateTranslation()
{
return $"/{Prefix}/audio/translation{QueryString}";
return $"{Prefix}/audio/translation{QueryString}";
}

private string Files()
Expand Down
10 changes: 9 additions & 1 deletion OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
namespace OpenAI.EndpointProviders;
using OpenAI.ObjectModels.RequestModels;

namespace OpenAI.EndpointProviders;

internal interface IOpenAiEndpointProvider
{
string ModelRetrieve(string model);
string CompletionCreate();
string EditCreate();
string ModelsList();
string ModelsDelete(string modelId);
string FilesList();
string FilesUpload();
string FileDelete(string fileId);
Expand All @@ -17,6 +20,11 @@ internal interface IOpenAiEndpointProvider
string FineTuneCancel(string fineTuneId);
string FineTuneListEvents(string fineTuneId);
string FineTuneDelete(string fineTuneId);
string FineTuningJobCreate();
string FineTuningJobList(FineTuningJobListRequest? fineTuningJobListRequest);
string FineTuningJobRetrieve(string fineTuningJobId);
string FineTuningJobCancel(string fineTuningJobId);
string FineTuningJobListEvents(string fineTuningJobId);
string EmbeddingCreate();
string ModerationCreate();
string ImageCreate();
Expand Down
47 changes: 46 additions & 1 deletion OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace OpenAI.EndpointProviders;
using System.Net;
using OpenAI.ObjectModels.RequestModels;

namespace OpenAI.EndpointProviders;

internal class OpenAiEndpointProvider : IOpenAiEndpointProvider
{
Expand Down Expand Up @@ -99,6 +102,48 @@ public string FineTuneDelete(string fineTuneId)
return $"/{_apiVersion}/models/{fineTuneId}";
}

public string FineTuningJobCreate()
{
return $"/{_apiVersion}/fine_tuning/jobs";
}

public string FineTuningJobList(FineTuningJobListRequest? fineTuningJobListRequest)
{
var url = $"/{_apiVersion}/fine_tuning/jobs";
if (fineTuningJobListRequest != null)
{
var queryParams = new List<string>();
if (fineTuningJobListRequest.After != null)
queryParams.Add($"after={WebUtility.UrlEncode(fineTuningJobListRequest.After)}");
if (fineTuningJobListRequest.Limit.HasValue)
queryParams.Add($"limit={fineTuningJobListRequest.Limit.Value}");

if (queryParams.Any())
url = $"{url}?{string.Join("&", queryParams)}";
}
return url;
}

public string FineTuningJobRetrieve(string fineTuningJobId)
{
return $"/{_apiVersion}/fine_tuning/jobs/{fineTuningJobId}";
}

public string FineTuningJobCancel(string fineTuningJobId)
{
return $"/{_apiVersion}/fine_tuning/jobs/{fineTuningJobId}/cancel";
}

public string FineTuningJobListEvents(string fineTuningJobId)
{
return $"/{_apiVersion}/fine_tuning/jobs/{fineTuningJobId}/events";
}

public string ModelsDelete(string modelId)
{
return $"/{_apiVersion}/models/{modelId}";
}

public string EmbeddingCreate()
{
return $"/{_apiVersion}/embeddings";
Expand Down
2 changes: 1 addition & 1 deletion OpenAI.SDK/Extensions/HttpclientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace OpenAI.Extensions;

public static class HttpClientExtensions
{
public static async Task<TResponse> PostAndReadAsAsync<TResponse>(this HttpClient client, string uri, object requestModel, CancellationToken cancellationToken = default)
public static async Task<TResponse> PostAndReadAsAsync<TResponse>(this HttpClient client, string uri, object? requestModel, CancellationToken cancellationToken = default)
{
var response = await client.PostAsJsonAsync(uri, requestModel, new JsonSerializerOptions
{
Expand Down
59 changes: 59 additions & 0 deletions OpenAI.SDK/Interfaces/IFineTuningJobService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;

namespace OpenAI.Interfaces;

/// <summary>
/// Manage fine-tuning jobs to tailor a model to your specific training data.
/// Related guide: <a href="https://platform.openai.com/docs/guides/fine-tuning">Fine-tune models</a>
/// </summary>
public interface IFineTuningJobService
{
/// <summary>
/// Creates a job that fine-tunes a specified model from a given dataset.
/// Response includes details of the enqueued job including job status and the name of the fine-tuned models once
/// complete.
/// </summary>
/// <param name="createFineTuningJobRequest"></param>
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
/// <returns></returns>
Task<FineTuningJobResponse> CreateFineTuningJob(FineTuningJobCreateRequest createFineTuningJobRequest, CancellationToken cancellationToken = default);

/// <summary>
/// List your organization's fine-tuning jobs
/// </summary>
/// <param name="fineTuningJobListRequest"></param>
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
/// <returns></returns>
Task<FineTuningJobListResponse> ListFineTuningJobs(FineTuningJobListRequest? fineTuningJobListRequest =null,CancellationToken cancellationToken = default);

/// <summary>
/// Gets info about the fine-tuning job.
/// </summary>
/// <param name="fineTuningJobId">The ID of the fine-tuning job</param>
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
/// <returns></returns>
Task<FineTuningJobResponse> RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default);

/// <summary>
/// Immediately cancel a fine-tuning job.
/// </summary>
/// <param name="fineTuningJobId">The ID of the fine-tuning job to cancel</param>
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
/// <returns></returns>
Task<FineTuningJobResponse> CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default);

/// <summary>
/// Get fine-grained status updates for a fine-tuning job.
/// </summary>
/// <param name="model"></param>
/// <param name="stream">
/// Whether to stream events for the fine-tuning job. If set to true, events will be sent as data-only server-sent events
/// as they become available. The stream will terminate with a data: [DONE] message when the job is finished
/// (succeeded, cancelled, or failed).
/// If set to false, only events generated so far will be returned.
/// </param>
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
/// <returns></returns>
Task<Stream> ListFineTuningJobEvents(FineTuningJobListEventsRequest model, bool? stream = null, CancellationToken cancellationToken = default);
}
8 changes: 8 additions & 0 deletions OpenAI.SDK/Interfaces/IModelService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,12 @@ public interface IModelService
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
/// <returns></returns>
Task<ModelRetrieveResponse> RetrieveModel(string model, CancellationToken cancellationToken = default);

/// <summary>
/// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model.
/// </summary>
/// <param name="modelId">The model to delete</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<ModelDeleteResponse?> DeleteModel(string modelId, CancellationToken cancellationToken = default);
}
5 changes: 5 additions & 0 deletions OpenAI.SDK/Interfaces/IOpenAIService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public interface IOpenAIService

public IFineTuneService FineTunes { get; }

/// <summary>
/// Manage fine-tuning jobs to tailor a model to your specific training data.
/// </summary>
public IFineTuningJobService FineTuningJob { get; }

public IModerationService Moderation { get; }

/// <summary>
Expand Down
Loading
Loading