From 4bef2eed25a4f6cb98e6e0147e647418ed2b6877 Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Wed, 20 Mar 2024 15:44:24 +0800 Subject: [PATCH] chat add workflow process --- .../base/chat/chat/answer/index.tsx | 14 ++- .../chat/chat/answer/workflow-process.tsx | 92 +++++++++++++++++++ web/app/components/base/chat/types.ts | 2 +- .../workflow/hooks/use-workflow-run.ts | 1 + .../workflow/panel/debug-and-preview/hooks.ts | 46 +++++++++- web/app/components/workflow/run/node.tsx | 5 +- web/i18n/en-US/workflow.ts | 1 + web/i18n/zh-Hans/workflow.ts | 1 + 8 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 web/app/components/base/chat/chat/answer/workflow-process.tsx diff --git a/web/app/components/base/chat/chat/answer/index.tsx b/web/app/components/base/chat/chat/answer/index.tsx index e64a9ae3ed..39737df555 100644 --- a/web/app/components/base/chat/chat/answer/index.tsx +++ b/web/app/components/base/chat/chat/answer/index.tsx @@ -13,6 +13,7 @@ import AgentContent from './agent-content' import BasicContent from './basic-content' import SuggestedQuestions from './suggested-questions' import More from './more' +import WorkflowProcess from './workflow-process' import { AnswerTriangle } from '@/app/components/base/icons/src/vender/solid/general' import LoadingAnim from '@/app/components/app/chat/loading-anim' import Citation from '@/app/components/app/chat/citation' @@ -46,6 +47,7 @@ const Answer: FC = ({ agent_thoughts, more, annotation, + workflowProcess, } = item const hasAgentThoughts = !!agent_thoughts?.length @@ -70,7 +72,12 @@ const Answer: FC = ({
-
+
{ !responding && ( = ({ /> ) } + { + workflowProcess && ( + + ) + } { responding && !content && !hasAgentThoughts && (
diff --git a/web/app/components/base/chat/chat/answer/workflow-process.tsx b/web/app/components/base/chat/chat/answer/workflow-process.tsx new file mode 100644 index 0000000000..cf352ff5d2 --- /dev/null +++ b/web/app/components/base/chat/chat/answer/workflow-process.tsx @@ -0,0 +1,92 @@ +import { + useMemo, + useState, +} from 'react' +import { useTranslation } from 'react-i18next' +import type { WorkflowProcess } from '../../types' +import { CheckCircle } from '@/app/components/base/icons/src/vender/solid/general' +import { AlertCircle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' +import { Loading02 } from '@/app/components/base/icons/src/vender/line/general' +import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' +import { WorkflowRunningStatus } from '@/app/components/workflow/types' +import NodePanel from '@/app/components/workflow/run/node' + +type WorkflowProcessProps = { + data: WorkflowProcess +} +const WorkflowProcessItem = ({ + data, +}: WorkflowProcessProps) => { + const { t } = useTranslation() + const [collapse, setCollapse] = useState(true) + const running = data.status === WorkflowRunningStatus.Running + const succeeded = data.status === WorkflowRunningStatus.Succeeded + const failed = data.status === WorkflowRunningStatus.Failed || data.status === WorkflowRunningStatus.Stopped + + const background = useMemo(() => { + if (running && !collapse) + return 'linear-gradient(180deg, #E1E4EA 0%, #EAECF0 100%)' + + if (succeeded && !collapse) + return 'linear-gradient(180deg, #ECFDF3 0%, #F6FEF9 100%)' + + if (failed && !collapse) + return 'linear-gradient(180deg, #FEE4E2 0%, #FEF3F2 100%)' + }, [running, succeeded, failed, collapse]) + + return ( +
+
setCollapse(!collapse)} + > + { + running && ( + + ) + } + { + succeeded && ( + + ) + } + { + failed && ( + + ) + } +
+ {t('workflow.common.workflowProcess')} +
+ +
+ { + !collapse && ( +
+ { + data.tracing.map(node => ( +
+ +
+ )) + } +
+ ) + } +
+ ) +} + +export default WorkflowProcessItem diff --git a/web/app/components/base/chat/types.ts b/web/app/components/base/chat/types.ts index 9eec1811fd..092670a295 100644 --- a/web/app/components/base/chat/types.ts +++ b/web/app/components/base/chat/types.ts @@ -52,7 +52,7 @@ export type ChatConfig = Omit & { export type WorkflowProcess = { status: WorkflowRunningStatus - nodes: NodeTracing[] + tracing: NodeTracing[] } export type ChatItem = IChatItem & { diff --git a/web/app/components/workflow/hooks/use-workflow-run.ts b/web/app/components/workflow/hooks/use-workflow-run.ts index 5587859f3e..5bea2ca6ad 100644 --- a/web/app/components/workflow/hooks/use-workflow-run.ts +++ b/web/app/components/workflow/hooks/use-workflow-run.ts @@ -164,6 +164,7 @@ export const useWorkflowRun = () => { draft.result = { ...draft?.result, ...data, + status: WorkflowRunningStatus.Running, } })) diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts index dfa4ce841d..32b99d7570 100644 --- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts +++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts @@ -7,6 +7,7 @@ import { import { useTranslation } from 'react-i18next' import { produce, setAutoFreeze } from 'immer' import { useWorkflowRun } from '../../hooks' +import { WorkflowRunningStatus } from '../../types' import type { ChatItem, Inputs, @@ -261,13 +262,50 @@ export const useChat = ( }) handleUpdateChatList(newChatList) }, - onWorkflowStarted: () => { + onWorkflowStarted: ({ workflow_run_id }) => { + responseItem.workflow_run_id = workflow_run_id + responseItem.workflowProcess = { + status: WorkflowRunningStatus.Running, + tracing: [], + } + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) }, - onWorkflowFinished: () => { + onWorkflowFinished: ({ data }) => { + responseItem.workflowProcess!.status = data.status as WorkflowRunningStatus + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) }, - onNodeStarted: () => { + onNodeStarted: ({ data }) => { + responseItem.workflowProcess!.tracing!.push(data as any) + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) }, - onNodeFinished: () => { + onNodeFinished: ({ data }) => { + const currentIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.node_id === data.node_id) + responseItem.workflowProcess!.tracing[currentIndex] = data as any + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) }, }, ) diff --git a/web/app/components/workflow/run/node.tsx b/web/app/components/workflow/run/node.tsx index 19cf573435..63c03067a2 100644 --- a/web/app/components/workflow/run/node.tsx +++ b/web/app/components/workflow/run/node.tsx @@ -14,9 +14,10 @@ import type { NodeTracing } from '@/types/workflow' type Props = { nodeInfo: NodeTracing collapsed?: boolean + className?: string } -const NodePanel: FC = ({ nodeInfo, collapsed = true }) => { +const NodePanel: FC = ({ nodeInfo, collapsed = true, className }) => { const [collapseState, setCollapseState] = useState(collapsed) const { t } = useTranslation() @@ -38,7 +39,7 @@ const NodePanel: FC = ({ nodeInfo, collapsed = true }) => { } return ( -
+