2024-02-29 16:21:25 +08:00
|
|
|
|
package dto
|
|
|
|
|
|
|
2025-08-14 20:05:06 +08:00
|
|
|
|
import (
|
|
|
|
|
|
"encoding/json"
|
2025-08-25 14:33:12 +08:00
|
|
|
|
"reflect"
|
2025-08-14 20:05:06 +08:00
|
|
|
|
"strings"
|
|
|
|
|
|
|
2025-10-11 15:30:09 +08:00
|
|
|
|
"github.com/QuantumNous/new-api/common"
|
|
|
|
|
|
"github.com/QuantumNous/new-api/types"
|
|
|
|
|
|
|
2025-08-14 20:05:06 +08:00
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
)
|
2025-04-18 19:36:18 +08:00
|
|
|
|
|
2024-02-29 16:21:25 +08:00
|
|
|
|
type ImageRequest struct {
|
2025-08-15 13:46:34 +08:00
|
|
|
|
Model string `json:"model"`
|
|
|
|
|
|
Prompt string `json:"prompt" binding:"required"`
|
|
|
|
|
|
N uint `json:"n,omitempty"`
|
2025-08-23 13:12:15 +08:00
|
|
|
|
Size string `json:"size,omitempty"`
|
|
|
|
|
|
Quality string `json:"quality,omitempty"`
|
|
|
|
|
|
ResponseFormat string `json:"response_format,omitempty"`
|
|
|
|
|
|
Style json.RawMessage `json:"style,omitempty"`
|
2025-08-15 13:46:34 +08:00
|
|
|
|
User json.RawMessage `json:"user,omitempty"`
|
|
|
|
|
|
ExtraFields json.RawMessage `json:"extra_fields,omitempty"`
|
|
|
|
|
|
Background json.RawMessage `json:"background,omitempty"`
|
|
|
|
|
|
Moderation json.RawMessage `json:"moderation,omitempty"`
|
|
|
|
|
|
OutputFormat json.RawMessage `json:"output_format,omitempty"`
|
|
|
|
|
|
OutputCompression json.RawMessage `json:"output_compression,omitempty"`
|
|
|
|
|
|
PartialImages json.RawMessage `json:"partial_images,omitempty"`
|
|
|
|
|
|
// Stream bool `json:"stream,omitempty"`
|
|
|
|
|
|
Watermark *bool `json:"watermark,omitempty"`
|
2025-08-24 21:52:56 +08:00
|
|
|
|
// 用匿名参数接收额外参数
|
|
|
|
|
|
Extra map[string]json.RawMessage `json:"-"`
|
2024-02-29 16:21:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 14:33:12 +08:00
|
|
|
|
func (i *ImageRequest) UnmarshalJSON(data []byte) error {
|
|
|
|
|
|
// 先解析成 map[string]interface{}
|
|
|
|
|
|
var rawMap map[string]json.RawMessage
|
|
|
|
|
|
if err := common.Unmarshal(data, &rawMap); err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 用 struct tag 获取所有已定义字段名
|
|
|
|
|
|
knownFields := GetJSONFieldNames(reflect.TypeOf(*i))
|
|
|
|
|
|
|
|
|
|
|
|
// 再正常解析已定义字段
|
|
|
|
|
|
type Alias ImageRequest
|
|
|
|
|
|
var known Alias
|
|
|
|
|
|
if err := common.Unmarshal(data, &known); err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
*i = ImageRequest(known)
|
|
|
|
|
|
|
|
|
|
|
|
// 提取多余字段
|
|
|
|
|
|
i.Extra = make(map[string]json.RawMessage)
|
|
|
|
|
|
for k, v := range rawMap {
|
|
|
|
|
|
if _, ok := knownFields[k]; !ok {
|
|
|
|
|
|
i.Extra[k] = v
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 15:29:07 +08:00
|
|
|
|
// 序列化时需要重新把字段平铺
|
|
|
|
|
|
func (r ImageRequest) MarshalJSON() ([]byte, error) {
|
|
|
|
|
|
// 将已定义字段转为 map
|
|
|
|
|
|
type Alias ImageRequest
|
|
|
|
|
|
alias := Alias(r)
|
2025-09-11 12:28:57 +08:00
|
|
|
|
base, err := common.Marshal(alias)
|
2025-09-10 15:29:07 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var baseMap map[string]json.RawMessage
|
2025-09-11 12:28:57 +08:00
|
|
|
|
if err := common.Unmarshal(base, &baseMap); err != nil {
|
2025-09-10 15:29:07 +08:00
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-03 12:44:33 +08:00
|
|
|
|
// 不能合并ExtraFields!!!!!!!!
|
2025-09-10 15:29:07 +08:00
|
|
|
|
// 合并 ExtraFields
|
2025-10-03 12:44:33 +08:00
|
|
|
|
//for k, v := range r.Extra {
|
|
|
|
|
|
// if _, exists := baseMap[k]; !exists {
|
|
|
|
|
|
// baseMap[k] = v
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2025-09-10 15:29:07 +08:00
|
|
|
|
|
2025-10-03 12:44:33 +08:00
|
|
|
|
return common.Marshal(baseMap)
|
2025-09-10 15:29:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 14:33:12 +08:00
|
|
|
|
func GetJSONFieldNames(t reflect.Type) map[string]struct{} {
|
|
|
|
|
|
fields := make(map[string]struct{})
|
|
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
|
|
|
field := t.Field(i)
|
|
|
|
|
|
|
|
|
|
|
|
// 跳过匿名字段(例如 ExtraFields)
|
|
|
|
|
|
if field.Anonymous {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tag := field.Tag.Get("json")
|
|
|
|
|
|
if tag == "-" || tag == "" {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 取逗号前字段名(排除 omitempty 等)
|
|
|
|
|
|
name := tag
|
|
|
|
|
|
if commaIdx := indexComma(tag); commaIdx != -1 {
|
|
|
|
|
|
name = tag[:commaIdx]
|
|
|
|
|
|
}
|
|
|
|
|
|
fields[name] = struct{}{}
|
|
|
|
|
|
}
|
|
|
|
|
|
return fields
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func indexComma(s string) int {
|
|
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
|
|
if s[i] == ',' {
|
|
|
|
|
|
return i
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return -1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-14 20:05:06 +08:00
|
|
|
|
func (i *ImageRequest) GetTokenCountMeta() *types.TokenCountMeta {
|
|
|
|
|
|
var sizeRatio = 1.0
|
|
|
|
|
|
var qualityRatio = 1.0
|
|
|
|
|
|
|
|
|
|
|
|
if strings.HasPrefix(i.Model, "dall-e") {
|
|
|
|
|
|
// Size
|
|
|
|
|
|
if i.Size == "256x256" {
|
|
|
|
|
|
sizeRatio = 0.4
|
|
|
|
|
|
} else if i.Size == "512x512" {
|
|
|
|
|
|
sizeRatio = 0.45
|
|
|
|
|
|
} else if i.Size == "1024x1024" {
|
|
|
|
|
|
sizeRatio = 1
|
|
|
|
|
|
} else if i.Size == "1024x1792" || i.Size == "1792x1024" {
|
|
|
|
|
|
sizeRatio = 2
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if i.Model == "dall-e-3" && i.Quality == "hd" {
|
|
|
|
|
|
qualityRatio = 2.0
|
|
|
|
|
|
if i.Size == "1024x1792" || i.Size == "1792x1024" {
|
|
|
|
|
|
qualityRatio = 1.5
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// not support token count for dalle
|
|
|
|
|
|
return &types.TokenCountMeta{
|
|
|
|
|
|
CombineText: i.Prompt,
|
|
|
|
|
|
MaxTokens: 1584,
|
|
|
|
|
|
ImagePriceRatio: sizeRatio * qualityRatio * float64(i.N),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (i *ImageRequest) IsStream(c *gin.Context) bool {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-23 13:12:15 +08:00
|
|
|
|
func (i *ImageRequest) SetModelName(modelName string) {
|
|
|
|
|
|
if modelName != "" {
|
|
|
|
|
|
i.Model = modelName
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-02-29 16:21:25 +08:00
|
|
|
|
type ImageResponse struct {
|
2024-07-19 00:45:52 +08:00
|
|
|
|
Data []ImageData `json:"data"`
|
|
|
|
|
|
Created int64 `json:"created"`
|
2025-08-24 21:52:56 +08:00
|
|
|
|
Extra any `json:"extra,omitempty"`
|
2024-07-19 00:45:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
type ImageData struct {
|
|
|
|
|
|
Url string `json:"url"`
|
|
|
|
|
|
B64Json string `json:"b64_json"`
|
|
|
|
|
|
RevisedPrompt string `json:"revised_prompt"`
|
2024-02-29 16:21:25 +08:00
|
|
|
|
}
|