mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-18 15:35:56 +08:00
fix: one step run (#14724)
This commit is contained in:
parent
cd46ebbb34
commit
e53052ab7a
@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React, { useCallback } from 'react'
|
import React, { useCallback, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
import {
|
import {
|
||||||
@ -24,8 +24,9 @@ import { Variable02 } from '@/app/components/base/icons/src/vender/solid/develop
|
|||||||
import { BubbleX } from '@/app/components/base/icons/src/vender/line/others'
|
import { BubbleX } from '@/app/components/base/icons/src/vender/line/others'
|
||||||
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
|
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
import type { FileEntity } from '@/app/components/base/file-uploader/types'
|
||||||
|
|
||||||
interface Props {
|
type Props = {
|
||||||
payload: InputVar
|
payload: InputVar
|
||||||
value: any
|
value: any
|
||||||
onChange: (value: any) => void
|
onChange: (value: any) => void
|
||||||
@ -94,6 +95,21 @@ const FormItem: FC<Props> = ({
|
|||||||
const isArrayLikeType = [InputVarType.contexts, InputVarType.iterator].includes(type)
|
const isArrayLikeType = [InputVarType.contexts, InputVarType.iterator].includes(type)
|
||||||
const isContext = type === InputVarType.contexts
|
const isContext = type === InputVarType.contexts
|
||||||
const isIterator = type === InputVarType.iterator
|
const isIterator = type === InputVarType.iterator
|
||||||
|
const singleFileValue = useMemo(() => {
|
||||||
|
if (payload.variable === '#files#')
|
||||||
|
return value?.[0] || []
|
||||||
|
|
||||||
|
return value ? [value] : []
|
||||||
|
}, [payload.variable, value])
|
||||||
|
const handleSingleFileChange = useCallback((files: FileEntity[]) => {
|
||||||
|
if (payload.variable === '#files#')
|
||||||
|
onChange(files)
|
||||||
|
else if (files.length)
|
||||||
|
onChange(files[0])
|
||||||
|
else
|
||||||
|
onChange(null)
|
||||||
|
}, [onChange, payload.variable])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn(className)}>
|
<div className={cn(className)}>
|
||||||
{!isArrayLikeType && (
|
{!isArrayLikeType && (
|
||||||
@ -161,13 +177,8 @@ const FormItem: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
{(type === InputVarType.singleFile) && (
|
{(type === InputVarType.singleFile) && (
|
||||||
<FileUploaderInAttachmentWrapper
|
<FileUploaderInAttachmentWrapper
|
||||||
value={value ? [value] : []}
|
value={singleFileValue}
|
||||||
onChange={(files) => {
|
onChange={handleSingleFileChange}
|
||||||
if (files.length)
|
|
||||||
onChange(files[0])
|
|
||||||
else
|
|
||||||
onChange(null)
|
|
||||||
}}
|
|
||||||
fileConfig={{
|
fileConfig={{
|
||||||
allowed_file_types: inStepRun
|
allowed_file_types: inStepRun
|
||||||
? [
|
? [
|
||||||
|
@ -50,8 +50,11 @@ function formatValue(value: string | any, type: InputVarType) {
|
|||||||
if (type === InputVarType.multiFiles)
|
if (type === InputVarType.multiFiles)
|
||||||
return getProcessedFiles(value)
|
return getProcessedFiles(value)
|
||||||
|
|
||||||
if (type === InputVarType.singleFile)
|
if (type === InputVarType.singleFile) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return getProcessedFiles(value)
|
||||||
return getProcessedFiles([value])[0]
|
return getProcessedFiles([value])[0]
|
||||||
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { unionBy } from 'lodash-es'
|
import { unionBy } from 'lodash-es'
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
@ -139,6 +139,11 @@ const useOneStepRun = <T>({
|
|||||||
const checkValid = checkValidFns[data.type]
|
const checkValid = checkValidFns[data.type]
|
||||||
const appId = useAppStore.getState().appDetail?.id
|
const appId = useAppStore.getState().appDetail?.id
|
||||||
const [runInputData, setRunInputData] = useState<Record<string, any>>(defaultRunInputData || {})
|
const [runInputData, setRunInputData] = useState<Record<string, any>>(defaultRunInputData || {})
|
||||||
|
const runInputDataRef = useRef(runInputData)
|
||||||
|
const handleSetRunInputData = useCallback((data: Record<string, any>) => {
|
||||||
|
runInputDataRef.current = data
|
||||||
|
setRunInputData(data)
|
||||||
|
}, [])
|
||||||
const iterationTimes = iteratorInputKey ? runInputData[iteratorInputKey].length : 0
|
const iterationTimes = iteratorInputKey ? runInputData[iteratorInputKey].length : 0
|
||||||
const [runResult, setRunResult] = useState<any>(null)
|
const [runResult, setRunResult] = useState<any>(null)
|
||||||
|
|
||||||
@ -421,7 +426,8 @@ const useOneStepRun = <T>({
|
|||||||
handleRun,
|
handleRun,
|
||||||
handleStop,
|
handleStop,
|
||||||
runInputData,
|
runInputData,
|
||||||
setRunInputData,
|
runInputDataRef,
|
||||||
|
setRunInputData: handleSetRunInputData,
|
||||||
runResult,
|
runResult,
|
||||||
iterationRunResult,
|
iterationRunResult,
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import MemoryConfig from '../_base/components/memory-config'
|
|||||||
import VarReferencePicker from '../_base/components/variable/var-reference-picker'
|
import VarReferencePicker from '../_base/components/variable/var-reference-picker'
|
||||||
import ConfigVision from '../_base/components/config-vision'
|
import ConfigVision from '../_base/components/config-vision'
|
||||||
import useConfig from './use-config'
|
import useConfig from './use-config'
|
||||||
|
import { findVariableWhenOnLLMVision } from '../utils'
|
||||||
import type { LLMNodeType } from './types'
|
import type { LLMNodeType } from './types'
|
||||||
import ConfigPrompt from './components/config-prompt'
|
import ConfigPrompt from './components/config-prompt'
|
||||||
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
|
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
|
||||||
@ -102,15 +103,16 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVisionModel) {
|
if (isVisionModel && data.vision.enabled && data.vision.configs?.variable_selector) {
|
||||||
const variableName = data.vision.configs?.variable_selector?.[1] || t(`${i18nPrefix}.files`)!
|
const currentVariable = findVariableWhenOnLLMVision(data.vision.configs.variable_selector, availableVars)
|
||||||
|
|
||||||
forms.push(
|
forms.push(
|
||||||
{
|
{
|
||||||
label: t(`${i18nPrefix}.vision`)!,
|
label: t(`${i18nPrefix}.vision`)!,
|
||||||
inputs: [{
|
inputs: [{
|
||||||
label: variableName!,
|
label: currentVariable?.variable as any,
|
||||||
variable: '#files#',
|
variable: '#files#',
|
||||||
type: InputVarType.files,
|
type: currentVariable?.formType as any,
|
||||||
required: false,
|
required: false,
|
||||||
}],
|
}],
|
||||||
values: { '#files#': visionFiles },
|
values: { '#files#': visionFiles },
|
||||||
|
@ -306,6 +306,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
|||||||
handleRun,
|
handleRun,
|
||||||
handleStop,
|
handleStop,
|
||||||
runInputData,
|
runInputData,
|
||||||
|
runInputDataRef,
|
||||||
setRunInputData,
|
setRunInputData,
|
||||||
runResult,
|
runResult,
|
||||||
toVarInputs,
|
toVarInputs,
|
||||||
@ -331,27 +332,27 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
|||||||
const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
|
const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
|
||||||
const newVars = {
|
const newVars = {
|
||||||
...newPayload,
|
...newPayload,
|
||||||
'#context#': runInputData['#context#'],
|
'#context#': runInputDataRef.current['#context#'],
|
||||||
'#files#': runInputData['#files#'],
|
'#files#': runInputDataRef.current['#files#'],
|
||||||
}
|
}
|
||||||
setRunInputData(newVars)
|
setRunInputData(newVars)
|
||||||
}, [runInputData, setRunInputData])
|
}, [runInputDataRef, setRunInputData])
|
||||||
|
|
||||||
const contexts = runInputData['#context#']
|
const contexts = runInputData['#context#']
|
||||||
const setContexts = useCallback((newContexts: string[]) => {
|
const setContexts = useCallback((newContexts: string[]) => {
|
||||||
setRunInputData({
|
setRunInputData({
|
||||||
...runInputData,
|
...runInputDataRef.current,
|
||||||
'#context#': newContexts,
|
'#context#': newContexts,
|
||||||
})
|
})
|
||||||
}, [runInputData, setRunInputData])
|
}, [runInputDataRef, setRunInputData])
|
||||||
|
|
||||||
const visionFiles = runInputData['#files#']
|
const visionFiles = runInputData['#files#']
|
||||||
const setVisionFiles = useCallback((newFiles: any[]) => {
|
const setVisionFiles = useCallback((newFiles: any[]) => {
|
||||||
setRunInputData({
|
setRunInputData({
|
||||||
...runInputData,
|
...runInputDataRef.current,
|
||||||
'#files#': newFiles,
|
'#files#': newFiles,
|
||||||
})
|
})
|
||||||
}, [runInputData, setRunInputData])
|
}, [runInputDataRef, setRunInputData])
|
||||||
|
|
||||||
const allVarStrArr = (() => {
|
const allVarStrArr = (() => {
|
||||||
const arr = isChatModel ? (inputs.prompt_template as PromptItem[]).filter(item => item.edition_type !== EditionType.jinja2).map(item => item.text) : [(inputs.prompt_template as PromptItem).text]
|
const arr = isChatModel ? (inputs.prompt_template as PromptItem[]).filter(item => item.edition_type !== EditionType.jinja2).map(item => item.text) : [(inputs.prompt_template as PromptItem).text]
|
||||||
|
@ -6,6 +6,7 @@ import VarReferencePicker from '../_base/components/variable/var-reference-picke
|
|||||||
import Editor from '../_base/components/prompt/editor'
|
import Editor from '../_base/components/prompt/editor'
|
||||||
import ResultPanel from '../../run/result-panel'
|
import ResultPanel from '../../run/result-panel'
|
||||||
import ConfigVision from '../_base/components/config-vision'
|
import ConfigVision from '../_base/components/config-vision'
|
||||||
|
import { findVariableWhenOnLLMVision } from '../utils'
|
||||||
import useConfig from './use-config'
|
import useConfig from './use-config'
|
||||||
import type { ParameterExtractorNodeType } from './types'
|
import type { ParameterExtractorNodeType } from './types'
|
||||||
import ExtractParameter from './components/extract-parameter/list'
|
import ExtractParameter from './components/extract-parameter/list'
|
||||||
@ -21,6 +22,7 @@ import Tooltip from '@/app/components/base/tooltip'
|
|||||||
import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
|
import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
|
||||||
import { VarType } from '@/app/components/workflow/types'
|
import { VarType } from '@/app/components/workflow/types'
|
||||||
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
|
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
|
||||||
|
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.nodes.parameterExtractor'
|
const i18nPrefix = 'workflow.nodes.parameterExtractor'
|
||||||
const i18nCommonPrefix = 'workflow.common'
|
const i18nCommonPrefix = 'workflow.common'
|
||||||
@ -51,6 +53,7 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
|
|||||||
handleReasoningModeChange,
|
handleReasoningModeChange,
|
||||||
availableVars,
|
availableVars,
|
||||||
availableNodesWithParent,
|
availableNodesWithParent,
|
||||||
|
availableVisionVars,
|
||||||
inputVarValues,
|
inputVarValues,
|
||||||
varInputs,
|
varInputs,
|
||||||
isVisionModel,
|
isVisionModel,
|
||||||
@ -63,10 +66,50 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
|
|||||||
handleStop,
|
handleStop,
|
||||||
runResult,
|
runResult,
|
||||||
setInputVarValues,
|
setInputVarValues,
|
||||||
|
visionFiles,
|
||||||
|
setVisionFiles,
|
||||||
} = useConfig(id, data)
|
} = useConfig(id, data)
|
||||||
|
|
||||||
const model = inputs.model
|
const model = inputs.model
|
||||||
|
|
||||||
|
const singleRunForms = (() => {
|
||||||
|
const forms: FormProps[] = []
|
||||||
|
|
||||||
|
forms.push(
|
||||||
|
{
|
||||||
|
label: t('workflow.nodes.llm.singleRun.variable')!,
|
||||||
|
inputs: [{
|
||||||
|
label: t(`${i18nPrefix}.inputVar`)!,
|
||||||
|
variable: 'query',
|
||||||
|
type: InputVarType.paragraph,
|
||||||
|
required: true,
|
||||||
|
}, ...varInputs],
|
||||||
|
values: inputVarValues,
|
||||||
|
onChange: setInputVarValues,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isVisionModel && data.vision.enabled && data.vision.configs?.variable_selector) {
|
||||||
|
const currentVariable = findVariableWhenOnLLMVision(data.vision.configs.variable_selector, availableVisionVars)
|
||||||
|
|
||||||
|
forms.push(
|
||||||
|
{
|
||||||
|
label: t('workflow.nodes.llm.vision')!,
|
||||||
|
inputs: [{
|
||||||
|
label: currentVariable?.variable as any,
|
||||||
|
variable: '#files#',
|
||||||
|
type: currentVariable?.formType as any,
|
||||||
|
required: false,
|
||||||
|
}],
|
||||||
|
values: { '#files#': visionFiles },
|
||||||
|
onChange: keyValue => setVisionFiles((keyValue as any)['#files#']),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return forms
|
||||||
|
})()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='pt-2'>
|
<div className='pt-2'>
|
||||||
<div className='px-4 space-y-4'>
|
<div className='px-4 space-y-4'>
|
||||||
@ -213,18 +256,7 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
|
|||||||
<BeforeRunForm
|
<BeforeRunForm
|
||||||
nodeName={inputs.title}
|
nodeName={inputs.title}
|
||||||
onHide={hideSingleRun}
|
onHide={hideSingleRun}
|
||||||
forms={[
|
forms={singleRunForms}
|
||||||
{
|
|
||||||
inputs: [{
|
|
||||||
label: t(`${i18nPrefix}.inputVar`)!,
|
|
||||||
variable: 'query',
|
|
||||||
type: InputVarType.paragraph,
|
|
||||||
required: true,
|
|
||||||
}, ...varInputs],
|
|
||||||
values: inputVarValues,
|
|
||||||
onChange: setInputVarValues,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
runningStatus={runningStatus}
|
runningStatus={runningStatus}
|
||||||
onRun={handleRun}
|
onRun={handleRun}
|
||||||
onStop={handleStop}
|
onStop={handleStop}
|
||||||
|
@ -165,6 +165,10 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
|
|||||||
return [VarType.number, VarType.string].includes(varPayload.type)
|
return [VarType.number, VarType.string].includes(varPayload.type)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const filterVisionInputVar = useCallback((varPayload: Var) => {
|
||||||
|
return [VarType.file, VarType.arrayFile].includes(varPayload.type)
|
||||||
|
}, [])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
availableVars,
|
availableVars,
|
||||||
availableNodesWithParent,
|
availableNodesWithParent,
|
||||||
@ -173,6 +177,13 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
|
|||||||
filterVar: filterInputVar,
|
filterVar: filterInputVar,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
availableVars: availableVisionVars,
|
||||||
|
} = useAvailableVarList(id, {
|
||||||
|
onlyLeafNodeVar: false,
|
||||||
|
filterVar: filterVisionInputVar,
|
||||||
|
})
|
||||||
|
|
||||||
const handleCompletionParamsChange = useCallback((newParams: Record<string, any>) => {
|
const handleCompletionParamsChange = useCallback((newParams: Record<string, any>) => {
|
||||||
const newInputs = produce(inputs, (draft) => {
|
const newInputs = produce(inputs, (draft) => {
|
||||||
draft.model.completion_params = newParams
|
draft.model.completion_params = newParams
|
||||||
@ -223,13 +234,15 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
|
|||||||
handleRun,
|
handleRun,
|
||||||
handleStop,
|
handleStop,
|
||||||
runInputData,
|
runInputData,
|
||||||
|
runInputDataRef,
|
||||||
setRunInputData,
|
setRunInputData,
|
||||||
runResult,
|
runResult,
|
||||||
} = useOneStepRun<ParameterExtractorNodeType>({
|
} = useOneStepRun<ParameterExtractorNodeType>({
|
||||||
id,
|
id,
|
||||||
data: inputs,
|
data: inputs,
|
||||||
defaultRunInputData: {
|
defaultRunInputData: {
|
||||||
query: '',
|
'query': '',
|
||||||
|
'#files#': [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -247,6 +260,14 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
|
|||||||
setRunInputData(newPayload)
|
setRunInputData(newPayload)
|
||||||
}, [setRunInputData])
|
}, [setRunInputData])
|
||||||
|
|
||||||
|
const visionFiles = runInputData['#files#']
|
||||||
|
const setVisionFiles = useCallback((newFiles: any[]) => {
|
||||||
|
setRunInputData({
|
||||||
|
...runInputDataRef.current,
|
||||||
|
'#files#': newFiles,
|
||||||
|
})
|
||||||
|
}, [runInputDataRef, setRunInputData])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
readOnly,
|
readOnly,
|
||||||
handleInputVarChange,
|
handleInputVarChange,
|
||||||
@ -264,6 +285,7 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
|
|||||||
hasSetBlockStatus,
|
hasSetBlockStatus,
|
||||||
availableVars,
|
availableVars,
|
||||||
availableNodesWithParent,
|
availableNodesWithParent,
|
||||||
|
availableVisionVars,
|
||||||
isSupportFunctionCall,
|
isSupportFunctionCall,
|
||||||
handleReasoningModeChange,
|
handleReasoningModeChange,
|
||||||
handleMemoryChange,
|
handleMemoryChange,
|
||||||
@ -279,6 +301,8 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
|
|||||||
handleStop,
|
handleStop,
|
||||||
runResult,
|
runResult,
|
||||||
setInputVarValues,
|
setInputVarValues,
|
||||||
|
visionFiles,
|
||||||
|
setVisionFiles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import React from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import VarReferencePicker from '../_base/components/variable/var-reference-picker'
|
import VarReferencePicker from '../_base/components/variable/var-reference-picker'
|
||||||
import ConfigVision from '../_base/components/config-vision'
|
import ConfigVision from '../_base/components/config-vision'
|
||||||
|
import { findVariableWhenOnLLMVision } from '../utils'
|
||||||
import useConfig from './use-config'
|
import useConfig from './use-config'
|
||||||
import ClassList from './components/class-list'
|
import ClassList from './components/class-list'
|
||||||
import AdvancedSetting from './components/advanced-setting'
|
import AdvancedSetting from './components/advanced-setting'
|
||||||
@ -15,6 +16,7 @@ import ResultPanel from '@/app/components/workflow/run/result-panel'
|
|||||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||||
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
|
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||||
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
|
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
|
||||||
|
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.nodes.questionClassifiers'
|
const i18nPrefix = 'workflow.nodes.questionClassifiers'
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ const Panel: FC<NodePanelProps<QuestionClassifierNodeType>> = ({
|
|||||||
hasSetBlockStatus,
|
hasSetBlockStatus,
|
||||||
availableVars,
|
availableVars,
|
||||||
availableNodesWithParent,
|
availableNodesWithParent,
|
||||||
|
availableVisionVars,
|
||||||
handleInstructionChange,
|
handleInstructionChange,
|
||||||
inputVarValues,
|
inputVarValues,
|
||||||
varInputs,
|
varInputs,
|
||||||
@ -51,10 +54,50 @@ const Panel: FC<NodePanelProps<QuestionClassifierNodeType>> = ({
|
|||||||
handleStop,
|
handleStop,
|
||||||
runResult,
|
runResult,
|
||||||
filterVar,
|
filterVar,
|
||||||
|
visionFiles,
|
||||||
|
setVisionFiles,
|
||||||
} = useConfig(id, data)
|
} = useConfig(id, data)
|
||||||
|
|
||||||
const model = inputs.model
|
const model = inputs.model
|
||||||
|
|
||||||
|
const singleRunForms = (() => {
|
||||||
|
const forms: FormProps[] = []
|
||||||
|
|
||||||
|
forms.push(
|
||||||
|
{
|
||||||
|
label: t('workflow.nodes.llm.singleRun.variable')!,
|
||||||
|
inputs: [{
|
||||||
|
label: t(`${i18nPrefix}.inputVars`)!,
|
||||||
|
variable: 'query',
|
||||||
|
type: InputVarType.paragraph,
|
||||||
|
required: true,
|
||||||
|
}, ...varInputs],
|
||||||
|
values: inputVarValues,
|
||||||
|
onChange: setInputVarValues,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isVisionModel && data.vision.enabled && data.vision.configs?.variable_selector) {
|
||||||
|
const currentVariable = findVariableWhenOnLLMVision(data.vision.configs.variable_selector, availableVisionVars)
|
||||||
|
|
||||||
|
forms.push(
|
||||||
|
{
|
||||||
|
label: t('workflow.nodes.llm.vision')!,
|
||||||
|
inputs: [{
|
||||||
|
label: currentVariable?.variable as any,
|
||||||
|
variable: '#files#',
|
||||||
|
type: currentVariable?.formType as any,
|
||||||
|
required: false,
|
||||||
|
}],
|
||||||
|
values: { '#files#': visionFiles },
|
||||||
|
onChange: keyValue => setVisionFiles((keyValue as any)['#files#']),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return forms
|
||||||
|
})()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='pt-2'>
|
<div className='pt-2'>
|
||||||
<div className='px-4 space-y-4'>
|
<div className='px-4 space-y-4'>
|
||||||
@ -143,18 +186,7 @@ const Panel: FC<NodePanelProps<QuestionClassifierNodeType>> = ({
|
|||||||
<BeforeRunForm
|
<BeforeRunForm
|
||||||
nodeName={inputs.title}
|
nodeName={inputs.title}
|
||||||
onHide={hideSingleRun}
|
onHide={hideSingleRun}
|
||||||
forms={[
|
forms={singleRunForms}
|
||||||
{
|
|
||||||
inputs: [{
|
|
||||||
label: t(`${i18nPrefix}.inputVars`)!,
|
|
||||||
variable: 'query',
|
|
||||||
type: InputVarType.paragraph,
|
|
||||||
required: true,
|
|
||||||
}, ...varInputs],
|
|
||||||
values: inputVarValues,
|
|
||||||
onChange: setInputVarValues,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
runningStatus={runningStatus}
|
runningStatus={runningStatus}
|
||||||
onRun={handleRun}
|
onRun={handleRun}
|
||||||
onStop={handleStop}
|
onStop={handleStop}
|
||||||
|
@ -124,6 +124,10 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
|
|||||||
return [VarType.number, VarType.string].includes(varPayload.type)
|
return [VarType.number, VarType.string].includes(varPayload.type)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const filterVisionInputVar = useCallback((varPayload: Var) => {
|
||||||
|
return [VarType.file, VarType.arrayFile].includes(varPayload.type)
|
||||||
|
}, [])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
availableVars,
|
availableVars,
|
||||||
availableNodesWithParent,
|
availableNodesWithParent,
|
||||||
@ -132,6 +136,13 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
|
|||||||
filterVar: filterInputVar,
|
filterVar: filterInputVar,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
availableVars: availableVisionVars,
|
||||||
|
} = useAvailableVarList(id, {
|
||||||
|
onlyLeafNodeVar: false,
|
||||||
|
filterVar: filterVisionInputVar,
|
||||||
|
})
|
||||||
|
|
||||||
const hasSetBlockStatus = {
|
const hasSetBlockStatus = {
|
||||||
history: false,
|
history: false,
|
||||||
query: isChatMode ? checkHasQueryBlock(inputs.instruction) : false,
|
query: isChatMode ? checkHasQueryBlock(inputs.instruction) : false,
|
||||||
@ -161,13 +172,15 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
|
|||||||
handleRun,
|
handleRun,
|
||||||
handleStop,
|
handleStop,
|
||||||
runInputData,
|
runInputData,
|
||||||
|
runInputDataRef,
|
||||||
setRunInputData,
|
setRunInputData,
|
||||||
runResult,
|
runResult,
|
||||||
} = useOneStepRun<QuestionClassifierNodeType>({
|
} = useOneStepRun<QuestionClassifierNodeType>({
|
||||||
id,
|
id,
|
||||||
data: inputs,
|
data: inputs,
|
||||||
defaultRunInputData: {
|
defaultRunInputData: {
|
||||||
query: '',
|
'query': '',
|
||||||
|
'#files#': [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -195,6 +208,14 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
|
|||||||
setRunInputData(newPayload)
|
setRunInputData(newPayload)
|
||||||
}, [setRunInputData])
|
}, [setRunInputData])
|
||||||
|
|
||||||
|
const visionFiles = runInputData['#files#']
|
||||||
|
const setVisionFiles = useCallback((newFiles: any[]) => {
|
||||||
|
setRunInputData({
|
||||||
|
...runInputDataRef.current,
|
||||||
|
'#files#': newFiles,
|
||||||
|
})
|
||||||
|
}, [runInputDataRef, setRunInputData])
|
||||||
|
|
||||||
const filterVar = useCallback((varPayload: Var) => {
|
const filterVar = useCallback((varPayload: Var) => {
|
||||||
return varPayload.type === VarType.string
|
return varPayload.type === VarType.string
|
||||||
}, [])
|
}, [])
|
||||||
@ -212,6 +233,7 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
|
|||||||
hasSetBlockStatus,
|
hasSetBlockStatus,
|
||||||
availableVars,
|
availableVars,
|
||||||
availableNodesWithParent,
|
availableNodesWithParent,
|
||||||
|
availableVisionVars,
|
||||||
handleInstructionChange,
|
handleInstructionChange,
|
||||||
varInputs,
|
varInputs,
|
||||||
inputVarValues,
|
inputVarValues,
|
||||||
@ -228,6 +250,8 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
|
|||||||
query,
|
query,
|
||||||
setQuery,
|
setQuery,
|
||||||
runResult,
|
runResult,
|
||||||
|
visionFiles,
|
||||||
|
setVisionFiles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
web/app/components/workflow/nodes/utils.ts
Normal file
30
web/app/components/workflow/nodes/utils.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import type {
|
||||||
|
NodeOutPutVar,
|
||||||
|
ValueSelector,
|
||||||
|
} from '@/app/components/workflow/types'
|
||||||
|
import { InputVarType } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
|
export const findVariableWhenOnLLMVision = (valueSelector: ValueSelector, availableVars: NodeOutPutVar[]) => {
|
||||||
|
const currentVariableNode = availableVars.find((availableVar) => {
|
||||||
|
if (valueSelector[0] === 'sys' && availableVar.isStartNode)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return valueSelector[0] === availableVar.nodeId
|
||||||
|
})
|
||||||
|
const currentVariable = currentVariableNode?.vars.find((variable) => {
|
||||||
|
if (valueSelector[0] === 'sys' && variable.variable === `sys.${valueSelector[1]}`)
|
||||||
|
return true
|
||||||
|
return variable.variable === valueSelector[1]
|
||||||
|
})
|
||||||
|
|
||||||
|
let formType = ''
|
||||||
|
if (currentVariable?.type === 'array[file]')
|
||||||
|
formType = InputVarType.multiFiles
|
||||||
|
if (currentVariable?.type === 'file')
|
||||||
|
formType = InputVarType.singleFile
|
||||||
|
|
||||||
|
return currentVariable && {
|
||||||
|
...currentVariable,
|
||||||
|
formType,
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user