feat: implement image editing request handling and response conversion for Imagen API

This commit is contained in:
Laisky.Cai
2025-03-16 14:21:38 +00:00
parent fa794e7bd5
commit 580fec6359
9 changed files with 363 additions and 80 deletions

View File

@@ -73,12 +73,12 @@ func convertImageRemixRequest(c *gin.Context) (any, error) {
}
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
rawReq := new(OpenaiImageEditRequest)
rawReq := new(model.OpenaiImageEditRequest)
if err := c.ShouldBind(rawReq); err != nil {
return nil, errors.Wrap(err, "parse image edit form")
}
return rawReq.toFluxRemixRequest()
return Convert2FluxRemixRequest(rawReq)
}
// ConvertRequest converts the request to the format that the target API expects.

View File

@@ -6,22 +6,12 @@ import (
"image"
"image/png"
"io"
"mime/multipart"
"time"
"github.com/pkg/errors"
"github.com/songquanpeng/one-api/relay/model"
)
type OpenaiImageEditRequest struct {
Image *multipart.FileHeader `json:"image" form:"image" binding:"required"`
Prompt string `json:"prompt" form:"prompt" binding:"required"`
Mask *multipart.FileHeader `json:"mask" form:"mask" binding:"required"`
Model string `json:"model" form:"model" binding:"required"`
N int `json:"n" form:"n" binding:"min=0,max=10"`
Size string `json:"size" form:"size"`
ResponseFormat string `json:"response_format" form:"response_format"`
}
// toFluxRemixRequest convert OpenAI's image edit request to Flux's remix request.
//
// Note that the mask formats of OpenAI and Flux are different:
@@ -31,14 +21,14 @@ type OpenaiImageEditRequest struct {
//
// Both OpenAI's Image and Mask are browser-native ImageData,
// which need to be converted to base64 dataURI format.
func (r *OpenaiImageEditRequest) toFluxRemixRequest() (*InpaintingImageByFlusReplicateRequest, error) {
if r.ResponseFormat != "b64_json" {
func Convert2FluxRemixRequest(req *model.OpenaiImageEditRequest) (*InpaintingImageByFlusReplicateRequest, error) {
if req.ResponseFormat != "b64_json" {
return nil, errors.New("response_format must be b64_json for replicate models")
}
fluxReq := &InpaintingImageByFlusReplicateRequest{
Input: FluxInpaintingInput{
Prompt: r.Prompt,
Prompt: req.Prompt,
Seed: int(time.Now().UnixNano()),
Steps: 30,
Guidance: 3,
@@ -48,7 +38,7 @@ func (r *OpenaiImageEditRequest) toFluxRemixRequest() (*InpaintingImageByFlusRep
},
}
imgFile, err := r.Image.Open()
imgFile, err := req.Image.Open()
if err != nil {
return nil, errors.Wrap(err, "open image file")
}
@@ -58,7 +48,7 @@ func (r *OpenaiImageEditRequest) toFluxRemixRequest() (*InpaintingImageByFlusRep
return nil, errors.Wrap(err, "read image file")
}
maskFile, err := r.Mask.Open()
maskFile, err := req.Mask.Open()
if err != nil {
return nil, errors.Wrap(err, "open mask file")
}

View File

@@ -10,6 +10,7 @@ import (
"net/http"
"testing"
"github.com/songquanpeng/one-api/relay/model"
"github.com/stretchr/testify/require"
)
@@ -50,7 +51,7 @@ func TestOpenaiImageEditRequest_toFluxRemixRequest(t *testing.T) {
maskFileHeader, err := createFileHeader("mask", "test.png", maskBuf.Bytes())
require.NoError(t, err)
req := &OpenaiImageEditRequest{
req := &model.OpenaiImageEditRequest{
Image: imgFileHeader,
Mask: maskFileHeader,
Prompt: "Test prompt",
@@ -58,7 +59,7 @@ func TestOpenaiImageEditRequest_toFluxRemixRequest(t *testing.T) {
ResponseFormat: "b64_json",
}
fluxReq, err := req.toFluxRemixRequest()
fluxReq, err := Convert2FluxRemixRequest(req)
require.NoError(t, err)
require.NotNil(t, fluxReq)
require.Equal(t, req.Prompt, fluxReq.Input.Prompt)