【amc】 合并前端代码
parent
ae25db7ad1
commit
569f94280f
@ -0,0 +1,45 @@
|
||||
import type {NodeDefault} from '../../types'
|
||||
import {BlockEnum} from '../../types'
|
||||
import type {VannaNodeType} from './types'
|
||||
import {ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS} from '@/app/components/workflow/blocks'
|
||||
import {ReasoningModeType} from "@/app/components/workflow/nodes/parameter-extractor/types";
|
||||
|
||||
const nodeDefault: NodeDefault<VannaNodeType> = {
|
||||
defaultValue: {
|
||||
query: [],
|
||||
model: {
|
||||
provider: '',
|
||||
name: '',
|
||||
mode: 'chat',
|
||||
completion_params: {
|
||||
temperature: 0.7,
|
||||
},
|
||||
},
|
||||
reasoning_mode: ReasoningModeType.prompt,
|
||||
vision: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
getAvailablePrevNodes(isChatMode: boolean) {
|
||||
return isChatMode
|
||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
||||
},
|
||||
getAvailableNextNodes(isChatMode: boolean) {
|
||||
return isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
||||
},
|
||||
checkValid(payload: VannaNodeType) {
|
||||
let isValid = true
|
||||
let errorMessages = ''
|
||||
if (!payload.query || payload.query.length === 0){
|
||||
errorMessages = '输入变量不能为空'
|
||||
}
|
||||
|
||||
return {
|
||||
isValid,
|
||||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
@ -0,0 +1,35 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import type { VannaNodeType } from './types'
|
||||
import type { NodeProps } from '@/app/components/workflow/types'
|
||||
|
||||
import ModelSelector from "@/app/components/header/account-setting/model-provider-page/model-selector";
|
||||
import {
|
||||
useTextGenerationCurrentProviderAndModelAndModelList
|
||||
} from "@/app/components/header/account-setting/model-provider-page/hooks";
|
||||
|
||||
const Node: FC<NodeProps<VannaNodeType>> = ({
|
||||
data,
|
||||
}) => {
|
||||
|
||||
const { provider, name: modelId } = data.model || {}
|
||||
const {
|
||||
textGenerationModelList,
|
||||
} = useTextGenerationCurrentProviderAndModelAndModelList()
|
||||
const hasSetModel = provider && modelId
|
||||
|
||||
return (
|
||||
<div className='mb-1 space-y-0.5 px-3 py-1'>
|
||||
{hasSetModel && (
|
||||
<ModelSelector
|
||||
defaultModel={{ provider, model: modelId }}
|
||||
modelList={textGenerationModelList}
|
||||
triggerClassName='!h-6 !rounded-md'
|
||||
readonly
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Node)
|
||||
@ -0,0 +1,155 @@
|
||||
import React, {FC} from 'react'
|
||||
import {useTranslation} from 'react-i18next'
|
||||
import useConfig from './use-config'
|
||||
import type {VannaNodeType} from './types'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import {InputVarType, NodePanelProps} from '@/app/components/workflow/types'
|
||||
import ModelParameterModal from "@/app/components/header/account-setting/model-provider-page/model-parameter-modal";
|
||||
import VarReferencePicker from "@/app/components/workflow/nodes/_base/components/variable/var-reference-picker";
|
||||
import BeforeRunForm from "@/app/components/workflow/nodes/_base/components/before-run-form";
|
||||
import ResultPanel from "@/app/components/workflow/run/result-panel";
|
||||
import type {Props as FormProps} from "@/app/components/workflow/nodes/_base/components/before-run-form/form";
|
||||
import {findVariableWhenOnLLMVision} from "@/app/components/workflow/nodes/utils";
|
||||
import Split from "@/app/components/workflow/nodes/_base/components/split";
|
||||
import OutputVars, {VarItem} from "@/app/components/workflow/nodes/_base/components/output-vars";
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.parameterExtractor'
|
||||
|
||||
const Panel: FC<NodePanelProps<VannaNodeType>> = (
|
||||
{
|
||||
id,
|
||||
data,
|
||||
}) => {
|
||||
const {t} = useTranslation()
|
||||
|
||||
const {
|
||||
readOnly,
|
||||
inputs,
|
||||
handleCompletionParamsChange,
|
||||
handleInputVarChange,
|
||||
handleModelChanged,
|
||||
isShowSingleRun,
|
||||
hideSingleRun,
|
||||
handleRun,
|
||||
handleStop,
|
||||
runResult,
|
||||
runningStatus,
|
||||
filterVar,
|
||||
varInputs,
|
||||
inputVarValues,
|
||||
setInputVarValues,
|
||||
isVisionModel,
|
||||
availableVisionVars,
|
||||
visionFiles,
|
||||
setVisionFiles,
|
||||
} = useConfig(id, data)
|
||||
|
||||
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 (
|
||||
<div className='mt-2'>
|
||||
<div className='space-y-4 px-4 pb-4'>
|
||||
<Field
|
||||
title={'模型'}
|
||||
>
|
||||
<ModelParameterModal
|
||||
popupClassName='!w-[387px]'
|
||||
isInWorkflow
|
||||
isAdvancedMode={true}
|
||||
mode={model?.mode}
|
||||
provider={model?.provider}
|
||||
completionParams={model?.completion_params}
|
||||
modelId={model?.name}
|
||||
setModel={handleModelChanged}
|
||||
onCompletionParamsChange={handleCompletionParamsChange}
|
||||
hideDebugWithMultipleModel
|
||||
debugWithMultipleModel={false}
|
||||
readonly={readOnly}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field
|
||||
title={'输入变量'}
|
||||
>
|
||||
<VarReferencePicker
|
||||
readonly={readOnly}
|
||||
nodeId={id}
|
||||
isShowNodeName
|
||||
value={inputs.query || []}
|
||||
onChange={handleInputVarChange}
|
||||
filterVar={filterVar}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
</div>
|
||||
<Split />
|
||||
<div>
|
||||
<OutputVars>
|
||||
<VarItem
|
||||
name='output'
|
||||
type='string'
|
||||
description={'查询出结果的数据'}
|
||||
/>
|
||||
<VarItem
|
||||
name='sql'
|
||||
type='string'
|
||||
description={'生成的sql语句'}
|
||||
/>
|
||||
</OutputVars>
|
||||
</div>
|
||||
|
||||
{isShowSingleRun && (
|
||||
<BeforeRunForm
|
||||
nodeName={inputs.title}
|
||||
onHide={hideSingleRun}
|
||||
forms={singleRunForms}
|
||||
runningStatus={runningStatus}
|
||||
onRun={handleRun}
|
||||
onStop={handleStop}
|
||||
result={<ResultPanel {...runResult} showSteps={false}/>}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Panel)
|
||||
@ -0,0 +1,20 @@
|
||||
import type {
|
||||
CommonNodeType,
|
||||
Memory,
|
||||
ModelConfig, ValueSelector,
|
||||
VisionSetting
|
||||
} from '@/app/components/workflow/types'
|
||||
import {Param, ReasoningModeType} from "@/app/components/workflow/nodes/parameter-extractor/types";
|
||||
|
||||
export type VannaNodeType = CommonNodeType & {
|
||||
model: ModelConfig
|
||||
query: ValueSelector
|
||||
instruction: string
|
||||
reasoning_mode: ReasoningModeType
|
||||
parameters: Param[]
|
||||
memory?: Memory
|
||||
vision: {
|
||||
enabled: boolean
|
||||
configs?: VisionSetting
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
import type {VannaNodeType} from './types'
|
||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import {
|
||||
useNodesReadOnly,
|
||||
} from '@/app/components/workflow/hooks'
|
||||
import {useCallback, useRef, useState} from "react";
|
||||
import produce from "immer";
|
||||
import {ValueSelector, Var, VarType} from "@/app/components/workflow/types";
|
||||
import useOneStepRun from "@/app/components/workflow/nodes/_base/hooks/use-one-step-run";
|
||||
import useConfigVision from "@/app/components/workflow/hooks/use-config-vision";
|
||||
import useAvailableVarList from "@/app/components/workflow/nodes/_base/hooks/use-available-var-list";
|
||||
|
||||
const useConfig = (id: string, payload: VannaNodeType) => {
|
||||
const {nodesReadOnly: readOnly} = useNodesReadOnly()
|
||||
const {inputs, setInputs} = useNodeCrud<VannaNodeType>(id, payload)
|
||||
const inputRef = useRef(inputs)
|
||||
const [modelChanged, setModelChanged] = useState(false)
|
||||
|
||||
// model
|
||||
const model = inputs.model || {
|
||||
provider: '',
|
||||
name: '',
|
||||
mode: 'chat',
|
||||
completion_params: {
|
||||
temperature: 0.7,
|
||||
},
|
||||
}
|
||||
|
||||
const modelMode = inputs.model?.mode
|
||||
|
||||
// single run
|
||||
const {
|
||||
isShowSingleRun,
|
||||
hideSingleRun,
|
||||
getInputVars,
|
||||
runningStatus,
|
||||
handleRun,
|
||||
handleStop,
|
||||
runInputData,
|
||||
runInputDataRef,
|
||||
setRunInputData,
|
||||
runResult,
|
||||
} = useOneStepRun<VannaNodeType>({
|
||||
id,
|
||||
data: inputs,
|
||||
defaultRunInputData: {
|
||||
'query': '',
|
||||
'#files#': [],
|
||||
},
|
||||
})
|
||||
|
||||
const {
|
||||
isVisionModel,
|
||||
handleVisionResolutionEnabledChange,
|
||||
handleVisionResolutionChange,
|
||||
handleModelChanged: handleVisionConfigAfterModelChanged,
|
||||
} = useConfigVision(model, {
|
||||
payload: inputs.vision,
|
||||
onChange: (newPayload) => {
|
||||
const newInputs = produce(inputs, (draft) => {
|
||||
draft.vision = newPayload
|
||||
})
|
||||
setInputs(newInputs)
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
const filterVisionInputVar = useCallback((varPayload: Var) => {
|
||||
return [VarType.file, VarType.arrayFile].includes(varPayload.type)
|
||||
}, [])
|
||||
|
||||
|
||||
const {
|
||||
availableVars: availableVisionVars,
|
||||
} = useAvailableVarList(id, {
|
||||
onlyLeafNodeVar: false,
|
||||
filterVar: filterVisionInputVar,
|
||||
})
|
||||
|
||||
|
||||
const handleModelChanged = useCallback((model: { provider: string; modelId: string; mode?: string }) => {
|
||||
const newInputs = produce(inputRef.current, (draft) => {
|
||||
draft.model.provider = model.provider
|
||||
draft.model.name = model.modelId
|
||||
draft.model.mode = model.mode!
|
||||
})
|
||||
setInputs(newInputs)
|
||||
setModelChanged(true)
|
||||
}, [setInputs])
|
||||
|
||||
|
||||
const handleCompletionParamsChange = useCallback((newParams: Record<string, any>) => {
|
||||
debugger
|
||||
const newInputs = produce(inputs, (draft) => {
|
||||
draft.model.completion_params = newParams
|
||||
})
|
||||
setInputs(newInputs)
|
||||
}, [inputs, setInputs])
|
||||
|
||||
const handleInputVarChange = useCallback((newInputVar: ValueSelector | string) => {
|
||||
const newInputs = produce(inputs, (draft) => {
|
||||
draft.query = newInputVar as ValueSelector || []
|
||||
})
|
||||
setInputs(newInputs)
|
||||
}, [inputs, setInputs])
|
||||
|
||||
const filterVar = useCallback((varPayload: Var) => {
|
||||
return [VarType.string].includes(varPayload.type)
|
||||
}, [])
|
||||
|
||||
const varInputs = getInputVars([inputs.instruction])
|
||||
const inputVarValues = (() => {
|
||||
const vars: Record<string, any> = {}
|
||||
Object.keys(runInputData)
|
||||
.forEach((key) => {
|
||||
vars[key] = runInputData[key]
|
||||
})
|
||||
return vars
|
||||
})()
|
||||
|
||||
|
||||
const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
|
||||
setRunInputData(newPayload)
|
||||
}, [setRunInputData])
|
||||
|
||||
const visionFiles = runInputData['#files#']
|
||||
const setVisionFiles = useCallback((newFiles: any[]) => {
|
||||
setRunInputData({
|
||||
...runInputDataRef.current,
|
||||
'#files#': newFiles,
|
||||
})
|
||||
}, [runInputDataRef, setRunInputData])
|
||||
|
||||
|
||||
return {
|
||||
readOnly,
|
||||
inputs,
|
||||
filterVar,
|
||||
isShowSingleRun,
|
||||
hideSingleRun,
|
||||
getInputVars,
|
||||
runningStatus,
|
||||
handleRun,
|
||||
handleStop,
|
||||
runInputData,
|
||||
runInputDataRef,
|
||||
setRunInputData,
|
||||
isVisionModel,
|
||||
runResult,
|
||||
varInputs,
|
||||
inputVarValues,
|
||||
setInputVarValues,
|
||||
handleModelChanged,
|
||||
handleInputVarChange,
|
||||
handleCompletionParamsChange,
|
||||
availableVisionVars,
|
||||
visionFiles,
|
||||
setVisionFiles
|
||||
}
|
||||
}
|
||||
|
||||
export default useConfig
|
||||
@ -0,0 +1,5 @@
|
||||
import type {VannaNodeType} from './types'
|
||||
|
||||
export const checkNodeValid = (payload: VannaNodeType) => {
|
||||
return true
|
||||
}
|
||||
Loading…
Reference in New Issue