尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FastGPT 工作流 loopRun 循环节点开发全解:从 parallelRun 差异到 dispatcher 实现

FastGPT 工作流 loopRun 循环节点开发全解:从 parallelRun 差异到 dispatcher 实现 FastGPT 工作流 loopRun 循环节点开发全解从 parallelRun 差异到 dispatcher 实现【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT本文基于 FastGPT 开源仓库中的 loopRun 节点开发文档.agents/design/core/workflow/loop-run/development.md结合packages/global与packages/service下的真实源码系统梳理 loopRun 节点从类型枚举、节点模板、后端 dispatcher 到前端画板组件的完整落地路径。读者可借此理解 FastGPT 工作流引擎中嵌套容器类节点loop / parallelRun / loopRun的设计范式掌握如何基于既有节点复用骨架、增量改动地扩展新的工作流节点类型。一、loopRun 节点是什么loopRun 是 FastGPT 工作流引擎中的串行循环节点它以一个容器节点的形式承载一段子流程支持两种循环模式——数组模式array逐个遍历数组元素以及条件模式conditional按迭代次数循环直到loopRunBreak信号节点命中。它的设计蓝本是 parallelRun并行批量节点开发文档明确指出该节点以 commit0855cc6e06c56f8fa2ea9aaab491d43bb4413be8的 parallelRun 实现为蓝本语义与交互细节以 Notion 设计稿为准。从当前仓库源码看loopRun 相关实现已经完整落地节点类型枚举packages/global/core/workflow/node/constant.ts中FlowNodeTypeEnum新增loopRun/loopRunStart/loopRunBreak三个成员且isNestedParentNodeType()将loopRun与loop/parallelRun一并归入嵌套父容器节点类型集合源码注释原文为loop / parallelRun / loopRun。节点模板packages/global/core/workflow/template/system/loopRun/目录下存在loopRun.ts、loopRunStart.ts、loopRunBreak.ts三个模板文件。后端 dispatcherpackages/service/core/workflow/dispatch/loopRun/目录下存在runLoopRun.ts、runLoopRunStart.ts、runLoopRunBreak.ts、service.ts四个文件。回调注册packages/service/core/workflow/dispatch/constants.ts中callbackMap将FlowNodeTypeEnum.loopRun/loopRunStart/loopRunBreak分别映射到dispatchLoopRun/dispatchLoopRunStart/dispatchLoopRunBreak。二、与 parallelRun 的核心差异一份速览对照loopRun 与 parallelRun 同为嵌套容器节点但语义截然不同。开发文档给出的差异表是理解整个节点设计的钥匙结合源码可归纳如下维度parallelRunloopRun并发模型batchRun并行串行forawait输入模式只支持 arrayarray / conditional 二选一终止条件数组取尽数组取尽array 模式/loopRunBreak命中 / 系统兜底重试有0-5 次默认 3无并发数配置有env 上限无输出固定 3 个success/full/status用户自定义字段 errorTextloopRunIterations/loopRunHistory仅在调试 nodeResponse 中子节点子流程无独立 Start 节点loopRunStartunique自动生成loopRunBreak信号节点可多个interactive不支持支持对齐旧 loopruntimeNodes 隔离每任务 cloneDeep进入 loopRun 时 cloneDeep 一次迭代间共享变量newVariables每任务独立跨迭代累加结束回写 parent这些差异直接映射到代码结构runLoopRun.ts中主循环是while (true)内的串行await runWorkflow(...)见下文主循环剖析而 parallelRun 则位于packages/service/core/workflow/dispatch/parallelRun/runParallelRun.ts采用批量并行 retry 累加器模式。开发文档特别说明parallelRun 不共用pushSubWorkflowUsage/collectResponseFeedbacks这套工具它在 retry 循环里做了带累加器的就地聚合抽出去反而复杂。三、类型与枚举层改动3.1 节点类型枚举packages/global/core/workflow/node/constant.tsFlowNodeTypeEnum新增 3 个成员loopRun loopRun、loopRunStart loopRunStart、loopRunBreak loopRunBreakisNestedParentNodeType()增加FlowNodeTypeEnum.loopRun判断使 loopRun 被纳入嵌套父容器集合交互类节点类型集合在 parallelRun 体内禁止、loopRun 允许的集合中也包含FlowNodeTypeEnum.loopRunStart这与loopRun 支持 interactive、parallelRun 不支持的差异一致。3.2 输入输出 keypackages/global/core/workflow/constants.ts中NodeInputKeyEnum新增loopRunModearray | conditionalloopRunInputArray——文档特意强调不复用nestedInputArray避免与旧 loop / parallelRun 的loopInputArray字符串值冲突loopCustomOutputs——自定义输出字段声明区。NodeOutputKeyEnum新增errorText若已存在则复用currentIndex/currentItem/currentIterationloopRunStart 动态输出。文档明确指出不需要新增 status enum——loopRun 没有 parallelStatus 这种状态输出。3.3 运行时类型扩展packages/global/core/workflow/runtime/type.ts中DispatchNodeResponseType增加loopRunInput?、loopRunIterations?、loopRunHistory?、loopRunDetail?。WorkflowInteractiveResponseType已有loopInteractive类型loopRun 复用现有结构currentIndex改名对齐为iteration可选或直接复用字段。runLoopRun.ts的实际返回也印证了这一点nodeResponse中携带totalPoints、loopRunInput、loopRunIterations、loopRunHistory、childResponseCount出错时附加errorText这些调试信息仅供前端 WholeResponseModal 展示不进入用户自定义输出。3.4 模板输入层复用packages/global/core/workflow/template/input.ts复用现有Input_Template_Children_Node_List/Input_Template_Node_Width/Input_Template_Node_Height/Input_Template_NESTED_NODE_OFFSET并新增Input_Template_LoopCustomOutputs参考代码节点的Output_Template_AddOutput做一个声明区输入。四、节点模板LoopRunNode / LoopRunStartNode / LoopRunBreakNode三个模板均位于packages/global/core/workflow/template/system/loopRun/并已在template/constants.ts中注册到systemNodes。4.1 LoopRunNode容器节点loopRun.ts导出了LoopRunModeEnumarray/conditional与LoopRunNode模板。其配置要点templateType: FlowNodeTemplateTypeEnum.toolsisTool: trueshowStatus: truecatchError: false默认不捕获错误由外层决定isShowInContext使用createHideInContext在父节点是 loopRun / parallelRun 时从上下文隐藏——即禁止循环 / 并行容器嵌套courseUrl: /guide/build/workflow/nodes/loop_run指向官方指南文档inputs 结构loopRunModeselect 渲染必填默认array选项含 array / conditional 两个 mode各自带 icon 与描述loopRunInputArrayreference 渲染valueType: arrayAny必填默认[]loopCustomOutputsaddInputParam渲染声明式输入区valueType: dynamiccustomInputConfig里selectValueTypeList放开全部WorkflowIOValueTypeEnum值类型供用户选择且showDescription: false、showDefaultValue: false其余复用Input_Template_Children_Node_List与宽高、offset 三个嵌套布局模板outputs只保留一个errorTextFlowNodeOutputTypeEnum.errorstring 类型。用户自定义输出字段由loopCustomOutputs声明后前端通过 dynamic output 镜像到 outputs——对应开发文档outputs 只保留 errorText用户自定义字段由 dynamic output 声明迭代数与历史仅在 nodeResponse 调试信息中返回的描述。4.2 LoopRunStartNode入口信号节点loopRunStart.ts中的LoopRunStartNodeunique: trueforbidDelete: true——每个 loopRun 容器内自动生成且唯一不可删除templateType: systemInputshowTargetHandle: false仅作为子流程起点inputs 全部为 hidden 隐藏输入loopRunMode透传父节点模式、nestedStartInputarray 模式下透传当前数组元素、nestedStartIndex透传迭代序号outputs 静态暴露 3 个currentIndexnumber0-based、currentItemany当前元素、currentIterationnumber1-based 迭代计数。值得注意模板上 3 个 output 都声明为静态但开发文档指出其 UI 上按父节点 loopRunMode 动态显示——array 模式暴露 currentIndex currentItemconditional 模式暴露 currentIteration。这属于前端展示层对 output 可见性的动态控制。4.3 LoopRunBreakNode条件模式终止信号loopRunBreak.ts中的LoopRunBreakNodeshowSourceHandle: false、showTargetHandle: true——只有 target handle是纯输入信号节点inputs: []、outputs: []——不携带任何数据isShowInContext是一个接收上下文的函数在侧边栏拖入容器时按parentType loopRun判断无目标容器时退回画布是否已有 loopRun 节点hasLoopRunNode画布内则以ctx.parentType loopRun为准。这确保了 break 节点只能出现在 loopRun 容器内部。五、后端 Dispatcher 主循环剖析5.1 入口与回调注册packages/service/core/workflow/dispatch/constants.ts中import { dispatchLoopRun } from ./loopRun/runLoopRun; import { dispatchLoopRunStart } from ./loopRun/runLoopRunStart; import { dispatchLoopRunBreak } from ./loopRun/runLoopRunBreak; ... [FlowNodeTypeEnum.loopRun]: dispatchLoopRun, [FlowNodeTypeEnum.loopRunStart]: dispatchLoopRunStart, [FlowNodeTypeEnum.loopRunBreak]: dispatchLoopRunBreak,三个 dispatcher 的职责分工对齐parallelRun/目录结构runLoopRun.ts— 主 dispatcher串行循环的调度核心runLoopRunStart.ts— 简单透传参考runLoopStart.ts把注入的 iteration/index/item 透传给子流程runLoopRunBreak.ts— 纯信号节点dispatchLoopRunBreak返回空 data仅在 flowResponses 中留下 moduleType 标记。5.2 参数与前置校验dispatchLoopRun接收ModuleDispatchProps从中取出loopRunMode默认array、loopRunInputArray、childrenNodeIdList。进入主循环前有一个preCheckError前置校验块const preCheckError (() { if (mode LoopRunModeEnum.array !Array.isArray(inputArray)) { return i18nT(workflow:loop_run_input_not_array); } if (mode LoopRunModeEnum.array inputArray.length maxLength) { return maxIterationsMessage; } // Without a break node, conditional mode can only stop at WORKFLOW_MAX_LOOP_TIMES. if ( mode LoopRunModeEnum.conditional !hasLoopRunBreakChild(runtimeNodes, childrenNodeIdList) ) { return i18nT(workflow:loop_run_conditional_requires_break); } return undefined; })();三条规则分别对应array 模式输入必须是数组数组长度不能超过serviceEnv.WORKFLOW_MAX_LOOP_TIMESpackages/service/env.ts中复用已有 env未新增配置conditional 模式必须在子流程内至少存在一个loopRunBreak子节点通过hasLoopRunBreakChild检查否则只能靠WORKFLOW_MAX_LOOP_TIMES兜底终止。校验失败通过getNodeErrResponse返回错误且错误以errorText协议暴露socatchErrorand downstream error-handle routing see them——即错误能被 catchError 与下游错误处理路由识别。5.3 循环级隔离与 interactive 恢复进入主循环前let isolatedNodes cloneDeep(runtimeNodes); const isolatedEdges cloneDeep(runtimeEdges);与 parallelRun 每任务 cloneDeep 不同loopRun 是进入时 cloneDeep 一次、迭代间共享同一份 runtimeNodes这正是文档差异表中的关键一条。同时interactiveData从lastInteractive?.type loopRunInteractive恢复恢复时用rewriteNodeOutputByHistories(isolatedNodes, interactiveData.childrenResponse)将上一轮交互中断时子流程内部节点输出回填保证续跑轮次的引用能正确解析loopHistory从interactiveData.loopHistory恢复pendingIterationSummary保存中断前的运行时摘要恢复后通过mergeRuntimeNodeResponseSummary合并从而在不保留完整子节点详情的情况下依然能统计已完成节点、子节点数与耗时。5.4 主循环串行 for await核心结构runLoopRun.ts中while (true)停止检查每轮开头checkIsStopping()用户中断则 break数组取尽判断array 模式下以iteration - 1为下标取元素index inputArray.length即exhaustedbreak注释特意强调Check exhaustion before maxLength soinputArray.length maxLengthruns cleanly——即数组长度恰好等于上限时应能完整跑完上限兜底iteration maxLength时置maxIterationsExceeded true并 break主要保护 conditional 模式注入入口非恢复轮次调用injectLoopRunStart({ nodes, childrenNodeIdList, mode, item, index, iteration })恢复轮次则把interactiveData.childrenResponse.entryNodeIds中的节点重新标记为isEntry true隔离变量状态props.variableState.clone()得到本轮迭代独立的 variableState并用createContainerRunStateSnapshot记录本轮开始时的容器运行态快照供中断/失败时回写 parent 使用执行子流程await runWorkflow({ ...props, variableState: iterationVariableState, lastInteractive, nodeResponseParentId: iterationResponseId, runtimeNodes: isolatedNodes, runtimeEdges: cloneDeep(storeEdges2RuntimeEdges(...)) })——这里nodeResponseParentId被设为${loopRunNodeResponseId}:iter:${iteration}格式的虚拟任务 ID为每个迭代轮次创建独立的响应子树聚合收集assistantResponses、customFeedbackspushSubWorkflowUsage累计 token 用量collectResponseFeedbacks收集反馈读取自定义输出快照readCustomOutputSnapshot(...)按finishedNodeIds过滤后读取 ref 值详见 5.6包装迭代详情pushIterationDetail把本轮包装成虚拟任务节点moduleType: loopRun、moduleName使用parallel_task文案 { index: iteration }参数、loopInputValue/loopOutputValue分别记录本轮输入与快照、含runningTime与totalPoints通过nodeResponseSink.publish发布到响应树使 WholeResponseModal 能按迭代分层展示分支处理交互响应response.workflowInteractiveResponse立即syncContainerRunState回写 parent 并pushIterationDetail后 break返回loopRunInteractive类型交互本轮有错误iterationSummary.hasError写入带error的迭代详情loopHistory追加{ iteration, customOutputs, success: false, error }后 break正常结束写成功详情loopHistory.push({ iteration, customOutputs, success: true })syncContainerRunState回写变量与外部节点输出iterationSummary.hasLoopRunBreakbreakconditional 模式命中 break 信号清理恢复态恢复轮次结束后清除其他子节点的isEntry标志flowNodeType ! loopRunStart的节点重置interactiveData置 undefinediteration进入下一轮。5.5 结束聚合与错误协议循环结束后const lastEntry loopHistory[loopHistory.length - 1]; const lastSnapshot: Recordstring, any lastEntry?.customOutputs ?? {};data取最后一项快照lastEntry.customOutputs实现最后一项 customOutputs → 动态 outputserrorText三级判定maxIterationsExceeded时用最大迭代提示否则若最后一项success false用该项error再 fallback 到loop_run_iteration_failed关键细节循环失败时不产出toolResponse注释说明交给工具运行器的 errorMessage 兜底避免用空快照挡住错误信息出错时error: { [NodeOutputKeyEnum.errorText]: errorText }与nodeResponse.errorText同时设置供 OTel span 状态与下游错误路由读取interactive响应携带loopRunInteractive类型及loopHistory/childrenResponse/iteration/pendingIterationSummary实现下次进入从中断轮次续跑。5.6 service.ts 中的四个工具函数packages/service/core/workflow/dispatch/loopRun/service.ts是 loopRun 的专属工具库①pickCustomOutputInputs(inputs, outputs)从 inputs 中筛选出用户自定义输出声明要求i.canEdit true且在 outputs 中存在同 key 的FlowNodeOutputTypeEnum.dynamic镜像。代码注释解释了双重校验的原因——canEdit 本身是通用的『用户可改 key/type』标记单独用会把未来新增的 canEdit 输入如迭代配置项误当成输出声明必须通过 dynamic output 镜像二次确认这是被NodeLoopRun.useEffect真正镜像过的声明项。②readCustomOutputSnapshot(...)读取 ref 写快照。当传入finishedNodeIds失败轮次时对每个声明项解析其 ref 目标并逐一校验是否本轮已完成ref 为空或指向全局变量节点VARIABLE_NODE_ID→ 放行ref 指向循环体外节点不在childrenNodeIdList中如循环体外被变量更新节点改写的代码节点输出→ 放行豁免跳过分支守卫ref 指向体内节点但不在finishedNodeIds→ 快照值为undefined防止上一轮残留的陈旧值泄漏到失败轮次。通过校验的 ref 用getReferenceVariableValue解析并formatVariableValByType按声明的 valueType 格式化。成功轮finishedNodeIds为 undefined则全字段有值。③injectLoopRunStart(...)就地修改 runtimeNodes仅处理childrenNodeIdList内且flowNodeType loopRunStart的节点置isEntry true并注入三个 hidden 输入——loopRunMode透传模式、nestedStartInputarray 模式填当前 itemconditional 模式置 undefined、nestedStartIndexarray 模式填 0-basedindex ?? 0conditional 模式填 1-basediteration。函数注释明确Array mode injects 0-based index; conditional mode injects 1-based iteration.④hasLoopRunBreakChild(runtimeNodes, childrenNodeIdList)在子节点集合中查找是否存在loopRunBreak类型节点供 conditional 模式 break 预检使用。5.7 跨 dispatcher 下沉工具开发文档指出pushSubWorkflowUsage与collectResponseFeedbacks原本在loop/service.ts中实现现下沉到packages/service/core/workflow/dispatch/utils.ts由 loop / loopRun 共用参数名index→iteration两者语义等价都是 1-based 迭代计数。这属于 loopRun feature PR 的去重改动而非 bug 修复。从runLoopRun.ts的 import 可见它同时引用了 utils.ts 中的collectResponseFeedbacks、getRuntimeNodeResponseSummary、getNodeErrResponse、mergeRuntimeNodeResponseSummary、pushSubWorkflowUsage与文档描述一致。parallelRun 由于 retry 循环内做带累加器的就地聚合不共用这套工具。六、前端画板节点组件前端改动集中在projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/Loop/目录新增三个组件NodeLoopRun.tsx— 容器节点组件参考NodeParallelRun.tsx用useNestedNodehook 处理大小与子节点列表conditional 模式下没有nestedInputArrayuseNestedNode需加开关或跳过该 input新增loopRunModeselect 切换切换时清理 loopRunStart 的 ref 并 toast 提醒新增loopCustomOutputs自定义输出声明 UI参考代码节点的RenderOutput模式NodeLoopRunStart.tsx— start 节点 UI参考NodeLoopStart.tsx但输出字段按父节点loopRunMode动态显示NodeLoopRunBreak.tsx— 极简信号卡片只有 target handle 和图标文字Flow/index.tsx节点类型映射新增 3 条 dynamic importhooks/useNestedNode.tsnestedInputArray读取改为可选conditional 模式无该 input 时跳过 valueType 推断或新增arrayInputKey参数允许 loopRun 传loopRunInputArrayhooks/useWorkflow.tsx/hooks/useKeyboard.tsx节点复制/删除白名单与跨容器 copy/paste 规则补充 loopRun 系列components/NodeTemplates/list.tsxloopRun 子流程内禁止添加 loop / loopRun / parallelRun允许 interactive区别于 parallelRun拖入 loopRun 时自动创建loopRunStart子节点nodes/render/NodeCard.tsxloopRun 容器节点menuForbid{{ copy: true }}与 parallelRun 一致nodes/render/RenderInput/templates/Reference.tsx确认 loopRunStart 的动态 outputs 可被子流程内其他节点正常引用projects/app/src/components/core/chat/components/WholeResponseModal.tsx按 parallelRun 的展示逻辑追加 loopRun 每轮详情loopRunDetail。NodeTemplatesPopover.tsx无需改动模板列表从systemNodes派生workflowComputeContext.tsx也无需改动嵌套容器大小计算通用。图标与 i18npackages/web/components/common/Icon/constants.ts注册 3 个图标core/workflow/template/loopRun/loopRunStart/loopRunBreakicons/core/workflow/template/loopRun.svg/loopRunLinear.tsx新建linear 可先拷贝 parallelRunLinear 做 placeholder。从loopRun.ts/loopRunStart.ts/loopRunBreak.ts模板的avatar字段core/workflow/template/loopRun、loopRunLinear等可见图标路径与注册保持一致packages/web/i18n/{zh-CN,en,zh-Hant}/workflow.json新增 keyloop_run/intro_loop_run/loop_run_execution_logic、loop_run_mode/loop_run_mode_array/loop_run_mode_conditional、loop_run_input_array、loop_custom_outputs/loop_custom_outputs_tip、loop_iterations/loop_history、loop_run_break/loop_run_break_tip、loop_run_start/current_index/current_item/current_iteration、loop_run_mode_switch_warning等。源码中实际用到的 i18n key如loop_run_input_not_array、loop_run_conditional_requires_break、loop_run_max_iterations_exceeded、loop_run_iteration_failed、parallel_task与此清单相印证。配置与系统由于 loopRun 无并发数配置packages/global/common/system/types/index.ts与projects/app/src/service/common/system/index.ts无需增加前端限制字段projects/app/.env.template无需新增变量——上限统一复用WORKFLOW_MAX_LOOP_TIMES。七、测试清单与验证方法开发文档规划了两组针对 dispatcher 的单元测试均新建于test/cases/packages/service/core/workflow/dispatch/loopRun/service.test.ts工具函数readCustomOutputSnapshotfinishedNodeIds为 undefined成功轮→ 全字段有值只包含部分节点 → 未包含节点的 ref 返回 undefinedref 目标节点不存在 → undefinedextractFinishedNodeIds从 flowResponses 正确推导 nodeId 集合injectLoopRunStartarray 模式注入 indexitemconditional 模式注入 iteration。runLoopRun.test.ts主循环行为array 模式数组取尽正常返回array 模式中途节点出错 → loopHistory 最后一项success: false快照按已完成节点过滤conditional 模式 loopRunBreak 命中 → 正常返回conditional 模式超过WORKFLOW_MAX_LOOP_TIMES→ 系统兜底报错interactive 响应 → 返回 loopInteractive下次进入从中断轮次续跑catchErrortrue出错 → 走 errorTextcatchErrorfalse出错 → 直接抛。全量验证阶段Phase 6要求pnpm test全量跑、pnpm lint并做前端手工验证清单拖节点 / 切模式 / 数组模式跑通 / 条件模式跑通 / break 生效 / interactive 暂停恢复 / catchErrortrue/false。八、实现期间引入的跨模块改动开发文档专门用一节区分loopRun 功能本身与实现期间顺手改到的跨模块改动这几处对其他节点也有影响值得单独留意8.1 dispatch 错误归一化packages/service/core/workflow/dispatch/index.ts在 dispatcher 返回{error}catchErrorfalse 分支补了一段逻辑从nodeResponseBase?.errorText兜底取getErrText(result.error)统一写入nodeResponse.error。动机loopRun / parallelRun 需要稳定方式识别失败轮次。此前 dispatcher throw 的 catch 兜底分支本来就写nodeResponse.errorOTel span status 也读nodeResponse.error唯独非 throw 路径不写导致失败检测链路断裂。归一化后三个消费方catch 兜底 / 失败检测 / OTel统一读同一字段errorText保留给 UI 展示schema 注释// Just show。顺带修复parallelRun/service.ts一直在用flowResponses.find((r) r.error)但因链路缺失始终落到 fallback 文案parallel_task_not_reach_end——归一化后 parallelRun 也能拿到真实错误OTel span error status 在此路径上正确触发。DispatchNodeResponseSchema中error本就是可选字段grep 过所有消费方无破坏。8.2 WholeResponseModal 单元素数组解包projects/app/src/components/core/chat/components/WholeResponseModal.tsxL512-L527updateVarResult本来是updateList.map(...)的数组单行配置时展示为[{...}]内部 value 又是数组时会出现[[...]]视觉双层嵌套。现改为长度为 1 且r[0] ! null r[0] ! undefined时解包外层多行仍按数组展示[null]无效引用保留外层以便用户识别无效引用。对非 loopRun 用户属展示改善而非功能改动。8.3 useNestedNode 子节点尺寸订阅projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useNestedNode.tsL55-L65原逻辑用setTimeout(() resetParentNodeSizeAndPosition(nodeId), 50)快速拖入子节点时定时器抢跑在 ReactFlow 测量宽高之前bounds 偏小。现改为订阅WorkflowInitContext.nodes中所有 parent 匹配的子节点${id}:${width}x${height}拼接成的字符串 signalsignal 变化触发重算。loop / parallelRun 同用useNestedNode同时受益文档建议对 loop / parallelRun 拖拽体验做一次回归验证。九、开放问题与后续演进方向开发文档列出了 5 个在开发中可能需要与用户对齐的开放问题理解它们有助于把握该节点的边界useNestedNode是否重构为支持可选arrayInputKey当前 hook 只读nestedInputArrayloopRun 用独立 keyloopRunInputArray。方案 A 是 hook 增加arrayInputKey参数建议复用度高方案 B 是 loopRun 组件内不用 hook、单独写大小同步逻辑自定义输出声明 UI 复用策略代码节点的Output_Template_AddOutput语义是代码产出输出而 loopRun 的 custom outputs 语义是引用子流程内节点输出、声明为 parent 节点的 output——需确认直接复用现有组件还是新写一个 ref-based 声明器interactive 暂停恢复的 customOutputs 快照中断并非失败建议不在 interactive 时写 loopHistory恢复后按正常轮处理源码实现正是如此interactive 分支直接 break 并返回loopHistory原样不追加记录loopRunBreak误连到 loopRun 子流程外部静态校验层面需严格卡住父容器归属模板层的isShowInContext函数已从 UI 层面限制 break 只能拖入 loopRun 容器FlowNodeTypeEnum.nestedEnd旧 loopEnd与 loopRun 的关系loopRun 不使用 nestedEndruntime 也不应匹配到它。十、小结读懂 FastGPT 嵌套容器节点扩展范式loopRun 的落地路径展示了一条 FastGPT 扩展工作流节点的完整范式global 层定义类型契约枚举FlowNodeTypeEnum/NodeInputKeyEnum/NodeOutputKeyEnum→ 运行时类型DispatchNodeResponseType→ 节点模板template/system/loopRun/*→ 注册到systemNodesservice 层实现运行时语义dispatch/constants.ts注册回调 →dispatch/loopRun/*实现串行循环、快照读写、break 信号与 interactive 恢复 → 跨节点工具下沉到dispatch/utils.tsweb 层落地交互画板组件、图标、i18n、键盘/复制规则、模板列表约束测试与全量验证工具函数级单测 主循环行为级单测 pnpm test/pnpm lint全量回归。对想要二次开发 FastGPT 工作流引擎的读者而言loopRun 与 parallelRun 的对照关系并发 vs 串行、固定输出 vs 自定义输出、支持 vs 不支持 interactive本身就是理解引擎调度模型的最佳切片文中引用的源码路径均可直接在当前仓库中继续深入阅读例如 runLoopRun.ts、service.ts、loopRun.ts 与 node/constant.ts。【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表