diff --git a/workflow/model/dto/flow/flow_execution_dto.go b/workflow/model/dto/flow/flow_execution_dto.go index 2d79c3b..0bedc82 100644 --- a/workflow/model/dto/flow/flow_execution_dto.go +++ b/workflow/model/dto/flow/flow_execution_dto.go @@ -49,6 +49,7 @@ type GetModelInfoReq struct { type GetModelInfoRes struct { Model struct { + FirstFrame string `json:"firstFrame"` LastFrame string `json:"lastFrame"` ResponseTokenField string `json:"responseTokenField"` ResponseMapping map[string]any `json:"responseMapping"` diff --git a/workflow/service/flow/lambda_node.go b/workflow/service/flow/lambda_node.go index 48e4c8d..64b3115 100644 --- a/workflow/service/flow/lambda_node.go +++ b/workflow/service/flow/lambda_node.go @@ -11,6 +11,7 @@ import ( flowDto "ai-agent/workflow/model/dto/flow" "context" "fmt" + "path/filepath" "strconv" "strings" "sync" @@ -292,7 +293,23 @@ func VideoModelLambda(ctx context.Context, input any) (any, error) { } videoUrl = newS + msg.FileURL } else { - videoUrl = videoURL[0] + var bytes []byte + bytes, err = GetFileBytesFromURL(ctx, videoURL[0]) + if err != nil { + return nil, fmt.Errorf("下载图片失败: %w", err) + } + // 构造文件名 + fileName := fmt.Sprintf("ai_video_%d%s", time.Now().UnixMilli(), strings.ToLower(filepath.Ext(videoURL[0]))) + // 上传到你的OSS(你项目已有的Upload方法) + var upResp *dto.UploadFileBytesRes + upResp, err = Upload(ctx, &dto.UploadFileBytesReq{ + FileName: fileName, + FileBytes: bytes, + }) + if err != nil { + return nil, fmt.Errorf("上传OSS失败: %w", err) + } + videoUrl = upResp.FileURL } outputRes := make([]node.NodeFormField, 0) diff --git a/workflow/service/flow/lambda_node_imp.go b/workflow/service/flow/lambda_node_imp.go index 972310f..fc3eeb5 100644 --- a/workflow/service/flow/lambda_node_imp.go +++ b/workflow/service/flow/lambda_node_imp.go @@ -788,18 +788,41 @@ func VideoOptimizeNode(ctx context.Context, nodeInput *flowDto.NodeExecutionInpu } func DataConversionNode(ctx context.Context, nodeInput *flowDto.NodeExecutionInput, skillName string, form []map[string]any, userForm []map[string]any) ([]node.NodeFormField, error) { - if strings.Contains(nodeInput.Config.Name, "字幕") { + if strings.Contains(nodeInput.Config.Name, "字幕") || strings.Contains(nodeInput.Config.Name, "视频") { jsonStr := `` - for _, field := range nodeInput.Config.OutputConfig { - jsonStr, _ = sjson.Set(jsonStr, field.Field, field.Value) - } outputRes := make([]node.NodeFormField, 0) - outputRes = append(outputRes, node.NodeFormField{ - Field: fmt.Sprintf("data_conversion"), - Value: gconv.Map(jsonStr), - Label: fmt.Sprintf("data_conversion"), - Type: "string", - }) + for _, field := range nodeInput.Config.OutputConfig { + if strings.Contains(nodeInput.Config.Name, "视频") { + for _, item := range nodeInput.Global.ExecutedNodes { + refNode, ok := nodeInput.Global.ConfigMap[item.NodeId] + if !ok { + continue + } + for _, v := range refNode.FormConfig { + if v.Field == field.Value { + jsonStr, _ = sjson.Set(jsonStr, field.Field, v.Value) + } + } + } + } else { + jsonStr, _ = sjson.Set(jsonStr, field.Field, field.Value) + } + } + if strings.Contains(nodeInput.Config.Name, "视频") { + outputRes = append(outputRes, node.NodeFormField{ + Field: fmt.Sprintf("data_content"), + Value: gconv.Map(jsonStr), + Label: fmt.Sprintf("data_content"), + Type: "string", + }) + } else { + outputRes = append(outputRes, node.NodeFormField{ + Field: fmt.Sprintf("data_conversion"), + Value: gconv.Map(jsonStr), + Label: fmt.Sprintf("data_conversion"), + Type: "string", + }) + } return outputRes, nil } @@ -1035,7 +1058,7 @@ func GetNodeContextContent(execInput *flowDto.FlowExecutionInput, nodeEntity *en // 取指定字段 for _, f := range source.Field { for _, v := range refNode.FormConfig { - if strings.Contains(v.Label, f) { + if v.Label == f { input = append(input, v) } } diff --git a/workflow/service/flow/lambda_node_util.go b/workflow/service/flow/lambda_node_util.go index 142ac4d..6af2455 100644 --- a/workflow/service/flow/lambda_node_util.go +++ b/workflow/service/flow/lambda_node_util.go @@ -299,7 +299,22 @@ func GetModelResult(ctx context.Context, sessionId string, nodeInput *flowDto.No if !nodeInput.Global.IsDialogue { sessionId = "" } - + needSequential := false + for _, item := range userForm { + if g.NewVar(item).IsMap() { + valMap := gconv.Map(item) + for _, v := range valMap { + if g.NewVar(v).IsMap() { + vv := gconv.Map(v) + for kk, vvv := range vv { + if kk == "return_last_frame" { + needSequential = vvv.(bool) + } + } + } + } + } + } composeResult, err := GetComposeResult(ctx, buildType, nodeInput.Config.ModelConfig.ModelName, nodeInput.Config.PromptContent, skillName, form, userForm, nodeInput.Global.FileUrl, sessionId, nodeInput.Config.Id, nodeInput.Config.Name) if err != nil { return nil, err @@ -316,13 +331,12 @@ func GetModelResult(ctx context.Context, sessionId string, nodeInput *flowDto.No mapTaskResult = make([]map[string]any, len(composeResult.Messages.Rounds)) var taskResultMap map[string]any - needSequential := false if buildType == 1 { if needSequential { for idx, item := range composeResult.Messages.Rounds { if !g.IsEmpty(taskResultMap) { var set string - set, err = sjson.Set(gconv.String(item), modelInfo.Model.LastFrame, gconv.String(taskResultMap[modelInfo.Model.ResponseBody])) + set, err = sjson.Set(gconv.String(item), modelInfo.Model.FirstFrame, gconv.String(taskResultMap["content"])) if err != nil { return nil, err } @@ -339,7 +353,7 @@ func GetModelResult(ctx context.Context, sessionId string, nodeInput *flowDto.No } if nodeInput.Config.NodeCode == node.NodeTypeVideoModel { - ext := GetFileTypeByPath(gconv.String(taskResult[modelInfo.Model.ResponseBody])) + ext := GetFileTypeByPath(gconv.String(taskResult["content"])) if ext == "image" { taskResultMap = taskResult } else {