feat: 新增主动拉取与多类型回调功能
- 新增 ActivePull 实体、DAO、DTO 及 Service,支持主动拉取任务管理 - 新增 ComposeCallback、VideoCallback、HttpNodeCallback 多类型回调接口 - FlowExecution 增加 NodeGroupId 和 TotalTokens 字段,支持节点组追踪与 Token 统计 - ExecutedNodes 结构由字符串列表改为包含执行状态的节点对象列表 - 重构回调通知机制,统一 Notify 函数调用 - 优化输出项类型判断逻辑,新增文件类型标识
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
@@ -58,7 +59,6 @@ func JudgeLambda(ctx context.Context, input any) (string, error) {
|
||||
outputResult = append(outputResult, field)
|
||||
}
|
||||
}
|
||||
|
||||
contextParts := ""
|
||||
for _, v := range nodeInput.Config.FormConfig {
|
||||
contextParts = fmt.Sprintf("%s,%s:%s", contextParts, v.Label, v.Value)
|
||||
@@ -68,51 +68,128 @@ func JudgeLambda(ctx context.Context, input any) (string, error) {
|
||||
contextParts = fmt.Sprintf("%s,%s:%s", contextParts, v.Label, v.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if !g.IsEmpty(nodeInput.Global.Desc) {
|
||||
contextParts = fmt.Sprintf("%s,%s:%s", contextParts, "描述", nodeInput.Global.Desc)
|
||||
}
|
||||
configMap := gconv.Map(nodeInput.Config.Config)
|
||||
ids := gconv.Strings(configMap["branch_ids"])
|
||||
branchIdNameMap := gconv.Map(configMap["branch_id_name_map"])
|
||||
|
||||
// 【重构】构建提示词:展示ID和对应的名称
|
||||
var branchIdNameLines []string
|
||||
for _, id := range ids {
|
||||
name := gconv.String(branchIdNameMap[id])
|
||||
branchIdNameLines = append(branchIdNameLines, fmt.Sprintf("%s: %s", id, name))
|
||||
}
|
||||
|
||||
getIsChatModel, err := GetIsChatModel(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req := flowDto.ComposeMessagesReq{
|
||||
BuildType: 2,
|
||||
ModelName: getIsChatModel.ModelName,
|
||||
SkillName: "",
|
||||
Cause: "判断节点",
|
||||
Form: map[string]any{"prompt": strings.Join(branchIdNameLines, "\n")},
|
||||
UserForm: map[string]any{"prompt": contextParts},
|
||||
UserFiles: nodeInput.Global.FileUrl,
|
||||
SessionId: nodeInput.Global.SessionId,
|
||||
}
|
||||
msg, err := ComposeMessages(ctx, &req)
|
||||
composeResult, err := GetComposeResult(ctx, 2, getIsChatModel.Model.ModelName, "", "", []map[string]any{{"prompt": strings.Join(branchIdNameLines, "\n")}}, []map[string]any{{"prompt": contextParts}}, nodeInput.Global.FileUrl, nodeInput.Global.SessionId, nodeInput.Config.Id, "判断节点")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if g.IsEmpty(msg.Messages) {
|
||||
if g.IsEmpty(composeResult.TaskId) {
|
||||
return "", fmt.Errorf("msg is empty")
|
||||
}
|
||||
|
||||
content := ""
|
||||
for key, _ := range getIsChatModel.ResponseBody {
|
||||
content = gconv.String(msg.Messages[key])
|
||||
for key, _ := range getIsChatModel.Model.ResponseBody {
|
||||
content = gconv.String(composeResult.Messages.Rounds[0][key])
|
||||
}
|
||||
fmt.Printf("JudgeLambda路由:目标节点ID=%s\n", gconv.String(content))
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func BatchModelLambda(ctx context.Context, input any) (any, error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
skillName, from, userFrom := BuildParam(nodeInput)
|
||||
reqMap := make([]map[string]any, 0)
|
||||
for _, userItem := range userFrom {
|
||||
m := gconv.Map(userItem)
|
||||
for _, i := range nodeInput.Config.InputSource {
|
||||
for _, f := range i.Field {
|
||||
val := m[f]
|
||||
if !g.IsEmpty(val) {
|
||||
if g.NewVar(val).IsSlice() {
|
||||
slice := gconv.SliceAny(val)
|
||||
for _, item := range slice {
|
||||
reqMap = append(reqMap, map[string]any{f: item})
|
||||
}
|
||||
} else {
|
||||
reqMap = append(reqMap, map[string]any{f: val})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 结果按索引存放,保证顺序
|
||||
res := make([][]node.NodeFormField, len(reqMap))
|
||||
var wg sync.WaitGroup
|
||||
// 用一个通道标记是否完成
|
||||
done := make(chan struct{})
|
||||
// 错误只存一个
|
||||
var execErr error
|
||||
|
||||
// 并发执行
|
||||
for idx, item := range reqMap {
|
||||
wg.Add(1)
|
||||
go func(idx int, userItem map[string]any) {
|
||||
defer wg.Done()
|
||||
|
||||
singleUserFrom := []map[string]any{userItem}
|
||||
output, err := TextNode(ctx, nodeInput, skillName, from, singleUserFrom)
|
||||
if err != nil {
|
||||
// 并发安全赋值错误
|
||||
if execErr == nil {
|
||||
execErr = err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 直接按原索引写,顺序绝对正确
|
||||
res[idx] = output
|
||||
}(idx, item)
|
||||
}
|
||||
|
||||
fmt.Printf("JudgeLambda路由:目标节点ID=%s\n", gconv.String(content))
|
||||
// 后台等待所有协程完成,然后关闭 done 通道
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
return content, nil
|
||||
// 等待全部完成
|
||||
<-done
|
||||
|
||||
// 如果有错误,直接返回
|
||||
if execErr != nil {
|
||||
return nil, execErr
|
||||
}
|
||||
|
||||
// 全局自增 i
|
||||
var globalIndex int
|
||||
var outputRes []node.NodeFormField
|
||||
for _, items := range res {
|
||||
for _, item := range items {
|
||||
// 1. 拿到原来的 Field:例如 "text_content:2:0"
|
||||
oldField := item.Field
|
||||
// 2. 找到最后一个 : 的位置
|
||||
if idx := strings.LastIndex(oldField, ":"); idx != -1 {
|
||||
// 3. 截断前面部分,拼接上新的 globalIndex
|
||||
item.Field = oldField[:idx+1] + fmt.Sprint(globalIndex)
|
||||
}
|
||||
// Label 同理
|
||||
oldLabel := item.Label
|
||||
if idx := strings.LastIndex(oldLabel, ":"); idx != -1 {
|
||||
item.Label = oldLabel[:idx+1] + fmt.Sprint(globalIndex)
|
||||
}
|
||||
outputRes = append(outputRes, item)
|
||||
}
|
||||
globalIndex++
|
||||
}
|
||||
|
||||
nodeInput.Config.OutputResult = outputRes
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
// TextModelLambda 构建文案
|
||||
@@ -122,7 +199,7 @@ func TextModelLambda(ctx context.Context, input any) (any, error) {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
skillName, from, userFrom := BuildParam(nodeInput)
|
||||
outputRes, err := TextNode(ctx, nodeInput.Global.SessionId, nodeInput.Config.ModelConfig.ModelName, skillName, from, userFrom, nodeInput.Config.ModelConfig.ModelResponse, nodeInput.Global.FileUrl)
|
||||
outputRes, err := TextNode(ctx, nodeInput, skillName, from, userFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -137,7 +214,7 @@ func ImageModelLambda(ctx context.Context, input any) (any, error) {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
skillName, from, userFrom := BuildParam(nodeInput)
|
||||
outputRes, err := ImgNode(ctx, nodeInput.Global.SessionId, nodeInput.Config.ModelConfig.ModelName, skillName, from, userFrom, nodeInput.Config.ModelConfig.ModelResponse, nodeInput.Global.FileUrl)
|
||||
outputRes, err := ImgNode(ctx, nodeInput, skillName, from, userFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -145,7 +222,213 @@ func ImageModelLambda(ctx context.Context, input any) (any, error) {
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
// AudioModelLambda 构建音频
|
||||
func AudioModelLambda(ctx context.Context, input any) (any, error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
skillName, from, userFrom := BuildParam(nodeInput)
|
||||
outputRes, err := AudioOptimizeNode(ctx, nodeInput, skillName, from, userFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeInput.Config.OutputResult = outputRes
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
// VideoModelLambda 构建视频
|
||||
func VideoModelLambda(ctx context.Context, input any) (any, error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
|
||||
skillName, from, userFrom := BuildParam(nodeInput)
|
||||
res, err := VideoOptimizeNode(ctx, nodeInput, skillName, from, userFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
videoURL := make([]string, 0)
|
||||
for _, v := range res {
|
||||
if strings.Contains(v.Field, "content") {
|
||||
videoURL = append(videoURL, gconv.String(v.Value))
|
||||
}
|
||||
}
|
||||
if g.IsEmpty(videoURL) {
|
||||
return nil, fmt.Errorf("视频合成失败:模型生成视频失败")
|
||||
}
|
||||
waitRes, err := VideoConcat(ctx, videoURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := new(flowDto.VideoCallbackReq)
|
||||
if err = gconv.Struct(waitRes, msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
urlPrefix, err := utils.GetFileAddressPrefix(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputRes := make([]node.NodeFormField, 0)
|
||||
if nodeInput.Config.IsSaveFile {
|
||||
outputRes = append(outputRes, node.NodeFormField{
|
||||
Field: fmt.Sprintf("video_oss_url:content:%d", 0),
|
||||
Value: msg.FileURL,
|
||||
Label: fmt.Sprintf("video_oss_url:content:%d", 0),
|
||||
Type: "string",
|
||||
})
|
||||
} else {
|
||||
outputRes = append(outputRes, node.NodeFormField{
|
||||
Field: fmt.Sprintf("concat_video_url:content:%d", 0),
|
||||
Value: urlPrefix + msg.FileURL,
|
||||
Label: fmt.Sprintf("concat_video_url:content:%d", 0),
|
||||
Type: "string",
|
||||
})
|
||||
}
|
||||
nodeInput.Config.OutputResult = outputRes
|
||||
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
// HttpLambda 构建HTTP(S)接口
|
||||
func HttpLambda(ctx context.Context, input any) (any, error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
outputRes := make([]node.NodeFormField, 0)
|
||||
var err error
|
||||
outputRes, err = HttpNode(ctx, nodeInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeInput.Config.OutputResult = outputRes
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
// DataConversionLambda 构建数据转换
|
||||
func DataConversionLambda(ctx context.Context, input any) (any, error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("入参类型错误")
|
||||
}
|
||||
skillName, from, userFrom := BuildParam(nodeInput)
|
||||
outputRes, err := DataConversionNode(ctx, nodeInput, skillName, from, userFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeInput.Config.OutputResult = outputRes
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
func DataMergeLambda(ctx context.Context, input any) (res any, err error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("参数合并入参类型错误")
|
||||
}
|
||||
|
||||
// var nodeIds []string
|
||||
// for _, item := range nodeInput.Config.InputSource {
|
||||
// nodeIds = append(nodeIds, item.NodeId)
|
||||
// }
|
||||
//
|
||||
// // 检查是否所有输入节点都执行完成,并且检查是否有节点失败
|
||||
// checkAllExecuted := func() (allExecuted bool, hasFailed bool, failedNode string) {
|
||||
// executedCount := 0
|
||||
// for _, executedNode := range nodeInput.Global.ExecutedNodes {
|
||||
// // 检查是否是我们需要的输入节点,并且它失败了
|
||||
// for _, targetId := range nodeIds {
|
||||
// if executedNode.NodeId == targetId {
|
||||
// if executedNode.Status == node.NodeExecutionStatusFailed.Code() {
|
||||
// return false, true, targetId
|
||||
// }
|
||||
// executedCount++
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return executedCount == len(nodeIds), false, ""
|
||||
// }
|
||||
//
|
||||
// // 初次检查
|
||||
// allExecuted, hasFailed, failedNode := checkAllExecuted()
|
||||
// if hasFailed {
|
||||
// return nil, fmt.Errorf("输入节点[%s]执行失败", failedNode)
|
||||
// }
|
||||
//
|
||||
// // 如果不是全部都已执行,阻塞等待直到全部完成、上下文取消或有节点失败
|
||||
// if !allExecuted {
|
||||
// // 轮询检查,每500ms检查一次,依赖ctx超时控制
|
||||
// ticker := time.NewTicker(500 * time.Millisecond)
|
||||
// defer ticker.Stop()
|
||||
//
|
||||
// for {
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// // 如果上下文已经取消,说明已有节点报错,直接退出
|
||||
// return nil, ctx.Err()
|
||||
// case <-ticker.C:
|
||||
// // 重新检查所有节点
|
||||
// allExecuted, hasFailed, failedNode := checkAllExecuted()
|
||||
// if hasFailed {
|
||||
// // 有一个输入节点失败,直接退出
|
||||
// return nil, fmt.Errorf("输入节点[%s]执行失败", failedNode)
|
||||
// }
|
||||
// if allExecuted {
|
||||
// // 全部执行完成,退出循环继续执行
|
||||
// goto allDone
|
||||
// }
|
||||
//
|
||||
// // 再次检查上下文是否已经取消,如果已经取消则立即退出
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// return nil, ctx.Err()
|
||||
// default:
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//allDone:
|
||||
//
|
||||
// // 最终检查:所有输入节点都成功了吗
|
||||
// _, hasFailed, failedNode = checkAllExecuted()
|
||||
// if hasFailed {
|
||||
// // 有一个输入节点失败,直接退出
|
||||
// return nil, fmt.Errorf("输入节点[%s]执行失败", failedNode)
|
||||
// }
|
||||
//
|
||||
// // 构建已执行节点ID的map,方便合并时查找
|
||||
// executedMap := make(map[string]*flowDto.ExecutedNode, len(nodeInput.Global.ExecutedNodes))
|
||||
// for _, en := range nodeInput.Global.ExecutedNodes {
|
||||
// executedMap[en.NodeId] = &en
|
||||
// }
|
||||
//
|
||||
// // 合并所有输入源节点的输出结果
|
||||
// for _, inputSource := range nodeInput.Config.InputSource {
|
||||
// // 每次循环都检查上下文是否已取消,提前退出
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// return nil, ctx.Err()
|
||||
// default:
|
||||
// }
|
||||
// // 再次检查该节点是否失败
|
||||
// if en, ok := executedMap[inputSource.NodeId]; ok && en.Status == node.NodeExecutionStatusFailed.Code() {
|
||||
// return nil, fmt.Errorf("输入节点[%s]执行失败", inputSource.NodeId)
|
||||
// }
|
||||
// sourceNodeConfig := nodeInput.Global.ConfigMap[inputSource.NodeId]
|
||||
// if sourceNodeConfig != nil && len(sourceNodeConfig.OutputResult) > 0 {
|
||||
// nodeInput.Config.OutputResult = append(nodeInput.Config.OutputResult, sourceNodeConfig.OutputResult...)
|
||||
// }
|
||||
// }
|
||||
|
||||
return nodeInput, nil
|
||||
}
|
||||
|
||||
func MergeLambda(ctx context.Context, input any) (res any, err error) {
|
||||
nodeInput, ok := input.(*flowDto.NodeExecutionInput)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("汇总节点入参类型错误")
|
||||
@@ -155,7 +438,8 @@ func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
dataMap := make(map[string]node.NodeFormField)
|
||||
_, outputMap, _ := GetNodeContextContent(nodeInput.Global, nodeInput.Config)
|
||||
for _, valueAny := range outputMap {
|
||||
if field, ok := valueAny.(node.NodeFormField); ok {
|
||||
field := node.NodeFormField{}
|
||||
if field, ok = valueAny.(node.NodeFormField); ok {
|
||||
dataMap[field.Field] = field
|
||||
}
|
||||
}
|
||||
@@ -163,7 +447,7 @@ func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
// 2. 提取所有文案:text_content_0,1,2...
|
||||
var contents []node.NodeFormField
|
||||
for i := 0; ; i++ {
|
||||
key := fmt.Sprintf("text_url:%d", i)
|
||||
key := fmt.Sprintf("text_content:%d", i)
|
||||
val, has := dataMap[key]
|
||||
if !has || val.Value == "" {
|
||||
break
|
||||
@@ -179,7 +463,7 @@ func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
if !has || val.Value == "" {
|
||||
break
|
||||
}
|
||||
images = append(images, val.Value)
|
||||
images = append(images, gconv.String(val.Value))
|
||||
}
|
||||
|
||||
// 4. 🔥 核心算法:图片按顺序连续归属给每条文案
|
||||
@@ -232,8 +516,8 @@ func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
if len(contents) > 0 {
|
||||
for i, val := range contents {
|
||||
item := Item{
|
||||
Content: url + val.Value, // 文案
|
||||
Images: textImgMap[i], // 自动绑定该条目的图片(没有则为空切片)
|
||||
Content: url + gconv.String(val.Value), // 文案
|
||||
Images: textImgMap[i], // 自动绑定该条目的图片(没有则为空切片)
|
||||
}
|
||||
allItems = append(allItems, item)
|
||||
}
|
||||
@@ -254,24 +538,8 @@ func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
|
||||
// 遍历所有【独立图文条目】 → 每条生成独立HTML、独立上传OSS、独立输出记录
|
||||
for idx, item := range allItems {
|
||||
// item 结构包含:Content(string) + Images([]string)
|
||||
// 支持任意来源:文生图、图生文、单独文、单独图、文图合并
|
||||
|
||||
// 生成单条HTML
|
||||
htmlContent := BuildHtml(item.Content, item.Images)
|
||||
|
||||
// 上传OSS(每条独立上传)
|
||||
fileName := fmt.Sprintf("item_%d_%d.html", idx, time.Now().UnixMilli())
|
||||
ossResult, err := Upload(ctx, &dto.UploadFileBytesReq{
|
||||
FileBytes: []byte(htmlContent),
|
||||
FileName: fileName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 拼接成一条输出记录
|
||||
// 每条记录包含:HTML内容 + 访问URL + 文案 + 图片列表
|
||||
outputRecords = append(outputRecords,
|
||||
node.NodeFormField{
|
||||
Field: fmt.Sprintf("item_html_%d", idx),
|
||||
@@ -279,25 +547,26 @@ func MergeLambda(ctx context.Context, input any) (any, error) {
|
||||
Label: fmt.Sprintf("条目%d HTML", idx+1),
|
||||
Type: "textarea",
|
||||
},
|
||||
node.NodeFormField{
|
||||
Field: fmt.Sprintf("item_html_url_%d", idx),
|
||||
Value: ossResult.FileURL,
|
||||
Label: fmt.Sprintf("条目%d 地址", idx+1),
|
||||
Type: "text",
|
||||
},
|
||||
node.NodeFormField{
|
||||
Field: fmt.Sprintf("item_txt_url_%d", idx),
|
||||
Value: item.Content,
|
||||
Label: fmt.Sprintf("条目%d 文案", idx+1),
|
||||
Type: "text",
|
||||
},
|
||||
node.NodeFormField{
|
||||
Field: fmt.Sprintf("item_image_url_%d", idx),
|
||||
Value: strings.Join(item.Images, ","),
|
||||
Label: fmt.Sprintf("条目%d 图片", idx+1),
|
||||
Type: "text",
|
||||
},
|
||||
)
|
||||
if nodeInput.Config.IsSaveFile {
|
||||
// 上传OSS(每条独立上传)
|
||||
fileName := fmt.Sprintf("item_%d_%d.html", idx, time.Now().UnixMilli())
|
||||
ossResult, err := Upload(ctx, &dto.UploadFileBytesReq{
|
||||
FileBytes: []byte(htmlContent),
|
||||
FileName: fileName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputRecords = append(outputRecords,
|
||||
node.NodeFormField{
|
||||
Field: fmt.Sprintf("item_html_url_%d", idx),
|
||||
Value: ossResult.FileURL,
|
||||
Label: fmt.Sprintf("条目%d 地址", idx+1),
|
||||
Type: "text",
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 最终输出多条记录
|
||||
@@ -313,11 +582,12 @@ func SummaryLambda(ctx context.Context, input any) (any, error) {
|
||||
|
||||
// 聚合所有已执行节点的输出结果
|
||||
var summaryResult []map[string]interface{}
|
||||
for _, nodeID := range execInput.Global.ExecutedNodes {
|
||||
for _, executedNode := range execInput.Global.ExecutedNodes {
|
||||
nodeID := executedNode.NodeId
|
||||
nodeConfig := execInput.Global.ConfigMap[nodeID]
|
||||
if nodeConfig != nil && len(nodeConfig.OutputResult) > 0 {
|
||||
for _, field := range nodeConfig.OutputResult {
|
||||
if strings.Contains(field.Field, "item_html_url") || strings.Contains(field.Field, "img_url") || strings.Contains(field.Field, "text_url") {
|
||||
if strings.Contains(field.Field, "http_file_url") || strings.Contains(field.Field, "audio_oss_url") || strings.Contains(field.Field, "video_oss_url") || strings.Contains(field.Field, "item_html_url") || strings.Contains(field.Field, "img_oss_url") || strings.Contains(field.Field, "text_url") {
|
||||
// 生成 毫秒时间戳 作为 KEY
|
||||
timeKey := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||
item := make(map[string]interface{})
|
||||
@@ -376,18 +646,6 @@ func SummaryLambda(ctx context.Context, input any) (any, error) {
|
||||
return execInput, err
|
||||
}
|
||||
|
||||
// VideoModelLambda 构建视频
|
||||
func VideoModelLambda(ctx context.Context, input any) (any, error) {
|
||||
fmt.Println("VideoModelLambda:", input)
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// AudioModelLambda 构建音频
|
||||
func AudioModelLambda(ctx context.Context, input any) (any, error) {
|
||||
fmt.Println("AudioModelLambda:", input)
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// CustomLambda 构建自定义
|
||||
func CustomLambda(ctx context.Context, input any) (any, error) {
|
||||
fmt.Println("CustomLambda:", input)
|
||||
|
||||
Reference in New Issue
Block a user