From afe5890c4ef66852fd21c1cccba9f4f4eeaf98b8 Mon Sep 17 00:00:00 2001 From: Aceld Date: Thu, 6 Apr 2023 18:52:27 +0800 Subject: [PATCH 01/16] add ImageEditRequest.ResponseFormat --- image.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/image.go b/image.go index d10fde1b4..16d7eaf31 100644 --- a/image.go +++ b/image.go @@ -57,11 +57,12 @@ func (c *Client) CreateImage(ctx context.Context, request ImageRequest) (respons // ImageEditRequest represents the request structure for the image API. type ImageEditRequest struct { - Image *os.File `json:"image,omitempty"` - Mask *os.File `json:"mask,omitempty"` - Prompt string `json:"prompt,omitempty"` - N int `json:"n,omitempty"` - Size string `json:"size,omitempty"` + Image *os.File `json:"image,omitempty"` + Mask *os.File `json:"mask,omitempty"` + Prompt string `json:"prompt,omitempty"` + N int `json:"n,omitempty"` + Size string `json:"size,omitempty"` + ResponseFormat string `json:"response_format,omitempty"` } // CreateEditImage - API call to create an image. This is the main endpoint of the DALL-E API. @@ -103,6 +104,10 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) if err != nil { return } + err = writer.WriteField("response_format", request.ResponseFormat) + if err != nil { + return + } writer.Close() urlSuffix := "/images/edits" req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.fullURL(urlSuffix), body) From 45d45c93af4c9ec633fbbc7fd60edafdebca7b75 Mon Sep 17 00:00:00 2001 From: aceld Date: Thu, 6 Apr 2023 21:01:28 +0800 Subject: [PATCH 02/16] add ImageEditRequest/ImageVariRequest.ResponseFormat --- image.go | 11 ++++++++--- image_test.go | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/image.go b/image.go index 16d7eaf31..033f4a4b0 100644 --- a/image.go +++ b/image.go @@ -122,9 +122,10 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) // ImageVariRequest represents the request structure for the image API. type ImageVariRequest struct { - Image *os.File `json:"image,omitempty"` - N int `json:"n,omitempty"` - Size string `json:"size,omitempty"` + Image *os.File `json:"image,omitempty"` + N int `json:"n,omitempty"` + Size string `json:"size,omitempty"` + ResponseFormat string `json:"response_format,omitempty"` } // CreateVariImage - API call to create an image variation. This is the main endpoint of the DALL-E API. @@ -151,6 +152,10 @@ func (c *Client) CreateVariImage(ctx context.Context, request ImageVariRequest) if err != nil { return } + err = writer.WriteField("response_format", request.ResponseFormat) + if err != nil { + return + } writer.Close() //https://platform.openai.com/docs/api-reference/images/create-variation urlSuffix := "/images/variations" diff --git a/image_test.go b/image_test.go index 9917b7881..d56cdcb1a 100644 --- a/image_test.go +++ b/image_test.go @@ -119,11 +119,12 @@ func TestImageEdit(t *testing.T) { }() req := ImageEditRequest{ - Image: origin, - Mask: mask, - Prompt: "There is a turtle in the pool", - N: 3, - Size: CreateImageSize1024x1024, + Image: origin, + Mask: mask, + Prompt: "There is a turtle in the pool", + N: 3, + Size: CreateImageSize1024x1024, + ResponseFormat: CreateImageResponseFormatURL, } _, err = client.CreateEditImage(ctx, req) checks.NoError(t, err, "CreateImage error") @@ -221,9 +222,10 @@ func TestImageVariation(t *testing.T) { }() req := ImageVariRequest{ - Image: origin, - N: 3, - Size: CreateImageSize1024x1024, + Image: origin, + N: 3, + Size: CreateImageSize1024x1024, + ResponseFormat: CreateImageResponseFormatURL, } _, err = client.CreateVariImage(ctx, req) checks.NoError(t, err, "CreateImage error") From 85a4d2e0878d53c1a39cae6e9f17261b5473c5fc Mon Sep 17 00:00:00 2001 From: Aceld Date: Tue, 18 Apr 2023 16:41:09 +0800 Subject: [PATCH 03/16] complete image_test --- image_test.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/image_test.go b/image_test.go index b049ffa89..ab1bd2521 100644 --- a/image_test.go +++ b/image_test.go @@ -155,10 +155,11 @@ func TestImageEditWithoutMask(t *testing.T) { }() req := ImageEditRequest{ - Image: origin, - Prompt: "There is a turtle in the pool", - N: 3, - Size: CreateImageSize1024x1024, + Image: origin, + Prompt: "There is a turtle in the pool", + N: 3, + Size: CreateImageSize1024x1024, + ResponseFormat: CreateImageResponseFormatURL, } _, err = client.CreateEditImage(ctx, req) checks.NoError(t, err, "CreateImage error") @@ -338,6 +339,10 @@ func TestImageFormBuilderFailures(t *testing.T) { _, err = client.CreateEditImage(ctx, req) checks.ErrorIs(t, err, mockFailedErr, "CreateImage should return error if form builder fails") + failForField = "response_format" + _, err = client.CreateEditImage(ctx, req) + checks.ErrorIs(t, err, mockFailedErr, "CreateImage should return error if form builder fails") + failForField = "" mockBuilder.mockClose = func() error { return mockFailedErr @@ -378,6 +383,10 @@ func TestVariImageFormBuilderFailures(t *testing.T) { return nil } + failForField = "prompt" + _, err = client.CreateVariImage(ctx, req) + checks.ErrorIs(t, err, mockFailedErr, "CreateVariImage should return error if form builder fails") + failForField = "n" _, err = client.CreateVariImage(ctx, req) checks.ErrorIs(t, err, mockFailedErr, "CreateVariImage should return error if form builder fails") @@ -386,6 +395,10 @@ func TestVariImageFormBuilderFailures(t *testing.T) { _, err = client.CreateVariImage(ctx, req) checks.ErrorIs(t, err, mockFailedErr, "CreateVariImage should return error if form builder fails") + failForField = "response_format" + _, err = client.CreateVariImage(ctx, req) + checks.ErrorIs(t, err, mockFailedErr, "CreateVariImage should return error if form builder fails") + failForField = "" mockBuilder.mockClose = func() error { return mockFailedErr From 0423b07d9fa6a9de828300976455e226780918e6 Mon Sep 17 00:00:00 2001 From: Aceld Date: Tue, 18 Apr 2023 16:47:49 +0800 Subject: [PATCH 04/16] delete var prompt param --- image.go | 6 ++++++ image_test.go | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/image.go b/image.go index 16112fe80..21703bda7 100644 --- a/image.go +++ b/image.go @@ -86,14 +86,17 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) if err != nil { return } + err = builder.writeField("n", strconv.Itoa(request.N)) if err != nil { return } + err = builder.writeField("size", request.Size) if err != nil { return } + err = builder.writeField("response_format", request.ResponseFormat) if err != nil { return @@ -139,14 +142,17 @@ func (c *Client) CreateVariImage(ctx context.Context, request ImageVariRequest) if err != nil { return } + err = builder.writeField("size", request.Size) if err != nil { return } + err = builder.writeField("response_format", request.ResponseFormat) if err != nil { return } + err = builder.close() if err != nil { return diff --git a/image_test.go b/image_test.go index ab1bd2521..4a7dad58f 100644 --- a/image_test.go +++ b/image_test.go @@ -383,10 +383,6 @@ func TestVariImageFormBuilderFailures(t *testing.T) { return nil } - failForField = "prompt" - _, err = client.CreateVariImage(ctx, req) - checks.ErrorIs(t, err, mockFailedErr, "CreateVariImage should return error if form builder fails") - failForField = "n" _, err = client.CreateVariImage(ctx, req) checks.ErrorIs(t, err, mockFailedErr, "CreateVariImage should return error if form builder fails") From 5088b38b1b2f343713ca5bbac622d3452f2ce50e Mon Sep 17 00:00:00 2001 From: Aceld Date: Thu, 20 Apr 2023 13:12:07 +0800 Subject: [PATCH 05/16] fix:model param type, add moderation Model Name const. --- moderation.go | 17 +++++++++++++++-- moderation_test.go | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/moderation.go b/moderation.go index ff789a617..7709ea731 100644 --- a/moderation.go +++ b/moderation.go @@ -5,10 +5,23 @@ import ( "net/http" ) +// The moderation endpoint is a tool you can use to check whether content complies with OpenAI's usage policies. +// Developers can thus identify content that our usage policies prohibits and take action, for instance by filtering it. + +// The default is text-moderation-latest which will be automatically upgraded over time. +// This ensures you are always using our most accurate model. +// If you use text-moderation-stable, we will provide advanced notice before updating the model. +// Accuracy of text-moderation-stable may be slightly lower than for text-moderation-latest. +const ( + ModerationTextStable = "text-moderation-stable" + ModerationTextLatest = "text-moderation-latest" + ModerationText001 = "image-moderation-001" +) + // ModerationRequest represents a request structure for moderation API. type ModerationRequest struct { - Input string `json:"input,omitempty"` - Model *string `json:"model,omitempty"` + Input string `json:"input,omitempty"` + Model string `json:"model,omitempty"` } // Result represents one of possible moderation results. diff --git a/moderation_test.go b/moderation_test.go index 3535bc807..2c1145627 100644 --- a/moderation_test.go +++ b/moderation_test.go @@ -34,7 +34,7 @@ func TestModerations(t *testing.T) { // create an edit request model := "text-moderation-stable" moderationReq := ModerationRequest{ - Model: &model, + Model: model, Input: "I want to kill them.", } _, err = client.Moderations(ctx, moderationReq) @@ -77,7 +77,7 @@ func handleModerationEndpoint(w http.ResponseWriter, r *http.Request) { res := ModerationResponse{ ID: strconv.Itoa(int(time.Now().Unix())), - Model: *moderationReq.Model, + Model: moderationReq.Model, } res.Results = append(res.Results, result) From 6cd1c3391863220a01451b87965fd29743e71e3a Mon Sep 17 00:00:00 2001 From: Aceld Date: Thu, 20 Apr 2023 13:30:59 +0800 Subject: [PATCH 06/16] rename ModerationText001 --- moderation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moderation.go b/moderation.go index 7709ea731..b386ddb95 100644 --- a/moderation.go +++ b/moderation.go @@ -15,7 +15,7 @@ import ( const ( ModerationTextStable = "text-moderation-stable" ModerationTextLatest = "text-moderation-latest" - ModerationText001 = "image-moderation-001" + ModerationText001 = "text-moderation-001" ) // ModerationRequest represents a request structure for moderation API. From ce80107d65f0416a0c506e5e329bb50b25f8d674 Mon Sep 17 00:00:00 2001 From: Aceld Date: Fri, 21 Apr 2023 11:35:09 +0800 Subject: [PATCH 07/16] add example: and --- README.md | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/README.md b/README.md index 7526ea333..14d1f44a6 100644 --- a/README.md +++ b/README.md @@ -462,3 +462,229 @@ func main() { } ``` + +
+Generate Embeddings + +```go +package main + +import ( + "context" + "encoding/gob" + "fmt" + "github.com/sashabaranov/go-openai" + "io/ioutil" + "os" + "strings" +) + +func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([]float32, error) { + + resp, err := client.CreateEmbeddings(ctx, openai.EmbeddingRequest{ + Input: input, + Model: openai.AdaEmbeddingV2, + }) + + if err != nil { + return nil, err + } + + return resp.Data[0].Embedding, nil +} + +func main() { + ctx := context.Background() + client := openai.NewClient("your token") + + // Load selections.txt, format like this: + /* + Welcome to the go-openai interface, which will be the gateway for golang software engineers to enter the OpenAI development world.\n + My name is Aceld, and I am a Golang software development engineer. I like young and beautiful girls.\n + The competition was held over two days,24 July and 2 August. The qualifying round was the first day with the apparatus final on the second day.\n + There are 4 types of gymnastics apparatus: floor, vault, pommel horse, and rings. The apparatus final is a competition between the top 8 gymnasts in each apparatus.\n + ... + */ + data, err := ioutil.ReadFile("selections.txt") + if err != nil { + panic(err) + } + + // Split by line + lines := strings.Split(string(data), "\n") + + var selections []string + for _, line := range lines { + selections = append(selections, line) + } + + // Generate embeddings + var selectionsEmbeddings [][]float32 + for _, selection := range selections { + embedding, err := getEmbedding(ctx, client, []string{selection}) + if err != nil { + fmt.Printf("GetEmedding error: %v\n", err) + return + } + selectionsEmbeddings = append(selectionsEmbeddings, embedding) + } + + // Write embeddings binary data to file + file, err := os.Create("embeddings.bin") + if err != nil { + fmt.Printf("Create file error: %v\n", err) + return + } + defer file.Close() + + encoder := gob.NewEncoder(file) + err = encoder.Encode(selectionsEmbeddings) + if err != nil { + fmt.Printf("Encode error: %v\n", err) + return + } + + return +} +``` +
+ +
+Embedding Similarity Search + +```go +package main + +import ( + "context" + "encoding/gob" + "fmt" + "github.com/sashabaranov/go-openai" + "io/ioutil" + "math" + "os" + "sort" + "strings" +) + +func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([]float32, error) { + + resp, err := client.CreateEmbeddings(ctx, openai.EmbeddingRequest{ + Input: input, + Model: openai.AdaEmbeddingV2, + }) + + if err != nil { + return nil, err + } + + return resp.Data[0].Embedding, nil +} + +// Calculate cosine similarity +func cosineSimilarity(v1, v2 []float32) float32 { + dot := dotProduct(v1, v2) + v1Magnitude := math.Sqrt(float64(dotProduct(v1, v1))) + v2Magnitude := math.Sqrt(float64(dotProduct(v2, v2))) + return float32(float64(dot) / (v1Magnitude * v2Magnitude)) +} + +// Calculate dot product +func dotProduct(v1, v2 []float32) float32 { + var result float32 + for i := 0; i < len(v1); i++ { + result += v1[i] * v2[i] + } + return result +} + +// Sort the index in descending order of similarity +func sortIndexes(scores []float32) []int { + indexes := make([]int, len(scores)) + for i := range indexes { + indexes[i] = i + } + sort.SliceStable(indexes, func(i, j int) bool { + return scores[indexes[i]] > scores[indexes[j]] + }) + return indexes +} + +func main() { + ctx := context.Background() + client := openai.NewClient("your token") + + // "embeddings.bin" from exp: + file, err := os.Open("embeddings.bin") + if err != nil { + panic(err) + } + defer file.Close() + + // load all embeddings from local binary file + var allEmbeddings [][]float32 + decoder := gob.NewDecoder(file) + if err := decoder.Decode(&allEmbeddings); err != nil { + fmt.Printf("Decode error: %v\n", err) + return + } + + // make some input you like + input := "I am a Golang Software Engineer, I like girls." + + // get embedding of input + inputEmbd, err := getEmbedding(ctx, client, []string{input}) + if err != nil { + fmt.Printf("GetEmedding error: %v\n", err) + return + } + + // Calculate similarity through cosine matching algorithm + var questionScores []float32 + for _, embed := range allEmbeddings { + score := cosineSimilarity(embed, inputEmbd) + questionScores = append(questionScores, score) + } + + // Take the subscripts of the top few selections with the highest similarity + sortedIndexes := sortIndexes(questionScores) + sortedIndexes = sortedIndexes[:3] // Top 3 + + fmt.Println("input:", input) + fmt.Println("----------------------") + fmt.Println("similarity section:") + selectionsFile, err := os.Open("selections.txt") + if err != nil { + fmt.Printf("Open file error: %v\n", err) + return + } + defer selectionsFile.Close() + + fileData, err := ioutil.ReadAll(selectionsFile) + if err != nil { + fmt.Printf("ReadAll file error: %v\n", err) + return + } + + // Split by line + selections := strings.Split(string(fileData), "\n") + + for _, index := range sortedIndexes { + selection := selections[index] + fmt.Printf("%.4f %s\n", questionScores[index], selection) + } + + // OutPut like this: + /* + input: I am a Golang Software Engineer, I like girls. + ---------------------- + similarity section: + 0.9319 My name is Aceld, and I am a Golang software development engineer. I like young and beautiful girls. + 0.7978 Welcome to the go openai interface, which will be the gateway for go software engineers to enter the OpenAI development world. + 0.6901 There are 4 types of gymnastics apparatus: floor, vault, pommel horse, and rings. The apparatus final is a competition between the top 8 gymnasts in each apparatus. + */ + + return +} +``` +
From 3704737e16ed2834f3d877d44a81916fbacbc9b5 Mon Sep 17 00:00:00 2001 From: Aceld Date: Wed, 26 Apr 2023 10:39:22 +0800 Subject: [PATCH 08/16] add DotProduct to Embeddings library, fix embedding example --- README.md | 23 ++++------------------- embeddings_utils.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 embeddings_utils.go diff --git a/README.md b/README.md index 14d1f44a6..51695380a 100644 --- a/README.md +++ b/README.md @@ -581,23 +581,6 @@ func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([ return resp.Data[0].Embedding, nil } -// Calculate cosine similarity -func cosineSimilarity(v1, v2 []float32) float32 { - dot := dotProduct(v1, v2) - v1Magnitude := math.Sqrt(float64(dotProduct(v1, v1))) - v2Magnitude := math.Sqrt(float64(dotProduct(v2, v2))) - return float32(float64(dot) / (v1Magnitude * v2Magnitude)) -} - -// Calculate dot product -func dotProduct(v1, v2 []float32) float32 { - var result float32 - for i := 0; i < len(v1); i++ { - result += v1[i] * v2[i] - } - return result -} - // Sort the index in descending order of similarity func sortIndexes(scores []float32) []int { indexes := make([]int, len(scores)) @@ -642,7 +625,9 @@ func main() { // Calculate similarity through cosine matching algorithm var questionScores []float32 for _, embed := range allEmbeddings { - score := cosineSimilarity(embed, inputEmbd) + // OpenAI embeddings are normalized to length 1, which means that: + // Cosine similarity can be computed slightly faster using just a dot product + score := openai.DotProduct(embed, inputEmbd) questionScores = append(questionScores, score) } @@ -678,7 +663,7 @@ func main() { /* input: I am a Golang Software Engineer, I like girls. ---------------------- - similarity section: + similarity selection: 0.9319 My name is Aceld, and I am a Golang software development engineer. I like young and beautiful girls. 0.7978 Welcome to the go openai interface, which will be the gateway for go software engineers to enter the OpenAI development world. 0.6901 There are 4 types of gymnastics apparatus: floor, vault, pommel horse, and rings. The apparatus final is a competition between the top 8 gymnasts in each apparatus. diff --git a/embeddings_utils.go b/embeddings_utils.go new file mode 100644 index 000000000..075ac6868 --- /dev/null +++ b/embeddings_utils.go @@ -0,0 +1,31 @@ +package openai + +import "math" + +// cosineSimilarity Calculate cosine similarity +// Note: +// We recommend cosine similarity. The choice of distance function typically doesn’t matter much. +// OpenAI embeddings are normalized to length 1, which means that: +// Cosine similarity can be computed slightly faster using just a dot product +// Cosine similarity and Euclidean distance will result in the identical rankings +// See: https://platform.openai.com/docs/guides/embeddings/limitations-risks +func CosineSimilarity(v1, v2 []float32) float32 { + // Calculate dot product + dot := DotProduct(v1, v2) + // Calculate magnitude of v1 + v1Magnitude := math.Sqrt(float64(DotProduct(v1, v1))) + // Calculate magnitude of v2 + v2Magnitude := math.Sqrt(float64(DotProduct(v2, v2))) + // Calculate cosine similarity + return float32(float64(dot) / (v1Magnitude * v2Magnitude)) +} + +// DotProduct Calculate dot product of two vectors +func DotProduct(v1, v2 []float32) float32 { + var result float32 + // Iterate over vectors and calculate dot product + for i := 0; i < len(v1); i++ { + result += v1[i] * v2[i] + } + return result +} From 973b7116852f5523a25ea07e6595dd02c840b9ba Mon Sep 17 00:00:00 2001 From: Aceld Date: Wed, 26 Apr 2023 10:42:28 +0800 Subject: [PATCH 09/16] Comment should end in a period (godot) --- embeddings_utils.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/embeddings_utils.go b/embeddings_utils.go index 075ac6868..00206eeca 100644 --- a/embeddings_utils.go +++ b/embeddings_utils.go @@ -2,12 +2,12 @@ package openai import "math" -// cosineSimilarity Calculate cosine similarity +// CosineSimilarity Calculate cosine similarity. // Note: // We recommend cosine similarity. The choice of distance function typically doesn’t matter much. // OpenAI embeddings are normalized to length 1, which means that: -// Cosine similarity can be computed slightly faster using just a dot product -// Cosine similarity and Euclidean distance will result in the identical rankings +// Cosine similarity can be computed slightly faster using just a dot product. +// Cosine similarity and Euclidean distance will result in the identical rankings. // See: https://platform.openai.com/docs/guides/embeddings/limitations-risks func CosineSimilarity(v1, v2 []float32) float32 { // Calculate dot product @@ -20,10 +20,10 @@ func CosineSimilarity(v1, v2 []float32) float32 { return float32(float64(dot) / (v1Magnitude * v2Magnitude)) } -// DotProduct Calculate dot product of two vectors +// DotProduct Calculate dot product of two vectors. func DotProduct(v1, v2 []float32) float32 { var result float32 - // Iterate over vectors and calculate dot product + // Iterate over vectors and calculate dot product. for i := 0; i < len(v1); i++ { result += v1[i] * v2[i] } From 21127223178e19b2a62961bbb8b5ad2b3dc42380 Mon Sep 17 00:00:00 2001 From: Aceld Date: Wed, 26 Apr 2023 10:52:31 +0800 Subject: [PATCH 10/16] add embeddings TestCosineSimilarity, TestDotProduct --- embeddings_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/embeddings_test.go b/embeddings_test.go index 252f7a5a0..875806386 100644 --- a/embeddings_test.go +++ b/embeddings_test.go @@ -89,3 +89,41 @@ func TestEmbeddingEndpoint(t *testing.T) { _, err = client.CreateEmbeddings(ctx, EmbeddingRequest{}) checks.NoError(t, err, "CreateEmbeddings error") } + +func TestCosineSimilarity(t *testing.T) { + v1 := []float32{1, 2, 3} + v2 := []float32{2, 4, 6} + expected := float32(1.0) + + result := CosineSimilarity(v1, v2) + if result != expected { + t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) + } + + v1 = []float32{1, 0, 0} + v2 = []float32{0, 1, 0} + expected = float32(0.0) + result = CosineSimilarity(v1, v2) + + if result != expected { + t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) + } +} + +func TestDotProduct(t *testing.T) { + v1 := []float32{1, 2, 3} + v2 := []float32{2, 4, 6} + expected := float32(28.0) + result := DotProduct(v1, v2) + if result != expected { + t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) + } + + v1 = []float32{1, 0, 0} + v2 = []float32{0, 1, 0} + expected = float32(0.0) + result = DotProduct(v1, v2) + if result != expected { + t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) + } +} From 63d5fa0ebcfa9d15cb722d60832c23b28fb2128c Mon Sep 17 00:00:00 2001 From: Aceld Date: Wed, 26 Apr 2023 18:21:22 +0800 Subject: [PATCH 11/16] delete CosineSimilarity --- embeddings_test.go | 20 -------------------- embeddings_utils.go | 20 -------------------- 2 files changed, 40 deletions(-) diff --git a/embeddings_test.go b/embeddings_test.go index 875806386..d0a2ce04a 100644 --- a/embeddings_test.go +++ b/embeddings_test.go @@ -90,26 +90,6 @@ func TestEmbeddingEndpoint(t *testing.T) { checks.NoError(t, err, "CreateEmbeddings error") } -func TestCosineSimilarity(t *testing.T) { - v1 := []float32{1, 2, 3} - v2 := []float32{2, 4, 6} - expected := float32(1.0) - - result := CosineSimilarity(v1, v2) - if result != expected { - t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) - } - - v1 = []float32{1, 0, 0} - v2 = []float32{0, 1, 0} - expected = float32(0.0) - result = CosineSimilarity(v1, v2) - - if result != expected { - t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) - } -} - func TestDotProduct(t *testing.T) { v1 := []float32{1, 2, 3} v2 := []float32{2, 4, 6} diff --git a/embeddings_utils.go b/embeddings_utils.go index 00206eeca..76efb66b2 100644 --- a/embeddings_utils.go +++ b/embeddings_utils.go @@ -1,25 +1,5 @@ package openai -import "math" - -// CosineSimilarity Calculate cosine similarity. -// Note: -// We recommend cosine similarity. The choice of distance function typically doesn’t matter much. -// OpenAI embeddings are normalized to length 1, which means that: -// Cosine similarity can be computed slightly faster using just a dot product. -// Cosine similarity and Euclidean distance will result in the identical rankings. -// See: https://platform.openai.com/docs/guides/embeddings/limitations-risks -func CosineSimilarity(v1, v2 []float32) float32 { - // Calculate dot product - dot := DotProduct(v1, v2) - // Calculate magnitude of v1 - v1Magnitude := math.Sqrt(float64(DotProduct(v1, v1))) - // Calculate magnitude of v2 - v2Magnitude := math.Sqrt(float64(DotProduct(v2, v2))) - // Calculate cosine similarity - return float32(float64(dot) / (v1Magnitude * v2Magnitude)) -} - // DotProduct Calculate dot product of two vectors. func DotProduct(v1, v2 []float32) float32 { var result float32 From b779885c16176cd5305fa42feb9c7109f13a11f2 Mon Sep 17 00:00:00 2001 From: Aceld Date: Tue, 13 Jun 2023 10:17:58 +0800 Subject: [PATCH 12/16] add example: and --- README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8f4e0218a..73c770506 100644 --- a/README.md +++ b/README.md @@ -524,13 +524,11 @@ func main() { package main import ( - "context" - "encoding/gob" - "fmt" - "github.com/sashabaranov/go-openai" - "io/ioutil" - "os" - "strings" + "context" + "encoding/gob" + "fmt" + "github.com/sashabaranov/go-openai" + "os" ) func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([]float32, error) { @@ -548,16 +546,16 @@ func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([ } func main() { - ctx := context.Background() - client := openai.NewClient("your token") + ctx := context.Background() + client := openai.NewClient("your token") // example selections selections := []string{ "Welcome to the go-openai interface, which will be the gateway for golang software engineers to enter the OpenAI development world.", "It was tasty and fresh. The other one I bought was old and tasted moldy. But this one was good.", "Great coffee at a good price. I'm a subscription buyer and I buy this month after month. What more can I say?", - "This chocolate is amazing..I love the taste and smell, this is the only chocolate for me...I found a new love!" + "This chocolate is amazing..I love the taste and smell, this is the only chocolate for me...I found a new love!", "I love this coffee! And such a great price. Will buy more when I am running out which will be soon.", "The Raspberry Tea Syrup is great. I can use it for hot and cold drinks as well in certain recipes.", "Everyone that dips with this loves it! So easy to use! Olive oil and tasty bread is all you need.", @@ -566,7 +564,7 @@ func main() { "My name is Aceld, and I am a Golang software development engineer. I like young and beautiful girls.", "The competition was held over two days,24 July and 2 August. The qualifying round was the first day with the apparatus final on the second day.", "There are 4 types of gymnastics apparatus: floor, vault, pommel horse, and rings. The apparatus final is a competition between the top 8 gymnasts in each apparatus.", - } + } // Generate embeddings var selectionsEmbeddings [][]float32 @@ -611,7 +609,6 @@ import ( "fmt" "github.com/sashabaranov/go-openai" "io/ioutil" - "math" "os" "sort" "strings" From 4e12e6daecebf366fbc6fbdc1c1f180b5b92172d Mon Sep 17 00:00:00 2001 From: Aceld Date: Fri, 16 Jun 2023 14:22:16 +0800 Subject: [PATCH 13/16] add example: and --- embeddings_utils.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embeddings_utils.go b/embeddings_utils.go index 76efb66b2..f333f5ba1 100644 --- a/embeddings_utils.go +++ b/embeddings_utils.go @@ -1,6 +1,7 @@ package openai // DotProduct Calculate dot product of two vectors. +/* func DotProduct(v1, v2 []float32) float32 { var result float32 // Iterate over vectors and calculate dot product. @@ -9,3 +10,4 @@ func DotProduct(v1, v2 []float32) float32 { } return result } +*/ From b0d7bf3a9651563fc252625c157e29ea363756b5 Mon Sep 17 00:00:00 2001 From: Aceld Date: Fri, 16 Jun 2023 14:42:49 +0800 Subject: [PATCH 14/16] add example: and --- embeddings_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embeddings_test.go b/embeddings_test.go index 1692bda16..93cfb775c 100644 --- a/embeddings_test.go +++ b/embeddings_test.go @@ -1,14 +1,12 @@ package openai_test import ( - . "github.com/sashabaranov/go-openai" - "github.com/sashabaranov/go-openai/internal/test/checks" - "math" - "bytes" "context" "encoding/json" "fmt" + . "github.com/sashabaranov/go-openai" + "github.com/sashabaranov/go-openai/internal/test/checks" "net/http" "testing" ) @@ -80,6 +78,7 @@ func TestEmbeddingEndpoint(t *testing.T) { checks.NoError(t, err, "CreateEmbeddings error") } +/* func TestDotProduct(t *testing.T) { v1 := []float32{1, 2, 3} v2 := []float32{2, 4, 6} @@ -97,3 +96,4 @@ func TestDotProduct(t *testing.T) { t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) } } +*/ From e2a23c5e4b9e98e7d47a761da5e395d5b8d58e47 Mon Sep 17 00:00:00 2001 From: Aceld Date: Fri, 16 Jun 2023 14:55:09 +0800 Subject: [PATCH 15/16] add example: and --- README.md | 26 +++++++++++++------------- embeddings_test.go | 3 +-- embeddings_utils.go | 2 -- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 73c770506..572e6c5f9 100644 --- a/README.md +++ b/README.md @@ -615,16 +615,15 @@ import ( ) func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([]float32, error) { - resp, err := client.CreateEmbeddings(ctx, openai.EmbeddingRequest{ - Input: input, + Input: input, Model: openai.AdaEmbeddingV2, }) - + if err != nil { return nil, err } - + return resp.Data[0].Embedding, nil } @@ -700,7 +699,7 @@ func main() { // Split by line selections := strings.Split(string(fileData), "\n") - + for _, index := range sortedIndexes { selection := selections[index] fmt.Printf("%.4f %s\n", questionScores[index], selection) @@ -717,19 +716,20 @@ func main() { Open-AI maintains clear documentation on how to [handle API errors](https://platform.openai.com/docs/guides/error-codes/api-errors) example: -``` +```go e := &openai.APIError{} + if errors.As(err, &e) { - switch e.HTTPStatusCode { - case 401: - // invalid auth or key (do not retry) + switch e.HTTPStatusCode { + case 401: + // invalid auth or key (do not retry) case 429: - // rate limiting or engine overload (wait and retry) + // rate limiting or engine overload (wait and retry) case 500: - // openai server error (retry) + // openai server error (retry) default: - // unhandled - } + // unhandled + } } ``` diff --git a/embeddings_test.go b/embeddings_test.go index 93cfb775c..1de35bd78 100644 --- a/embeddings_test.go +++ b/embeddings_test.go @@ -7,6 +7,7 @@ import ( "fmt" . "github.com/sashabaranov/go-openai" "github.com/sashabaranov/go-openai/internal/test/checks" + "math" "net/http" "testing" ) @@ -78,7 +79,6 @@ func TestEmbeddingEndpoint(t *testing.T) { checks.NoError(t, err, "CreateEmbeddings error") } -/* func TestDotProduct(t *testing.T) { v1 := []float32{1, 2, 3} v2 := []float32{2, 4, 6} @@ -96,4 +96,3 @@ func TestDotProduct(t *testing.T) { t.Errorf("Unexpected result. Expected: %v, but got %v", expected, result) } } -*/ diff --git a/embeddings_utils.go b/embeddings_utils.go index f333f5ba1..76efb66b2 100644 --- a/embeddings_utils.go +++ b/embeddings_utils.go @@ -1,7 +1,6 @@ package openai // DotProduct Calculate dot product of two vectors. -/* func DotProduct(v1, v2 []float32) float32 { var result float32 // Iterate over vectors and calculate dot product. @@ -10,4 +9,3 @@ func DotProduct(v1, v2 []float32) float32 { } return result } -*/ From 330ec636f8ada6ca22251f4099fd5f1988fe824a Mon Sep 17 00:00:00 2001 From: Aceld Date: Fri, 16 Jun 2023 14:59:52 +0800 Subject: [PATCH 16/16] sort import --- README.md | 6 ++++-- embeddings_test.go | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 572e6c5f9..7203f707a 100644 --- a/README.md +++ b/README.md @@ -527,8 +527,9 @@ import ( "context" "encoding/gob" "fmt" - "github.com/sashabaranov/go-openai" "os" + + "github.com/sashabaranov/go-openai" ) func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([]float32, error) { @@ -607,11 +608,12 @@ import ( "context" "encoding/gob" "fmt" - "github.com/sashabaranov/go-openai" "io/ioutil" "os" "sort" "strings" + + "github.com/sashabaranov/go-openai" ) func getEmbedding(ctx context.Context, client *openai.Client, input []string) ([]float32, error) { diff --git a/embeddings_test.go b/embeddings_test.go index 1de35bd78..c87e9bad5 100644 --- a/embeddings_test.go +++ b/embeddings_test.go @@ -5,11 +5,12 @@ import ( "context" "encoding/json" "fmt" - . "github.com/sashabaranov/go-openai" - "github.com/sashabaranov/go-openai/internal/test/checks" "math" "net/http" "testing" + + . "github.com/sashabaranov/go-openai" + "github.com/sashabaranov/go-openai/internal/test/checks" ) func TestEmbedding(t *testing.T) {