From 6b9cc927c0faba6845a08f74be228f0879ba82e1 Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 15 Mar 2024 21:41:18 +0800 Subject: [PATCH 1/5] feat: llm default value --- .../components/workflow/hooks/use-workflow.ts | 2 +- .../nodes/_base/components/memory-config.tsx | 2 +- .../nodes/_base/components/prompt/editor.tsx | 2 +- .../nodes/llm/components/config-prompt.tsx | 2 +- .../components/workflow/nodes/llm/panel.tsx | 22 +----- .../workflow/nodes/llm/use-config.ts | 79 ++++++++++++++++--- .../nodes/question-classifier/use-config.ts | 1 - web/app/components/workflow/types.ts | 1 - 8 files changed, 77 insertions(+), 34 deletions(-) diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts index 703182959354d2..f95ede2390b67c 100644 --- a/web/app/components/workflow/hooks/use-workflow.ts +++ b/web/app/components/workflow/hooks/use-workflow.ts @@ -236,7 +236,7 @@ export const useWorkflowInit = () => { workflowStore.setState({ nodesDefaultConfigs: nodesDefaultConfigsData.reduce((acc, block) => { if (!acc[block.type]) - acc[block.type] = { ...block.config, _isReady: true } + acc[block.type] = { ...block.config } return acc }, {} as Record), }) diff --git a/web/app/components/workflow/nodes/_base/components/memory-config.tsx b/web/app/components/workflow/nodes/_base/components/memory-config.tsx index e6ff4bba8f9aad..31ff34c89d4ba5 100644 --- a/web/app/components/workflow/nodes/_base/components/memory-config.tsx +++ b/web/app/components/workflow/nodes/_base/components/memory-config.tsx @@ -141,7 +141,7 @@ const MemoryConfig: FC = ({ disabled={readonly} /> = ({
{title}
-
{value.length}
+
{value?.length || 0}
{/* Operations */}
diff --git a/web/app/components/workflow/nodes/llm/components/config-prompt.tsx b/web/app/components/workflow/nodes/llm/components/config-prompt.tsx index 7593a38a3e81cd..40e5d67a5371c0 100644 --- a/web/app/components/workflow/nodes/llm/components/config-prompt.tsx +++ b/web/app/components/workflow/nodes/llm/components/config-prompt.tsx @@ -89,7 +89,7 @@ const ConfigPrompt: FC = ({ return (
- {isChatModel + {(isChatModel && Array.isArray(payload)) ? (
diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx index a462c55fc0272a..c293fd85dde785 100644 --- a/web/app/components/workflow/nodes/llm/panel.tsx +++ b/web/app/components/workflow/nodes/llm/panel.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react' -import React, { useEffect } from 'react' +import React from 'react' import { useTranslation } from 'react-i18next' import MemoryConfig from '../_base/components/memory-config' import VarReferencePicker from '../_base/components/variable/var-reference-picker' @@ -18,7 +18,6 @@ import { InputVarType, type NodePanelProps } from '@/app/components/workflow/typ import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' import ResultPanel from '@/app/components/workflow/run/result-panel' -import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' const i18nPrefix = 'workflow.nodes.llm' @@ -28,10 +27,6 @@ const Panel: FC> = ({ }) => { const { t } = useTranslation() const readOnly = false - const { - currentProvider, - currentModel, - } = useModelListAndDefaultModelAndCurrentProviderAndModel(1) const { inputs, @@ -62,7 +57,6 @@ const Panel: FC> = ({ runResult, } = useConfig(id, data) - const isChatApp = true // TODO: get from app context const model = inputs.model const singleRunForms = (() => { @@ -114,16 +108,6 @@ const Panel: FC> = ({ return forms })() - useEffect(() => { - if (currentProvider?.provider && currentModel?.model && !model.provider) { - handleModelChanged({ - provider: currentProvider?.provider, - modelId: currentModel?.model, - mode: currentModel?.model_properties?.mode as string, - }) - } - }, [model.provider, currentProvider, currentModel, handleModelChanged]) - return (
@@ -187,11 +171,11 @@ const Panel: FC> = ({ )} {/* Memory examples. Wait for design */} - {/* {isChatApp && isChatModel && ( + {/* {isChatModel && (
Memory examples(Designing)
)} */} {/* Memory */} - {isChatApp && ( + {isChatModel && ( <> { - const { inputs, setInputs } = useNodeCrud(id, payload) + const isChatMode = useIsChatMode() + const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type] + const { inputs, setInputs } = useNodeCrud(id, payload) + const inputRef = useRef(inputs) + useEffect(() => { + inputRef.current = inputs + }, [inputs]) // model const model = inputs.model const modelMode = inputs.model?.mode const isChatModel = modelMode === 'chat' const isCompletionModel = !isChatModel + const appendDefaultPromptConfig = useCallback((draft: LLMNodeType, defaultConfig: any, passInIsChatMode?: boolean) => { + const promptTemplates = defaultConfig.prompt_templates + if (passInIsChatMode === undefined ? isChatModel : passInIsChatMode) { + draft.prompt_template = promptTemplates.chat_model.prompts + } + else { + draft.prompt_template = promptTemplates.completion_model.prompt + if (!draft.memory) { + draft.memory = { + role_prefix: { + user: '', + assistant: '', + }, + window: { + enabled: false, + size: '', + }, + } + } + + draft.memory.role_prefix = { + user: promptTemplates.completion_model.conversation_histories_role.user_prefix, + assistant: promptTemplates.completion_model.conversation_histories_role.assistant_prefix, + } + } + }, [isChatModel]) + useEffect(() => { + const isReady = defaultConfig && Object.keys(defaultConfig).length > 0 + if (isReady) { + const newInputs = produce(inputs, (draft) => { + appendDefaultPromptConfig(draft, defaultConfig) + }) + setInputs(newInputs) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [defaultConfig, isChatModel]) + + const { + currentProvider, + currentModel, + } = useModelListAndDefaultModelAndCurrentProviderAndModel(1) + const handleModelChanged = useCallback((model: { provider: string; modelId: string; mode?: string }) => { - const newInputs = produce(inputs, (draft) => { + const newInputs = produce(inputRef.current, (draft) => { draft.model.provider = model.provider draft.model.name = model.modelId draft.model.mode = model.mode! - const isModeChange = model.mode !== inputs.model.mode - if (isModeChange) - draft.prompt_template = model.mode === 'chat' ? [{ role: PromptRole.system, text: '' }] : { text: '' } + const isModeChange = model.mode !== inputRef.current.model.mode + if (isModeChange && defaultConfig && Object.keys(defaultConfig).length > 0) + appendDefaultPromptConfig(draft, defaultConfig, model.mode === 'chat') }) setInputs(newInputs) - }, [inputs, setInputs]) + }, [setInputs, defaultConfig, appendDefaultPromptConfig]) + + useEffect(() => { + if (currentProvider?.provider && currentModel?.model && !model.provider) { + handleModelChanged({ + provider: currentProvider?.provider, + modelId: currentModel?.model, + mode: currentModel?.model_properties?.mode as string, + }) + } + }, [model.provider, currentProvider, currentModel, handleModelChanged]) const handleCompletionParamsChange = useCallback((newParams: Record) => { const newInputs = produce(inputs, (draft) => { @@ -152,6 +212,7 @@ const useConfig = (id: string, payload: LLMNodeType) => { const varInputs = toVarInputs(inputs.variables) return { + isChatMode, inputs, isChatModel, isCompletionModel, diff --git a/web/app/components/workflow/nodes/question-classifier/use-config.ts b/web/app/components/workflow/nodes/question-classifier/use-config.ts index a3db7d99d4c436..07106e208f2ce7 100644 --- a/web/app/components/workflow/nodes/question-classifier/use-config.ts +++ b/web/app/components/workflow/nodes/question-classifier/use-config.ts @@ -74,7 +74,6 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => { ...defaultConfig, query_variable_selector: inputs.query_variable_selector.length > 0 ? inputs.query_variable_selector : query_variable_selector, }) - console.log(query_variable_selector) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultConfig]) diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index bb8efb3bdc73bb..91d72a1486d7f4 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -33,7 +33,6 @@ export type CommonNodeType = { _isSingleRun?: boolean _runningStatus?: NodeRunningStatus _singleRunningStatus?: NodeRunningStatus - _isReady?: boolean selected?: boolean title: string desc: string From ec49da073e74c0a48da899cf30aecb9ef3a7b6ec Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 15 Mar 2024 21:54:16 +0800 Subject: [PATCH 2/5] feat: code default value --- .../workflow/nodes/code/use-config.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/web/app/components/workflow/nodes/code/use-config.ts b/web/app/components/workflow/nodes/code/use-config.ts index 7f6768a398d941..db2ed6fa36024e 100644 --- a/web/app/components/workflow/nodes/code/use-config.ts +++ b/web/app/components/workflow/nodes/code/use-config.ts @@ -1,20 +1,36 @@ -import { useCallback } from 'react' +import { useCallback, useEffect } from 'react' import produce from 'immer' import useVarList from '../_base/hooks/use-var-list' import useOutputVarList from '../_base/hooks/use-output-var-list' import { VarType } from '../../types' import type { Var } from '../../types' +import { useStore } from '../../store' import type { CodeLanguage, CodeNodeType } from './types' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run' const useConfig = (id: string, payload: CodeNodeType) => { + const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type] const { inputs, setInputs } = useNodeCrud(id, payload) const { handleVarListChange, handleAddVariable } = useVarList({ inputs, setInputs, }) + useEffect(() => { + if (inputs.code) + return + + const isReady = defaultConfig && Object.keys(defaultConfig).length > 0 + if (isReady) { + setInputs({ + ...inputs, + ...defaultConfig, + }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [defaultConfig]) + const handleCodeChange = useCallback((code: string) => { const newInputs = produce(inputs, (draft) => { draft.code = code From af9ae91934cdc2bb933a8fca5737ffeb0d8b20a5 Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 15 Mar 2024 21:58:56 +0800 Subject: [PATCH 3/5] feat: template transform default --- .../nodes/template-transform/use-config.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/web/app/components/workflow/nodes/template-transform/use-config.ts b/web/app/components/workflow/nodes/template-transform/use-config.ts index c5235fde1dcfa1..8310b1a2b3cce7 100644 --- a/web/app/components/workflow/nodes/template-transform/use-config.ts +++ b/web/app/components/workflow/nodes/template-transform/use-config.ts @@ -1,19 +1,36 @@ -import { useCallback } from 'react' +import { useCallback, useEffect } from 'react' import produce from 'immer' import useVarList from '../_base/hooks/use-var-list' import type { Var } from '../../types' import { VarType } from '../../types' +import { useStore } from '../../store' import type { TemplateTransformNodeType } from './types' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run' const useConfig = (id: string, payload: TemplateTransformNodeType) => { + const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type] + const { inputs, setInputs } = useNodeCrud(id, payload) const { handleVarListChange, handleAddVariable } = useVarList({ inputs, setInputs, }) + useEffect(() => { + if (inputs.template) + return + + const isReady = defaultConfig && Object.keys(defaultConfig).length > 0 + if (isReady) { + setInputs({ + ...inputs, + ...defaultConfig, + }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [defaultConfig]) + const handleCodeChange = useCallback((template: string) => { const newInputs = produce(inputs, (draft: any) => { draft.template = template From 338dd1c714057969bc823e0c1805794b9dc248d4 Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 15 Mar 2024 22:04:07 +0800 Subject: [PATCH 4/5] feat: http var limit --- web/app/components/workflow/nodes/http/panel.tsx | 2 ++ .../components/workflow/nodes/http/use-config.ts | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/web/app/components/workflow/nodes/http/panel.tsx b/web/app/components/workflow/nodes/http/panel.tsx index c8470fe0a96dff..b7f749e886d573 100644 --- a/web/app/components/workflow/nodes/http/panel.tsx +++ b/web/app/components/workflow/nodes/http/panel.tsx @@ -30,6 +30,7 @@ const Panel: FC> = ({ inputs, handleVarListChange, handleAddVariable, + filterVar, handleMethodChange, handleUrlChange, headers, @@ -75,6 +76,7 @@ const Panel: FC> = ({ readonly={readOnly} list={inputs.variables} onChange={handleVarListChange} + filterVar={filterVar} /> { draft.method = method }) setInputs(newInputs) - }, []) + }, [inputs, setInputs]) const handleUrlChange = useCallback((url: string) => { const newInputs = produce(inputs, (draft: HttpNodeType) => { draft.url = url }) setInputs(newInputs) - }, []) + }, [inputs, setInputs]) const { list: headers, @@ -66,6 +68,10 @@ const useConfig = (id: string, payload: HttpNodeType) => { setInputs(newInputs) }, [inputs, setInputs]) + const filterVar = useCallback((varPayload: Var) => { + return [VarType.string, VarType.number].includes(varPayload.type) + }, []) + // single run const { isShowSingleRun, @@ -95,12 +101,13 @@ const useConfig = (id: string, payload: HttpNodeType) => { const setInputVarValues = useCallback((newPayload: Record) => { setRunInputData(newPayload) - }, [runInputData, setRunInputData]) + }, [setRunInputData]) return { inputs, handleVarListChange, handleAddVariable, + filterVar, handleMethodChange, handleUrlChange, // headers From 5ee7fc4fdeddf1f1fe72def3dba9095019db7bb4 Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 15 Mar 2024 22:15:36 +0800 Subject: [PATCH 5/5] feat: tools vars limit --- .../nodes/tool/components/input-var-list.tsx | 5 ++++- .../components/workflow/nodes/tool/panel.tsx | 2 ++ .../workflow/nodes/tool/use-config.ts | 22 +++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/web/app/components/workflow/nodes/tool/components/input-var-list.tsx b/web/app/components/workflow/nodes/tool/components/input-var-list.tsx index 7bc0d79431b2ea..4933e6460b1967 100644 --- a/web/app/components/workflow/nodes/tool/components/input-var-list.tsx +++ b/web/app/components/workflow/nodes/tool/components/input-var-list.tsx @@ -4,7 +4,7 @@ import React, { useCallback } from 'react' import produce from 'immer' import type { ToolVarInput } from '../types' import { VarType as VarKindType } from '../types' -import { type ValueSelector } from '@/app/components/workflow/types' +import type { ValueSelector, Var } from '@/app/components/workflow/types' import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations' import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' @@ -17,6 +17,7 @@ type Props = { value: ToolVarInput[] onChange: (value: ToolVarInput[]) => void isSupportConstantValue?: boolean + filterVar?: (payload: Var, valueSelector: ValueSelector) => boolean } const InputVarList: FC = ({ @@ -26,6 +27,7 @@ const InputVarList: FC = ({ value, onChange, isSupportConstantValue, + filterVar, }) => { const language = useLanguage() @@ -92,6 +94,7 @@ const InputVarList: FC = ({ onChange={handleChange(variable)} isSupportConstantValue={isSupportConstantValue} defaultVarKindType={varInput?.variable_type} + filterVar={filterVar} /> {tooltip &&
{tooltip[language] || tooltip.en_US}
}
diff --git a/web/app/components/workflow/nodes/tool/panel.tsx b/web/app/components/workflow/nodes/tool/panel.tsx index 5a5573c264c4f9..4349801864e6af 100644 --- a/web/app/components/workflow/nodes/tool/panel.tsx +++ b/web/app/components/workflow/nodes/tool/panel.tsx @@ -28,6 +28,7 @@ const Panel: FC> = ({ inputs, toolInputVarSchema, setInputVar, + filterVar, toolSettingSchema, toolSettingValue, setToolSettingValue, @@ -80,6 +81,7 @@ const Panel: FC> = ({ schema={toolInputVarSchema as any} value={inputs.tool_parameters} onChange={setInputVar} + filterVar={filterVar} isSupportConstantValue /> diff --git a/web/app/components/workflow/nodes/tool/use-config.ts b/web/app/components/workflow/nodes/tool/use-config.ts index e28528266d0803..bf2816b31c0f87 100644 --- a/web/app/components/workflow/nodes/tool/use-config.ts +++ b/web/app/components/workflow/nodes/tool/use-config.ts @@ -12,10 +12,9 @@ import { fetchBuiltInToolList, fetchCollectionList, fetchCustomToolList, updateB import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema' import Toast from '@/app/components/base/toast' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' -import { InputVarType } from '@/app/components/workflow/types' -import type { InputVar } from '@/app/components/workflow/types' +import { InputVarType, VarType as VarVarType } from '@/app/components/workflow/types' +import type { InputVar, Var } from '@/app/components/workflow/types' import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run' - const useConfig = (id: string, payload: ToolNodeType) => { const { t } = useTranslation() const language = useLanguage() @@ -27,7 +26,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { * tool_configurations: tool setting, not dynamic setting * tool_parameters: tool dynamic setting(by user) */ - const { provider_id, provider_name, provider_type, tool_name, tool_configurations, tool_parameters: toolInputs } = inputs + const { provider_id, provider_name, provider_type, tool_name, tool_configurations } = inputs const isBuiltIn = provider_type === CollectionType.builtIn const [currCollection, setCurrCollection] = useState(null) const fetchCurrCollection = useCallback(async () => { @@ -43,6 +42,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { return fetchCurrCollection() + // eslint-disable-next-line react-hooks/exhaustive-deps }, [provider_id]) // Auth @@ -63,7 +63,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { }) await fetchCurrCollection() hideSetAuthModal() - }, [currCollection]) + }, [currCollection?.name, fetchCurrCollection, hideSetAuthModal, t]) const [currTool, setCurrTool] = useState(null) const formSchemas = currTool ? toolParametersToFormSchemas(currTool.parameters) : [] @@ -94,6 +94,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { }) }) setInputs(inputsWithDefaultValue) + // eslint-disable-next-line react-hooks/exhaustive-deps }, [currTool]) // setting when call @@ -104,6 +105,11 @@ const useConfig = (id: string, payload: ToolNodeType) => { }) }, [inputs, setInputs]) + // TODO: dynamic setting as the current var type + const filterVar = useCallback((varPayload: Var) => { + return varPayload.type !== VarVarType.arrayFile + }, []) + const isLoading = currTool && (isBuiltIn ? !currCollection : false) useEffect(() => { @@ -123,6 +129,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { if (currTool) setCurrTool(currTool) })() + // eslint-disable-next-line react-hooks/exhaustive-deps }, [provider_name]) // single run @@ -149,13 +156,13 @@ const useConfig = (id: string, payload: ToolNodeType) => { const singleRunForms = (() => { const formInputs: InputVar[] = [] toolInputVarSchema.forEach((item: any) => { - const targetItem = toolInputs.find(input => input.variable === item.variable) + // const targetItem = toolInputs.find(input => input.variable === item.variable) // TODO: support selector // if (targetItem?.variable_type === VarType.selector) { formInputs.push({ label: item.label[language] || item.label.en_US, variable: item.variable, - type: InputVarType.textInput, + type: InputVarType.textInput, // TODO: to form input required: item.required, }) // } @@ -176,6 +183,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { setToolSettingValue, toolInputVarSchema, setInputVar, + filterVar, currCollection, isShowAuthBtn, showSetAuth,