From 1f15857ec0dfee687a7810ba111c31496e9bd1b7 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 17:43:45 -0700
Subject: [PATCH 01/13] Create ObjectModels to support new Fine Tuning Job
https://platform.openai.com/docs/api-reference/fine-tuning
---
.../FineTuningJobCancelRequest.cs | 9 ++
.../FineTuningJobCreateRequest.cs | 122 ++++++++++++++++++
.../FineTuningJobListEventsResponse.cs | 11 ++
.../FineTuningJobListResponse.cs | 10 ++
.../FineTuningJobResponse.cs | 49 +++++++
5 files changed, 201 insertions(+)
create mode 100644 OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCancelRequest.cs
create mode 100644 OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs
create mode 100644 OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs
create mode 100644 OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs
create mode 100644 OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
diff --git a/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCancelRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCancelRequest.cs
new file mode 100644
index 00000000..75f7c19d
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCancelRequest.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.RequestModels;
+
+public record FineTuningJobCancelRequest
+{
+ [JsonPropertyName("fine_tuning_job_id")]
+ public string FineTuningJobId { get; set; }
+}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs
new file mode 100644
index 00000000..b9f87c6b
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs
@@ -0,0 +1,122 @@
+using OpenAI.ObjectModels.SharedModels;
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.RequestModels;
+
+public record FineTuningJobCreateRequest : IOpenAiModels.IModel
+{
+ ///
+ /// The ID of an uploaded file that contains training data.
+ /// See upload file for how to upload a file.
+ /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object with the keys "prompt"
+ /// and "completion". Additionally, you must upload your file with the purpose fine-tune.
+ /// See the fine-tuning guide
+ /// for
+ /// more details.
+ ///
+ [JsonPropertyName("training_file")]
+ public string TrainingFile { get; set; }
+
+ ///
+ /// The ID of an uploaded file that contains validation data.
+ /// If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These
+ /// metrics can be viewed in the
+ ///
+ /// fine-tuning results
+ /// file
+ ///
+ /// . Your train and validation data should be mutually exclusive.
+ /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object with the keys
+ /// "prompt" and "completion". Additionally, you must upload your file with the purpose fine-tune.
+ /// See the fine-tuning guide
+ /// for
+ /// more details.
+ ///
+ [JsonPropertyName("validation_file")]
+ public string? ValidationFile { get; set; }
+
+ ///
+ /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.
+ ///
+ [JsonPropertyName("n_epochs")]
+ public int? NEpochs { get; set; }
+
+ ///
+ /// The batch size to use for training. The batch size is the number of training examples used to train a single
+ /// forward and backward pass.
+ /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples in the training
+ /// set, capped at 256 - in general, we've found that larger batch sizes tend to work better for larger datasets.
+ ///
+ [JsonPropertyName("batch_size")]
+ public int? BatchSize { get; set; }
+
+ ///
+ /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original learning rate used
+ /// for pretraining multiplied by this value.
+ /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final batch_size(larger learning
+ /// rates tend to perform better with larger batch sizes). We recommend experimenting with values in the range 0.02 to
+ /// 0.2 to see what produces the best results.
+ ///
+ [JsonPropertyName("learning_rate_multiplier")]
+ public float? LearningRateMultiplier { get; set; }
+
+ ///
+ /// The weight to use for loss on the prompt tokens. This controls how much the model tries to learn to generate the
+ /// prompt (as compared to the completion which always has a weight of 1.0), and can add a stabilizing effect to
+ /// training when completions are short.
+ /// If prompts are extremely long (relative to completions), it may make sense to reduce this weight so as to avoid
+ /// over-prioritizing learning the prompt.
+ ///
+ [JsonPropertyName("prompt_loss_weight")]
+ public float? PromptLossWeight { get; set; }
+
+ ///
+ /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the validation set at the
+ /// end of every epoch.These metrics can be viewed in the
+ /// results file.
+ /// In order to compute classification metrics, you must provide a validation_file.Additionally, you must specify
+ /// classification_n_classes for multiclass classification or classification_positive_class for binary classification.
+ ///
+ [JsonPropertyName("compute_classification_metrics")]
+ public bool? ComputeClassificationMetrics { get; set; }
+
+ ///
+ /// The number of classes in a classification task.
+ /// This parameter is required for multiclass classification.
+ ///
+ [JsonPropertyName("classification_n_classes")]
+ public int? ClassificationNClasses { get; set; }
+
+ ///
+ /// The positive class in binary classification.
+ /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary classification.
+ ///
+ [JsonPropertyName("classification_positive_class")]
+ public string? ClassificationPositiveClass { get; set; }
+
+ //TODO documentation wasn't clear, I don't know which type of array is expected
+ ///
+ /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score is a generalization
+ /// of F-1 score. This is only used for binary classification.
+ /// With a beta of 1 (i.e.the F-1 score), precision and recall are given the same weight.A larger beta score puts more
+ /// weight on recall and less on precision. A smaller beta score puts more weight on precision and less on recall.
+ ///
+ [JsonPropertyName("classification_betas")]
+ public List? ClassificationBetas { get; set; }
+
+ ///
+ /// A string of up to 40 characters that will be added to your fine-tuned model name.
+ /// For example, a suffix of "custom-model-name" would produce a model name like
+ /// ada:ft-your-org:custom-model-name-2022-02-15-04-21-04.
+ ///
+ [JsonPropertyName("suffix")]
+ public string? Suffix { get; set; }
+
+
+ ///
+ /// The name of the base model to fine-tune. You can select one of "ada", "babbage", or "curie". To learn more about
+ /// these models, see the Models documentation.
+ ///
+ [JsonPropertyName("model")]
+ public string? Model { get; set; }
+}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs
new file mode 100644
index 00000000..140c1f12
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs
@@ -0,0 +1,11 @@
+using OpenAI.ObjectModels.SharedModels;
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+
+public record FineTuningJobListEventsResponse : BaseResponse
+{
+ [JsonPropertyName("data")]
+ public List Data { get; set; }
+}
+
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs
new file mode 100644
index 00000000..068121d8
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+
+public record FineTuningJobListResponse : BaseResponse
+{
+ [JsonPropertyName("data")]
+ public List Data { get; set; }
+}
+
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
new file mode 100644
index 00000000..c771e1f5
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
@@ -0,0 +1,49 @@
+using OpenAI.ObjectModels.SharedModels;
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+
+public record FineTuningJobResponse : BaseResponse, IOpenAiModels.IId, IOpenAiModels.IModel, IOpenAiModels.ICreatedAt
+{
+ [JsonPropertyName("id")]
+ public string Id { get; set; }
+
+ [JsonPropertyName("object")]
+ public string Object { get; set; }
+
+ [JsonPropertyName("created_at")]
+ public int CreatedAt { get; set; }
+
+ [JsonPropertyName("finished_at")]
+ public int? FinishedAt { get; set; }
+
+ [JsonPropertyName("model")]
+ public string Model { get; set; }
+
+ [JsonPropertyName("fine_tuned_model")]
+ public string? FineTunedModel { get; set; }
+
+ [JsonPropertyName("organization_id")]
+ public string OrganizationId { get; set; }
+
+ [JsonPropertyName("status")]
+ public string Status { get; set; }
+
+ [JsonPropertyName("hyperparameters")]
+ public HyperParametersResponse HyperParams { get; set; }
+
+ [JsonPropertyName("validation_files")]
+ public List ValidationFiles { get; set; }
+
+ [JsonPropertyName("training_files")]
+ public List TrainingFiles { get; set; }
+
+ [JsonPropertyName("result_files")]
+ public List ResultFiles { get; set; }
+
+ [JsonPropertyName("trained_tokens")]
+ public int? TrainedTokens { get; set; }
+
+ [JsonPropertyName("updated_at")]
+ public int? UpdatedAt { get; set; }
+}
From a5007e55e9f91b40a61eb1f183ffaebe1b53218a Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 17:44:05 -0700
Subject: [PATCH 02/13] Add FineTuningJobService
---
.../AzureOpenAiEndpointProvider.cs | 30 ++++++++++
.../IOpenAiEndpointProvider.cs | 6 ++
.../OpenAiEndpointProvider.cs | 30 ++++++++++
.../Interfaces/IFineTuningJobService.cs | 60 +++++++++++++++++++
OpenAI.SDK/Interfaces/IOpenAIService.cs | 5 ++
OpenAI.SDK/Managers/OpenAIFineTuningJob.cs | 44 ++++++++++++++
OpenAI.SDK/Managers/OpenAIService.cs | 3 +
7 files changed, 178 insertions(+)
create mode 100644 OpenAI.SDK/Interfaces/IFineTuningJobService.cs
create mode 100644 OpenAI.SDK/Managers/OpenAIFineTuningJob.cs
diff --git a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
index 090af9cd..61a4fc39 100644
--- a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
@@ -95,6 +95,36 @@ public string FineTuneDelete(string fineTuneId)
return $"{Prefix}/models/{fineTuneId}{QueryString}";
}
+ public string FineTuningJobCreate()
+ {
+ return $"{Prefix}/fine_tuning/jobs{QueryString}";
+ }
+
+ 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 FineTuningJobDelete(string fineTuningJobId)
+ {
+ return $"{Prefix}/models/{fineTuningJobId}{QueryString}";
+ }
+
public string EmbeddingCreate()
{
return $"{Prefix}/embeddings{QueryString}";
diff --git a/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
index 75adcee1..38dcd1ae 100644
--- a/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
@@ -17,6 +17,12 @@ internal interface IOpenAiEndpointProvider
string FineTuneCancel(string fineTuneId);
string FineTuneListEvents(string fineTuneId);
string FineTuneDelete(string fineTuneId);
+ string FineTuningJobCreate();
+ string FineTuningJobList();
+ string FineTuningJobRetrieve(string fineTuningJobId);
+ string FineTuningJobCancel(string fineTuningJobId);
+ string FineTuningJobListEvents(string fineTuningJobId);
+ string FineTuningJobDelete(string fineTuningJobId);
string EmbeddingCreate();
string ModerationCreate();
string ImageCreate();
diff --git a/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
index 40319dbc..f4ea9631 100644
--- a/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
@@ -99,6 +99,36 @@ public string FineTuneDelete(string fineTuneId)
return $"/{_apiVersion}/models/{fineTuneId}";
}
+ public string FineTuningJobCreate()
+ {
+ return $"/{_apiVersion}/fine_tuning/jobs";
+ }
+
+ public string FineTuningJobList()
+ {
+ return $"/{_apiVersion}/fine_tuning/jobs";
+ }
+
+ 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 FineTuningJobDelete(string fineTuningJobId)
+ {
+ return $"/{_apiVersion}/models/{fineTuningJobId}";
+ }
+
public string EmbeddingCreate()
{
return $"/{_apiVersion}/embeddings";
diff --git a/OpenAI.SDK/Interfaces/IFineTuningJobService.cs b/OpenAI.SDK/Interfaces/IFineTuningJobService.cs
new file mode 100644
index 00000000..86c2adf2
--- /dev/null
+++ b/OpenAI.SDK/Interfaces/IFineTuningJobService.cs
@@ -0,0 +1,60 @@
+using OpenAI.ObjectModels.RequestModels;
+using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+
+namespace OpenAI.Interfaces;
+
+///
+/// Manage fine-tuning jobs to tailor a model to your specific training data.
+/// Related guide: Fine-tune models
+///
+public interface IFineTuningJobService
+{
+ ///
+ /// 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.
+ ///
+ ///
+ /// Propagates notification that operations should be canceled.
+ ///
+ Task CreateFineTuningJob(FineTuningJobCreateRequest createFineTuningJobRequest, CancellationToken cancellationToken = default);
+
+ ///
+ /// List your organization's fine-tuning jobs
+ ///
+ /// Propagates notification that operations should be canceled.
+ ///
+ Task ListFineTuningJobs(CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets info about the fine-tuning job.
+ ///
+ /// The ID of the fine-tuning job
+ /// Propagates notification that operations should be canceled.
+ ///
+ Task RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default);
+
+ ///
+ /// Immediately cancel a fine-tuning job.
+ ///
+ /// The ID of the fine-tuning job to cancel
+ /// Propagates notification that operations should be canceled.
+ ///
+ Task CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default);
+
+ ///
+ /// Get fine-grained status updates for a fine-tuning job.
+ ///
+ /// The ID of the fine-tuning job to get events for.
+ ///
+ /// 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.
+ ///
+ /// Propagates notification that operations should be canceled.
+ ///
+ Task ListFineTuningJobEvents(string fineTuningJobId, bool? stream = null, CancellationToken cancellationToken = default);
+
+ Task DeleteFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default);
+}
diff --git a/OpenAI.SDK/Interfaces/IOpenAIService.cs b/OpenAI.SDK/Interfaces/IOpenAIService.cs
index dec050e3..671865d4 100644
--- a/OpenAI.SDK/Interfaces/IOpenAIService.cs
+++ b/OpenAI.SDK/Interfaces/IOpenAIService.cs
@@ -28,6 +28,11 @@ public interface IOpenAIService
public IFineTuneService FineTunes { get; }
+ ///
+ /// Manage fine-tuning jobs to tailor a model to your specific training data.
+ ///
+ public IFineTuningJobService FineTuningJob { get; }
+
public IModerationService Moderation { get; }
///
diff --git a/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs b/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs
new file mode 100644
index 00000000..9b1e53d1
--- /dev/null
+++ b/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs
@@ -0,0 +1,44 @@
+using OpenAI.Extensions;
+using OpenAI.Interfaces;
+using OpenAI.ObjectModels.RequestModels;
+using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+using System.Net.Http.Json;
+
+namespace OpenAI.Managers
+{
+ public partial class OpenAIService : IFineTuningJobService
+ {
+ public async Task CreateFineTuningJob(FineTuningJobCreateRequest createFineTuningJobRequest, CancellationToken cancellationToken = default)
+ {
+ return await _httpClient.PostAndReadAsAsync(_endpointProvider.FineTuningJobCreate(), createFineTuningJobRequest, cancellationToken);
+ }
+
+ public async Task ListFineTuningJobs(CancellationToken cancellationToken = default)
+ {
+ return (await _httpClient.GetFromJsonAsync(_endpointProvider.FineTuningJobList(), cancellationToken))!;
+ }
+
+ public async Task RetrieveFineTuningJob(string FineTuningJobId, CancellationToken cancellationToken = default)
+ {
+ return (await _httpClient.GetFromJsonAsync(_endpointProvider.FineTuningJobRetrieve(FineTuningJobId), cancellationToken))!;
+ }
+
+ public async Task CancelFineTuningJob(string FineTuningJobId, CancellationToken cancellationToken = default)
+ {
+ return await _httpClient.PostAndReadAsAsync(_endpointProvider.FineTuningJobCancel(FineTuningJobId), new FineTuningJobCancelRequest
+ {
+ FineTuningJobId = FineTuningJobId
+ }, cancellationToken);
+ }
+
+ public async Task ListFineTuningJobEvents(string FineTuningJobId, bool? stream = null, CancellationToken cancellationToken = default)
+ {
+ return await _httpClient.GetStreamAsync(_endpointProvider.FineTuningJobListEvents(FineTuningJobId), cancellationToken);
+ }
+
+ public async Task DeleteFineTuningJob(string FineTuningJobId, CancellationToken cancellationToken = default)
+ {
+ await _httpClient.DeleteAsync(_endpointProvider.FineTuningJobDelete(FineTuningJobId), cancellationToken);
+ }
+ }
+}
diff --git a/OpenAI.SDK/Managers/OpenAIService.cs b/OpenAI.SDK/Managers/OpenAIService.cs
index 3a356529..229b8abf 100644
--- a/OpenAI.SDK/Managers/OpenAIService.cs
+++ b/OpenAI.SDK/Managers/OpenAIService.cs
@@ -85,6 +85,9 @@ public void Dispose()
///
public IFineTuneService FineTunes => this;
+ ///
+ public IFineTuningJobService FineTuningJob => this;
+
///
public IModerationService Moderation => this;
From 5b2141e29c808b30690570b192b59e47d46c9985 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 17:44:17 -0700
Subject: [PATCH 03/13] Update Playground to support new FineTuningJob
---
.../TestHelpers/FineTuningJobTestHelper.cs | 90 +++++++++++++++++++
1 file changed, 90 insertions(+)
create mode 100644 OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
diff --git a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
new file mode 100644
index 00000000..c176bf31
--- /dev/null
+++ b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
@@ -0,0 +1,90 @@
+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);
+
+ try
+ {
+ const string fileName = "FineTuningSample1.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);
+ }
+
+ var createFineTuningJobResponse = await sdk.FineTuningJob.CreateFineTuningJob(new FineTuningJobCreateRequest
+ {
+ TrainingFile = uploadFilesResponse.Id,
+ Model = Models.Gpt_3_5_Turbo
+ });
+
+ var listFineTuningJobEventsStream = await sdk.FineTuningJob.ListFineTuningJobEvents(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.Completions.CreateCompletion(new CompletionCreateRequest
+ {
+ MaxTokens = 1,
+ Prompt = @"https://t.co/f93xEd2 Excited to share my latest blog post! ->",
+ Model = retrieveFineTuningJobResponse.FineTunedModel,
+ LogProbs = 2
+ });
+ 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.FineTuningJob.DeleteFineTuningJob(datum.FineTunedModel);
+ }
+ }
+}
\ No newline at end of file
From 832acd5cb27d6c51b52c469c0d768e1a7457ef67 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 18:10:56 -0700
Subject: [PATCH 04/13] Remove Object from FineTuningJobResponse
---
.../FineTuningJobResponseModels/FineTuningJobResponse.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
index c771e1f5..03d3bb90 100644
--- a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
@@ -8,9 +8,6 @@ public record FineTuningJobResponse : BaseResponse, IOpenAiModels.IId, IOpenAiMo
[JsonPropertyName("id")]
public string Id { get; set; }
- [JsonPropertyName("object")]
- public string Object { get; set; }
-
[JsonPropertyName("created_at")]
public int CreatedAt { get; set; }
From 051589ef89a78b5be29b62b0dbd8a8678ce38512 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 18:32:45 -0700
Subject: [PATCH 05/13] Add FineTuningJobSample2.jsonl file
---
OpenAI.Playground/OpenAI.Playground.csproj | 3 +++
OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl | 3 +++
2 files changed, 6 insertions(+)
create mode 100644 OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
diff --git a/OpenAI.Playground/OpenAI.Playground.csproj b/OpenAI.Playground/OpenAI.Playground.csproj
index 2ac0b3a5..258aaa00 100644
--- a/OpenAI.Playground/OpenAI.Playground.csproj
+++ b/OpenAI.Playground/OpenAI.Playground.csproj
@@ -56,6 +56,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl b/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
new file mode 100644
index 00000000..ea456358
--- /dev/null
+++ b/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
@@ -0,0 +1,3 @@
+{"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."}]}
From 316d96317d4a4633cf6a50d7910b2c706bd37baa Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 18:33:56 -0700
Subject: [PATCH 06/13] Update FineTuningJobTestHelper to use the correct
sample file
---
OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
index c176bf31..7e3f1100 100644
--- a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
+++ b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
@@ -13,7 +13,7 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISer
try
{
- const string fileName = "FineTuningSample1.jsonl";
+ const string fileName = "FineTuningJobSample2.jsonl";
var sampleFile = await FileExtensions.ReadAllBytesAsync($"SampleData/{fileName}");
ConsoleExtensions.WriteLine($"Uploading file {fileName}", ConsoleColor.DarkCyan);
From 08cf6f234a2ae2094a973b281586811758831850 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 18:43:11 -0700
Subject: [PATCH 07/13] Update the fine tuning job sample file to make it 10
samples
---
OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl b/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
index ea456358..e915df4e 100644
--- a/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
+++ b/OpenAI.Playground/SampleData/FineTuningJobSample2.jsonl
@@ -1,3 +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."}]}
\ No newline at end of file
From acf302de84dd339703396c7d1b9a19a92af659f1 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 18:43:23 -0700
Subject: [PATCH 08/13] Add a 5 second delay for the fine tune file to be ready
---
OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
index 7e3f1100..1e0c11d5 100644
--- a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
+++ b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
@@ -27,6 +27,9 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISer
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,
From 3d8b6181ffa101129f652431784ee5f55c250d02 Mon Sep 17 00:00:00 2001
From: aghimir3 <22482815+aghimir3@users.noreply.github.com>
Date: Sun, 27 Aug 2023 19:32:17 -0700
Subject: [PATCH 09/13] Update FineTuningJobResponse to match OpenAI
Documentation
Be in alignment with https://platform.openai.com/docs/api-reference/fine-tuning/object
---
.../FineTuningJobResponse.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
index 03d3bb90..cbb4404d 100644
--- a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
@@ -27,16 +27,16 @@ public record FineTuningJobResponse : BaseResponse, IOpenAiModels.IId, IOpenAiMo
public string Status { get; set; }
[JsonPropertyName("hyperparameters")]
- public HyperParametersResponse HyperParams { get; set; }
+ public HyperParametersResponse HyperParameters { get; set; }
- [JsonPropertyName("validation_files")]
- public List ValidationFiles { get; set; }
+ [JsonPropertyName("validation_file")]
+ public string? ValidationFile { get; set; }
- [JsonPropertyName("training_files")]
- public List TrainingFiles { get; set; }
+ [JsonPropertyName("training_file")]
+ public string TrainingFile { get; set; }
[JsonPropertyName("result_files")]
- public List ResultFiles { get; set; }
+ public List ResultFiles { get; set; }
[JsonPropertyName("trained_tokens")]
public int? TrainedTokens { get; set; }
From 5c49f2af852953367b19d47d635198b67aac5644 Mon Sep 17 00:00:00 2001
From: Massimo Cerqui
Date: Fri, 22 Sep 2023 11:25:41 +0200
Subject: [PATCH 10/13] Fix AzureOpenAi Audio Endpoints
---
OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
index 090af9cd..87bb8c73 100644
--- a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
@@ -127,12 +127,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()
From ee94c69443d51731370ebdd315c9803b2389a477 Mon Sep 17 00:00:00 2001
From: Massimo Cerqui
Date: Fri, 22 Sep 2023 13:01:34 +0200
Subject: [PATCH 11/13] Pump Azure Open Ai Default Api Version
---
OpenAI.SDK/OpenAiOptions.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/OpenAI.SDK/OpenAiOptions.cs b/OpenAI.SDK/OpenAiOptions.cs
index a2d1abcb..2bcdcaed 100644
--- a/OpenAI.SDK/OpenAiOptions.cs
+++ b/OpenAI.SDK/OpenAiOptions.cs
@@ -20,7 +20,7 @@ public class OpenAiOptions
{
private const string OpenAiDefaultApiVersion = "v1";
private const string OpenAiDefaultBaseDomain = "https://api.openai.com/";
- private const string AzureOpenAiDefaultApiVersion = "2023-03-15-preview";
+ private const string AzureOpenAiDefaultApiVersion = "2023-09-01-preview";
///
From 43d4f206673036f78dae1b93d9fe1a1673273d5c Mon Sep 17 00:00:00 2001
From: Tolga Kayhan
Date: Mon, 25 Sep 2023 22:13:34 +0100
Subject: [PATCH 12/13] fixes regarding code review
---
OpenAI.Playground/Program.cs | 4 +-
.../TestHelpers/FineTuningJobTestHelper.cs | 29 +++-
.../AzureOpenAiEndpointProvider.cs | 22 ++-
.../IOpenAiEndpointProvider.cs | 8 +-
.../OpenAiEndpointProvider.cs | 25 +++-
OpenAI.SDK/Extensions/HttpclientExtensions.cs | 2 +-
.../Interfaces/IFineTuningJobService.cs | 9 +-
OpenAI.SDK/Interfaces/IModelService.cs | 8 ++
OpenAI.SDK/Managers/OpenAIFineTuningJob.cs | 26 ++--
OpenAI.SDK/Managers/OpenAIModel.cs | 5 +
OpenAI.SDK/Managers/OpenAIService.cs | 1 -
.../RequestModels/FineTuneCreateRequest.cs | 3 +
.../FineTuningJobCreateRequest.cs | 129 +++++-------------
.../FineTuningJobListEventsRequest.cs | 29 ++++
.../FineTuningJobListEventsResponse.cs | 3 +
.../FineTuningJobListResponse.cs | 3 +
.../FineTuningJobResponse.cs | 89 +++++++++---
.../NEpochsConverter.cs | 42 ++++++
.../ModelDeleteResponse.cs | 10 ++
.../SharedModels/EventResponse.cs | 4 +-
.../SharedModels/HyperParametersResponse.cs | 5 +-
OpenAI.sln.DotSettings | 1 +
22 files changed, 301 insertions(+), 156 deletions(-)
create mode 100644 OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobListEventsRequest.cs
create mode 100644 OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/NEpochsConverter.cs
create mode 100644 OpenAI.SDK/ObjectModels/ResponseModels/ModelResponseModels/ModelDeleteResponse.cs
diff --git a/OpenAI.Playground/Program.cs b/OpenAI.Playground/Program.cs
index bb456ee6..d4079d46 100644
--- a/OpenAI.Playground/Program.cs
+++ b/OpenAI.Playground/Program.cs
@@ -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);
diff --git a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
index 1e0c11d5..6090de2c 100644
--- a/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
+++ b/OpenAI.Playground/TestHelpers/FineTuningJobTestHelper.cs
@@ -11,6 +11,13 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISer
{
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";
@@ -36,7 +43,11 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISer
Model = Models.Gpt_3_5_Turbo
});
- var listFineTuningJobEventsStream = await sdk.FineTuningJob.ListFineTuningJobEvents(createFineTuningJobResponse.Id, true);
+ var listFineTuningJobEventsStream = await sdk.FineTuningJob.ListFineTuningJobEvents(new FineTuningJobListEventsRequest
+ {
+ FineTuningJobId = createFineTuningJobResponse.Id
+ }, true);
+
using var streamReader = new StreamReader(listFineTuningJobEventsStream);
while (!streamReader.EndOfStream)
{
@@ -59,13 +70,17 @@ public static async Task RunCaseStudyIsTheModelMakingUntrueStatements(IOpenAISer
do
{
- var completionResult = await sdk.Completions.CreateCompletion(new CompletionCreateRequest
+ var completionResult = await sdk.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
- MaxTokens = 1,
- Prompt = @"https://t.co/f93xEd2 Excited to share my latest blog post! ->",
- Model = retrieveFineTuningJobResponse.FineTunedModel,
- LogProbs = 2
+ Messages = new List
+ {
+ 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());
@@ -87,7 +102,7 @@ public static async Task CleanUpAllFineTunings(IOpenAIService sdk)
var FineTuningJobs = await sdk.FineTuningJob.ListFineTuningJobs();
foreach (var datum in FineTuningJobs.Data)
{
- await sdk.FineTuningJob.DeleteFineTuningJob(datum.FineTunedModel);
+ await sdk.Models.DeleteModel(datum.FineTunedModel);
}
}
}
\ No newline at end of file
diff --git a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
index 61a4fc39..1cef5da5 100644
--- a/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/AzureOpenAiEndpointProvider.cs
@@ -1,4 +1,5 @@
using System.Net;
+using OpenAI.ObjectModels.RequestModels;
namespace OpenAI.EndpointProviders;
@@ -100,6 +101,23 @@ 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();
+ 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}";
@@ -120,9 +138,9 @@ public string FineTuningJobListEvents(string fineTuningJobId)
return $"{Prefix}/fine_tuning/jobs/{fineTuningJobId}/events{QueryString}";
}
- public string FineTuningJobDelete(string fineTuningJobId)
+ public string ModelsDelete(string modelId)
{
- return $"{Prefix}/models/{fineTuningJobId}{QueryString}";
+ return $"{Prefix}/models/{modelId}{QueryString}";
}
public string EmbeddingCreate()
diff --git a/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
index 38dcd1ae..2d85aaef 100644
--- a/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/IOpenAiEndpointProvider.cs
@@ -1,4 +1,6 @@
-namespace OpenAI.EndpointProviders;
+using OpenAI.ObjectModels.RequestModels;
+
+namespace OpenAI.EndpointProviders;
internal interface IOpenAiEndpointProvider
{
@@ -6,6 +8,7 @@ internal interface IOpenAiEndpointProvider
string CompletionCreate();
string EditCreate();
string ModelsList();
+ string ModelsDelete(string modelId);
string FilesList();
string FilesUpload();
string FileDelete(string fileId);
@@ -18,11 +21,10 @@ internal interface IOpenAiEndpointProvider
string FineTuneListEvents(string fineTuneId);
string FineTuneDelete(string fineTuneId);
string FineTuningJobCreate();
- string FineTuningJobList();
+ string FineTuningJobList(FineTuningJobListRequest? fineTuningJobListRequest);
string FineTuningJobRetrieve(string fineTuningJobId);
string FineTuningJobCancel(string fineTuningJobId);
string FineTuningJobListEvents(string fineTuningJobId);
- string FineTuningJobDelete(string fineTuningJobId);
string EmbeddingCreate();
string ModerationCreate();
string ImageCreate();
diff --git a/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs b/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
index f4ea9631..d1dfc682 100644
--- a/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
+++ b/OpenAI.SDK/EndpointProviders/OpenAiEndpointProvider.cs
@@ -1,4 +1,7 @@
-namespace OpenAI.EndpointProviders;
+using System.Net;
+using OpenAI.ObjectModels.RequestModels;
+
+namespace OpenAI.EndpointProviders;
internal class OpenAiEndpointProvider : IOpenAiEndpointProvider
{
@@ -104,9 +107,21 @@ public string FineTuningJobCreate()
return $"/{_apiVersion}/fine_tuning/jobs";
}
- public string FineTuningJobList()
+ public string FineTuningJobList(FineTuningJobListRequest? fineTuningJobListRequest)
{
- return $"/{_apiVersion}/fine_tuning/jobs";
+ var url = $"/{_apiVersion}/fine_tuning/jobs";
+ if (fineTuningJobListRequest != null)
+ {
+ var queryParams = new List();
+ 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)
@@ -124,9 +139,9 @@ public string FineTuningJobListEvents(string fineTuningJobId)
return $"/{_apiVersion}/fine_tuning/jobs/{fineTuningJobId}/events";
}
- public string FineTuningJobDelete(string fineTuningJobId)
+ public string ModelsDelete(string modelId)
{
- return $"/{_apiVersion}/models/{fineTuningJobId}";
+ return $"/{_apiVersion}/models/{modelId}";
}
public string EmbeddingCreate()
diff --git a/OpenAI.SDK/Extensions/HttpclientExtensions.cs b/OpenAI.SDK/Extensions/HttpclientExtensions.cs
index 054ed940..ecaa5379 100644
--- a/OpenAI.SDK/Extensions/HttpclientExtensions.cs
+++ b/OpenAI.SDK/Extensions/HttpclientExtensions.cs
@@ -7,7 +7,7 @@ namespace OpenAI.Extensions;
public static class HttpClientExtensions
{
- public static async Task PostAndReadAsAsync(this HttpClient client, string uri, object requestModel, CancellationToken cancellationToken = default)
+ public static async Task PostAndReadAsAsync(this HttpClient client, string uri, object? requestModel, CancellationToken cancellationToken = default)
{
var response = await client.PostAsJsonAsync(uri, requestModel, new JsonSerializerOptions
{
diff --git a/OpenAI.SDK/Interfaces/IFineTuningJobService.cs b/OpenAI.SDK/Interfaces/IFineTuningJobService.cs
index 86c2adf2..457a0cf2 100644
--- a/OpenAI.SDK/Interfaces/IFineTuningJobService.cs
+++ b/OpenAI.SDK/Interfaces/IFineTuningJobService.cs
@@ -22,9 +22,10 @@ public interface IFineTuningJobService
///
/// List your organization's fine-tuning jobs
///
+ ///
/// Propagates notification that operations should be canceled.
///
- Task ListFineTuningJobs(CancellationToken cancellationToken = default);
+ Task ListFineTuningJobs(FineTuningJobListRequest? fineTuningJobListRequest =null,CancellationToken cancellationToken = default);
///
/// Gets info about the fine-tuning job.
@@ -45,7 +46,7 @@ public interface IFineTuningJobService
///
/// Get fine-grained status updates for a fine-tuning job.
///
- /// The ID of the fine-tuning job to get events for.
+ ///
///
/// 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
@@ -54,7 +55,5 @@ public interface IFineTuningJobService
///
/// Propagates notification that operations should be canceled.
///
- Task ListFineTuningJobEvents(string fineTuningJobId, bool? stream = null, CancellationToken cancellationToken = default);
-
- Task DeleteFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default);
+ Task ListFineTuningJobEvents(FineTuningJobListEventsRequest model, bool? stream = null, CancellationToken cancellationToken = default);
}
diff --git a/OpenAI.SDK/Interfaces/IModelService.cs b/OpenAI.SDK/Interfaces/IModelService.cs
index 6c343160..d2c4c6b3 100644
--- a/OpenAI.SDK/Interfaces/IModelService.cs
+++ b/OpenAI.SDK/Interfaces/IModelService.cs
@@ -25,4 +25,12 @@ public interface IModelService
/// Propagates notification that operations should be canceled.
///
Task RetrieveModel(string model, CancellationToken cancellationToken = default);
+
+ ///
+ /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model.
+ ///
+ /// The model to delete
+ ///
+ ///
+ Task DeleteModel(string modelId, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs b/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs
index 9b1e53d1..694d05b5 100644
--- a/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs
+++ b/OpenAI.SDK/Managers/OpenAIFineTuningJob.cs
@@ -1,4 +1,5 @@
-using OpenAI.Extensions;
+using System.Net;
+using OpenAI.Extensions;
using OpenAI.Interfaces;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
@@ -13,32 +14,25 @@ public async Task CreateFineTuningJob(FineTuningJobCreate
return await _httpClient.PostAndReadAsAsync(_endpointProvider.FineTuningJobCreate(), createFineTuningJobRequest, cancellationToken);
}
- public async Task ListFineTuningJobs(CancellationToken cancellationToken = default)
+ public async Task ListFineTuningJobs(FineTuningJobListRequest? fineTuningJobListRequest, CancellationToken cancellationToken = default)
{
- return (await _httpClient.GetFromJsonAsync(_endpointProvider.FineTuningJobList(), cancellationToken))!;
- }
- public async Task RetrieveFineTuningJob(string FineTuningJobId, CancellationToken cancellationToken = default)
- {
- return (await _httpClient.GetFromJsonAsync(_endpointProvider.FineTuningJobRetrieve(FineTuningJobId), cancellationToken))!;
+ return (await _httpClient.GetFromJsonAsync(_endpointProvider.FineTuningJobList(fineTuningJobListRequest), cancellationToken))!;
}
- public async Task CancelFineTuningJob(string FineTuningJobId, CancellationToken cancellationToken = default)
+ public async Task RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default)
{
- return await _httpClient.PostAndReadAsAsync(_endpointProvider.FineTuningJobCancel(FineTuningJobId), new FineTuningJobCancelRequest
- {
- FineTuningJobId = FineTuningJobId
- }, cancellationToken);
+ return (await _httpClient.GetFromJsonAsync(_endpointProvider.FineTuningJobRetrieve(fineTuningJobId), cancellationToken))!;
}
- public async Task ListFineTuningJobEvents(string FineTuningJobId, bool? stream = null, CancellationToken cancellationToken = default)
+ public async Task CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default)
{
- return await _httpClient.GetStreamAsync(_endpointProvider.FineTuningJobListEvents(FineTuningJobId), cancellationToken);
+ return await _httpClient.PostAndReadAsAsync(_endpointProvider.FineTuningJobCancel(fineTuningJobId),null, cancellationToken: cancellationToken);
}
- public async Task DeleteFineTuningJob(string FineTuningJobId, CancellationToken cancellationToken = default)
+ public async Task ListFineTuningJobEvents(FineTuningJobListEventsRequest fineTuningJobRequestModel, bool? stream = null, CancellationToken cancellationToken = default)
{
- await _httpClient.DeleteAsync(_endpointProvider.FineTuningJobDelete(FineTuningJobId), cancellationToken);
+ return await _httpClient.GetStreamAsync(_endpointProvider.FineTuningJobListEvents(fineTuningJobRequestModel.FineTuningJobId), cancellationToken);
}
}
}
diff --git a/OpenAI.SDK/Managers/OpenAIModel.cs b/OpenAI.SDK/Managers/OpenAIModel.cs
index 9abbc500..7215de3f 100644
--- a/OpenAI.SDK/Managers/OpenAIModel.cs
+++ b/OpenAI.SDK/Managers/OpenAIModel.cs
@@ -15,4 +15,9 @@ public async Task RetrieveModel(string model, Cancellatio
{
return (await _httpClient.GetFromJsonAsync(_endpointProvider.ModelRetrieve(model), cancellationToken))!;
}
+
+ public async Task DeleteModel(string modelId, CancellationToken cancellationToken = default)
+ {
+ return await (await _httpClient.DeleteAsync(_endpointProvider.ModelsDelete(modelId), cancellationToken)).Content.ReadFromJsonAsync(cancellationToken: cancellationToken);
+ }
}
\ No newline at end of file
diff --git a/OpenAI.SDK/Managers/OpenAIService.cs b/OpenAI.SDK/Managers/OpenAIService.cs
index 229b8abf..7ed568ae 100644
--- a/OpenAI.SDK/Managers/OpenAIService.cs
+++ b/OpenAI.SDK/Managers/OpenAIService.cs
@@ -5,7 +5,6 @@
namespace OpenAI.Managers;
-//TODO Find a way to show default request values in documentation
public partial class OpenAIService : IOpenAIService, IDisposable
{
private readonly bool _disposeHttpClient;
diff --git a/OpenAI.SDK/ObjectModels/RequestModels/FineTuneCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/FineTuneCreateRequest.cs
index c9f0ee89..6e044e1d 100644
--- a/OpenAI.SDK/ObjectModels/RequestModels/FineTuneCreateRequest.cs
+++ b/OpenAI.SDK/ObjectModels/RequestModels/FineTuneCreateRequest.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
using OpenAI.ObjectModels.SharedModels;
namespace OpenAI.ObjectModels.RequestModels;
@@ -37,8 +38,10 @@ public record FineTuneCreateRequest : IOpenAiModels.IModel
///
/// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.
+ /// Set -1 for "auto value
///
[JsonPropertyName("n_epochs")]
+ [JsonConverter(typeof(NEpochsConverter))]
public int? NEpochs { get; set; }
///
diff --git a/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs
index b9f87c6b..b7fe6d60 100644
--- a/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs
+++ b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobCreateRequest.cs
@@ -1,5 +1,6 @@
-using OpenAI.ObjectModels.SharedModels;
-using System.Text.Json.Serialization;
+using System.Text.Json.Serialization;
+using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+using OpenAI.ObjectModels.SharedModels;
namespace OpenAI.ObjectModels.RequestModels;
@@ -7,116 +8,58 @@ public record FineTuningJobCreateRequest : IOpenAiModels.IModel
{
///
/// The ID of an uploaded file that contains training data.
- /// See upload file for how to upload a file.
- /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object with the keys "prompt"
- /// and "completion". Additionally, you must upload your file with the purpose fine-tune.
- /// See the fine-tuning guide
- /// for
- /// more details.
+ /// See upload file for how to upload a
+ /// file.
+ /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose
+ /// fine-tune
.
+ /// See the fine-tuning guide for more details.
///
[JsonPropertyName("training_file")]
public string TrainingFile { get; set; }
///
/// The ID of an uploaded file that contains validation data.
- /// If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These
- /// metrics can be viewed in the
- ///
- /// fine-tuning results
- /// file
- ///
- /// . Your train and validation data should be mutually exclusive.
- /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object with the keys
- /// "prompt" and "completion". Additionally, you must upload your file with the purpose fine-tune.
- /// See the fine-tuning guide
- /// for
- /// more details.
+ /// If you provide this file, the data is used to generate validation metrics periodically during fine-tuning.
+ /// These metrics can be viewed in the fine-tuning results file.
+ /// The same data should not be present in both train and validation files.
+ /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose fine-tune
.
+ /// See the fine-tuning guide for more details.
///
[JsonPropertyName("validation_file")]
public string? ValidationFile { get; set; }
///
- /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.
- ///
- [JsonPropertyName("n_epochs")]
- public int? NEpochs { get; set; }
-
- ///
- /// The batch size to use for training. The batch size is the number of training examples used to train a single
- /// forward and backward pass.
- /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples in the training
- /// set, capped at 256 - in general, we've found that larger batch sizes tend to work better for larger datasets.
- ///
- [JsonPropertyName("batch_size")]
- public int? BatchSize { get; set; }
-
- ///
- /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original learning rate used
- /// for pretraining multiplied by this value.
- /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final batch_size(larger learning
- /// rates tend to perform better with larger batch sizes). We recommend experimenting with values in the range 0.02 to
- /// 0.2 to see what produces the best results.
- ///
- [JsonPropertyName("learning_rate_multiplier")]
- public float? LearningRateMultiplier { get; set; }
-
- ///
- /// The weight to use for loss on the prompt tokens. This controls how much the model tries to learn to generate the
- /// prompt (as compared to the completion which always has a weight of 1.0), and can add a stabilizing effect to
- /// training when completions are short.
- /// If prompts are extremely long (relative to completions), it may make sense to reduce this weight so as to avoid
- /// over-prioritizing learning the prompt.
- ///
- [JsonPropertyName("prompt_loss_weight")]
- public float? PromptLossWeight { get; set; }
-
- ///
- /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the validation set at the
- /// end of every epoch.These metrics can be viewed in the
- /// results file.
- /// In order to compute classification metrics, you must provide a validation_file.Additionally, you must specify
- /// classification_n_classes for multiclass classification or classification_positive_class for binary classification.
+ /// The hyperparameters used for the fine-tuning job.
///
- [JsonPropertyName("compute_classification_metrics")]
- public bool? ComputeClassificationMetrics { get; set; }
+ [JsonPropertyName("hyperparameters")]
+ public HyperparametersRequestModel? Hyperparameters { get; set; } // This can be further detailed if the properties of the hyperparameters are known.
///
- /// The number of classes in a classification task.
- /// This parameter is required for multiclass classification.
+ /// A string of up to 18 characters that will be added to your fine-tuned model name.
+ /// For example, a suffix
of "custom-model-name" would produce a model name like
+ /// ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel
.
///
- [JsonPropertyName("classification_n_classes")]
- public int? ClassificationNClasses { get; set; }
-
- ///
- /// The positive class in binary classification.
- /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary classification.
- ///
- [JsonPropertyName("classification_positive_class")]
- public string? ClassificationPositiveClass { get; set; }
-
- //TODO documentation wasn't clear, I don't know which type of array is expected
- ///
- /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score is a generalization
- /// of F-1 score. This is only used for binary classification.
- /// With a beta of 1 (i.e.the F-1 score), precision and recall are given the same weight.A larger beta score puts more
- /// weight on recall and less on precision. A smaller beta score puts more weight on precision and less on recall.
- ///
- [JsonPropertyName("classification_betas")]
- public List? ClassificationBetas { get; set; }
+ [JsonPropertyName("suffix")]
+ public string? Suffix { get; set; } = null;
///
- /// A string of up to 40 characters that will be added to your fine-tuned model name.
- /// For example, a suffix of "custom-model-name" would produce a model name like
- /// ada:ft-your-org:custom-model-name-2022-02-15-04-21-04.
+ /// The name of the model to fine-tune. You can select one of the
+ /// supported models
+ /// .
///
- [JsonPropertyName("suffix")]
- public string? Suffix { get; set; }
-
+ [JsonPropertyName("model")]
+ public string Model { get; set; }
+}
+public class HyperparametersRequestModel
+{
///
- /// The name of the base model to fine-tune. You can select one of "ada", "babbage", or "curie". To learn more about
- /// these models, see the Models documentation.
+ /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.
+ /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we
+ /// support any number between 1 and 50 epochs.
+ /// "Auto" == -1
///
- [JsonPropertyName("model")]
- public string? Model { get; set; }
+ [JsonPropertyName("n_epochs")]
+ [JsonConverter(typeof(NEpochsConverter))]
+ public int? NEpochs { get; set; }
}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobListEventsRequest.cs b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobListEventsRequest.cs
new file mode 100644
index 00000000..e788c1d8
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/RequestModels/FineTuningJobListEventsRequest.cs
@@ -0,0 +1,29 @@
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.RequestModels
+{
+ public class FineTuningJobListEventsRequest:FineTuningJobListRequest
+ {
+ ///
+ /// The ID of the fine-tuning job to get events for.
+ ///
+ [JsonIgnore]
+ public string FineTuningJobId { get; set; }
+ }
+
+ public class FineTuningJobListRequest
+ {
+ ///
+ /// Identifier for the last job from the previous pagination request.
+ ///
+ [JsonPropertyName("after")]
+ public string? After { get; set; }
+
+ ///
+ /// Number of fine-tuning jobs to retrieve.
+ /// Defaults to 20.
+ ///
+ [JsonPropertyName("limit")]
+ public int? Limit { get; set; }
+ }
+}
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs
index 140c1f12..be4ca12b 100644
--- a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListEventsResponse.cs
@@ -7,5 +7,8 @@ public record FineTuningJobListEventsResponse : BaseResponse
{
[JsonPropertyName("data")]
public List Data { get; set; }
+
+ [JsonPropertyName("has_more")]
+ public bool HasMore { get; set; }
}
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs
index 068121d8..3f13cd78 100644
--- a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobListResponse.cs
@@ -6,5 +6,8 @@ public record FineTuningJobListResponse : BaseResponse
{
[JsonPropertyName("data")]
public List Data { get; set; }
+
+ [JsonPropertyName("has_more")]
+ public bool HasMore { get; set; }
}
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
index cbb4404d..dd50aaa6 100644
--- a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/FineTuningJobResponse.cs
@@ -1,46 +1,97 @@
-using OpenAI.ObjectModels.SharedModels;
-using System.Text.Json.Serialization;
+using System.Text.Json.Serialization;
+using OpenAI.ObjectModels.SharedModels;
namespace OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
public record FineTuningJobResponse : BaseResponse, IOpenAiModels.IId, IOpenAiModels.IModel, IOpenAiModels.ICreatedAt
{
- [JsonPropertyName("id")]
- public string Id { get; set; }
-
- [JsonPropertyName("created_at")]
- public int CreatedAt { get; set; }
-
+ ///
+ /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the
+ /// fine-tuning job is still running.
+ ///
[JsonPropertyName("finished_at")]
public int? FinishedAt { get; set; }
- [JsonPropertyName("model")]
- public string Model { get; set; }
-
+ ///
+ /// The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still
+ /// running.
+ ///
[JsonPropertyName("fine_tuned_model")]
public string? FineTunedModel { get; set; }
+ ///
+ /// The organization that owns the fine-tuning job.
+ ///
[JsonPropertyName("organization_id")]
- public string OrganizationId { get; set; }
+ public string? OrganizationId { get; set; }
+ ///
+ /// The current status of the fine-tuning job, which can be either created, pending, running, succeeded, failed, or
+ /// cancelled.
+ ///
[JsonPropertyName("status")]
public string Status { get; set; }
+ ///
+ /// The hyperparameters used for the fine-tuning job. See the fine-tuning guide for more details.
+ ///
[JsonPropertyName("hyperparameters")]
- public HyperParametersResponse HyperParameters { get; set; }
-
- [JsonPropertyName("validation_file")]
- public string? ValidationFile { get; set; }
+ public Hyperparameters HyperparametersData { get; set; }
+ ///
+ /// The file ID used for training. You can retrieve the training data with the Files API.
+ ///
[JsonPropertyName("training_file")]
public string TrainingFile { get; set; }
+ ///
+ /// The file ID used for validation. You can retrieve the validation results with the Files API.
+ ///
+ [JsonPropertyName("validation_file")]
+ public string? ValidationFile { get; set; }
+
+ ///
+ /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the Files API.
+ ///
[JsonPropertyName("result_files")]
public List ResultFiles { get; set; }
+ ///
+ /// The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning
+ /// job is still running.
+ ///
[JsonPropertyName("trained_tokens")]
public int? TrainedTokens { get; set; }
- [JsonPropertyName("updated_at")]
- public int? UpdatedAt { get; set; }
-}
+ ///
+ /// The Unix timestamp (in seconds) for when the fine-tuning job was created.
+ ///
+ [JsonPropertyName("created_at")]
+ public int CreatedAt { get; set; }
+
+ ///
+ /// The object identifier, which can be referenced in the API endpoints.
+ ///
+ [JsonPropertyName("id")]
+ public string Id { get; set; }
+
+ ///
+ /// The base model that is being fine-tuned.
+ ///
+ [JsonPropertyName("model")]
+ public string Model { get; set; }
+
+
+ public class Hyperparameters
+ {
+ ///
+ /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.
+ /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we
+ /// support any number between 1 and 50 epochs.
+ /// "Auto" == -1
+ ///
+ [JsonPropertyName("n_epochs")]
+ [JsonConverter(typeof(NEpochsConverter))]
+ public int? NEpochs { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/NEpochsConverter.cs b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/NEpochsConverter.cs
new file mode 100644
index 00000000..ae88f22a
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/FineTuningJobResponseModels/NEpochsConverter.cs
@@ -0,0 +1,42 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
+
+public class NEpochsConverter : JsonConverter
+{
+ public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ switch (reader.TokenType)
+ {
+ case JsonTokenType.String:
+ {
+ var stringValue = reader.GetString();
+ if (stringValue?.ToLower() == "auto")
+ return -1;
+ break;
+ }
+ case JsonTokenType.Number:
+ return reader.GetInt32();
+ case JsonTokenType.Null:
+ return null;
+ }
+
+ throw new JsonException($"Unexpected token type: {reader.TokenType}");
+ }
+
+ public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options)
+ {
+ if (value.HasValue)
+ {
+ if (value.Value == -1)
+ writer.WriteStringValue("auto");
+ else
+ writer.WriteNumberValue(value.Value);
+ }
+ else
+ {
+ writer.WriteNullValue();
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/ModelResponseModels/ModelDeleteResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/ModelResponseModels/ModelDeleteResponse.cs
new file mode 100644
index 00000000..4bc146bb
--- /dev/null
+++ b/OpenAI.SDK/ObjectModels/ResponseModels/ModelResponseModels/ModelDeleteResponse.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace OpenAI.ObjectModels.ResponseModels.ModelResponseModels;
+
+public record ModelDeleteResponse : BaseResponse
+{
+ [JsonPropertyName("id")] public string Id { get; set; }
+
+ [JsonPropertyName("deleted")] public bool Deleted { get; set; }
+}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/SharedModels/EventResponse.cs b/OpenAI.SDK/ObjectModels/SharedModels/EventResponse.cs
index a6e1bbf4..9d74f2e6 100644
--- a/OpenAI.SDK/ObjectModels/SharedModels/EventResponse.cs
+++ b/OpenAI.SDK/ObjectModels/SharedModels/EventResponse.cs
@@ -4,11 +4,13 @@ namespace OpenAI.ObjectModels.SharedModels;
public record EventResponse
{
- [JsonPropertyName("object")] public string Object { get; set; }
+ [JsonPropertyName("object")] public string? ObjectTypeName { get; set; }
+ [JsonPropertyName("id")] public string? Id { get; set; }
[JsonPropertyName("created_at")] public int? CreatedAt { get; set; }
[JsonPropertyName("level")] public string Level { get; set; }
[JsonPropertyName("message")] public string Message { get; set; }
+ [JsonPropertyName("type")] public string Type { get; set; }
}
\ No newline at end of file
diff --git a/OpenAI.SDK/ObjectModels/SharedModels/HyperParametersResponse.cs b/OpenAI.SDK/ObjectModels/SharedModels/HyperParametersResponse.cs
index ef9f0784..f64ca5a5 100644
--- a/OpenAI.SDK/ObjectModels/SharedModels/HyperParametersResponse.cs
+++ b/OpenAI.SDK/ObjectModels/SharedModels/HyperParametersResponse.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using OpenAI.ObjectModels.ResponseModels.FineTuningJobResponseModels;
namespace OpenAI.ObjectModels.SharedModels;
@@ -9,7 +10,9 @@ public record HyperParametersResponse
[JsonPropertyName("learning_rate_multiplier")]
public float? LearningRateMultiplier { get; set; }
- [JsonPropertyName("n_epochs")] public int? NEpochs { get; set; }
+ [JsonPropertyName("n_epochs")]
+ [JsonConverter(typeof(NEpochsConverter))]
+ public int? NEpochs { get; set; }
[JsonPropertyName("prompt_loss_weight")]
public float? PromptLossWeight { get; set; }
diff --git a/OpenAI.sln.DotSettings b/OpenAI.sln.DotSettings
index cfc5f601..1bc445ce 100644
--- a/OpenAI.sln.DotSettings
+++ b/OpenAI.sln.DotSettings
@@ -5,6 +5,7 @@
True
True
True
+ True
True
True
From 877df2767ba5e78247c71d1e75b8d52b28fa8c52 Mon Sep 17 00:00:00 2001
From: Tolga Kayhan
Date: Fri, 6 Oct 2023 21:09:01 +0100
Subject: [PATCH 13/13] Version bump and changelog update
---
OpenAI.SDK/OpenAI.csproj | 2 +-
Readme.md | 16 ++++------------
2 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/OpenAI.SDK/OpenAI.csproj b/OpenAI.SDK/OpenAI.csproj
index 71e72667..0cd760c9 100644
--- a/OpenAI.SDK/OpenAI.csproj
+++ b/OpenAI.SDK/OpenAI.csproj
@@ -11,7 +11,7 @@
OpenAI-Betalgo.png
true
OpenAI SDK by Betalgo
- 7.1.5
+ 7.2.0
Tolga Kayhan, Betalgo
Betalgo Up Ltd.
OpenAI ChatGPT, Whisper, GPT-4 and DALL·E dotnet SDK
diff --git a/Readme.md b/Readme.md
index ce18e7d2..3d854872 100644
--- a/Readme.md
+++ b/Readme.md
@@ -222,6 +222,10 @@ I will always be using the latest libraries, and future releases will frequently
I am incredibly busy. If I forgot your name, please accept my apologies and let me know so I can add it to the list.
## Changelog
+### 7.2.0
+- Added Chatgpt Finetununig support thanks to @aghimir3
+- Default Azure Openai version increased thanks to @mac8005
+- Fixed Azure Openai Audio endpoint thanks to @mac8005
### 7.1.5
- Added error handling for PlatformNotSupportedException in PostAsStreamAsync when using HttpClient.Send, now falls back to SendRequestPreNet6 for compatibility on platforms like MAUI, Mac. Thanks to @Almis90
- We now have a function caller describe method that automatically generates function descriptions. This method is available in the utilities library. Thanks to @vbandi
@@ -249,15 +253,3 @@ I am incredibly busy. If I forgot your name, please accept my apologies and let
//Now
var openAiService = new OpenAIService(options, httpClient);
```
-### 6.8.6
-- Updated Azure OpenAI default API version to the preview version to support ChatGPT. thanks to all [issue reporters](https://github.com/betalgo/openai/issues/181)
-- Added support for an optional chat `name` field. thanks to @shanepowell
-- Breaking Change
- - `FineTuneCreateRequest.PromptLossWeight` converto to float thanks to @JohnJ0808
-### 6.8.5
-- Mostly bug fixes
-- Fixed Moderation functions. https://github.com/betalgo/openai/issues/214 thanks to @scolmarg @AbdelAzizMohamedMousa @digitalvir
-- Added File Stream support for Whisper, Thanks to @Swimburger
-- Fixed Whisper default response type, Thanks to @Swimburger
-- Performance improvements and code clean up,again Thanks to @Swimburger 👏
-- Code clenaup, Thanks to @WeihanLi