From b3784b053d3ceeb280b230e0f306a66d13441650 Mon Sep 17 00:00:00 2001 From: lnk Date: Mon, 26 May 2025 15:32:11 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E4=BC=A0=E5=A4=9A=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- image.go | 28 +++++++++++++++------------- image_api_test.go | 4 ++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/image.go b/image.go index 72077ce41..d4fa5cf09 100644 --- a/image.go +++ b/image.go @@ -134,15 +134,15 @@ func (c *Client) CreateImage(ctx context.Context, request ImageRequest) (respons // ImageEditRequest represents the request structure for the image API. type ImageEditRequest struct { - Image io.Reader `json:"image,omitempty"` - Mask io.Reader `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"` - Quality string `json:"quality,omitempty"` - User string `json:"user,omitempty"` + Image []io.Reader `json:"image,omitempty"` + Mask io.Reader `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"` + Quality string `json:"quality,omitempty"` + User string `json:"user,omitempty"` } // CreateEditImage - API call to create an image. This is the main endpoint of the DALL-E API. @@ -150,10 +150,12 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) body := &bytes.Buffer{} builder := c.createFormBuilder(body) - // image, filename is not required - err = builder.CreateFormFileReader("image", request.Image, "") - if err != nil { - return + for _, img := range request.Image { + // image, filename is not required + err = builder.CreateFormFileReader("image", img, "") + if err != nil { + return + } } // mask, it is optional diff --git a/image_api_test.go b/image_api_test.go index f6057b77d..6ae25d78c 100644 --- a/image_api_test.go +++ b/image_api_test.go @@ -100,7 +100,7 @@ func TestImageEdit(t *testing.T) { defer mask.Close() _, err = client.CreateEditImage(context.Background(), openai.ImageEditRequest{ - Image: origin, + Image: []io.Reader{origin}, Mask: mask, Prompt: "There is a turtle in the pool", N: 3, @@ -122,7 +122,7 @@ func TestImageEditWithoutMask(t *testing.T) { defer origin.Close() _, err = client.CreateEditImage(context.Background(), openai.ImageEditRequest{ - Image: origin, + Image: []io.Reader{origin}, Prompt: "There is a turtle in the pool", N: 3, Size: openai.CreateImageSize1024x1024, From 1ed6304a142b472ae5da927c7a3511aea333a1f7 Mon Sep 17 00:00:00 2001 From: lnk Date: Tue, 27 May 2025 16:07:57 +0800 Subject: [PATCH 2/5] images --- image.go | 4 ++-- image_api_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/image.go b/image.go index d4fa5cf09..624c957c5 100644 --- a/image.go +++ b/image.go @@ -134,7 +134,7 @@ func (c *Client) CreateImage(ctx context.Context, request ImageRequest) (respons // ImageEditRequest represents the request structure for the image API. type ImageEditRequest struct { - Image []io.Reader `json:"image,omitempty"` + Images []io.Reader `json:"images,omitempty"` Mask io.Reader `json:"mask,omitempty"` Prompt string `json:"prompt,omitempty"` Model string `json:"model,omitempty"` @@ -150,7 +150,7 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) body := &bytes.Buffer{} builder := c.createFormBuilder(body) - for _, img := range request.Image { + for _, img := range request.Images { // image, filename is not required err = builder.CreateFormFileReader("image", img, "") if err != nil { diff --git a/image_api_test.go b/image_api_test.go index 6ae25d78c..1041b9430 100644 --- a/image_api_test.go +++ b/image_api_test.go @@ -100,7 +100,7 @@ func TestImageEdit(t *testing.T) { defer mask.Close() _, err = client.CreateEditImage(context.Background(), openai.ImageEditRequest{ - Image: []io.Reader{origin}, + Images: []io.Reader{origin}, Mask: mask, Prompt: "There is a turtle in the pool", N: 3, @@ -122,7 +122,7 @@ func TestImageEditWithoutMask(t *testing.T) { defer origin.Close() _, err = client.CreateEditImage(context.Background(), openai.ImageEditRequest{ - Image: []io.Reader{origin}, + Images: []io.Reader{origin}, Prompt: "There is a turtle in the pool", N: 3, Size: openai.CreateImageSize1024x1024, From d00fd4e1742cb12295811caffdd673a9e941f6f9 Mon Sep 17 00:00:00 2001 From: lnk Date: Wed, 28 May 2025 18:37:39 +0800 Subject: [PATCH 3/5] support azure images/edits --- client.go | 2 ++ image.go | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/client.go b/client.go index cef375348..3d34434bc 100644 --- a/client.go +++ b/client.go @@ -250,6 +250,8 @@ var azureDeploymentsEndpoints = []string{ "/audio/translations", "/audio/speech", "/images/generations", + "/images/edits", + "/images/variations", } // fullURL returns full URL for request. diff --git a/image.go b/image.go index 624c957c5..5e75ceecb 100644 --- a/image.go +++ b/image.go @@ -3,6 +3,7 @@ package openai import ( "bytes" "context" + "fmt" "io" "net/http" "strconv" @@ -150,9 +151,23 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) body := &bytes.Buffer{} builder := c.createFormBuilder(body) - for _, img := range request.Images { + for i, img := range request.Images { // image, filename is not required - err = builder.CreateFormFileReader("image", img, "") + // 判断文件类型 + var data []byte + data, err = io.ReadAll(img) + if err != nil { + return + } + fileType := http.DetectContentType(data) + if len(fileType) < 6 { + err = fmt.Errorf("invalid file type: %s", fileType) + return + } + // 截取文件类型后缀 + ext := fileType[6:] + filename := fmt.Sprintf("%d.%s", i, ext) + err = builder.CreateFormFileReader("image", img, filename) if err != nil { return } @@ -182,9 +197,11 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) return } - err = builder.WriteField("response_format", request.ResponseFormat) - if err != nil { - return + if request.ResponseFormat != "" { + err = builder.WriteField("response_format", request.ResponseFormat) + if err != nil { + return + } } err = builder.Close() From 9037d6097ed9bec38475ecd323da0d6cd4afd9a6 Mon Sep 17 00:00:00 2001 From: lnk Date: Wed, 28 May 2025 18:40:26 +0800 Subject: [PATCH 4/5] support azure images/edits --- image.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/image.go b/image.go index 5e75ceecb..7657ee085 100644 --- a/image.go +++ b/image.go @@ -152,8 +152,7 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) builder := c.createFormBuilder(body) for i, img := range request.Images { - // image, filename is not required - // 判断文件类型 + // judge file type var data []byte data, err = io.ReadAll(img) if err != nil { @@ -164,7 +163,7 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) err = fmt.Errorf("invalid file type: %s", fileType) return } - // 截取文件类型后缀 + // get file extension ext := fileType[6:] filename := fmt.Sprintf("%d.%s", i, ext) err = builder.CreateFormFileReader("image", img, filename) From 890560b84a52e85e7c3ed33aad1603e315914fbd Mon Sep 17 00:00:00 2001 From: lnk Date: Wed, 28 May 2025 20:00:41 +0800 Subject: [PATCH 5/5] minFileTypeLength --- image.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/image.go b/image.go index 7657ee085..b38f6b0cf 100644 --- a/image.go +++ b/image.go @@ -70,6 +70,10 @@ const ( CreateImageOutputFormatWEBP = "webp" ) +const ( + minFileTypeLength = 6 // "image/" +) + // ImageRequest represents the request structure for the image API. type ImageRequest struct { Prompt string `json:"prompt,omitempty"` @@ -159,12 +163,12 @@ func (c *Client) CreateEditImage(ctx context.Context, request ImageEditRequest) return } fileType := http.DetectContentType(data) - if len(fileType) < 6 { + if len(fileType) < minFileTypeLength { err = fmt.Errorf("invalid file type: %s", fileType) return } // get file extension - ext := fileType[6:] + ext := fileType[minFileTypeLength:] filename := fmt.Sprintf("%d.%s", i, ext) err = builder.CreateFormFileReader("image", img, filename) if err != nil {