Merge branch 'feat/rag-2' of https://github.com/langgenius/dify into feat/rag-2

This commit is contained in:
twwu 2025-07-14 16:26:03 +08:00
commit cb8fab7364
27 changed files with 297 additions and 124 deletions

View File

@ -90,6 +90,7 @@ from .datasets.rag_pipeline import (
datasource_content_preview,
rag_pipeline,
rag_pipeline_datasets,
rag_pipeline_draft_variable,
rag_pipeline_import,
rag_pipeline_workflow,
)

View File

@ -53,6 +53,7 @@ class RagPipelineImportApi(Resource):
yaml_content=args.get("yaml_content"),
yaml_url=args.get("yaml_url"),
pipeline_id=args.get("pipeline_id"),
dataset_name=args.get("name"),
)
session.commit()

View File

@ -1,3 +1,4 @@
import re
from core.app.app_config.entities import RagPipelineVariableEntity, VariableEntity
from models.workflow import Workflow
@ -30,10 +31,34 @@ class WorkflowVariablesConfigManager:
"""
variables = []
user_input_form = workflow.rag_pipeline_user_input_form()
# filter variables by start_node_id
for variable in user_input_form:
if variable.get("belong_to_node_id") == start_node_id or variable.get("belong_to_node_id") == "shared":
variables.append(RagPipelineVariableEntity.model_validate(variable))
# get second step node
rag_pipeline_variables = workflow.rag_pipeline_variables
if not rag_pipeline_variables:
return []
variables_map = {item["variable"]: item for item in rag_pipeline_variables}
# get datasource node data
datasource_node_data = None
datasource_nodes = workflow.graph_dict.get("nodes", [])
for datasource_node in datasource_nodes:
if datasource_node.get("id") == start_node_id:
datasource_node_data = datasource_node.get("data", {})
break
if datasource_node_data:
datasource_parameters = datasource_node_data.get("datasource_parameters", {})
for key, value in datasource_parameters.items():
if value.get("value") and isinstance(value.get("value"), str):
pattern = r"\{\{#([a-zA-Z0-9_]{1,50}(?:\.[a-zA-Z0-9_][a-zA-Z0-9_]{0,29}){1,10})#\}\}"
match = re.match(pattern, value["value"])
if match:
full_path = match.group(1)
last_part = full_path.split(".")[-1]
variables_map.pop(last_part)
all_second_step_variables = list(variables_map.values())
for item in all_second_step_variables:
if item.get("belong_to_node_id") == start_node_id or item.get("belong_to_node_id") == "shared":
variables.append(RagPipelineVariableEntity.model_validate(item))
return variables

View File

@ -123,6 +123,7 @@ class RagPipelineDslService:
yaml_url: Optional[str] = None,
pipeline_id: Optional[str] = None,
dataset: Optional[Dataset] = None,
dataset_name: Optional[str] = None,
) -> RagPipelineImportInfo:
"""Import an app from YAML content or URL."""
import_id = str(uuid.uuid4())
@ -265,7 +266,7 @@ class RagPipelineDslService:
dependencies=check_dependencies_pending_data,
)
# create dataset
name = pipeline.name
name = dataset_name or pipeline.name
description = pipeline.description
icon_type = data.get("rag_pipeline", {}).get("icon_type")
icon = data.get("rag_pipeline", {}).get("icon")
@ -883,6 +884,7 @@ class RagPipelineDslService:
import_mode=ImportMode.YAML_CONTENT.value,
yaml_content=rag_pipeline_dataset_create_entity.yaml_content,
dataset=None,
dataset_name=rag_pipeline_dataset_create_entity.name,
)
return {
"id": rag_pipeline_import_info.id,

View File

@ -15,6 +15,9 @@ import {
usePipelineStartRun,
} from '../hooks'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { useConfigsMap } from '../hooks/use-configs-map'
import { useSetWorkflowVarsWithValue } from '@/app/components/workflow/hooks/use-fetch-workflow-inspect-vars'
import { useInspectVarsCrud } from '../hooks/use-inspect-vars-crud'
type RagPipelineMainProps = Pick<WorkflowProps, 'nodes' | 'edges' | 'viewport'>
const RagPipelineMain = ({
@ -62,6 +65,27 @@ const RagPipelineMain = ({
handleExportDSL,
} = useDSL()
const configsMap = useConfigsMap()
const { fetchInspectVars } = useSetWorkflowVarsWithValue({
...configsMap,
})
const {
hasNodeInspectVars,
hasSetInspectVar,
fetchInspectVarValue,
editInspectVarValue,
renameInspectVarName,
appendNodeInspectVars,
deleteInspectVar,
deleteNodeInspectorVars,
deleteAllInspectorVars,
isInspectVarEdited,
resetToLastRunVar,
invalidateSysVarValues,
resetConversationVar,
invalidateConversationVarValues,
} = useInspectVarsCrud()
const hooksStore = useMemo(() => {
return {
availableNodesMetaData,
@ -78,6 +102,22 @@ const RagPipelineMain = ({
getWorkflowRunAndTraceUrl,
exportCheck,
handleExportDSL,
fetchInspectVars,
hasNodeInspectVars,
hasSetInspectVar,
fetchInspectVarValue,
editInspectVarValue,
renameInspectVarName,
appendNodeInspectVars,
deleteInspectVar,
deleteNodeInspectorVars,
deleteAllInspectorVars,
isInspectVarEdited,
resetToLastRunVar,
invalidateSysVarValues,
resetConversationVar,
invalidateConversationVarValues,
configsMap,
}
}, [
availableNodesMetaData,
@ -94,6 +134,22 @@ const RagPipelineMain = ({
getWorkflowRunAndTraceUrl,
exportCheck,
handleExportDSL,
fetchInspectVars,
hasNodeInspectVars,
hasSetInspectVar,
fetchInspectVarValue,
editInspectVarValue,
renameInspectVarName,
appendNodeInspectVars,
deleteInspectVar,
deleteNodeInspectorVars,
deleteAllInspectorVars,
isInspectVarEdited,
resetToLastRunVar,
invalidateSysVarValues,
resetConversationVar,
invalidateConversationVarValues,
configsMap,
])
return (

View File

@ -0,0 +1,13 @@
import { useMemo } from 'react'
import { useStore } from '@/app/components/workflow/store'
import { FlowType } from '@/types/common'
export const useConfigsMap = () => {
const pipelineId = useStore(s => s.pipelineId)
return useMemo(() => {
return {
flowId: pipelineId!,
flowType: FlowType.ragPipeline,
}
}, [pipelineId])
}

View File

@ -0,0 +1,13 @@
import { useInspectVarsCrudCommon } from '../../workflow/hooks/use-inspect-vars-crud-common'
import { useConfigsMap } from './use-configs-map'
export const useInspectVarsCrud = () => {
const configsMap = useConfigsMap()
const apis = useInspectVarsCrudCommon({
...configsMap,
})
return {
...apis,
}
}

View File

@ -18,7 +18,7 @@ import {
useWorkflowRun,
useWorkflowStartRun,
} from '../hooks'
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
import { useWorkflowStore } from '@/app/components/workflow/store'
type WorkflowMainProps = Pick<WorkflowProps, 'nodes' | 'edges' | 'viewport'>
const WorkflowMain = ({
@ -67,16 +67,16 @@ const WorkflowMain = ({
handleWorkflowStartRunInChatflow,
handleWorkflowStartRunInWorkflow,
} = useWorkflowStartRun()
const appId = useStore(s => s.appId)
const availableNodesMetaData = useAvailableNodesMetaData()
const { getWorkflowRunAndTraceUrl } = useGetRunAndTraceUrl()
const {
exportCheck,
handleExportDSL,
} = useDSL()
const configsMap = useConfigsMap()
const { fetchInspectVars } = useSetWorkflowVarsWithValue({
flowId: appId,
...useConfigsMap(),
...configsMap,
})
const {
hasNodeInspectVars,
@ -94,7 +94,6 @@ const WorkflowMain = ({
resetConversationVar,
invalidateConversationVarValues,
} = useInspectVarsCrud()
const configsMap = useConfigsMap()
const hooksStore = useMemo(() => {
return {

View File

@ -1,12 +1,13 @@
import { useMemo } from 'react'
import { useStore } from '@/app/components/workflow/store'
import { FlowType } from '@/types/common'
export const useConfigsMap = () => {
const appId = useStore(s => s.appId)
return useMemo(() => {
return {
conversationVarsUrl: `apps/${appId}/workflows/draft/conversation-variables`,
systemVarsUrl: `apps/${appId}/workflows/draft/system-variables`,
flowId: appId!,
flowType: FlowType.appFlow,
}
}, [appId])
}

View File

@ -1,12 +1,9 @@
import { useStore } from '@/app/components/workflow/store'
import { useInspectVarsCrudCommon } from '../../workflow/hooks/use-inspect-vars-crud-common'
import { useConfigsMap } from './use-configs-map'
export const useInspectVarsCrud = () => {
const appId = useStore(s => s.appId)
const configsMap = useConfigsMap()
const apis = useInspectVarsCrudCommon({
flowId: appId,
...configsMap,
})

View File

@ -31,11 +31,11 @@ export const useWorkflowRun = () => {
const { doSyncWorkflowDraft } = useNodesSyncDraft()
const { handleUpdateWorkflowCanvas } = useWorkflowUpdate()
const pathname = usePathname()
const appId = useAppStore.getState().appDetail?.id
const invalidAllLastRun = useInvalidAllLastRun(appId as string)
const configsMap = useConfigsMap()
const { flowId, flowType } = configsMap
const invalidAllLastRun = useInvalidAllLastRun(flowType, flowId)
const { fetchInspectVars } = useSetWorkflowVarsWithValue({
flowId: appId as string,
...configsMap,
})

View File

@ -17,8 +17,8 @@ import {
import Toast from '../../base/toast'
import RestoringTitle from './restoring-title'
import Button from '@/app/components/base/button'
import { useStore as useAppStore } from '@/app/components/app/store'
import { useInvalidAllLastRun } from '@/service/use-workflow'
import { useHooksStore } from '../hooks-store'
export type HeaderInRestoringProps = {
onRestoreSettled?: () => void
@ -28,9 +28,8 @@ const HeaderInRestoring = ({
}: HeaderInRestoringProps) => {
const { t } = useTranslation()
const workflowStore = useWorkflowStore()
const appDetail = useAppStore.getState().appDetail
const invalidAllLastRun = useInvalidAllLastRun(appDetail!.id)
const configsMap = useHooksStore(s => s.configsMap)
const invalidAllLastRun = useInvalidAllLastRun(configsMap?.flowType, configsMap?.flowId)
const {
deleteAllInspectVars,
} = workflowStore.getState()

View File

@ -17,6 +17,7 @@ import type {
Node,
ValueSelector,
} from '@/app/components/workflow/types'
import type { FlowType } from '@/types/common'
export type AvailableNodesMetaData = {
nodes: NodeDefault[]
@ -61,8 +62,8 @@ export type CommonHooksFnMap = {
resetConversationVar: (varId: string) => Promise<void>
invalidateConversationVarValues: () => void
configsMap?: {
conversationVarsUrl: string
systemVarsUrl: string
flowId: string
flowType: FlowType
}
}

View File

@ -6,22 +6,21 @@ import type { Node } from '@/app/components/workflow/types'
import { fetchAllInspectVars } from '@/service/workflow'
import { useInvalidateConversationVarValues, useInvalidateSysVarValues } from '@/service/use-workflow'
import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync'
import type { FlowType } from '@/types/common'
type Params = {
flowType: FlowType
flowId: string
conversationVarsUrl: string
systemVarsUrl: string
}
export const useSetWorkflowVarsWithValue = ({
flowType,
flowId,
conversationVarsUrl,
systemVarsUrl,
}: Params) => {
const workflowStore = useWorkflowStore()
const store = useStoreApi()
const invalidateConversationVarValues = useInvalidateConversationVarValues(conversationVarsUrl)
const invalidateSysVarValues = useInvalidateSysVarValues(systemVarsUrl)
const invalidateConversationVarValues = useInvalidateConversationVarValues(flowType, flowId)
const invalidateSysVarValues = useInvalidateSysVarValues(flowType, flowId)
const { handleCancelAllNodeSuccessStatus } = useNodesInteractionsWithoutSync()
const setInspectVarsToStore = useCallback((inspectVars: VarInInspect[]) => {
@ -68,10 +67,10 @@ export const useSetWorkflowVarsWithValue = ({
const fetchInspectVars = useCallback(async () => {
invalidateConversationVarValues()
invalidateSysVarValues()
const data = await fetchAllInspectVars(flowId)
const data = await fetchAllInspectVars(flowType, flowId)
setInspectVarsToStore(data)
handleCancelAllNodeSuccessStatus() // to make sure clear node output show the unset status
}, [invalidateConversationVarValues, invalidateSysVarValues, flowId, setInspectVarsToStore, handleCancelAllNodeSuccessStatus])
}, [invalidateConversationVarValues, invalidateSysVarValues, flowType, flowId, setInspectVarsToStore, handleCancelAllNodeSuccessStatus])
return {
fetchInspectVars,
}

View File

@ -3,38 +3,39 @@ import { useWorkflowStore } from '@/app/components/workflow/store'
import type { ValueSelector } from '@/app/components/workflow/types'
import type { VarInInspect } from '@/types/workflow'
import { VarInInspectType } from '@/types/workflow'
import {
useDeleteAllInspectorVars,
useDeleteInspectVar,
useDeleteNodeInspectorVars,
useEditInspectorVar,
useInvalidateConversationVarValues,
useInvalidateSysVarValues,
useResetConversationVar,
useResetToLastRunValue,
} from '@/service/use-workflow'
import { useCallback } from 'react'
import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import produce from 'immer'
import type { Node } from '@/app/components/workflow/types'
import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync'
import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync'
import type { FlowType } from '@/types/common'
import useFLow from '@/service/use-flow'
type Params = {
flowId: string
conversationVarsUrl: string
systemVarsUrl: string
flowType: FlowType
}
export const useInspectVarsCrudCommon = ({
flowId,
conversationVarsUrl,
systemVarsUrl,
flowType,
}: Params) => {
const workflowStore = useWorkflowStore()
const invalidateConversationVarValues = useInvalidateConversationVarValues(conversationVarsUrl!)
const {
useInvalidateConversationVarValues,
useInvalidateSysVarValues,
useResetConversationVar,
useResetToLastRunValue,
useDeleteAllInspectorVars,
useDeleteNodeInspectorVars,
useDeleteInspectVar,
useEditInspectorVar,
} = useFLow({ flowType })
const invalidateConversationVarValues = useInvalidateConversationVarValues(flowId)
const { mutateAsync: doResetConversationVar } = useResetConversationVar(flowId)
const { mutateAsync: doResetToLastRunValue } = useResetToLastRunValue(flowId)
const invalidateSysVarValues = useInvalidateSysVarValues(systemVarsUrl!)
const invalidateSysVarValues = useInvalidateSysVarValues(flowId)
const { mutateAsync: doDeleteAllInspectorVars } = useDeleteAllInspectorVars(flowId)
const { mutate: doDeleteNodeInspectorVars } = useDeleteNodeInspectorVars(flowId)
@ -89,7 +90,6 @@ export const useInspectVarsCrudCommon = ({
const fetchInspectVarValue = useCallback(async (selector: ValueSelector) => {
const {
appId,
setNodeInspectVars,
} = workflowStore.getState()
const nodeId = selector[0]
@ -103,9 +103,9 @@ export const useInspectVarsCrudCommon = ({
invalidateConversationVarValues()
return
}
const vars = await fetchNodeInspectVars(appId, nodeId)
const vars = await fetchNodeInspectVars(flowType, flowId, nodeId)
setNodeInspectVars(nodeId, vars)
}, [workflowStore, invalidateSysVarValues, invalidateConversationVarValues])
}, [workflowStore, flowType, flowId, invalidateSysVarValues, invalidateConversationVarValues])
// after last run would call this
const appendNodeInspectVars = useCallback((nodeId: string, payload: VarInInspect[], allNodes: Node[]) => {

View File

@ -4,12 +4,14 @@ import {
useConversationVarValues,
useSysVarValues,
} from '@/service/use-workflow'
import { FlowType } from '@/types/common'
const useInspectVarsCrud = () => {
const nodesWithInspectVars = useStore(s => s.nodesWithInspectVars)
const configsMap = useHooksStore(s => s.configsMap)
const { data: conversationVars } = useConversationVarValues(configsMap?.conversationVarsUrl)
const { data: systemVars } = useSysVarValues(configsMap?.systemVarsUrl)
const isRagPipeline = configsMap?.flowType === FlowType.ragPipeline
const { data: conversationVars } = useConversationVarValues(configsMap?.flowType, !isRagPipeline ? configsMap?.flowId : '')
const { data: systemVars } = useSysVarValues(configsMap?.flowType, !isRagPipeline ? configsMap?.flowId : '')
const hasNodeInspectVars = useHooksStore(s => s.hasNodeInspectVars)
const hasSetInspectVar = useHooksStore(s => s.hasSetInspectVar)
const fetchInspectVarValue = useHooksStore(s => s.fetchInspectVarValue)

View File

@ -59,6 +59,8 @@ import { useLogs } from '@/app/components/workflow/run/hooks'
import PanelWrap from '../before-run-form/panel-wrap'
import SpecialResultPanel from '@/app/components/workflow/run/special-result-panel'
import { Stop } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { FlowType } from '@/types/common'
type BasePanelProps = {
children: ReactNode
@ -184,6 +186,7 @@ const BasePanel: FC<BasePanelProps> = ({
nodesMap,
} = useNodesMetaData()
const configsMap = useHooksStore(s => s.configsMap)
const {
isShowSingleRun,
hideSingleRun,
@ -205,6 +208,8 @@ const BasePanel: FC<BasePanelProps> = ({
getFilteredExistVarForms,
} = useLastRun<typeof data>({
id,
flowId: configsMap?.flowId || '',
flowType: configsMap?.flowType || FlowType.appFlow,
data,
defaultRunInputData: nodesMap?.[data.type]?.defaultRunInputData || {},
isPaused,

View File

@ -8,6 +8,8 @@ import NoData from './no-data'
import { useLastRun } from '@/service/use-workflow'
import { RiLoader2Line } from '@remixicon/react'
import type { NodeTracing } from '@/types/workflow'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { FlowType } from '@/types/common'
type Props = {
appId: string
@ -35,6 +37,7 @@ const LastRun: FC<Props> = ({
isPaused,
...otherResultPanelProps
}) => {
const configsMap = useHooksStore(s => s.configsMap)
const isOneStepRunSucceed = oneStepRunRunningStatus === NodeRunningStatus.Succeeded
const isOneStepRunFailed = oneStepRunRunningStatus === NodeRunningStatus.Failed
// hide page and return to page would lost the oneStepRunRunningStatus
@ -44,7 +47,7 @@ const LastRun: FC<Props> = ({
const hidePageOneStepRunFinished = [NodeRunningStatus.Succeeded, NodeRunningStatus.Failed].includes(hidePageOneStepFinishedStatus!)
const canRunLastRun = !isRunAfterSingleRun || isOneStepRunSucceed || isOneStepRunFailed || (pageHasHide && hidePageOneStepRunFinished)
const { data: lastRunResult, isFetching, error } = useLastRun(appId, nodeId, canRunLastRun)
const { data: lastRunResult, isFetching, error } = useLastRun(configsMap?.flowType || FlowType.appFlow, configsMap?.flowId || '', nodeId, canRunLastRun)
const isRunning = useMemo(() => {
if(isPaused)
return false

View File

@ -57,6 +57,8 @@ const singleRunFormParamsHooks: Record<BlockEnum, any> = {
[BlockEnum.IterationStart]: undefined,
[BlockEnum.LoopStart]: undefined,
[BlockEnum.LoopEnd]: undefined,
[BlockEnum.DataSource]: undefined,
[BlockEnum.KnowledgeBase]: undefined,
}
const useSingleRunFormParamsHooks = (nodeType: BlockEnum) => {
@ -89,6 +91,8 @@ const getDataForCheckMoreHooks: Record<BlockEnum, any> = {
[BlockEnum.Assigner]: undefined,
[BlockEnum.LoopStart]: undefined,
[BlockEnum.LoopEnd]: undefined,
[BlockEnum.DataSource]: undefined,
[BlockEnum.KnowledgeBase]: undefined,
}
const useGetDataForCheckMoreHooks = <T>(nodeType: BlockEnum) => {
@ -119,6 +123,8 @@ const useLastRun = <T>({
const {
id,
flowId,
flowType,
data,
} = oneStepRunParams
const oneStepRunRes = useOneStepRun({
@ -129,7 +135,6 @@ const useLastRun = <T>({
})
const {
appId,
hideSingleRun,
handleRun: doCallRunApi,
getInputVars,
@ -199,7 +204,7 @@ const useLastRun = <T>({
setInitShowLastRunTab(false)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initShowLastRunTab])
const invalidLastRun = useInvalidLastRun(appId!, id)
const invalidLastRun = useInvalidLastRun(flowType, flowId, id)
const handleRunWithParams = async (data: Record<string, any>) => {
const { isValid } = checkValid()

View File

@ -11,7 +11,6 @@ import { getNodeInfoById, isConversationVar, isENV, isSystemVar, toNodeOutputVar
import type { CommonNodeType, InputVar, ValueSelector, Var, Variable } from '@/app/components/workflow/types'
import { BlockEnum, InputVarType, NodeRunningStatus, VarType } from '@/app/components/workflow/types'
import { useStore as useAppStore } from '@/app/components/app/store'
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
import { fetchNodeInspectVars, getIterationSingleNodeRunUrl, getLoopSingleNodeRunUrl, singleNodeRun } from '@/service/workflow'
import Toast from '@/app/components/base/toast'
@ -52,6 +51,7 @@ import {
} from 'reactflow'
import { useInvalidLastRun } from '@/service/use-workflow'
import useInspectVarsCrud from '../../../hooks/use-inspect-vars-crud'
import type { FlowType } from '@/types/common'
// eslint-disable-next-line ts/no-unsafe-function-type
const checkValidFns: Record<BlockEnum, Function> = {
[BlockEnum.LLM]: checkLLMValid,
@ -72,6 +72,8 @@ const checkValidFns: Record<BlockEnum, Function> = {
export type Params<T> = {
id: string
flowId: string
flowType: FlowType
data: CommonNodeType<T>
defaultRunInputData: Record<string, any>
moreDataForCheckValid?: any
@ -106,6 +108,8 @@ const varTypeToInputVarType = (type: VarType, {
const useOneStepRun = <T>({
id,
flowId,
flowType,
data,
defaultRunInputData,
moreDataForCheckValid,
@ -153,7 +157,6 @@ const useOneStepRun = <T>({
const checkValid = checkValidFns[data.type]
const appId = useAppStore.getState().appDetail?.id
const [runInputData, setRunInputData] = useState<Record<string, any>>(defaultRunInputData || {})
const runInputDataRef = useRef(runInputData)
const handleSetRunInputData = useCallback((data: Record<string, any>) => {
@ -168,7 +171,7 @@ const useOneStepRun = <T>({
const {
setShowSingleRunPanel,
} = workflowStore.getState()
const invalidLastRun = useInvalidLastRun(appId!, id)
const invalidLastRun = useInvalidLastRun(flowType, flowId!, id)
const [runResult, doSetRunResult] = useState<NodeRunResult | null>(null)
const {
appendNodeInspectVars,
@ -195,7 +198,7 @@ const useOneStepRun = <T>({
}
// run fail may also update the inspect vars when the node set the error default output.
const vars = await fetchNodeInspectVars(appId!, id)
const vars = await fetchNodeInspectVars(flowType, flowId!, id)
const { getNodes } = store.getState()
const nodes = getNodes()
appendNodeInspectVars(id, vars, nodes)
@ -205,7 +208,7 @@ const useOneStepRun = <T>({
invalidateSysVarValues()
invalidateConversationVarValues() // loop, iteration, variable assigner node can update the conversation variables, but to simple the logic(some nodes may also can update in the future), all nodes refresh.
}
}, [isRunAfterSingleRun, runningStatus, appId, id, store, appendNodeInspectVars, invalidLastRun, isStartNode, invalidateSysVarValues, invalidateConversationVarValues])
}, [isRunAfterSingleRun, runningStatus, flowId, id, store, appendNodeInspectVars, invalidLastRun, isStartNode, invalidateSysVarValues, invalidateConversationVarValues])
const { handleNodeDataUpdate }: { handleNodeDataUpdate: (data: any) => void } = useNodeDataUpdate()
const setNodeRunning = () => {
@ -305,14 +308,14 @@ const useOneStepRun = <T>({
else {
postData.inputs = submitData
}
res = await singleNodeRun(appId!, id, postData) as any
res = await singleNodeRun(flowType, flowId!, id, postData) as any
}
else if (isIteration) {
setIterationRunResult([])
let _iterationResult: NodeTracing[] = []
let _runResult: any = null
ssePost(
getIterationSingleNodeRunUrl(isChatMode, appId!, id),
getIterationSingleNodeRunUrl(flowType, isChatMode, flowId!, id),
{ body: { inputs: submitData } },
{
onWorkflowStarted: noop,
@ -415,7 +418,7 @@ const useOneStepRun = <T>({
let _loopResult: NodeTracing[] = []
let _runResult: any = null
ssePost(
getLoopSingleNodeRunUrl(isChatMode, appId!, id),
getLoopSingleNodeRunUrl(flowType, isChatMode, flowId!, id),
{ body: { inputs: submitData } },
{
onWorkflowStarted: noop,
@ -633,7 +636,6 @@ const useOneStepRun = <T>({
}
return {
appId,
isShowSingleRun,
hideSingleRun,
showSingleRun,

View File

@ -34,7 +34,7 @@ import {
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { getThreadMessages } from '@/app/components/base/chat/utils'
import { useInvalidAllLastRun } from '@/service/use-workflow'
import { useParams } from 'next/navigation'
import { useHooksStore } from '../../hooks-store'
type GetAbortController = (abortController: AbortController) => void
type SendCallback = {
@ -58,8 +58,8 @@ export const useChat = (
const taskIdRef = useRef('')
const [isResponding, setIsResponding] = useState(false)
const isRespondingRef = useRef(false)
const { appId } = useParams()
const invalidAllLastRun = useInvalidAllLastRun(appId as string)
const configsMap = useHooksStore(s => s.configsMap)
const invalidAllLastRun = useInvalidAllLastRun(configsMap?.flowType, configsMap?.flowId)
const { fetchInspectVars } = useSetWorkflowVarsWithValue()
const [suggestedQuestions, setSuggestQuestions] = useState<string[]>([])
const suggestedQuestionsAbortControllerRef = useRef<AbortController | null>(null)

View File

@ -17,6 +17,7 @@ import RestoreConfirmModal from './restore-confirm-modal'
import DeleteConfirmModal from './delete-confirm-modal'
import VersionInfoModal from '@/app/components/app/app-publisher/version-info-modal'
import Toast from '@/app/components/base/toast'
import { useHooksStore } from '../../hooks-store'
const HISTORY_PER_PAGE = 10
const INITIAL_PAGE = 1
@ -46,9 +47,8 @@ export const VersionHistoryPanel = ({
const currentVersion = useStore(s => s.currentVersion)
const setCurrentVersion = useStore(s => s.setCurrentVersion)
const userProfile = useAppContextSelector(s => s.userProfile)
const appId = useStore(s => s.appId)
const pipelineId = useStore(s => s.pipelineId)
const invalidAllLastRun = useInvalidAllLastRun(appId || pipelineId || '')
const configsMap = useHooksStore(s => s.configsMap)
const invalidAllLastRun = useInvalidAllLastRun(configsMap?.flowType, configsMap?.flowId)
const {
deleteAllInspectVars,
} = workflowStore.getState()

33
web/service/use-flow.ts Normal file
View File

@ -0,0 +1,33 @@
import type { FlowType } from '@/types/common'
import {
useDeleteAllInspectorVars as useDeleteAllInspectorVarsInner,
useDeleteInspectVar as useDeleteInspectVarInner,
useDeleteNodeInspectorVars as useDeleteNodeInspectorVarsInner,
useEditInspectorVar as useEditInspectorVarInner,
useInvalidateConversationVarValues as useInvalidateConversationVarValuesInner,
useInvalidateSysVarValues as useInvalidateSysVarValuesInner,
useResetConversationVar as useResetConversationVarInner,
useResetToLastRunValue as useResetToLastRunValueInner,
} from './use-workflow'
import { curry } from 'lodash-es'
type Params = {
flowType: FlowType
}
const useFLow = ({
flowType,
}: Params) => {
return {
useInvalidateConversationVarValues: curry(useInvalidateConversationVarValuesInner)(flowType),
useInvalidateSysVarValues: curry(useInvalidateSysVarValuesInner)(flowType),
useResetConversationVar: curry(useResetConversationVarInner)(flowType),
useResetToLastRunValue: curry(useResetToLastRunValueInner)(flowType),
useDeleteAllInspectorVars: curry(useDeleteAllInspectorVarsInner)(flowType),
useDeleteNodeInspectorVars: curry(useDeleteNodeInspectorVarsInner)(flowType),
useDeleteInspectVar: curry(useDeleteInspectVarInner)(flowType),
useEditInspectorVar: curry(useEditInspectorVarInner)(flowType),
}
}
export default useFLow

View File

@ -12,6 +12,8 @@ import type {
} from '@/types/workflow'
import type { CommonResponse } from '@/models/common'
import { useInvalid, useReset } from './use-base'
import type { FlowType } from '@/types/common'
import { getFlowPrefix } from './utils'
const NAME_SPACE = 'workflow'
@ -102,12 +104,12 @@ export const usePublishWorkflow = () => {
}
const useLastRunKey = [NAME_SPACE, 'last-run']
export const useLastRun = (appID: string, nodeId: string, enabled: boolean) => {
export const useLastRun = (flowType: FlowType, flowId: string, nodeId: string, enabled: boolean) => {
return useQuery<NodeTracing>({
enabled,
queryKey: [...useLastRunKey, appID, nodeId],
queryKey: [...useLastRunKey, flowType, flowId, nodeId],
queryFn: async () => {
return get(`apps/${appID}/workflows/draft/nodes/${nodeId}/last-run`, {}, {
return get(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/nodes/${nodeId}/last-run`, {}, {
silent: true,
})
},
@ -115,103 +117,101 @@ export const useLastRun = (appID: string, nodeId: string, enabled: boolean) => {
})
}
export const useInvalidLastRun = (appId: string, nodeId: string) => {
return useInvalid([NAME_SPACE, 'last-run', appId, nodeId])
export const useInvalidLastRun = (flowType: FlowType, flowId: string, nodeId: string) => {
return useInvalid([NAME_SPACE, flowType, 'last-run', flowId, nodeId])
}
// Rerun workflow or change the version of workflow
export const useInvalidAllLastRun = (appId: string) => {
return useInvalid([NAME_SPACE, 'last-run', appId])
export const useInvalidAllLastRun = (flowType?: FlowType, flowId?: string) => {
return useInvalid([NAME_SPACE, flowType, 'last-run', flowId])
}
const useConversationVarValuesKey = [NAME_SPACE, 'conversation-variable']
export const useConversationVarValues = (url?: string) => {
export const useConversationVarValues = (flowType?: FlowType, flowId?: string) => {
return useQuery({
enabled: !!url,
queryKey: [...useConversationVarValuesKey, url],
enabled: !!flowId,
queryKey: [NAME_SPACE, flowType, 'conversation var values', flowId],
queryFn: async () => {
const { items } = (await get(url || '')) as { items: VarInInspect[] }
const { items } = (await get(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/conversation-variables`)) as { items: VarInInspect[] }
return items
},
})
}
export const useInvalidateConversationVarValues = (url: string) => {
return useInvalid([...useConversationVarValuesKey, url])
export const useInvalidateConversationVarValues = (flowType: FlowType, flowId: string) => {
return useInvalid([NAME_SPACE, flowType, 'conversation var values', flowId])
}
export const useResetConversationVar = (appId: string) => {
export const useResetConversationVar = (flowType: FlowType, flowId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'reset conversation var', appId],
mutationKey: [NAME_SPACE, flowType, 'reset conversation var', flowId],
mutationFn: async (varId: string) => {
return put(`apps/${appId}/workflows/draft/variables/${varId}/reset`)
return put(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/variables/${varId}/reset`)
},
})
}
export const useResetToLastRunValue = (appId: string) => {
export const useResetToLastRunValue = (flowType: FlowType, flowId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'reset to last run value', appId],
mutationKey: [NAME_SPACE, flowType, 'reset to last run value', flowId],
mutationFn: async (varId: string): Promise<{ value: any }> => {
return put(`apps/${appId}/workflows/draft/variables/${varId}/reset`)
return put(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/variables/${varId}/reset`)
},
})
}
export const useSysVarValuesKey = [NAME_SPACE, 'sys-variable']
export const useSysVarValues = (url?: string) => {
export const useSysVarValues = (flowType?: FlowType, flowId?: string) => {
return useQuery({
enabled: !!url,
queryKey: [...useSysVarValuesKey, url],
enabled: !!flowId,
queryKey: [NAME_SPACE, flowType, 'sys var values', flowId],
queryFn: async () => {
const { items } = (await get(url || '')) as { items: VarInInspect[] }
const { items } = (await get(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/system-variables`)) as { items: VarInInspect[] }
return items
},
})
}
export const useInvalidateSysVarValues = (url: string) => {
return useInvalid([...useSysVarValuesKey, url])
export const useInvalidateSysVarValues = (flowType: FlowType, flowId: string) => {
return useInvalid([NAME_SPACE, flowType, 'sys var values', flowId])
}
export const useDeleteAllInspectorVars = (appId: string) => {
export const useDeleteAllInspectorVars = (flowType: FlowType, flowId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'delete all inspector vars', appId],
mutationKey: [NAME_SPACE, flowType, 'delete all inspector vars', flowId],
mutationFn: async () => {
return del(`apps/${appId}/workflows/draft/variables`)
return del(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/variables`)
},
})
}
export const useDeleteNodeInspectorVars = (appId: string) => {
export const useDeleteNodeInspectorVars = (flowType: FlowType, flowId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'delete node inspector vars', appId],
mutationKey: [NAME_SPACE, flowType, 'delete node inspector vars', flowId],
mutationFn: async (nodeId: string) => {
return del(`apps/${appId}/workflows/draft/nodes/${nodeId}/variables`)
return del(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/nodes/${nodeId}/variables`)
},
})
}
export const useDeleteInspectVar = (appId: string) => {
export const useDeleteInspectVar = (flowType: FlowType, flowId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'delete inspector var', appId],
mutationKey: [NAME_SPACE, flowType, 'delete inspector var', flowId],
mutationFn: async (varId: string) => {
return del(`apps/${appId}/workflows/draft/variables/${varId}`)
return del(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/variables/${varId}`)
},
})
}
// edit the name or value of the inspector var
export const useEditInspectorVar = (appId: string) => {
export const useEditInspectorVar = (flowType: FlowType, flowId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'edit inspector var', appId],
mutationKey: [NAME_SPACE, flowType, 'edit inspector var', flowId],
mutationFn: async ({ varId, ...rest }: {
varId: string
name?: string
value?: any
}) => {
return patch(`apps/${appId}/workflows/draft/variables/${varId}`, {
return patch(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/variables/${varId}`, {
body: rest,
})
},

10
web/service/utils.ts Normal file
View File

@ -0,0 +1,10 @@
import { FlowType } from '@/types/common'
export const flowPrefixMap = {
[FlowType.appFlow]: 'apps',
[FlowType.ragPipeline]: 'rag/pipelines',
}
export const getFlowPrefix = (type?: FlowType) => {
return flowPrefixMap[type!] || flowPrefixMap[FlowType.appFlow]
}

View File

@ -10,6 +10,8 @@ import type {
} from '@/types/workflow'
import type { BlockEnum } from '@/app/components/workflow/types'
import type { VarInInspect } from '@/types/workflow'
import type { FlowType } from '@/types/common'
import { getFlowPrefix } from './utils'
export const fetchWorkflowDraft = (url: string) => {
return get(url, {}, { silent: true }) as Promise<FetchWorkflowDraftResponse>
@ -34,16 +36,16 @@ export const fetchChatRunHistory: Fetcher<ChatRunHistoryResponse, string> = (url
return get<ChatRunHistoryResponse>(url)
}
export const singleNodeRun = (appId: string, nodeId: string, params: object) => {
return post(`apps/${appId}/workflows/draft/nodes/${nodeId}/run`, { body: params })
export const singleNodeRun = (flowType: FlowType, flowId: string, nodeId: string, params: object) => {
return post(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/nodes/${nodeId}/run`, { body: params })
}
export const getIterationSingleNodeRunUrl = (isChatFlow: boolean, appId: string, nodeId: string) => {
return `apps/${appId}/${isChatFlow ? 'advanced-chat/' : ''}workflows/draft/iteration/nodes/${nodeId}/run`
export const getIterationSingleNodeRunUrl = (flowType: FlowType, isChatFlow: boolean, flowId: string, nodeId: string) => {
return `${getFlowPrefix(flowType)}/${flowId}/${isChatFlow ? 'advanced-chat/' : ''}workflows/draft/iteration/nodes/${nodeId}/run`
}
export const getLoopSingleNodeRunUrl = (isChatFlow: boolean, appId: string, nodeId: string) => {
return `apps/${appId}/${isChatFlow ? 'advanced-chat/' : ''}workflows/draft/loop/nodes/${nodeId}/run`
export const getLoopSingleNodeRunUrl = (flowType: FlowType, isChatFlow: boolean, flowId: string, nodeId: string) => {
return `${getFlowPrefix(flowType)}/${flowId}/${isChatFlow ? 'advanced-chat/' : ''}workflows/draft/loop/nodes/${nodeId}/run`
}
export const fetchPublishedWorkflow: Fetcher<FetchWorkflowDraftResponse, string> = (url) => {
@ -78,13 +80,13 @@ export const fetchCurrentValueOfConversationVariable: Fetcher<ConversationVariab
return get<ConversationVariableResponse>(url, { params })
}
const fetchAllInspectVarsOnePage = async (appId: string, page: number): Promise<{ total: number, items: VarInInspect[] }> => {
return get(`apps/${appId}/workflows/draft/variables`, {
const fetchAllInspectVarsOnePage = async (flowType: FlowType, flowId: string, page: number): Promise<{ total: number, items: VarInInspect[] }> => {
return get(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/variables`, {
params: { page, limit: 100 },
})
}
export const fetchAllInspectVars = async (appId: string): Promise<VarInInspect[]> => {
const res = await fetchAllInspectVarsOnePage(appId, 1)
export const fetchAllInspectVars = async (flowType: FlowType, flowId: string): Promise<VarInInspect[]> => {
const res = await fetchAllInspectVarsOnePage(flowType, flowId, 1)
const { items, total } = res
if (total <= 100)
return items
@ -92,7 +94,7 @@ export const fetchAllInspectVars = async (appId: string): Promise<VarInInspect[]
const pageCount = Math.ceil(total / 100)
const promises = []
for (let i = 2; i <= pageCount; i++)
promises.push(fetchAllInspectVarsOnePage(appId, i))
promises.push(fetchAllInspectVarsOnePage(flowType, flowId, i))
const restData = await Promise.all(promises)
restData.forEach(({ items: item }) => {
@ -101,7 +103,7 @@ export const fetchAllInspectVars = async (appId: string): Promise<VarInInspect[]
return items
}
export const fetchNodeInspectVars = async (appId: string, nodeId: string): Promise<VarInInspect[]> => {
const { items } = (await get(`apps/${appId}/workflows/draft/nodes/${nodeId}/variables`)) as { items: VarInInspect[] }
export const fetchNodeInspectVars = async (flowType: FlowType, flowId: string, nodeId: string): Promise<VarInInspect[]> => {
const { items } = (await get(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/nodes/${nodeId}/variables`)) as { items: VarInInspect[] }
return items
}

4
web/types/common.ts Normal file
View File

@ -0,0 +1,4 @@
export enum FlowType {
appFlow = 'appFlow',
ragPipeline = 'ragPipeline',
}