Repository: sashabaranov/go-openai (go)

Issue:
`c.fullURL(urlSuffix)` should be `c.fullURL(urlSuffix, c.Model)`  ?
file image.go

`c.fullURL(urlSuffix)` should be `c.fullURL(urlSuffix, c.Model)`  ?


code lines: 71, 134, 184

Pull request description:
fixed #594
fix #594 APITypeAzure dall-e-3 model url

**Describe the change**
fix #594 APITypeAzure dall-e-3 model url


Issue: #594


Patch:
diff --git a/README.md b/README.md
index 4cb77db..9a479c0 100644
--- a/README.md
+++ b/README.md
@@ -453,7 +453,7 @@ func main() {
 	config := openai.DefaultAzureConfig("your Azure OpenAI Key", "https://your Azure OpenAI Endpoint")
 	// If you use a deployment name different from the model name, you can customize the AzureModelMapperFunc function
 	// config.AzureModelMapperFunc = func(model string) string {
-	// 	azureModelMapping = map[string]string{
+	// 	azureModelMapping := map[string]string{
 	// 		"gpt-3.5-turbo": "your gpt-3.5-turbo deployment name",
 	// 	}
 	// 	return azureModelMapping[model]
@@ -559,7 +559,7 @@ func main() {
 
 	//If you use a deployment name different from the model name, you can customize the AzureModelMapperFunc function
 	//config.AzureModelMapperFunc = func(model string) string {
-	//    azureModelMapping = map[string]string{
+	//    azureModelMapping := map[string]string{
 	//        "gpt-3.5-turbo":"your gpt-3.5-turbo deployment name",
 	//    }
 	//    return azureModelMapping[model]
diff --git a/chat.go b/chat.go
index 5b87b6b..33b8755 100644
--- a/chat.go
+++ b/chat.go
@@ -200,7 +200,15 @@ type ChatCompletionRequest struct {
 	// incorrect: `"logit_bias":{"You": 6}`, correct: `"logit_bias":{"1639": 6}`
 	// refs: https://platform.openai.com/docs/api-reference/chat/create#chat/create-logit_bias
 	LogitBias map[string]int `json:"logit_bias,omitempty"`
-	User      string         `json:"user,omitempty"`
+	// LogProbs indicates whether to return log probabilities of the output tokens or not.
+	// If true, returns the log probabilities of each output token returned in the content of message.
+	// This option is currently not available on the gpt-4-vision-preview model.
+	LogProbs bool `json:"logprobs,omitempty"`
+	// TopLogProbs is an integer between 0 and 5 specifying the number of most likely tokens to return at each
+	// token position, each with an associated log probability.
+	// logprobs must be set to true if this parameter is used.
+	TopLogProbs int    `json:"top_logprobs,omitempty"`
+	User        string `json:"user,omitempty"`
 	// Deprecated: use Tools instead.
 	Functions []FunctionDefinition `json:"functions,omitempty"`
 	// Deprecated: use ToolChoice instead.
@@ -244,6 +252,28 @@ type FunctionDefinition struct {
 // Deprecated: use FunctionDefinition instead.
 type FunctionDefine = FunctionDefinition
 
+type TopLogProbs struct {
+	Token   string  `json:"token"`
+	LogProb float64 `json:"logprob"`
+	Bytes   []byte  `json:"bytes,omitempty"`
+}
+
+// LogProb represents the probability information for a token.
+type LogProb struct {
+	Token   string  `json:"token"`
+	LogProb float64 `json:"logprob"`
+	Bytes   []byte  `json:"bytes,omitempty"` // Omitting the field if it is null
+	// TopLogProbs is a list of the most likely tokens and their log probability, at this token position.
+	// In rare cases, there may be fewer than the number of requested top_logprobs returned.
+	TopLogProbs []TopLogProbs `json:"top_logprobs"`
+}
+
+// LogProbs is the top-level structure containing the log probability information.
+type LogProbs struct {
+	// Content is a list of message content tokens with log probability information.
+	Content []LogProb `json:"content"`
+}
+
 type FinishReason string
 
 const (
@@ -273,6 +303,7 @@ type ChatCompletionChoice struct {
 	// content_filter: Omitted content due to a flag from our content filters
 	// null: API response still in progress or incomplete
 	FinishReason FinishReason `json:"finish_reason"`
+	LogProbs     *LogProbs    `json:"logprobs,omitempty"`
 }
 
 // ChatCompletionResponse represents a response structure for chat completion API.
diff --git a/embeddings.go b/embeddings.go
index 7e2aa7e..f79df9d 100644
--- a/embeddings.go
+++ b/embeddings.go
@@ -13,108 +13,30 @@ var ErrVectorLengthMismatch = errors.New("vector length mismatch")
 
 // EmbeddingModel enumerates the models which can be used
 // to generate Embedding vectors.
-type EmbeddingModel int
-
-// String implements the fmt.Stringer interface.
-func (e EmbeddingModel) String() string {
-	return enumToString[e]
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (e EmbeddingModel) MarshalText() ([]byte, error) {
-	return []byte(e.String()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-// On unrecognized value, it sets |e| to Unknown.
-func (e *EmbeddingModel) UnmarshalText(b []byte) error {
-	if val, ok := stringToEnum[(string(b))]; ok {
-		*e = val
-		return nil
-	}
-
-	*e = Unknown
-
-	return nil
-}
+type EmbeddingModel string
 
 const (
-	Unknown EmbeddingModel = iota
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	AdaSimilarity
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	BabbageSimilarity
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	CurieSimilarity
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	DavinciSimilarity
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	AdaSearchDocument
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	AdaSearchQuery
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	BabbageSearchDocument
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	BabbageSearchQuery
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	CurieSearchDocument
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	CurieSearchQuery
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	DavinciSearchDocument
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	DavinciSearchQuery
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	AdaCodeSearchCode
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	AdaCodeSearchText
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	BabbageCodeSearchCode
-	// Deprecated: Will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
-	BabbageCodeSearchText
-	AdaEmbeddingV2
+	// Deprecated: The following block will be shut down on January 04, 2024. Use text-embedding-ada-002 instead.
+	AdaSimilarity         EmbeddingModel = "text-similarity-ada-001"
+	BabbageSimilarity     EmbeddingModel = "text-similarity-babbage-001"
+	CurieSimilarity       EmbeddingModel = "text-similarity-curie-001"
+	DavinciSimilarity     EmbeddingModel = "text-similarity-davinci-001"
+	AdaSearchDocument     EmbeddingModel = "text-search-ada-doc-001"
+	AdaSearchQuery        EmbeddingModel = "text-search-ada-query-001"
+	BabbageSearchDocument EmbeddingModel = "text-search-babbage-doc-001"
+	BabbageSearchQuery    EmbeddingModel = "text-search-babbage-query-001"
+	CurieSearchDocument   EmbeddingModel = "text-search-curie-doc-001"
+	CurieSearchQuery      EmbeddingModel = "text-search-curie-query-001"
+	DavinciSearchDocument EmbeddingModel = "text-search-davinci-doc-001"
+	DavinciSearchQuery    EmbeddingModel = "text-search-davinci-query-001"
+	AdaCodeSearchCode     EmbeddingModel = "code-search-ada-code-001"
+	AdaCodeSearchText     EmbeddingModel = "code-search-ada-text-001"
+	BabbageCodeSearchCode EmbeddingModel = "code-search-babbage-code-001"
+	BabbageCodeSearchText EmbeddingModel = "code-search-babbage-text-001"
+
+	AdaEmbeddingV2 EmbeddingModel = "text-embedding-ada-002"
 )
 
-var enumToString = map[EmbeddingModel]string{
-	AdaSimilarity:         "text-similarity-ada-001",
-	BabbageSimilarity:     "text-similarity-babbage-001",
-	CurieSimilarity:       "text-similarity-curie-001",
-	DavinciSimilarity:     "text-similarity-davinci-001",
-	AdaSearchDocument:     "text-search-ada-doc-001",
-	AdaSearchQuery:        "text-search-ada-query-001",
-	BabbageSearchDocument: "text-search-babbage-doc-001",
-	BabbageSearchQuery:    "text-search-babbage-query-001",
-	CurieSearchDocument:   "text-search-curie-doc-001",
-	CurieSearchQuery:      "text-search-curie-query-001",
-	DavinciSearchDocument: "text-search-davinci-doc-001",
-	DavinciSearchQuery:    "text-search-davinci-query-001",
-	AdaCodeSearchCode:     "code-search-ada-code-001",
-	AdaCodeSearchText:     "code-search-ada-text-001",
-	BabbageCodeSearchCode: "code-search-babbage-code-001",
-	BabbageCodeSearchText: "code-search-babbage-text-001",
-	AdaEmbeddingV2:        "text-embedding-ada-002",
-}
-
-var stringToEnum = map[string]EmbeddingModel{
-	"text-similarity-ada-001":       AdaSimilarity,
-	"text-similarity-babbage-001":   BabbageSimilarity,
-	"text-similarity-curie-001":     CurieSimilarity,
-	"text-similarity-davinci-001":   DavinciSimilarity,
-	"text-search-ada-doc-001":       AdaSearchDocument,
-	"text-search-ada-query-001":     AdaSearchQuery,
-	"text-search-babbage-doc-001":   BabbageSearchDocument,
-	"text-search-babbage-query-001": BabbageSearchQuery,
-	"text-search-curie-doc-001":     CurieSearchDocument,
-	"text-search-curie-query-001":   CurieSearchQuery,
-	"text-search-davinci-doc-001":   DavinciSearchDocument,
-	"text-search-davinci-query-001": DavinciSearchQuery,
-	"code-search-ada-code-001":      AdaCodeSearchCode,
-	"code-search-ada-text-001":      AdaCodeSearchText,
-	"code-search-babbage-code-001":  BabbageCodeSearchCode,
-	"code-search-babbage-text-001":  BabbageCodeSearchText,
-	"text-embedding-ada-002":        AdaEmbeddingV2,
-}
-
 // Embedding is a special format of data representation that can be easily utilized by machine
 // learning models and algorithms. The embedding is an information dense representation of the
 // semantic meaning of a piece of text. Each embedding is a vector of floating point numbers,
@@ -306,7 +228,7 @@ func (c *Client) CreateEmbeddings(
 	conv EmbeddingRequestConverter,
 ) (res EmbeddingResponse, err error) {
 	baseReq := conv.Convert()
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/embeddings", baseReq.Model.String()), withBody(baseReq))
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/embeddings", baseReq.Model), withBody(baseReq))
 	if err != nil {
 		return
 	}
diff --git a/image.go b/image.go
index 4fe8b3a..665de1a 100644
--- a/image.go
+++ b/image.go
@@ -68,7 +68,7 @@ type ImageResponseDataInner struct {
 // CreateImage - API call to create an image. This is the main endpoint of the DALL-E API.
 func (c *Client) CreateImage(ctx context.Context, request ImageRequest) (response ImageResponse, err error) {
 	urlSuffix := "/images/generations"
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix), withBody(request))
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix, request.Model), withBody(request))
 	if err != nil {
 		return
 	}
@@ -82,6 +82,7 @@ type ImageEditRequest struct {
 	Image          *os.File `json:"image,omitempty"`
 	Mask           *os.File `json:"mask,omitempty"`
 	Prompt         string   `json:"prompt,omitempty"`
+	Model          string   `json:"model,omitempty"`
 	N              int      `json:"n,omitempty"`
 	Size           string   `json:"size,omitempty"`
 	ResponseFormat string   `json:"response_format,omitempty"`
@@ -131,7 +132,7 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest)
 		return
 	}
 
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/images/edits"),
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/images/edits", request.Model),
 		withBody(body), withContentType(builder.FormDataContentType()))
 	if err != nil {
 		return
@@ -144,6 +145,7 @@ 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"`
+	Model          string   `json:"model,omitempty"`
 	N              int      `json:"n,omitempty"`
 	Size           string   `json:"size,omitempty"`
 	ResponseFormat string   `json:"response_format,omitempty"`
@@ -181,7 +183,7 @@ func (c *Client) CreateVariImage(ctx context.Context, request ImageVariRequest)
 		return
 	}
 
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/images/variations"),
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/images/variations", request.Model),
 		withBody(body), withContentType(builder.FormDataContentType()))
 	if err != nil {
 		return


Test patch:
diff --git a/embeddings_test.go b/embeddings_test.go
index af04d96..846d199 100644
--- a/embeddings_test.go
+++ b/embeddings_test.go
@@ -47,7 +47,7 @@ func TestEmbedding(t *testing.T) {
 		// the AdaSearchQuery type
 		marshaled, err := json.Marshal(embeddingReq)
 		checks.NoError(t, err, "Could not marshal embedding request")
-		if !bytes.Contains(marshaled, []byte(`"model":"`+model.String()+`"`)) {
+		if !bytes.Contains(marshaled, []byte(`"model":"`+model+`"`)) {
 			t.Fatalf("Expected embedding request to contain model field")
 		}
 
@@ -61,7 +61,7 @@ func TestEmbedding(t *testing.T) {
 		}
 		marshaled, err = json.Marshal(embeddingReqStrings)
 		checks.NoError(t, err, "Could not marshal embedding request")
-		if !bytes.Contains(marshaled, []byte(`"model":"`+model.String()+`"`)) {
+		if !bytes.Contains(marshaled, []byte(`"model":"`+model+`"`)) {
 			t.Fatalf("Expected embedding request to contain model field")
 		}
 
@@ -75,28 +75,12 @@ func TestEmbedding(t *testing.T) {
 		}
 		marshaled, err = json.Marshal(embeddingReqTokens)
 		checks.NoError(t, err, "Could not marshal embedding request")
-		if !bytes.Contains(marshaled, []byte(`"model":"`+model.String()+`"`)) {
+		if !bytes.Contains(marshaled, []byte(`"model":"`+model+`"`)) {
 			t.Fatalf("Expected embedding request to contain model field")
 		}
 	}
 }
 
-func TestEmbeddingModel(t *testing.T) {
-	var em openai.EmbeddingModel
-	err := em.UnmarshalText([]byte("text-similarity-ada-001"))
-	checks.NoError(t, err, "Could not marshal embedding model")
-
-	if em != openai.AdaSimilarity {
-		t.Errorf("Model is not equal to AdaSimilarity")
-	}
-
-	err = em.UnmarshalText([]byte("some-non-existent-model"))
-	checks.NoError(t, err, "Could not marshal embedding model")
-	if em != openai.Unknown {
-		t.Errorf("Model is not equal to Unknown")
-	}
-}
-
 func TestEmbeddingEndpoint(t *testing.T) {
 	client, server, teardown := setupOpenAITestServer()
 	defer teardown()