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

pull/21398/head
twwu 11 months ago
commit bad451d5ec

@ -21,7 +21,7 @@ const Publisher = () => {
const handleOpenChange = useCallback((newOpen: boolean) => { const handleOpenChange = useCallback((newOpen: boolean) => {
if (newOpen) if (newOpen)
handleSyncWorkflowDraft() handleSyncWorkflowDraft(true)
setOpen(newOpen) setOpen(newOpen)
}, [handleSyncWorkflowDraft]) }, [handleSyncWorkflowDraft])

@ -1,6 +1,6 @@
import { useCallback } from 'react' import { useCallback } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useStore } from '../store' import { useWorkflowStore } from '../store'
import { getVarType, toNodeAvailableVars } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { getVarType, toNodeAvailableVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import type { import type {
Node, Node,
@ -13,8 +13,7 @@ import { useStoreApi } from 'reactflow'
export const useWorkflowVariables = () => { export const useWorkflowVariables = () => {
const { t } = useTranslation() const { t } = useTranslation()
const environmentVariables = useStore(s => s.environmentVariables) const workflowStore = useWorkflowStore()
const conversationVariables = useStore(s => s.conversationVariables)
const getNodeAvailableVars = useCallback(({ const getNodeAvailableVars = useCallback(({
parentNode, parentNode,
@ -31,6 +30,11 @@ export const useWorkflowVariables = () => {
hideEnv?: boolean hideEnv?: boolean
hideChatVar?: boolean hideChatVar?: boolean
}): NodeOutPutVar[] => { }): NodeOutPutVar[] => {
const {
conversationVariables,
environmentVariables,
ragPipelineVariables,
} = workflowStore.getState()
return toNodeAvailableVars({ return toNodeAvailableVars({
parentNode, parentNode,
t, t,
@ -38,9 +42,10 @@ export const useWorkflowVariables = () => {
isChatMode, isChatMode,
environmentVariables: hideEnv ? [] : environmentVariables, environmentVariables: hideEnv ? [] : environmentVariables,
conversationVariables: (isChatMode && !hideChatVar) ? conversationVariables : [], conversationVariables: (isChatMode && !hideChatVar) ? conversationVariables : [],
ragVariables: ragPipelineVariables,
filterVar, filterVar,
}) })
}, [conversationVariables, environmentVariables, t]) }, [t, workflowStore])
const getCurrentVariableType = useCallback(({ const getCurrentVariableType = useCallback(({
parentNode, parentNode,
@ -59,6 +64,11 @@ export const useWorkflowVariables = () => {
isChatMode: boolean isChatMode: boolean
isConstant?: boolean isConstant?: boolean
}) => { }) => {
const {
conversationVariables,
environmentVariables,
ragPipelineVariables,
} = workflowStore.getState()
return getVarType({ return getVarType({
parentNode, parentNode,
valueSelector, valueSelector,
@ -69,8 +79,9 @@ export const useWorkflowVariables = () => {
isConstant, isConstant,
environmentVariables, environmentVariables,
conversationVariables, conversationVariables,
ragVariables: ragPipelineVariables,
}) })
}, [conversationVariables, environmentVariables]) }, [workflowStore])
return { return {
getNodeAvailableVars, getNodeAvailableVars,

@ -22,6 +22,7 @@ import type { StartNodeType } from '@/app/components/workflow/nodes/start/types'
import type { ConversationVariable, EnvironmentVariable, Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types' import type { ConversationVariable, EnvironmentVariable, Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
import type { VariableAssignerNodeType } from '@/app/components/workflow/nodes/variable-assigner/types' import type { VariableAssignerNodeType } from '@/app/components/workflow/nodes/variable-assigner/types'
import type { Field as StructField } from '@/app/components/workflow/nodes/llm/types' import type { Field as StructField } from '@/app/components/workflow/nodes/llm/types'
import type { RAGPipelineVariable } from '@/models/pipeline'
import { import {
HTTP_REQUEST_OUTPUT_STRUCT, HTTP_REQUEST_OUTPUT_STRUCT,
@ -51,6 +52,10 @@ export const isConversationVar = (valueSelector: ValueSelector) => {
return valueSelector[0] === 'conversation' return valueSelector[0] === 'conversation'
} }
export const isRagVariableVar = (valueSelector: ValueSelector) => {
return valueSelector[0] === 'rag'
}
const inputVarTypeToVarType = (type: InputVarType): VarType => { const inputVarTypeToVarType = (type: InputVarType): VarType => {
return ({ return ({
[InputVarType.number]: VarType.number, [InputVarType.number]: VarType.number,
@ -170,6 +175,7 @@ const formatItem = (
item: any, item: any,
isChatMode: boolean, isChatMode: boolean,
filterVar: (payload: Var, selector: ValueSelector) => boolean, filterVar: (payload: Var, selector: ValueSelector) => boolean,
ragVars?: Var[],
): NodeOutPutVar => { ): NodeOutPutVar => {
const { id, data } = item const { id, data } = item
@ -460,7 +466,7 @@ const formatItem = (
} }
case BlockEnum.DataSource: { case BlockEnum.DataSource: {
res.vars = DataSourceNodeDefault.getOutputVars?.(data as DataSourceNodeType) || [] res.vars = DataSourceNodeDefault.getOutputVars?.(data as DataSourceNodeType, ragVars) || []
break break
} }
@ -484,6 +490,18 @@ const formatItem = (
}) as Var[] }) as Var[]
break break
} }
case 'rag': {
res.vars = data.ragVariables.map((ragVarialbe: RAGPipelineVariable) => {
return {
variable: `rag.${ragVarialbe.variable}`,
type: inputVarTypeToVarType(ragVarialbe.type as any),
des: ragVarialbe.label,
isRagVariable: true,
}
}) as Var[]
break
}
} }
const { error_strategy } = data const { error_strategy } = data
@ -564,6 +582,7 @@ export const toNodeOutputVars = (
filterVar = (_payload: Var, _selector: ValueSelector) => true, filterVar = (_payload: Var, _selector: ValueSelector) => true,
environmentVariables: EnvironmentVariable[] = [], environmentVariables: EnvironmentVariable[] = [],
conversationVariables: ConversationVariable[] = [], conversationVariables: ConversationVariable[] = [],
ragVariables: RAGPipelineVariable[] = [],
): NodeOutPutVar[] => { ): NodeOutPutVar[] => {
// ENV_NODE data format // ENV_NODE data format
const ENV_NODE = { const ENV_NODE = {
@ -583,6 +602,15 @@ export const toNodeOutputVars = (
chatVarList: conversationVariables, chatVarList: conversationVariables,
}, },
} }
// RAG_PIPELINE_NODE data format
const RAG_PIPELINE_NODE = {
id: 'rag',
data: {
title: 'SHARED INPUTS',
type: 'rag',
ragVariables: ragVariables.filter(ragVariable => ragVariable.belong_to_node_id === 'shared'),
},
}
// Sort nodes in reverse chronological order (most recent first) // Sort nodes in reverse chronological order (most recent first)
const sortedNodes = [...nodes].sort((a, b) => { const sortedNodes = [...nodes].sort((a, b) => {
if (a.data.type === BlockEnum.Start) return 1 if (a.data.type === BlockEnum.Start) return 1
@ -599,9 +627,20 @@ export const toNodeOutputVars = (
...sortedNodes.filter(node => SUPPORT_OUTPUT_VARS_NODE.includes(node?.data?.type)), ...sortedNodes.filter(node => SUPPORT_OUTPUT_VARS_NODE.includes(node?.data?.type)),
...(environmentVariables.length > 0 ? [ENV_NODE] : []), ...(environmentVariables.length > 0 ? [ENV_NODE] : []),
...((isChatMode && conversationVariables.length > 0) ? [CHAT_VAR_NODE] : []), ...((isChatMode && conversationVariables.length > 0) ? [CHAT_VAR_NODE] : []),
...(RAG_PIPELINE_NODE.data.ragVariables.length > 0 ? [RAG_PIPELINE_NODE] : []),
].map((node) => { ].map((node) => {
let ragVariablesInDataSource: RAGPipelineVariable[] = []
if (node.data.type === BlockEnum.DataSource)
ragVariablesInDataSource = ragVariables.filter(ragVariable => ragVariable.belong_to_node_id === node.id)
return { return {
...formatItem(node, isChatMode, filterVar), ...formatItem(node, isChatMode, filterVar, ragVariablesInDataSource.map(
(ragVariable: RAGPipelineVariable) => ({
variable: ragVariable.variable,
type: inputVarTypeToVarType(ragVariable.type as any),
description: ragVariable.label,
isRagVariable: true,
} as Var),
)),
isStartNode: node.data.type === BlockEnum.Start, isStartNode: node.data.type === BlockEnum.Start,
} }
}).filter(item => item.vars.length > 0) }).filter(item => item.vars.length > 0)
@ -719,6 +758,7 @@ export const getVarType = ({
isConstant, isConstant,
environmentVariables = [], environmentVariables = [],
conversationVariables = [], conversationVariables = [],
ragVariables = [],
}: { }: {
valueSelector: ValueSelector valueSelector: ValueSelector
parentNode?: Node | null parentNode?: Node | null
@ -729,6 +769,7 @@ export const getVarType = ({
isConstant?: boolean isConstant?: boolean
environmentVariables?: EnvironmentVariable[] environmentVariables?: EnvironmentVariable[]
conversationVariables?: ConversationVariable[] conversationVariables?: ConversationVariable[]
ragVariables?: RAGPipelineVariable[]
}): VarType => { }): VarType => {
if (isConstant) if (isConstant)
return VarType.string return VarType.string
@ -739,6 +780,7 @@ export const getVarType = ({
undefined, undefined,
environmentVariables, environmentVariables,
conversationVariables, conversationVariables,
ragVariables,
) )
const isIterationInnerVar = parentNode?.data.type === BlockEnum.Iteration const isIterationInnerVar = parentNode?.data.type === BlockEnum.Iteration
@ -782,6 +824,7 @@ export const getVarType = ({
const isSystem = isSystemVar(valueSelector) const isSystem = isSystemVar(valueSelector)
const isEnv = isENV(valueSelector) const isEnv = isENV(valueSelector)
const isChatVar = isConversationVar(valueSelector) const isChatVar = isConversationVar(valueSelector)
const isRagVariable = isRagVariableVar(valueSelector)
const startNode = availableNodes.find((node: any) => { const startNode = availableNodes.find((node: any) => {
return node?.data.type === BlockEnum.Start return node?.data.type === BlockEnum.Start
}) })
@ -795,7 +838,7 @@ export const getVarType = ({
let type: VarType = VarType.string let type: VarType = VarType.string
let curr: any = targetVar.vars let curr: any = targetVar.vars
if (isSystem || isEnv || isChatVar) { if (isSystem || isEnv || isChatVar || isRagVariable) {
return curr.find((v: any) => v.variable === (valueSelector as ValueSelector).join('.'))?.type return curr.find((v: any) => v.variable === (valueSelector as ValueSelector).join('.'))?.type
} }
else { else {
@ -846,6 +889,7 @@ export const toNodeAvailableVars = ({
isChatMode, isChatMode,
environmentVariables, environmentVariables,
conversationVariables, conversationVariables,
ragVariables,
filterVar, filterVar,
}: { }: {
parentNode?: Node | null parentNode?: Node | null
@ -857,6 +901,8 @@ export const toNodeAvailableVars = ({
environmentVariables?: EnvironmentVariable[] environmentVariables?: EnvironmentVariable[]
// chat var // chat var
conversationVariables?: ConversationVariable[] conversationVariables?: ConversationVariable[]
// rag variables
ragVariables?: RAGPipelineVariable[]
filterVar: (payload: Var, selector: ValueSelector) => boolean filterVar: (payload: Var, selector: ValueSelector) => boolean
}): NodeOutPutVar[] => { }): NodeOutPutVar[] => {
const beforeNodesOutputVars = toNodeOutputVars( const beforeNodesOutputVars = toNodeOutputVars(
@ -865,6 +911,7 @@ export const toNodeAvailableVars = ({
filterVar, filterVar,
environmentVariables, environmentVariables,
conversationVariables, conversationVariables,
ragVariables,
) )
const isInIteration = parentNode?.data.type === BlockEnum.Iteration const isInIteration = parentNode?.data.type === BlockEnum.Iteration
if (isInIteration) { if (isInIteration) {

@ -23,6 +23,7 @@ import type { Field } from '@/app/components/workflow/nodes/llm/types'
import { FILE_STRUCT } from '@/app/components/workflow/constants' import { FILE_STRUCT } from '@/app/components/workflow/constants'
import { Loop } from '@/app/components/base/icons/src/vender/workflow' import { Loop } from '@/app/components/base/icons/src/vender/workflow'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import { InputField } from '@/app/components/base/icons/src/vender/pipeline'
type ObjectChildrenProps = { type ObjectChildrenProps = {
nodeId: string nodeId: string
@ -67,6 +68,7 @@ const Item: FC<ItemProps> = ({
const isSys = itemData.variable.startsWith('sys.') const isSys = itemData.variable.startsWith('sys.')
const isEnv = itemData.variable.startsWith('env.') const isEnv = itemData.variable.startsWith('env.')
const isChatVar = itemData.variable.startsWith('conversation.') const isChatVar = itemData.variable.startsWith('conversation.')
const isRagVariable = itemData.isRagVariable
const objStructuredOutput: StructuredOutput | null = useMemo(() => { const objStructuredOutput: StructuredOutput | null = useMemo(() => {
if (!isObj) return null if (!isObj) return null
@ -148,10 +150,11 @@ const Item: FC<ItemProps> = ({
onMouseDown={e => e.preventDefault()} onMouseDown={e => e.preventDefault()}
> >
<div className='flex w-0 grow items-center'> <div className='flex w-0 grow items-center'>
{!isEnv && !isChatVar && !isLoopVar && <Variable02 className={cn('h-3.5 w-3.5 shrink-0 text-text-accent', isException && 'text-text-warning')} />} {!isEnv && !isChatVar && !isLoopVar && !isRagVariable && <Variable02 className={cn('h-3.5 w-3.5 shrink-0 text-text-accent', isException && 'text-text-warning')} />}
{isEnv && <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />} {isEnv && <Env className='h-3.5 w-3.5 shrink-0 text-util-colors-violet-violet-600' />}
{isChatVar && <BubbleX className='h-3.5 w-3.5 shrink-0 text-util-colors-teal-teal-700' />} {isChatVar && <BubbleX className='h-3.5 w-3.5 shrink-0 text-util-colors-teal-teal-700' />}
{isLoopVar && <Loop className='h-3.5 w-3.5 shrink-0 text-util-colors-cyan-cyan-500' />} {isLoopVar && <Loop className='h-3.5 w-3.5 shrink-0 text-util-colors-cyan-cyan-500' />}
{isRagVariable && <InputField className='h-3.5 w-3.5 shrink-0 text-text-accent' />}
{!isEnv && !isChatVar && ( {!isEnv && !isChatVar && (
<div title={itemData.variable} className='system-sm-medium ml-1 w-0 grow truncate text-text-secondary'>{itemData.variable}</div> <div title={itemData.variable} className='system-sm-medium ml-1 w-0 grow truncate text-text-secondary'>{itemData.variable}</div>
)} )}

@ -11,6 +11,28 @@ const metaData = genNodeMetaData({
const nodeDefault: NodeDefault<DataSourceNodeType> = { const nodeDefault: NodeDefault<DataSourceNodeType> = {
metaData, metaData,
defaultValue: { defaultValue: {
fileExtensions: [
'txt',
'markdown',
'mdx',
'pdf',
'html',
'xlsx',
'xls',
'vtt',
'properties',
'doc',
'docx',
'csv',
'eml',
'msg',
'pptx',
'xml',
'epub',
'ppt',
'md',
'html',
],
datasource_parameters: {}, datasource_parameters: {},
datasource_configurations: {}, datasource_configurations: {},
}, },
@ -20,7 +42,7 @@ const nodeDefault: NodeDefault<DataSourceNodeType> = {
errorMessage: '', errorMessage: '',
} }
}, },
getOutputVars(payload) { getOutputVars(payload, ragVars = []) {
const { const {
provider_type, provider_type,
} = payload } = payload
@ -40,6 +62,7 @@ const nodeDefault: NodeDefault<DataSourceNodeType> = {
] ]
: [] : []
), ),
...ragVars,
] ]
}, },
} }

@ -288,6 +288,7 @@ export type Var = {
isException?: boolean isException?: boolean
isLoopVariable?: boolean isLoopVariable?: boolean
nodeId?: string nodeId?: string
isRagVariable?: boolean
} }
export type NodeOutPutVar = { export type NodeOutPutVar = {
@ -313,7 +314,7 @@ export type NodeDefault<T = {}> = {
} }
defaultValue: Partial<T> defaultValue: Partial<T>
checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string } checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string }
getOutputVars?: (payload: T) => Var[] getOutputVars?: (payload: T, ragVariables?: Var[]) => Var[]
} }
export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue) => void export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue) => void

Loading…
Cancel
Save