fix: 兼容像素分辨率参数
This commit is contained in:
parent
97f29ed156
commit
a8fa8dd212
@ -207,6 +207,14 @@ func (imageSizeProcessor) Process(params map[string]any, modelType string, conte
|
||||
width, height = constrainImageDimensions(width, height, capability)
|
||||
params["width"] = width
|
||||
params["height"] = height
|
||||
if stringFromAny(params["aspect_ratio"]) == "" {
|
||||
aspectRatio := aspectRatioFromDimensions(width, height)
|
||||
allowed := aspectRatioAllowed(capability["aspect_ratio_allowed"], firstNonEmptyString(stringFromAny(params["resolution"]), context.resolution))
|
||||
if processed, ok := validateAndAdjustAspectRatio(aspectRatio, capability, allowed); ok && processed != "" {
|
||||
params["aspect_ratio"] = processed
|
||||
context.aspectRatio = processed
|
||||
}
|
||||
}
|
||||
resolution := normalizeImageResolutionForCapability(firstNonEmptyString(stringFromAny(params["resolution"]), context.resolution), width, height, capability)
|
||||
if resolution != "" {
|
||||
params["resolution"] = resolution
|
||||
@ -248,7 +256,10 @@ func imageDimensionsFromParams(params map[string]any) (int, int, bool) {
|
||||
if width > 0 && height > 0 {
|
||||
return width, height, true
|
||||
}
|
||||
return parsePixelSizeString(stringFromAny(params["size"]))
|
||||
if width, height, ok := parsePixelSizeString(stringFromAny(params["size"])); ok {
|
||||
return width, height, true
|
||||
}
|
||||
return parsePixelSizeString(stringFromAny(params["resolution"]))
|
||||
}
|
||||
|
||||
func imageSizeCapabilityConfigured(capability map[string]any) bool {
|
||||
@ -431,6 +442,30 @@ func imageResolutionFromDimensions(width int, height int) string {
|
||||
}
|
||||
}
|
||||
|
||||
func aspectRatioFromDimensions(width int, height int) string {
|
||||
if width <= 0 || height <= 0 {
|
||||
return ""
|
||||
}
|
||||
divisor := gcd(width, height)
|
||||
return fmt.Sprintf("%d:%d", width/divisor, height/divisor)
|
||||
}
|
||||
|
||||
func gcd(a int, b int) int {
|
||||
if a < 0 {
|
||||
a = -a
|
||||
}
|
||||
if b < 0 {
|
||||
b = -b
|
||||
}
|
||||
for b != 0 {
|
||||
a, b = b, a%b
|
||||
}
|
||||
if a == 0 {
|
||||
return 1
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func closestImageResolution(target string, allowed []string) string {
|
||||
order := []string{"1K", "2K", "3K", "4K", "8K"}
|
||||
targetIndex := indexOfString(order, target)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
|
||||
@ -699,6 +700,65 @@ func TestParamProcessorImageSizeConstraintsNormalizeExplicitDimensions(t *testin
|
||||
t.Fatalf("expected image size preprocessing log against output_size_range, got %+v", result.Log.Changes)
|
||||
}
|
||||
|
||||
func TestParamProcessorImageSizeConstraintsAcceptPixelResolutionStrings(t *testing.T) {
|
||||
candidate := store.RuntimeModelCandidate{
|
||||
ModelType: "image_generate",
|
||||
Capabilities: map[string]any{
|
||||
"image_generate": map[string]any{
|
||||
"output_resolutions": []any{"1K", "2K", "4K"},
|
||||
"aspect_ratio_allowed": []any{
|
||||
"1:1",
|
||||
"16:9",
|
||||
"9:16",
|
||||
},
|
||||
"output_size_range": []any{655360, 8294400},
|
||||
"width_height_range": []any{1, 3840},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, body := range map[string]map[string]any{
|
||||
"resolution": {
|
||||
"model": "gpt-image-2",
|
||||
"prompt": "draw",
|
||||
"resolution": "3840x2160",
|
||||
},
|
||||
"size": {
|
||||
"model": "gpt-image-2",
|
||||
"prompt": "draw",
|
||||
"size": "3840x2160",
|
||||
},
|
||||
"non-standard-resolution": {
|
||||
"model": "gpt-image-2",
|
||||
"prompt": "draw",
|
||||
"resolution": "3600x1900",
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
processed := preprocessRequest("images.generations", body, candidate)
|
||||
expectedWidth := 3840
|
||||
expectedHeight := 2160
|
||||
if name == "non-standard-resolution" {
|
||||
expectedWidth = 3600
|
||||
expectedHeight = 1900
|
||||
}
|
||||
if processed["width"] != expectedWidth || processed["height"] != expectedHeight {
|
||||
t.Fatalf("pixel resolution string should populate width/height, got %+v", processed)
|
||||
}
|
||||
if processed["aspect_ratio"] != "16:9" {
|
||||
t.Fatalf("pixel resolution string should infer aspect_ratio, got %+v", processed)
|
||||
}
|
||||
if processed["resolution"] != "4K" {
|
||||
t.Fatalf("pixel resolution string should normalize resolution to allowed bucket, got %+v", processed)
|
||||
}
|
||||
expectedSize := fmt.Sprintf("%dx%d", expectedWidth, expectedHeight)
|
||||
if processed["size"] != expectedSize {
|
||||
t.Fatalf("size should stay synchronized with normalized width/height, got %+v", processed)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParamProcessorImageSizeConstraintsNormalizeEditDimensions(t *testing.T) {
|
||||
body := map[string]any{
|
||||
"model": "gpt-image-2",
|
||||
|
||||
@ -29,7 +29,7 @@ func validateAndAdjustAspectRatio(aspectRatio string, capability map[string]any,
|
||||
if containsString(allowed, aspectRatio) {
|
||||
return aspectRatio, true
|
||||
}
|
||||
return allowed[0], true
|
||||
return closestAspectRatio(aspectRatio, allowed), true
|
||||
}
|
||||
|
||||
func isMediaModelTypeWithAspectRatio(capability map[string]any) bool {
|
||||
@ -445,6 +445,33 @@ func adjustAspectRatioToRange(value string, minValue float64, maxValue float64,
|
||||
return ratioString(maxValue)
|
||||
}
|
||||
|
||||
func closestAspectRatio(value string, allowed []string) string {
|
||||
if len(allowed) == 0 {
|
||||
return value
|
||||
}
|
||||
current, ok := aspectRatioNumber(value)
|
||||
if !ok {
|
||||
return allowed[0]
|
||||
}
|
||||
closest := ""
|
||||
minDiff := math.Inf(1)
|
||||
for _, candidate := range allowed {
|
||||
ratio, ok := aspectRatioNumber(candidate)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
diff := math.Abs(ratio - current)
|
||||
if diff < minDiff {
|
||||
minDiff = diff
|
||||
closest = candidate
|
||||
}
|
||||
}
|
||||
if closest != "" {
|
||||
return closest
|
||||
}
|
||||
return allowed[0]
|
||||
}
|
||||
|
||||
func ratioString(value float64) string {
|
||||
if value <= 0 {
|
||||
return "1:1"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user