Repository: sashabaranov/go-openai
Pull request #548 (2023-11-07 22:04:49)

test: fix compile error in api integration test
**Describe the change**
The compilation of the integration test is broken. It seems to have regressed due to the refactoring in PR #[522](https://github.com/sashabaranov/go-openai/pull/522/files#diff-e746382823c9b7cef735e766c987a5523b86a0d1be3236000c5c3e3ddfd7c55bL12).

**Describe your solution**
Imported "github.com/sashabaranov/go-openai" and fixed the reference error.

**Tests**
None

**Additional context**
Issue: #547


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/sashabaranov/go-openai/pull/548?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#548](https://app.codecov.io/gh/sashabaranov/go-openai/pull/548?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (309cd21) into [master](https://app.codecov.io/gh/sashabaranov/go-openai/commit/a20eb08b79e5c34882888a401020b47c145357ff?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (a20eb08) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##           master     #548   +/-   ##
=======================================
  Coverage   97.85%   97.85%           
=======================================
  Files          20       20           
  Lines         978      978           
=======================================
  Hits          957      957           
  Misses         15       15           
  Partials        6        6           
```




vvatanabe: @sashabaranov Please check it;D

Patch:
diff --git a/assistant.go b/assistant.go
index d75eebe..de49be6 100644
--- a/assistant.go
+++ b/assistant.go
@@ -10,46 +10,43 @@ import (
 const (
 	assistantsSuffix      = "/assistants"
 	assistantsFilesSuffix = "/files"
+	openaiAssistantsV1    = "assistants=v1"
 )
 
 type Assistant struct {
-	ID           string  `json:"id"`
-	Object       string  `json:"object"`
-	CreatedAt    int64   `json:"created_at"`
-	Name         *string `json:"name,omitempty"`
-	Description  *string `json:"description,omitempty"`
-	Model        string  `json:"model"`
-	Instructions *string `json:"instructions,omitempty"`
-	Tools        []any   `json:"tools,omitempty"`
+	ID           string          `json:"id"`
+	Object       string          `json:"object"`
+	CreatedAt    int64           `json:"created_at"`
+	Name         *string         `json:"name,omitempty"`
+	Description  *string         `json:"description,omitempty"`
+	Model        string          `json:"model"`
+	Instructions *string         `json:"instructions,omitempty"`
+	Tools        []AssistantTool `json:"tools,omitempty"`
 
 	httpHeader
 }
 
-type AssistantTool struct {
-	Type string `json:"type"`
-}
-
-type AssistantToolCodeInterpreter struct {
-	AssistantTool
-}
+type AssistantToolType string
 
-type AssistantToolRetrieval struct {
-	AssistantTool
-}
+const (
+	AssistantToolTypeCodeInterpreter AssistantToolType = "code_interpreter"
+	AssistantToolTypeRetrieval       AssistantToolType = "retrieval"
+	AssistantToolTypeFunction        AssistantToolType = "function"
+)
 
-type AssistantToolFunction struct {
-	AssistantTool
-	Function FunctionDefinition `json:"function"`
+type AssistantTool struct {
+	Type     AssistantToolType   `json:"type"`
+	Function *FunctionDefinition `json:"function,omitempty"`
 }
 
 type AssistantRequest struct {
-	Model        string         `json:"model"`
-	Name         *string        `json:"name,omitempty"`
-	Description  *string        `json:"description,omitempty"`
-	Instructions *string        `json:"instructions,omitempty"`
-	Tools        []any          `json:"tools,omitempty"`
-	FileIDs      []string       `json:"file_ids,omitempty"`
-	Metadata     map[string]any `json:"metadata,omitempty"`
+	Model        string          `json:"model"`
+	Name         *string         `json:"name,omitempty"`
+	Description  *string         `json:"description,omitempty"`
+	Instructions *string         `json:"instructions,omitempty"`
+	Tools        []AssistantTool `json:"tools,omitempty"`
+	FileIDs      []string        `json:"file_ids,omitempty"`
+	Metadata     map[string]any  `json:"metadata,omitempty"`
 }
 
 // AssistantsList is a list of assistants.
@@ -59,6 +56,14 @@ type AssistantsList struct {
 	httpHeader
 }
 
+type AssistantDeleteResponse struct {
+	ID      string `json:"id"`
+	Object  string `json:"object"`
+	Deleted bool   `json:"deleted"`
+
+	httpHeader
+}
+
 type AssistantFile struct {
 	ID          string `json:"id"`
 	Object      string `json:"object"`
@@ -80,7 +85,8 @@ type AssistantFilesList struct {
 
 // CreateAssistant creates a new assistant.
 func (c *Client) CreateAssistant(ctx context.Context, request AssistantRequest) (response Assistant, err error) {
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(assistantsSuffix), withBody(request))
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(assistantsSuffix), withBody(request),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -95,7 +101,8 @@ func (c *Client) RetrieveAssistant(
 	assistantID string,
 ) (response Assistant, err error) {
 	urlSuffix := fmt.Sprintf("%s/%s", assistantsSuffix, assistantID)
-	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix))
+	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -111,7 +118,8 @@ func (c *Client) ModifyAssistant(
 	request AssistantRequest,
 ) (response Assistant, err error) {
 	urlSuffix := fmt.Sprintf("%s/%s", assistantsSuffix, assistantID)
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix), withBody(request))
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix), withBody(request),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -124,9 +132,10 @@ func (c *Client) ModifyAssistant(
 func (c *Client) DeleteAssistant(
 	ctx context.Context,
 	assistantID string,
-) (response Assistant, err error) {
+) (response AssistantDeleteResponse, err error) {
 	urlSuffix := fmt.Sprintf("%s/%s", assistantsSuffix, assistantID)
-	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix))
+	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -163,7 +172,8 @@ func (c *Client) ListAssistants(
 	}
 
 	urlSuffix := fmt.Sprintf("%s%s", assistantsSuffix, encodedValues)
-	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix))
+	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -180,7 +190,8 @@ func (c *Client) CreateAssistantFile(
 ) (response AssistantFile, err error) {
 	urlSuffix := fmt.Sprintf("%s/%s%s", assistantsSuffix, assistantID, assistantsFilesSuffix)
 	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix),
-		withBody(request))
+		withBody(request),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -196,7 +207,8 @@ func (c *Client) RetrieveAssistantFile(
 	fileID string,
 ) (response AssistantFile, err error) {
 	urlSuffix := fmt.Sprintf("%s/%s%s/%s", assistantsSuffix, assistantID, assistantsFilesSuffix, fileID)
-	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix))
+	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -212,7 +224,8 @@ func (c *Client) DeleteAssistantFile(
 	fileID string,
 ) (err error) {
 	urlSuffix := fmt.Sprintf("%s/%s%s/%s", assistantsSuffix, assistantID, assistantsFilesSuffix, fileID)
-	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix))
+	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
@@ -250,7 +263,8 @@ func (c *Client) ListAssistantFiles(
 	}
 
 	urlSuffix := fmt.Sprintf("%s/%s%s%s", assistantsSuffix, assistantID, assistantsFilesSuffix, encodedValues)
-	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix))
+	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
+		withBetaAssistantV1())
 	if err != nil {
 		return
 	}
diff --git a/client.go b/client.go
index 65ece81..056226c 100644
--- a/client.go
+++ b/client.go
@@ -83,6 +83,12 @@ func withContentType(contentType string) requestOption {
 	}
 }
 
+func withBetaAssistantV1() requestOption {
+	return func(args *requestOptions) {
+		args.header.Set("OpenAI-Beta", "assistants=v1")
+	}
+}
+
 func (c *Client) newRequest(ctx context.Context, method, url string, setters ...requestOption) (*http.Request, error) {
 	// Default Options
 	args := &requestOptions{
diff --git a/image.go b/image.go
index 4addcdb..4fe8b3a 100644
--- a/image.go
+++ b/image.go
@@ -13,6 +13,9 @@ const (
 	CreateImageSize256x256   = "256x256"
 	CreateImageSize512x512   = "512x512"
 	CreateImageSize1024x1024 = "1024x1024"
+	// dall-e-3 supported only.
+	CreateImageSize1792x1024 = "1792x1024"
+	CreateImageSize1024x1792 = "1024x1792"
 )
 
 const (
@@ -20,11 +23,29 @@ const (
 	CreateImageResponseFormatB64JSON = "b64_json"
 )
 
+const (
+	CreateImageModelDallE2 = "dall-e-2"
+	CreateImageModelDallE3 = "dall-e-3"
+)
+
+const (
+	CreateImageQualityHD       = "hd"
+	CreateImageQualityStandard = "standard"
+)
+
+const (
+	CreateImageStyleVivid   = "vivid"
+	CreateImageStyleNatural = "natural"
+)
+
 // ImageRequest represents the request structure for the image API.
 type ImageRequest struct {
 	Prompt         string `json:"prompt,omitempty"`
+	Model          string `json:"model,omitempty"`
 	N              int    `json:"n,omitempty"`
+	Quality        string `json:"quality,omitempty"`
 	Size           string `json:"size,omitempty"`
+	Style          string `json:"style,omitempty"`
 	ResponseFormat string `json:"response_format,omitempty"`
 	User           string `json:"user,omitempty"`
 }
@@ -39,8 +60,9 @@ type ImageResponse struct {
 
 // ImageResponseDataInner represents a response data structure for image API.
 type ImageResponseDataInner struct {
-	URL     string `json:"url,omitempty"`
-	B64JSON string `json:"b64_json,omitempty"`
+	URL           string `json:"url,omitempty"`
+	B64JSON       string `json:"b64_json,omitempty"`
+	RevisedPrompt string `json:"revised_prompt,omitempty"`
 }
 
 // CreateImage - API call to create an image. This is the main endpoint of the DALL-E API.


Test patch:
diff --git a/api_integration_test.go b/api_integration_test.go
index 6be188b..736040c 100644
--- a/api_integration_test.go
+++ b/api_integration_test.go
@@ -9,6 +9,7 @@ import (
 	"os"
 	"testing"
 
+	"github.com/sashabaranov/go-openai"
 	"github.com/sashabaranov/go-openai/internal/test/checks"
 	"github.com/sashabaranov/go-openai/jsonschema"
 )
@@ -20,7 +21,7 @@ func TestAPI(t *testing.T) {
 	}
 
 	var err error
-	c := NewClient(apiToken)
+	c := openai.NewClient(apiToken)
 	ctx := context.Background()
 	_, err = c.ListEngines(ctx)
 	checks.NoError(t, err, "ListEngines error")
@@ -36,23 +37,23 @@ func TestAPI(t *testing.T) {
 		checks.NoError(t, err, "GetFile error")
 	} // else skip
 
-	embeddingReq := EmbeddingRequest{
+	embeddingReq := openai.EmbeddingRequest{
 		Input: []string{
 			"The food was delicious and the waiter",
 			"Other examples of embedding request",
 		},
-		Model: AdaSearchQuery,
+		Model: openai.AdaSearchQuery,
 	}
 	_, err = c.CreateEmbeddings(ctx, embeddingReq)
 	checks.NoError(t, err, "Embedding error")
 
 	_, err = c.CreateChatCompletion(
 		ctx,
-		ChatCompletionRequest{
-			Model: GPT3Dot5Turbo,
-			Messages: []ChatCompletionMessage{
+		openai.ChatCompletionRequest{
+			Model: openai.GPT3Dot5Turbo,
+			Messages: []openai.ChatCompletionMessage{
 				{
-					Role:    ChatMessageRoleUser,
+					Role:    openai.ChatMessageRoleUser,
 					Content: "Hello!",
 				},
 			},
@@ -63,11 +64,11 @@ func TestAPI(t *testing.T) {
 
 	_, err = c.CreateChatCompletion(
 		ctx,
-		ChatCompletionRequest{
-			Model: GPT3Dot5Turbo,
-			Messages: []ChatCompletionMessage{
+		openai.ChatCompletionRequest{
+			Model: openai.GPT3Dot5Turbo,
+			Messages: []openai.ChatCompletionMessage{
 				{
-					Role:    ChatMessageRoleUser,
+					Role:    openai.ChatMessageRoleUser,
 					Name:    "John_Doe",
 					Content: "Hello!",
 				},
@@ -76,9 +77,9 @@ func TestAPI(t *testing.T) {
 	)
 	checks.NoError(t, err, "CreateChatCompletion (with name) returned error")
 
-	stream, err := c.CreateCompletionStream(ctx, CompletionRequest{
+	stream, err := c.CreateCompletionStream(ctx, openai.CompletionRequest{
 		Prompt:    "Ex falso quodlibet",
-		Model:     GPT3Ada,
+		Model:     openai.GPT3Ada,
 		MaxTokens: 5,
 		Stream:    true,
 	})
@@ -103,15 +104,15 @@ func TestAPI(t *testing.T) {
 
 	_, err = c.CreateChatCompletion(
 		context.Background(),
-		ChatCompletionRequest{
-			Model: GPT3Dot5Turbo,
-			Messages: []ChatCompletionMessage{
+		openai.ChatCompletionRequest{
+			Model: openai.GPT3Dot5Turbo,
+			Messages: []openai.ChatCompletionMessage{
 				{
-					Role:    ChatMessageRoleUser,
+					Role:    openai.ChatMessageRoleUser,
 					Content: "What is the weather like in Boston?",
 				},
 			},
-			Functions: []FunctionDefinition{{
+			Functions: []openai.FunctionDefinition{{
 				Name: "get_current_weather",
 				Parameters: jsonschema.Definition{
 					Type: jsonschema.Object,
@@ -140,12 +141,12 @@ func TestAPIError(t *testing.T) {
 	}
 
 	var err error
-	c := NewClient(apiToken + "_invalid")
+	c := openai.NewClient(apiToken + "_invalid")
 	ctx := context.Background()
 	_, err = c.ListEngines(ctx)
 	checks.HasError(t, err, "ListEngines should fail with an invalid key")
 
-	var apiErr *APIError
+	var apiErr *openai.APIError
 	if !errors.As(err, &apiErr) {
 		t.Fatalf("Error is not an APIError: %+v", err)
 	}
diff --git a/image_api_test.go b/image_api_test.go
index 422f831..2eb46f2 100644
--- a/image_api_test.go
+++ b/image_api_test.go
@@ -19,7 +19,14 @@ func TestImages(t *testing.T) {
 	defer teardown()
 	server.RegisterHandler("/v1/images/generations", handleImageEndpoint)
 	_, err := client.CreateImage(context.Background(), openai.ImageRequest{
-		Prompt: "Lorem ipsum",
+		Prompt:         "Lorem ipsum",
+		Model:          openai.CreateImageModelDallE3,
+		N:              1,
+		Quality:        openai.CreateImageQualityHD,
+		Size:           openai.CreateImageSize1024x1024,
+		Style:          openai.CreateImageStyleVivid,
+		ResponseFormat: openai.CreateImageResponseFormatURL,
+		User:           "user",
 	})
 	checks.NoError(t, err, "CreateImage error")
 }