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

feat: implement new fine tuning API #27

Merged
merged 1 commit into from
Aug 26, 2023
Merged
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
48 changes: 48 additions & 0 deletions all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,54 @@ func testserverV1() *httptest.Server {
io.Copy(w, f)
}
})
mux.HandleFunc("/fine_tuning/jobs", func(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodPost:
f, err := os.Open("./testdata/finetuning-create.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(w, f)
}
})
mux.HandleFunc("/fine_tuning/jobs/abcdefghi/cancel", func(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodPost:
f, err := os.Open("./testdata/finetuning-cancel.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(w, f)
}
})
mux.HandleFunc("/fine_tuning/jobs/abcdefghi", func(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
f, err := os.Open("./testdata/finetuning-retrieve.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(w, f)
}
})
mux.HandleFunc("/fine_tuning/jobs/abcdefghi/events", func(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
f, err := os.Open("./testdata/finetuning-event-list.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(w, f)
}
})
mux.HandleFunc("/chat/completions", func(w http.ResponseWriter, req *http.Request) {
f, err := os.Open("./testdata/chat-completion.json")
if err != nil {
Expand Down
59 changes: 51 additions & 8 deletions endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,51 +141,57 @@ func (client *Client) CreateModeration(ctx context.Context, body ModerationCreat
}

// CreateFineTune: POST https://api.openai.com/v1/fine-tunes
// Deprecated: you should consider using the updating fine-tuning API https://platform.openai.com/docs/guides/fine-tuning
// 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.
// Learn more about Fine-tuning: https://beta.openai.com/docs/guides/fine-tuning
// See https://beta.openai.com/docs/api-reference/fine-tunes/create
// Learn more about Fine-tuning: https://platform.openai.com/docs/api-reference/fine-tuning
// See https://platform.openai.com/docs/api-reference/fine-tunes/create
func (client *Client) CreateFineTune(ctx context.Context, body FineTuneCreateRequestBody) (resp FineTuneCreateResponse, err error) {
p := "/fine-tunes"
return call(ctx, client, http.MethodPost, p, body, resp, nil)
}

// ListFineTunes: GET https://api.openai.com/v1/fine-tunes
// Deprecated: you should consider using the updating fine-tuning API https://platform.openai.com/docs/guides/fine-tuning
// List your organization's fine-tuning jobs.
// See https://beta.openai.com/docs/api-reference/fine-tunes/list
// See https://platform.openai.com/docs/api-reference/fine-tunes/list
func (client *Client) ListFineTunes(ctx context.Context) (resp FineTuneListResponse, err error) {
p := "/fine-tunes"
return call(ctx, client, http.MethodGet, p, nil, resp, nil)
}

// RetrieveFineTune: GET https://api.openai.com/v1/fine-tunes/{fine_tune_id}
// Deprecated: you should consider using the updating fine-tuning API https://platform.openai.com/docs/guides/fine-tuning
// Gets info about the fine-tune job.
// Learn more about Fine-tuning https://beta.openai.com/docs/guides/fine-tuning
// See https://beta.openai.com/docs/api-reference/fine-tunes/retrieve
// Learn more about Fine-tuning https://platform.openai.com/docs/api-reference/fine-tuning
// See https://platform.openai.com/docs/api-reference/fine-tunes/retrieve
func (client *Client) RetrieveFineTune(ctx context.Context, id string) (resp FineTuneRetrieveResponse, err error) {
p := fmt.Sprintf("/fine-tunes/%s", id)
return call(ctx, client, http.MethodGet, p, nil, resp, nil)
}

// CancelFineTune: POST https://api.openai.com/v1/fine-tunes/{fine_tune_id}/cancel
// Deprecated: you should consider using the updating fine-tuning API https://platform.openai.com/docs/guides/fine-tuning
// Immediately cancel a fine-tune job.
// See https://beta.openai.com/docs/api-reference/fine-tunes/cancel
// See https://platform.openai.com/docs/api-reference/fine-tunes/cancel
func (client *Client) CancelFineTune(ctx context.Context, id string) (resp FineTuneCancelResponse, err error) {
p := fmt.Sprintf("/fine-tunes/%s/cancel", id)
return call(ctx, client, http.MethodPost, p, nil, resp, nil)
}

// ListFineTuneEvents: GET https://api.openai.com/v1/fine-tunes/{fine_tune_id}/events
// Deprecated: you should consider using the updating fine-tuning API https://platform.openai.com/docs/guides/fine-tuning
// Get fine-grained status updates for a fine-tune job.
// See https://beta.openai.com/docs/api-reference/fine-tunes/events
// See https://platform.openai.com/docs/api-reference/fine-tunes/events
func (client *Client) ListFineTuneEvents(ctx context.Context, id string) (resp FineTuneListEventsResponse, err error) {
p := fmt.Sprintf("/fine-tunes/%s/events", id)
return call(ctx, client, http.MethodGet, p, nil, resp, nil)
}

// DeleteFineTuneModel: DELETE https://api.openai.com/v1/models/{model}
// Deprecated: you should consider using the updating fine-tuning API https://platform.openai.com/docs/guides/fine-tuning
// Delete a fine-tuned model. You must have the Owner role in your organization.
// See https://beta.openai.com/docs/api-reference/fine-tunes/delete-model
// See https://platform.openai.com/docs/api-reference/fine-tunes/delete-model
func (client *Client) DeleteFineTuneModel(ctx context.Context, id string) (resp FineTuneDeleteModelResponse, err error) {
p := fmt.Sprintf("/models/%s", id)
return call(ctx, client, http.MethodDelete, p, nil, resp, nil)
Expand All @@ -208,3 +214,40 @@ func (client *Client) ChatCompletion(ctx context.Context, body ChatCompletionReq
}
return call(ctx, client, http.MethodPost, p, body, resp, nil)
}

// CreateFineTuning: POST https://api.openai.com/v1/fine_tuning/jobs
// 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.
// Learn more about Fine-tuning: https://platform.openai.com/docs/guides/fine-tuning
// See https://platform.openai.com/docs/api-reference/fine-tuning/create
func (client *Client) CreateFineTuning(ctx context.Context, body FineTuningCreateRequestBody) (resp FineTuningJob, err error) {
p := "/fine_tuning/jobs"
return call(ctx, client, http.MethodPost, p, body, resp, nil)
}

// CancelFineTuning: POST https://api.openai.com/v1/fine_tuning/{fine_tuning_job_id}/cancel
// Immediately cancel a fine tuning job.
// Learn more about Fine-tuning https://platform.openai.com/docs/guides/fine-tuning
// See https://platform.openai.com/docs/api-reference/fine-tuning/cancel
func (client *Client) CancelFineTuning(ctx context.Context, id string) (resp FineTuningJob, err error) {
p := "/fine_tuning/jobs/" + id + "/cancel"
return call(ctx, client, http.MethodPost, p, nil, resp, nil)
}

// RetrieveFineTuning: GET https://api.openai.com/v1/fine_tuning/jobs//{fine_tuning_job_id}
// Gets info about the fine-tuning job.
// Learn more about Fine-tuning https://platform.openai.com/docs/guides/fine-tuning
// See https://platform.openai.com/docs/api-reference/fine-tuning/retrieve
func (client *Client) RetrieveFineTuning(ctx context.Context, id string) (resp FineTuningJob, err error) {
p := fmt.Sprintf("/fine_tuning/jobs/%s", id)
return call(ctx, client, http.MethodGet, p, nil, resp, nil)
}

// ListFineTuningEvents: GET https://api.openai.com/v1/fine_tuning/jobs/{fine_tuning_job_id}/events
// Get fine-grained status updates for a fine-tuning job.
// Learn more about Fine-tuning https://platform.openai.com/docs/guides/fine-tuning
// See https://platform.openai.com/docs/api-reference/fine-tuning/list-events
func (client *Client) ListFineTuningEvents(ctx context.Context, id string) (resp FineTuningListEventsResponse, err error) {
p := fmt.Sprintf("/fine_tuning/jobs/%s/events", id)
return call(ctx, client, http.MethodGet, p, nil, resp, nil)
}
45 changes: 45 additions & 0 deletions finetuning.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package openaigo

type FineTuningJob struct {
ID string `json:"id"`
Object string `json:"object"`
CreatedAt int64 `json:"created_at"`
FinishedAt int64 `json:"finished_at"`
Model string `json:"model"`
FineTunedModel string `json:"fine_tuned_model,omitempty"`
OrganizationID string `json:"organization_id"`
Status string `json:"status"`
Hyperparameters Hyperparameters `json:"hyperparameters"`
TrainingFile string `json:"training_file"`
ValidationFile string `json:"validation_file,omitempty"`
ResultFiles []string `json:"result_files"`
TrainedTokens int `json:"trained_tokens"`
}

type Hyperparameters struct {
Epochs int `json:"n_epochs"`
}

type FineTuningCreateRequestBody struct {
TrainingFile string `json:"training_file"`
ValidationFile string `json:"validation_file,omitempty"`
Model string `json:"model,omitempty"`
Hyperparameters *Hyperparameters `json:"hyperparameters,omitempty"`
Suffix string `json:"suffix,omitempty"`
}

type FineTuningListEventsResponse struct {
Object string `json:"object"`
Data []FineTuneEvent `json:"data"`
HasMore bool `json:"has_more"`
}

type FineTuningEvent struct {
Object string `json:"object"`
ID string `json:"id"`
CreatedAt int `json:"created_at"`
Level string `json:"level"`
Message string `json:"message"`
Data any `json:"data"`
Type string `json:"type"`
}
42 changes: 42 additions & 0 deletions finetuning_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package openaigo

import (
"context"
"testing"

. "github.com/otiai10/mint"
)

func TestClient_CreateFineTuning(t *testing.T) {
client := NewClient("")
client.BaseURL = mockserver.URL
res, err := client.CreateFineTuning(context.TODO(), FineTuningCreateRequestBody{
TrainingFile: "file-XGinujblHPwGLSztz8cPS8XY",
})
Expect(t, err).ToBe(nil)
Expect(t, res).TypeOf("openaigo.FineTuningJob")
}

func TestClient_RetrieveFineTuning(t *testing.T) {
client := NewClient("")
client.BaseURL = mockserver.URL
res, err := client.RetrieveFineTuning(context.TODO(), "abcdefghi")
Expect(t, err).ToBe(nil)
Expect(t, res).TypeOf("openaigo.FineTuningJob")
}

func TestClient_CancelFineTuning(t *testing.T) {
client := NewClient("")
client.BaseURL = mockserver.URL
res, err := client.CancelFineTuning(context.TODO(), "abcdefghi")
Expect(t, err).ToBe(nil)
Expect(t, res).TypeOf("openaigo.FineTuningJob")
}

func TestClient_ListFineTuningEvents(t *testing.T) {
client := NewClient("")
client.BaseURL = mockserver.URL
res, err := client.ListFineTuningEvents(context.TODO(), "abcdefghi")
Expect(t, err).ToBe(nil)
Expect(t, res).TypeOf("openaigo.FineTuningListEventsResponse")
}
20 changes: 20 additions & 0 deletions testdata/finetuning-cancel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"object": "fine_tuning.job",
"id": "ft-zRdUkP4QeZqeYjDcQL0wwam1",
"model": "davinci-002",
"created_at": 1692661014,
"finished_at": 1692661190,
"fine_tuned_model": "ft:davinci-002:my-org:custom_suffix:7q8mpxmy",
"organization_id": "org-123",
"result_files": [
"file-abc123"
],
"status": "succeeded",
"validation_file": null,
"training_file": "file-abc123",
"hyperparameters": {
"n_epochs": 4
},
"trained_tokens": 5768
}

20 changes: 20 additions & 0 deletions testdata/finetuning-create.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"object": "fine_tuning.job",
"id": "ft-zRdUkP4QeZqeYjDcQL0wwam1",
"model": "davinci-002",
"created_at": 1692661014,
"finished_at": 1692661190,
"fine_tuned_model": "ft:davinci-002:my-org:custom_suffix:7q8mpxmy",
"organization_id": "org-123",
"result_files": [
"file-abc123"
],
"status": "succeeded",
"validation_file": null,
"training_file": "file-abc123",
"hyperparameters": {
"n_epochs": 4
},
"trained_tokens": 5768
}

24 changes: 24 additions & 0 deletions testdata/finetuning-event-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"object": "list",
"data": [
{
"object": "fine_tuning.job.event",
"id": "ft-event-ddTJfwuMVpfLXseO0Am0Gqjm",
"created_at": 1692407401,
"level": "info",
"message": "Fine tuning job successfully completed",
"data": null,
"type": "message"
},
{
"object": "fine_tuning.job.event",
"id": "ft-event-tyiGuB72evQncpH87xe505Sv",
"created_at": 1692407400,
"level": "info",
"message": "New fine-tuned model created: ft:gpt-3.5-turbo:openai::7p4lURel",
"data": null,
"type": "message"
}
],
"has_more": true
}
20 changes: 20 additions & 0 deletions testdata/finetuning-retrieve.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"object": "fine_tuning.job",
"id": "ft-zRdUkP4QeZqeYjDcQL0wwam1",
"model": "davinci-002",
"created_at": 1692661014,
"finished_at": 1692661190,
"fine_tuned_model": "ft:davinci-002:my-org:custom_suffix:7q8mpxmy",
"organization_id": "org-123",
"result_files": [
"file-abc123"
],
"status": "succeeded",
"validation_file": null,
"training_file": "file-abc123",
"hyperparameters": {
"n_epochs": 4
},
"trained_tokens": 5768
}

Loading