mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-18 03:26:00 +08:00
feat: support var show
This commit is contained in:
parent
e624bf381b
commit
6a76e27b05
@ -3,7 +3,7 @@ import { isArray, uniq } from 'lodash-es'
|
|||||||
import type { CodeNodeType } from '../../../code/types'
|
import type { CodeNodeType } from '../../../code/types'
|
||||||
import type { EndNodeType } from '../../../end/types'
|
import type { EndNodeType } from '../../../end/types'
|
||||||
import type { AnswerNodeType } from '../../../answer/types'
|
import type { AnswerNodeType } from '../../../answer/types'
|
||||||
import type { LLMNodeType } from '../../../llm/types'
|
import type { LLMNodeType, StructuredOutput } from '../../../llm/types'
|
||||||
import type { KnowledgeRetrievalNodeType } from '../../../knowledge-retrieval/types'
|
import type { KnowledgeRetrievalNodeType } from '../../../knowledge-retrieval/types'
|
||||||
import type { IfElseNodeType } from '../../../if-else/types'
|
import type { IfElseNodeType } from '../../../if-else/types'
|
||||||
import type { TemplateTransformNodeType } from '../../../template-transform/types'
|
import type { TemplateTransformNodeType } from '../../../template-transform/types'
|
||||||
@ -20,6 +20,8 @@ import { BlockEnum, InputVarType, VarType } from '@/app/components/workflow/type
|
|||||||
import type { StartNodeType } from '@/app/components/workflow/nodes/start/types'
|
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 mockStructData from '@/app/components/workflow/nodes/llm/mock-struct-data'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HTTP_REQUEST_OUTPUT_STRUCT,
|
HTTP_REQUEST_OUTPUT_STRUCT,
|
||||||
KNOWLEDGE_RETRIEVAL_OUTPUT_STRUCT,
|
KNOWLEDGE_RETRIEVAL_OUTPUT_STRUCT,
|
||||||
@ -59,15 +61,18 @@ const findExceptVarInObject = (obj: any, filterVar: (payload: Var, selector: Val
|
|||||||
const res: Var = {
|
const res: Var = {
|
||||||
variable: obj.variable,
|
variable: obj.variable,
|
||||||
type: isFile ? VarType.file : VarType.object,
|
type: isFile ? VarType.file : VarType.object,
|
||||||
children: children.filter((item: Var) => {
|
children: children.length > 0 ? children.filter((item: Var) => {
|
||||||
const { children } = item
|
const { children } = item
|
||||||
const currSelector = [...value_selector, item.variable]
|
const isStructuredOutput = !!(children as StructuredOutput)?.schema
|
||||||
if (!children)
|
if (!isStructuredOutput) {
|
||||||
return filterVar(item, currSelector)
|
const currSelector = [...value_selector, item.variable]
|
||||||
|
if (!children)
|
||||||
const obj = findExceptVarInObject(item, filterVar, currSelector, false) // File doesn't contains file children
|
return filterVar(item, currSelector)
|
||||||
return obj.children && obj.children?.length > 0
|
const obj = findExceptVarInObject(item, filterVar, currSelector, false) // File doesn't contains file children
|
||||||
}),
|
return obj.children && (obj.children as Var[])?.length > 0
|
||||||
|
}
|
||||||
|
return true // TODO: handle structured output
|
||||||
|
}) : (children || []),
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -138,7 +143,14 @@ const formatItem = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
case BlockEnum.LLM: {
|
case BlockEnum.LLM: {
|
||||||
res.vars = LLM_OUTPUT_STRUCT
|
res.vars = [
|
||||||
|
...LLM_OUTPUT_STRUCT,
|
||||||
|
{
|
||||||
|
variable: 'structured_output',
|
||||||
|
type: VarType.object,
|
||||||
|
children: mockStructData,
|
||||||
|
},
|
||||||
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +416,7 @@ const formatItem = (
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
const obj = findExceptVarInObject(isFile ? { ...v, children } : v, filterVar, selector, isFile)
|
const obj = findExceptVarInObject(isFile ? { ...v, children } : v, filterVar, selector, isFile)
|
||||||
return obj?.children && obj?.children.length > 0
|
return obj?.children && ((obj?.children as Var[]).length > 0 || Object.keys((obj?.children as StructuredOutput)?.schema?.properties || {}).length > 0)
|
||||||
}).map((v) => {
|
}).map((v) => {
|
||||||
const isFile = v.type === VarType.file
|
const isFile = v.type === VarType.file
|
||||||
|
|
||||||
@ -428,6 +440,9 @@ const formatItem = (
|
|||||||
return findExceptVarInObject(isFile ? { ...v, children } : v, filterVar, selector, isFile)
|
return findExceptVarInObject(isFile ? { ...v, children } : v, filterVar, selector, isFile)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (res.nodeId === 'llm')
|
||||||
|
console.log(res)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
export const toNodeOutputVars = (
|
export const toNodeOutputVars = (
|
||||||
@ -527,8 +542,7 @@ export const getVarType = ({
|
|||||||
isConstant,
|
isConstant,
|
||||||
environmentVariables = [],
|
environmentVariables = [],
|
||||||
conversationVariables = [],
|
conversationVariables = [],
|
||||||
}:
|
}: {
|
||||||
{
|
|
||||||
valueSelector: ValueSelector
|
valueSelector: ValueSelector
|
||||||
parentNode?: Node | null
|
parentNode?: Node | null
|
||||||
isIterationItem?: boolean
|
isIterationItem?: boolean
|
||||||
@ -1094,11 +1108,13 @@ const varToValueSelectorList = (v: Var, parentValueSelector: ValueSelector, res:
|
|||||||
return
|
return
|
||||||
|
|
||||||
res.push([...parentValueSelector, v.variable])
|
res.push([...parentValueSelector, v.variable])
|
||||||
|
if (v.children) {
|
||||||
if (v.children && v.children.length > 0) {
|
if ((v.children as Var[])?.length > 0) {
|
||||||
v.children.forEach((child) => {
|
(v.children as Var[]).forEach((child) => {
|
||||||
varToValueSelectorList(child, [...parentValueSelector, v.variable], res)
|
varToValueSelectorList(child, [...parentValueSelector, v.variable], res)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
// TODO: handle structured output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,10 @@ import Input from '@/app/components/base/input'
|
|||||||
import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others'
|
import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others'
|
||||||
import { checkKeys } from '@/utils/var'
|
import { checkKeys } from '@/utils/var'
|
||||||
import { FILE_STRUCT } from '@/app/components/workflow/constants'
|
import { FILE_STRUCT } from '@/app/components/workflow/constants'
|
||||||
|
import type { StructuredOutput } from '../../../llm/types'
|
||||||
|
import PickerStructurePanel from '@/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/picker'
|
||||||
|
|
||||||
interface ObjectChildrenProps {
|
type ObjectChildrenProps = {
|
||||||
nodeId: string
|
nodeId: string
|
||||||
title: string
|
title: string
|
||||||
data: Var[]
|
data: Var[]
|
||||||
@ -28,7 +30,7 @@ interface ObjectChildrenProps {
|
|||||||
isSupportFileVar?: boolean
|
isSupportFileVar?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ItemProps {
|
type ItemProps = {
|
||||||
nodeId: string
|
nodeId: string
|
||||||
title: string
|
title: string
|
||||||
objPath: string[]
|
objPath: string[]
|
||||||
@ -51,8 +53,9 @@ const Item: FC<ItemProps> = ({
|
|||||||
isSupportFileVar,
|
isSupportFileVar,
|
||||||
isException,
|
isException,
|
||||||
}) => {
|
}) => {
|
||||||
const isFile = itemData.type === VarType.file
|
const isStructureOutput = itemData.type === VarType.object && (itemData.children as StructuredOutput)?.schema?.properties
|
||||||
const isObj = ([VarType.object, VarType.file].includes(itemData.type) && itemData.children && itemData.children.length > 0)
|
const isFile = itemData.type === VarType.file && !isStructureOutput
|
||||||
|
const isObj = ([VarType.object, VarType.file].includes(itemData.type) && itemData.children && (itemData.children as Var[]).length > 0)
|
||||||
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.')
|
||||||
@ -77,7 +80,7 @@ const Item: FC<ItemProps> = ({
|
|||||||
})
|
})
|
||||||
const [isChildrenHovering, setIsChildrenHovering] = useState(false)
|
const [isChildrenHovering, setIsChildrenHovering] = useState(false)
|
||||||
const isHovering = isItemHovering || isChildrenHovering
|
const isHovering = isItemHovering || isChildrenHovering
|
||||||
const open = isObj && isHovering
|
const open = (isObj || isStructureOutput) && isHovering
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onHovering && onHovering(isHovering)
|
onHovering && onHovering(isHovering)
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@ -125,7 +128,7 @@ const Item: FC<ItemProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='ml-1 shrink-0 text-xs font-normal text-text-tertiary capitalize'>{itemData.type}</div>
|
<div className='ml-1 shrink-0 text-xs font-normal text-text-tertiary capitalize'>{itemData.type}</div>
|
||||||
{isObj && (
|
{(isObj || isStructureOutput) && (
|
||||||
<ChevronRight className={cn('ml-0.5 w-3 h-3 text-text-quaternary', isHovering && 'text-text-tertiary')} />
|
<ChevronRight className={cn('ml-0.5 w-3 h-3 text-text-quaternary', isHovering && 'text-text-tertiary')} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -133,6 +136,9 @@ const Item: FC<ItemProps> = ({
|
|||||||
<PortalToFollowElemContent style={{
|
<PortalToFollowElemContent style={{
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
}}>
|
}}>
|
||||||
|
{isStructureOutput && (
|
||||||
|
<PickerStructurePanel root={{ attrName: itemData.variable }} payload={itemData.children as StructuredOutput} />
|
||||||
|
)}
|
||||||
{(isObj && !isFile) && (
|
{(isObj && !isFile) && (
|
||||||
// eslint-disable-next-line ts/no-use-before-define
|
// eslint-disable-next-line ts/no-use-before-define
|
||||||
<ObjectChildren
|
<ObjectChildren
|
||||||
@ -226,7 +232,7 @@ const ObjectChildren: FC<ObjectChildrenProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
type Props = {
|
||||||
hideSearch?: boolean
|
hideSearch?: boolean
|
||||||
searchBoxClassName?: string
|
searchBoxClassName?: string
|
||||||
vars: NodeOutPutVar[]
|
vars: NodeOutPutVar[]
|
||||||
@ -322,7 +328,7 @@ const VarReferenceVars: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
: <div className='pl-3 leading-[18px] text-xs font-medium text-gray-500 uppercase'>{t('workflow.common.noVar')}</div>}
|
: <div className='pl-3 leading-[18px] text-xs font-medium text-gray-500 uppercase'>{t('workflow.common.noVar')}</div>}
|
||||||
</ >
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default React.memo(VarReferenceVars)
|
export default React.memo(VarReferenceVars)
|
||||||
|
@ -14,6 +14,7 @@ import type {
|
|||||||
ErrorHandleTypeEnum,
|
ErrorHandleTypeEnum,
|
||||||
} from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
} from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
||||||
import type { WorkflowRetryConfig } from '@/app/components/workflow/nodes/_base/components/retry/types'
|
import type { WorkflowRetryConfig } from '@/app/components/workflow/nodes/_base/components/retry/types'
|
||||||
|
import type { StructuredOutput } from './nodes/llm/types'
|
||||||
|
|
||||||
export enum BlockEnum {
|
export enum BlockEnum {
|
||||||
Start = 'start',
|
Start = 'start',
|
||||||
@ -250,7 +251,7 @@ export enum VarType {
|
|||||||
export type Var = {
|
export type Var = {
|
||||||
variable: string
|
variable: string
|
||||||
type: VarType
|
type: VarType
|
||||||
children?: Var[] // if type is obj, has the children struct
|
children?: Var[] | StructuredOutput // if type is obj, has the children struct
|
||||||
isParagraph?: boolean
|
isParagraph?: boolean
|
||||||
isSelect?: boolean
|
isSelect?: boolean
|
||||||
options?: string[]
|
options?: string[]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user