mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
Workflow deep and workflow connection performance (#2664)
* feat: Workflow dispatch deep * perf: workflow connection
This commit is contained in:
@@ -36,3 +36,6 @@ HOME_URL=/
|
||||
# 日志等级: debug, info, warn, error
|
||||
LOG_LEVEL=debug
|
||||
STORE_LOG_LEVEL=warn
|
||||
|
||||
# 工作流最大运行次数,避免极端的死循环情况
|
||||
WORKFLOW_MAX_RUN_TIMES=500
|
@@ -27,6 +27,7 @@ import {
|
||||
import { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
|
||||
import { getWorkflowResponseWrite } from '@fastgpt/service/core/workflow/dispatch/utils';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
|
||||
|
||||
export type Props = {
|
||||
messages: ChatCompletionMessageParam[];
|
||||
@@ -120,7 +121,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
chatConfig,
|
||||
histories: chatMessages,
|
||||
stream: true,
|
||||
maxRunTimes: 200,
|
||||
maxRunTimes: WORKFLOW_MAX_RUN_TIMES,
|
||||
workflowStreamResponse: workflowResponseWrite
|
||||
});
|
||||
|
||||
|
@@ -9,6 +9,7 @@ import { PostWorkflowDebugProps, PostWorkflowDebugResponse } from '@/global/core
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { defaultApp } from '@/web/core/app/constants';
|
||||
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
|
||||
|
||||
async function handler(
|
||||
req: NextApiRequest,
|
||||
@@ -57,7 +58,7 @@ async function handler(
|
||||
chatConfig: defaultApp.chatConfig,
|
||||
histories: [],
|
||||
stream: false,
|
||||
maxRunTimes: 200
|
||||
maxRunTimes: WORKFLOW_MAX_RUN_TIMES
|
||||
});
|
||||
|
||||
pushChatUsage({
|
||||
|
@@ -59,6 +59,7 @@ import { getSystemTime } from '@fastgpt/global/common/time/timezone';
|
||||
import { rewriteNodeOutputByHistories } from '@fastgpt/global/core/workflow/runtime/utils';
|
||||
import { getWorkflowResponseWrite } from '@fastgpt/service/core/workflow/dispatch/utils';
|
||||
import { getPluginRunUserQuery } from '@fastgpt/service/core/workflow/utils';
|
||||
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
|
||||
|
||||
type FastGptWebChatProps = {
|
||||
chatId?: string; // undefined: get histories from messages, '': new chat, 'xxxxx': get histories from db
|
||||
@@ -264,7 +265,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
chatConfig,
|
||||
histories: newHistories,
|
||||
stream,
|
||||
maxRunTimes: 200,
|
||||
maxRunTimes: WORKFLOW_MAX_RUN_TIMES,
|
||||
workflowStreamResponse: workflowResponseWrite
|
||||
});
|
||||
}
|
||||
|
@@ -11,88 +11,98 @@ export const ConnectionSourceHandle = ({ nodeId }: { nodeId: string }) => {
|
||||
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
|
||||
const edges = useContextSelector(WorkflowContext, (v) => v.edges);
|
||||
|
||||
const node = useMemo(() => nodeList.find((node) => node.nodeId === nodeId), [nodeList, nodeId]);
|
||||
const { showSourceHandle, RightHandle, LeftHandlee, TopHandlee, BottomHandlee } = useMemo(() => {
|
||||
const node = nodeList.find((node) => node.nodeId === nodeId);
|
||||
|
||||
/* not node/not connecting node, hidden */
|
||||
const showSourceHandle = useMemo(() => {
|
||||
if (!node) return false;
|
||||
if (connectingEdge && connectingEdge.nodeId !== nodeId) return false;
|
||||
return true;
|
||||
}, [connectingEdge, node, nodeId]);
|
||||
/* not node/not connecting node, hidden */
|
||||
const showSourceHandle = (() => {
|
||||
if (!node) return false;
|
||||
if (connectingEdge && connectingEdge.nodeId !== nodeId) return false;
|
||||
return true;
|
||||
})();
|
||||
|
||||
const RightHandle = useMemo(() => {
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Right);
|
||||
const rightTargetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Right)
|
||||
);
|
||||
const RightHandle = (() => {
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Right);
|
||||
const rightTargetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Right)
|
||||
);
|
||||
|
||||
if (!node || !node?.sourceHandle?.right || rightTargetConnected) return null;
|
||||
if (!node || !node?.sourceHandle?.right || rightTargetConnected) return null;
|
||||
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Right}
|
||||
translate={[2, 0]}
|
||||
/>
|
||||
);
|
||||
}, [edges, node, nodeId]);
|
||||
const LeftHandlee = useMemo(() => {
|
||||
const leftTargetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Left)
|
||||
);
|
||||
if (!node || !node?.sourceHandle?.left || leftTargetConnected) return null;
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Right}
|
||||
translate={[2, 0]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
const LeftHandlee = (() => {
|
||||
const leftTargetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Left)
|
||||
);
|
||||
if (!node || !node?.sourceHandle?.left || leftTargetConnected) return null;
|
||||
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Left);
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Left);
|
||||
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Left}
|
||||
translate={[-6, 0]}
|
||||
/>
|
||||
);
|
||||
}, [edges, node, nodeId]);
|
||||
const TopHandlee = useMemo(() => {
|
||||
if (
|
||||
edges.some(
|
||||
(edge) => edge.target === nodeId && edge.targetHandle === NodeOutputKeyEnum.selectedTools
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Left}
|
||||
translate={[-6, 0]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
const TopHandlee = (() => {
|
||||
if (
|
||||
edges.some(
|
||||
(edge) => edge.target === nodeId && edge.targetHandle === NodeOutputKeyEnum.selectedTools
|
||||
)
|
||||
)
|
||||
)
|
||||
return null;
|
||||
return null;
|
||||
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Top);
|
||||
const topTargetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Top)
|
||||
);
|
||||
if (!node || !node?.sourceHandle?.top || topTargetConnected) return null;
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Top);
|
||||
const topTargetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Top)
|
||||
);
|
||||
if (!node || !node?.sourceHandle?.top || topTargetConnected) return null;
|
||||
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Top}
|
||||
translate={[0, -2]}
|
||||
/>
|
||||
);
|
||||
}, [edges, node, nodeId]);
|
||||
const BottomHandlee = useMemo(() => {
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Bottom);
|
||||
const targetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Bottom)
|
||||
);
|
||||
if (!node || !node?.sourceHandle?.bottom || targetConnected) return null;
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Top}
|
||||
translate={[0, -2]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
const BottomHandlee = (() => {
|
||||
const handleId = getHandleId(nodeId, 'source', Position.Bottom);
|
||||
const targetConnected = edges.some(
|
||||
(edge) => edge.targetHandle === getHandleId(nodeId, 'target', Position.Bottom)
|
||||
);
|
||||
if (!node || !node?.sourceHandle?.bottom || targetConnected) return null;
|
||||
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Bottom}
|
||||
translate={[0, 2]}
|
||||
/>
|
||||
);
|
||||
}, [edges, node, nodeId]);
|
||||
return (
|
||||
<SourceHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Bottom}
|
||||
translate={[0, 2]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
|
||||
return {
|
||||
showSourceHandle,
|
||||
RightHandle,
|
||||
LeftHandlee,
|
||||
TopHandlee,
|
||||
BottomHandlee
|
||||
};
|
||||
}, [connectingEdge, edges, nodeId, nodeList]);
|
||||
|
||||
return showSourceHandle ? (
|
||||
<>
|
||||
@@ -104,74 +114,96 @@ export const ConnectionSourceHandle = ({ nodeId }: { nodeId: string }) => {
|
||||
) : null;
|
||||
};
|
||||
|
||||
export const ConnectionTargetHandle = ({ nodeId }: { nodeId: string }) => {
|
||||
export const ConnectionTargetHandle = React.memo(function ConnectionTargetHandle({
|
||||
nodeId
|
||||
}: {
|
||||
nodeId: string;
|
||||
}) {
|
||||
const connectingEdge = useContextSelector(WorkflowContext, (ctx) => ctx.connectingEdge);
|
||||
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
|
||||
const edges = useContextSelector(WorkflowContext, (v) => v.edges);
|
||||
|
||||
const node = useMemo(() => nodeList.find((node) => node.nodeId === nodeId), [nodeList, nodeId]);
|
||||
const { showHandle, LeftHandle, rightHandle, topHandle, bottomHandle } = useMemo(() => {
|
||||
const node = nodeList.find((node) => node.nodeId === nodeId);
|
||||
const connectingNode = nodeList.find((node) => node.nodeId === connectingEdge?.nodeId);
|
||||
|
||||
const showHandle = useMemo(() => {
|
||||
if (!node) return false;
|
||||
if (connectingEdge && connectingEdge.nodeId === nodeId) return false;
|
||||
return true;
|
||||
}, [connectingEdge, node, nodeId]);
|
||||
const sourceEdges = edges.filter((edge) => edge.target === connectingNode?.nodeId);
|
||||
const connectingNodeSourceNodeIds = sourceEdges.map((edge) => edge.source);
|
||||
|
||||
const LeftHandle = useMemo(() => {
|
||||
if (!node || !node?.targetHandle?.left) return null;
|
||||
const showHandle = (() => {
|
||||
if (!node) return false;
|
||||
// Unable to connect oneself
|
||||
if (connectingEdge && connectingEdge.nodeId === nodeId) return false;
|
||||
// Unable to connect to the source node
|
||||
if (connectingNodeSourceNodeIds.includes(nodeId)) return false;
|
||||
return true;
|
||||
})();
|
||||
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Left);
|
||||
const LeftHandle = (() => {
|
||||
if (!node || !node?.targetHandle?.left) return null;
|
||||
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Left}
|
||||
translate={[-2, 0]}
|
||||
/>
|
||||
);
|
||||
}, [node, nodeId]);
|
||||
const rightHandle = useMemo(() => {
|
||||
if (!node || !node?.targetHandle?.right) return null;
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Left);
|
||||
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Right);
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Left}
|
||||
translate={[-2, 0]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
const rightHandle = (() => {
|
||||
if (!node || !node?.targetHandle?.right) return null;
|
||||
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Right}
|
||||
translate={[2, 0]}
|
||||
/>
|
||||
);
|
||||
}, [node, nodeId]);
|
||||
const topHandle = useMemo(() => {
|
||||
if (!node || !node?.targetHandle?.top) return null;
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Right);
|
||||
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Top);
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Right}
|
||||
translate={[2, 0]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
const topHandle = (() => {
|
||||
if (!node || !node?.targetHandle?.top) return null;
|
||||
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Top}
|
||||
translate={[0, -2]}
|
||||
/>
|
||||
);
|
||||
}, [node, nodeId]);
|
||||
const bottomHandle = useMemo(() => {
|
||||
if (!node || !node?.targetHandle?.bottom) return null;
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Top);
|
||||
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Bottom);
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Top}
|
||||
translate={[0, -2]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
const bottomHandle = (() => {
|
||||
if (!node || !node?.targetHandle?.bottom) return null;
|
||||
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Bottom}
|
||||
translate={[0, 2]}
|
||||
/>
|
||||
);
|
||||
}, [node, nodeId]);
|
||||
const handleId = getHandleId(nodeId, 'target', Position.Bottom);
|
||||
|
||||
return (
|
||||
<TargetHandle
|
||||
nodeId={nodeId}
|
||||
handleId={handleId}
|
||||
position={Position.Bottom}
|
||||
translate={[0, 2]}
|
||||
/>
|
||||
);
|
||||
})();
|
||||
|
||||
return {
|
||||
showHandle,
|
||||
LeftHandle,
|
||||
rightHandle,
|
||||
topHandle,
|
||||
bottomHandle
|
||||
};
|
||||
}, [connectingEdge, edges, nodeId, nodeList]);
|
||||
|
||||
return showHandle ? (
|
||||
<>
|
||||
@@ -181,7 +213,7 @@ export const ConnectionTargetHandle = ({ nodeId }: { nodeId: string }) => {
|
||||
{bottomHandle}
|
||||
</>
|
||||
) : null;
|
||||
};
|
||||
});
|
||||
|
||||
export default function Dom() {
|
||||
return <></>;
|
||||
|
@@ -248,6 +248,14 @@ const NodeCard = (props: Props) => {
|
||||
onChangeNode,
|
||||
toast
|
||||
]);
|
||||
const RenderHandle = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<ConnectionSourceHandle nodeId={nodeId} />
|
||||
<ConnectionTargetHandle nodeId={nodeId} />
|
||||
</>
|
||||
);
|
||||
}, [nodeId]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -283,8 +291,7 @@ const NodeCard = (props: Props) => {
|
||||
<NodeDebugResponse nodeId={nodeId} debugResult={debugResult} />
|
||||
{Header}
|
||||
{children}
|
||||
<ConnectionSourceHandle nodeId={nodeId} />
|
||||
<ConnectionTargetHandle nodeId={nodeId} />
|
||||
{RenderHandle}
|
||||
|
||||
<EditTitleModal maxLength={20} />
|
||||
</Box>
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||
import { addLog } from '@fastgpt/service/common/system/log';
|
||||
import { MongoApp } from '@fastgpt/service/core/app/schema';
|
||||
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
|
||||
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
|
||||
|
||||
export const getScheduleTriggerApp = async () => {
|
||||
@@ -55,7 +56,7 @@ export const getScheduleTriggerApp = async () => {
|
||||
chatConfig: defaultApp.chatConfig,
|
||||
histories: [],
|
||||
stream: false,
|
||||
maxRunTimes: 200
|
||||
maxRunTimes: WORKFLOW_MAX_RUN_TIMES
|
||||
});
|
||||
pushChatUsage({
|
||||
appName: app.name,
|
||||
|
Reference in New Issue
Block a user