fix: align video generation payloads

This commit is contained in:
2026-05-14 00:14:54 +08:00
parent f254551522
commit 3225833f96
11 changed files with 702 additions and 188 deletions
+5
View File
@@ -131,6 +131,11 @@ func estimateRequestTokens(body map[string]any) int {
if input := stringFromMap(body, "input"); input != "" {
text += input
}
for _, item := range contentItems(body["content"]) {
if stringFromAny(item["type"]) == "text" {
text += stringFromAny(item["text"])
}
}
if messages, ok := body["messages"].([]any); ok {
for _, raw := range messages {
message, _ := raw.(map[string]any)
@@ -6,6 +6,50 @@ import (
"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)
func TestVideoModelTypeInferenceReadsContentArray(t *testing.T) {
imageToVideo := modelTypeFromKind("videos.generations", map[string]any{
"model": "demo-video",
"content": []any{
map[string]any{"type": "text", "text": "animate it"},
map[string]any{"type": "image_url", "role": "first_frame", "image_url": map[string]any{"url": "https://example.com/frame.png"}},
},
})
if imageToVideo != "image_to_video" {
t.Fatalf("image content should infer image_to_video, got %s", imageToVideo)
}
omniVideo := modelTypeFromKind("videos.generations", map[string]any{
"model": "demo-video",
"content": []any{
map[string]any{"type": "text", "text": "edit it"},
map[string]any{"type": "video_url", "role": "reference_video", "video_url": map[string]any{"url": "https://example.com/ref.mp4"}},
},
})
if omniVideo != "omni_video" {
t.Fatalf("video content should infer omni_video, got %s", omniVideo)
}
textToVideo := modelTypeFromKind("videos.generations", map[string]any{
"model": "demo-video",
"content": []any{map[string]any{"type": "text", "text": "make a clip"}},
})
if textToVideo != "video_generate" {
t.Fatalf("text-only content should infer video_generate, got %s", textToVideo)
}
}
func TestVideoContentTextContributesToTokenEstimate(t *testing.T) {
tokens := estimateRequestTokens(map[string]any{
"model": "demo-video",
"content": []any{
map[string]any{"type": "text", "text": "a cinematic product reveal"},
},
})
if tokens <= 1 {
t.Fatalf("content text should contribute to token estimate, got %d", tokens)
}
}
func TestParamProcessorOmniFiltersUnsupportedVideoAndAudioContent(t *testing.T) {
body := map[string]any{
"model": "可灵O1",
+15 -1
View File
@@ -86,7 +86,7 @@ func taskMetrics(task store.GatewayTask, user *auth.User, body map[string]any, c
copyIfPresent(metrics, body, "style")
case "videos.generations":
metrics["hasReferenceImage"] = imageInputCount(body) > 0
metrics["hasReferenceVideo"] = hasAnyString(body, "video", "video_url", "videoUrl", "reference_video", "referenceVideo")
metrics["hasReferenceVideo"] = hasAnyString(body, "video", "video_url", "videoUrl", "reference_video", "referenceVideo") || hasVideoContent(body)
copyIfPresent(metrics, body, "duration")
copyIfPresent(metrics, body, "resolution")
copyIfPresent(metrics, body, "size")
@@ -303,9 +303,23 @@ func imageInputCount(body map[string]any) int {
count += len(values)
}
}
for _, item := range contentItems(body["content"]) {
if isImageContent(item) {
count++
}
}
return count
}
func hasVideoContent(body map[string]any) bool {
for _, item := range contentItems(body["content"]) {
if isVideoContent(item) {
return true
}
}
return false
}
func hasAnyString(body map[string]any, keys ...string) bool {
for _, key := range keys {
if stringFromMap(body, key) != "" {
+5
View File
@@ -718,6 +718,11 @@ func videoRequestHasReferenceImage(body map[string]any) bool {
return true
}
}
for _, item := range contentItems(body["content"]) {
if isImageContent(item) {
return true
}
}
return false
}