-
Notifications
You must be signed in to change notification settings - Fork 11.6k
即梦支持多图生视频 #1788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
即梦支持多图生视频 #1788
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -481,11 +481,20 @@ type TaskSubmitReq struct { | |
| Model string `json:"model,omitempty"` | ||
| Mode string `json:"mode,omitempty"` | ||
| Image string `json:"image,omitempty"` | ||
| Images []string `json:"images,omitempty"` | ||
| Size string `json:"size,omitempty"` | ||
| Duration int `json:"duration,omitempty"` | ||
| Metadata map[string]interface{} `json:"metadata,omitempty"` | ||
| } | ||
|
|
||
| func (t TaskSubmitReq) GetPrompt() string { | ||
| return t.Prompt | ||
| } | ||
|
|
||
| func (t TaskSubmitReq) HasImage() bool { | ||
| return len(t.Images) > 0 | ||
| } | ||
|
Comment on lines
+494
to
+496
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain
-func (t TaskSubmitReq) HasImage() bool {
- return len(t.Images) > 0
-}
+func (t TaskSubmitReq) HasImage() bool {
+ if len(t.Images) > 0 {
+ return true
+ }
+ return strings.TrimSpace(t.Image) != ""
+}🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "PWD: $(pwd)"
echo "---- locate TaskSubmitReq definition ----"
rg -n --hidden --no-ignore-vcs "type\s+TaskSubmitReq\b" -S || true
echo "---- show files defining TaskSubmitReq ----"
rg -n --hidden --no-ignore-vcs "type\s+TaskSubmitReq\b" -S | cut -d: -f1 | uniq | while read -r f; do
echo "=== $f ==="
sed -n '1,240p' "$f" || true
done
echo "---- relay/common/relay_info.go (lines 460-520) ----"
if [ -f relay/common/relay_info.go ]; then
sed -n '460,520p' relay/common/relay_info.go || true
else
rg -n --hidden --no-ignore-vcs "relay/common/relay_info.go" -S || true
fi
echo "---- HasImage implementations ----"
rg -n --hidden --no-ignore-vcs "func\s+\(t\s+\*?TaskSubmitReq\)\s+HasImage\s*\(" -S || true
echo "---- ValidateTaskRequestWithImageBinding occurrences ----"
rg -n --hidden --no-ignore-vcs "ValidateTaskRequestWithImageBinding" -S || true
echo "---- relay/common/relay_utils.go and image mentions ----"
if [ -f relay/common/relay_utils.go ]; then
sed -n '1,240p' relay/common/relay_utils.go || true
else
rg -n --hidden --no-ignore-vcs "relay_utils\.go" -S || true
fi
echo "---- search for Image / Images fields ----"
rg -n --hidden --no-ignore-vcs "\bImage(s)?\b" -S || trueLength of output: 17505 Merge legacy ValidateTaskRequestWithImageBinding uses c.ShouldBindJSON(&req) but does not copy req.Image → req.Images; TaskSubmitReq.HasImage only checks Images, so requests with only "image" are treated as no-image. Action: in relay/common/relay_utils.go, inside ValidateTaskRequestWithImageBinding (before calling ValidateTaskRequestWithImage), add the same compatibility block used in ValidateBasicTaskRequest: if len(req.Images) == 0 && strings.TrimSpace(req.Image) != "" { req.Images = []string{req.Image} }. 🤖 Prompt for AI Agents |
||
|
|
||
| type TaskInfo struct { | ||
| Code int `json:"code"` | ||
| TaskID string `json:"task_id"` | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,12 +2,23 @@ package common | |||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||
| "one-api/common" | ||||||||||||||||||||||||||||||||||||||
| "one-api/constant" | ||||||||||||||||||||||||||||||||||||||
| "one-api/dto" | ||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| "github.com/gin-gonic/gin" | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| type HasPrompt interface { | ||||||||||||||||||||||||||||||||||||||
| GetPrompt() string | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| type HasImage interface { | ||||||||||||||||||||||||||||||||||||||
| HasImage() bool | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func GetFullRequestURL(baseURL string, requestURL string, channelType int) string { | ||||||||||||||||||||||||||||||||||||||
| fullRequestURL := fmt.Sprintf("%s%s", baseURL, requestURL) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -30,3 +41,72 @@ func GetAPIVersion(c *gin.Context) string { | |||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return apiVersion | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func createTaskError(err error, code string, statusCode int, localError bool) *dto.TaskError { | ||||||||||||||||||||||||||||||||||||||
| return &dto.TaskError{ | ||||||||||||||||||||||||||||||||||||||
| Code: code, | ||||||||||||||||||||||||||||||||||||||
| Message: err.Error(), | ||||||||||||||||||||||||||||||||||||||
| StatusCode: statusCode, | ||||||||||||||||||||||||||||||||||||||
| LocalError: localError, | ||||||||||||||||||||||||||||||||||||||
| Error: err, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func storeTaskRequest(c *gin.Context, info *RelayInfo, action string, requestObj interface{}) { | ||||||||||||||||||||||||||||||||||||||
| info.Action = action | ||||||||||||||||||||||||||||||||||||||
| c.Set("task_request", requestObj) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func validatePrompt(prompt string) *dto.TaskError { | ||||||||||||||||||||||||||||||||||||||
| if strings.TrimSpace(prompt) == "" { | ||||||||||||||||||||||||||||||||||||||
| return createTaskError(fmt.Errorf("prompt is required"), "invalid_request", http.StatusBadRequest, true) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func ValidateBasicTaskRequest(c *gin.Context, info *RelayInfo, action string) *dto.TaskError { | ||||||||||||||||||||||||||||||||||||||
| var req TaskSubmitReq | ||||||||||||||||||||||||||||||||||||||
| if err := common.UnmarshalBodyReusable(c, &req); err != nil { | ||||||||||||||||||||||||||||||||||||||
| return createTaskError(err, "invalid_request", http.StatusBadRequest, true) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if taskErr := validatePrompt(req.Prompt); taskErr != nil { | ||||||||||||||||||||||||||||||||||||||
| return taskErr | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if len(req.Images) == 0 && strings.TrimSpace(req.Image) != "" { | ||||||||||||||||||||||||||||||||||||||
| // 兼容单图上传 | ||||||||||||||||||||||||||||||||||||||
| req.Images = []string{req.Image} | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| storeTaskRequest(c, info, action, req) | ||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func ValidateTaskRequestWithImage(c *gin.Context, info *RelayInfo, requestObj interface{}) *dto.TaskError { | ||||||||||||||||||||||||||||||||||||||
| hasPrompt, ok := requestObj.(HasPrompt) | ||||||||||||||||||||||||||||||||||||||
| if !ok { | ||||||||||||||||||||||||||||||||||||||
| return createTaskError(fmt.Errorf("request must have prompt"), "invalid_request", http.StatusBadRequest, true) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if taskErr := validatePrompt(hasPrompt.GetPrompt()); taskErr != nil { | ||||||||||||||||||||||||||||||||||||||
| return taskErr | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| action := constant.TaskActionTextGenerate | ||||||||||||||||||||||||||||||||||||||
| if hasImage, ok := requestObj.(HasImage); ok && hasImage.HasImage() { | ||||||||||||||||||||||||||||||||||||||
| action = constant.TaskActionGenerate | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| storeTaskRequest(c, info, action, requestObj) | ||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func ValidateTaskRequestWithImageBinding(c *gin.Context, info *RelayInfo) *dto.TaskError { | ||||||||||||||||||||||||||||||||||||||
| var req TaskSubmitReq | ||||||||||||||||||||||||||||||||||||||
| if err := c.ShouldBindJSON(&req); err != nil { | ||||||||||||||||||||||||||||||||||||||
| return createTaskError(err, "invalid_request_body", http.StatusBadRequest, false) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return ValidateTaskRequestWithImage(c, info, req) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+105
to
+112
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainFix Without this, adaptors using this path (e.g., vidu) misclassify requests and lose images. -func ValidateTaskRequestWithImageBinding(c *gin.Context, info *RelayInfo) *dto.TaskError {
- var req TaskSubmitReq
- if err := c.ShouldBindJSON(&req); err != nil {
- return createTaskError(err, "invalid_request_body", http.StatusBadRequest, false)
- }
-
- return ValidateTaskRequestWithImage(c, info, req)
-}
+func ValidateTaskRequestWithImageBinding(c *gin.Context, info *RelayInfo) *dto.TaskError {
+ var req TaskSubmitReq
+ if err := common.UnmarshalBodyReusable(c, &req); err != nil {
+ return createTaskError(err, "invalid_request", http.StatusBadRequest, true)
+ }
+ if len(req.Images) == 0 && strings.TrimSpace(req.Image) != "" {
+ req.Images = []string{req.Image}
+ }
+ return ValidateTaskRequestWithImage(c, info, req)
+}🏁 Script executed: #!/bin/bash
set -euo pipefail
printf "=== rg: ValidateTaskRequestWithImageBinding ===\n"
rg -n --hidden --no-ignore "ValidateTaskRequestWithImageBinding" -S || true
printf "\n=== show: relay/common/relay_utils.go (first 240 lines) ===\n"
if [ -f relay/common/relay_utils.go ]; then
sed -n '1,240p' relay/common/relay_utils.go || true
else
printf "relay/common/relay_utils.go not found\n"
fi
printf "\n=== rg: TaskSubmitReq definition ===\n"
rg -n --hidden --no-ignore "type\\s+TaskSubmitReq" -S || true
printf "\n=== rg: occurrences of TaskSubmitReq ===\n"
rg -n --hidden --no-ignore "TaskSubmitReq" -S || true
printf "\n=== rg: UnmarshalBodyReusable ===\n"
rg -n --hidden --no-ignore "UnmarshalBodyReusable" -S || true
printf "\n=== rg: createTaskError definition ===\n"
rg -n --hidden --no-ignore "func\\s+createTaskError" -S || true
printf "\n=== rg: ValidateTaskRequestWithImage definition ===\n"
rg -n --hidden --no-ignore "func\\s+ValidateTaskRequestWithImage" -S || trueLength of output: 7308 Fix ValidateTaskRequestWithImageBinding: use UnmarshalBodyReusable and merge single Mirror ValidateBasicTaskRequest (use common.UnmarshalBodyReusable and preserve single-image compatibility) — current ShouldBindJSON loses images for adaptors like vidu. Location: relay/common/relay_utils.go:105-112 -func ValidateTaskRequestWithImageBinding(c *gin.Context, info *RelayInfo) *dto.TaskError {
- var req TaskSubmitReq
- if err := c.ShouldBindJSON(&req); err != nil {
- return createTaskError(err, "invalid_request_body", http.StatusBadRequest, false)
- }
-
- return ValidateTaskRequestWithImage(c, info, req)
-}
+func ValidateTaskRequestWithImageBinding(c *gin.Context, info *RelayInfo) *dto.TaskError {
+ var req TaskSubmitReq
+ if err := common.UnmarshalBodyReusable(c, &req); err != nil {
+ return createTaskError(err, "invalid_request", http.StatusBadRequest, true)
+ }
+ if len(req.Images) == 0 && strings.TrimSpace(req.Image) != "" {
+ req.Images = []string{req.Image}
+ }
+ return ValidateTaskRequestWithImage(c, info, req)
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Validator path can misclassify image requests when only
imageis provided.ValidateTaskRequestWithImageBindingdoesn’t mergeimage->images, so action may be set to text-generation incorrectly. Either switch toValidateBasicTaskRequestor fix the validator (see relay/common/relay_utils.go). If you keep this path, ensure convert usesreq.Images.🏁 Script executed:
Length of output: 17116
Validator misclassifies single-image requests — merge image->images or switch validator
ValidateTaskRequestWithImageBinding binds into TaskSubmitReq but does not copy TaskSubmitReq.Image -> TaskSubmitReq.Images (ValidateBasicTaskRequest does), so HasImage() can be false when only "image" is provided and info.Action becomes text-generation — causing vidu to pick /text2video while the body contains images.
if len(req.Images) == 0 && strings.TrimSpace(req.Image) != "" {
req.Images = []string{req.Image}
}
Files: relay/common/relay_utils.go (ValidateTaskRequestWithImageBinding), relay/channel/task/vidu/adaptor.go (ValidateRequestAndSetAction).