diff --git a/web/app/components/app/configuration/config/automatic/instruction-editor-in-workflow.tsx b/web/app/components/app/configuration/config/automatic/instruction-editor-in-workflow.tsx index a6e922f39f..cc8b5bff0c 100644 --- a/web/app/components/app/configuration/config/automatic/instruction-editor-in-workflow.tsx +++ b/web/app/components/app/configuration/config/automatic/instruction-editor-in-workflow.tsx @@ -1,13 +1,13 @@ 'use client' import type { FC } from 'react' -import React, { useCallback, useMemo } from 'react' +import React, { useCallback } from 'react' import type { GeneratorType } from './types' import type { ValueSelector, Var } from '@/app/components/workflow/types' import { VarType } from '@/app/components/workflow/types' import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list' import InstructionEditor from './instruction-editor' import { useWorkflowVariableType } from '@/app/components/workflow/hooks' -import { useStore, useWorkflowStore } from '@/app/components/workflow/store' +import { useWorkflowStore } from '@/app/components/workflow/store' type Props = { nodeId: string @@ -27,10 +27,6 @@ const InstructionEditorInWorkflow: FC = ({ isShowCurrentBlock, }) => { const workflowStore = useWorkflowStore() - const nodesWithInspectVars = useStore(s => s.nodesWithInspectVars) - const isShowLastRunBlock = useMemo(() => { - return !!nodesWithInspectVars.find(node => node.nodeId === nodeId) - }, [nodesWithInspectVars]) const filterVar = useCallback((payload: Var, selector: ValueSelector) => { const { nodesWithInspectVars } = workflowStore.getState() const nodeId = selector?.[0] diff --git a/web/app/components/app/configuration/config/automatic/prompt-res.tsx b/web/app/components/app/configuration/config/automatic/prompt-res.tsx index 86728bb2bc..f110741b98 100644 --- a/web/app/components/app/configuration/config/automatic/prompt-res.tsx +++ b/web/app/components/app/configuration/config/automatic/prompt-res.tsx @@ -2,19 +2,25 @@ import PromptEditor from '@/app/components/base/prompt-editor' import type { WorkflowVariableBlockType } from '@/app/components/base/prompt-editor/types' import type { FC } from 'react' -import React from 'react' +import React, { useEffect } from 'react' type Props = { value: string workflowVariableBlock: WorkflowVariableBlockType } +const keyIdPrefix = 'prompt-res-editor' const PromptRes: FC = ({ value, workflowVariableBlock, }) => { + const [editorKey, setEditorKey] = React.useState('keyIdPrefix-0') + useEffect(() => { + setEditorKey(`${keyIdPrefix}-${Date.now()}`) + }, [value]) return ( { {/* right */}
setShowLeftPanel(true)} diff --git a/web/app/components/workflow/variable-inspect/right.tsx b/web/app/components/workflow/variable-inspect/right.tsx index 6ddd0d47d3..13f365abf7 100644 --- a/web/app/components/workflow/variable-inspect/right.tsx +++ b/web/app/components/workflow/variable-inspect/right.tsx @@ -3,9 +3,10 @@ import { RiArrowGoBackLine, RiCloseLine, RiMenuLine, + RiSparklingFill, } from '@remixicon/react' import { useStore } from '../store' -import type { BlockEnum } from '../types' +import { BlockEnum } from '../types' import useCurrentVars from '../hooks/use-inspect-vars-crud' import Empty from './empty' import ValueContent from './value-content' @@ -20,14 +21,30 @@ import Loading from '@/app/components/base/loading' import type { currentVarType } from './panel' import { VarInInspectType } from '@/types/workflow' import cn from '@/utils/classnames' +import useNodeInfo from '../nodes/_base/hooks/use-node-info' +import { useBoolean } from 'ahooks' +import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res' +import GetCodeGeneratorResModal from '../../app/configuration/config/code-generator/get-code-generator-res' +import { AppType } from '@/types/app' +import { useHooksStore } from '../hooks-store' +import { useCallback, useMemo } from 'react' +import { useNodesInteractions } from '../hooks' +import { CodeLanguage } from '../nodes/code/types' +import useNodeCrud from '../nodes/_base/hooks/use-node-crud' +import type { GenRes } from '@/service/debug' +import produce from 'immer' +import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '../../base/prompt-editor/plugins/update-block' +import { useEventEmitterContextContext } from '@/context/event-emitter' type Props = { + nodeId: string currentNodeVar?: currentVarType handleOpenMenu: () => void isValueFetching?: boolean } const Right = ({ + nodeId, currentNodeVar, handleOpenMenu, isValueFetching, @@ -74,6 +91,63 @@ const Right = ({ return String(value) } + const configsMap = useHooksStore(s => s.configsMap) + const { eventEmitter } = useEventEmitterContextContext() + const { handleNodeSelect } = useNodesInteractions() + const { node } = useNodeInfo(nodeId) + const { setInputs } = useNodeCrud(nodeId, node?.data) + const blockType = node?.data?.type + const isCodeBlock = blockType === BlockEnum.Code + const canShowPromptGenerator = [BlockEnum.LLM, BlockEnum.Code].includes(blockType) + const currentPrompt = useMemo(() => { + if (!canShowPromptGenerator) + return '' + if (blockType === BlockEnum.LLM) + return node?.data?.prompt_template?.text || node?.data?.prompt_template?.[0].text + + // if (blockType === BlockEnum.Agent) { + // return node?.data?.agent_parameters?.instruction?.value + // } + if (blockType === BlockEnum.Code) + return node?.data?.code + }, [canShowPromptGenerator]) + + const [isShowPromptGenerator, { + setTrue: doShowPromptGenerator, + setFalse: handleHidePromptGenerator, + }] = useBoolean(false) + const handleShowPromptGenerator = useCallback(() => { + handleNodeSelect(nodeId) + doShowPromptGenerator() + }, [doShowPromptGenerator, handleNodeSelect, nodeId]) + + const handleUpdatePrompt = useCallback((res: GenRes) => { + const newInputs = produce(node?.data, (draft: any) => { + switch (blockType) { + case BlockEnum.LLM: + if (draft?.prompt_template) { + if (Array.isArray(draft.prompt_template)) + draft.prompt_template[0].text = res.modified + else + draft.prompt_template.text = res.modified + } + break + + // Agent is a plugin, may has many instructions + // case BlockEnum.Agent: + // if (draft?.agent_parameters?.instruction) { + // draft.agent_parameters.instruction.value = res.modified + // } + // break + case BlockEnum.Code: + draft.code = res.modified + break + } + }) + setInputs(newInputs) + eventEmitter?.emit({ type: PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER, instanceId: `${nodeId}-chat-workflow-llm-prompt-editor` } as any) + handleHidePromptGenerator() + }, [setInputs, blockType, nodeId, node?.data, handleHidePromptGenerator]) return (
{/* header */} @@ -114,6 +188,16 @@ const Right = ({
{currentNodeVar && ( <> + {canShowPromptGenerator && ( + +
+ +
+
+ )} {currentNodeVar.var.edited && ( @@ -154,6 +238,28 @@ const Right = ({ )} {currentNodeVar && !isValueFetching && }
+ {isShowPromptGenerator && ( + isCodeBlock + ? + : + )}
) } diff --git a/web/i18n/en-US/app-debug.ts b/web/i18n/en-US/app-debug.ts index a6e0b91ea2..076f93e634 100644 --- a/web/i18n/en-US/app-debug.ts +++ b/web/i18n/en-US/app-debug.ts @@ -305,6 +305,7 @@ const translation = { press: 'Press', to: 'to ', insertContext: 'insert context', + optimizePromptTooltip: 'Optimize in Prompt Generator', }, resetConfig: { title: 'Confirm reset?', diff --git a/web/i18n/zh-Hans/app-debug.ts b/web/i18n/zh-Hans/app-debug.ts index 92f1db7b2d..b8b44e0e76 100644 --- a/web/i18n/zh-Hans/app-debug.ts +++ b/web/i18n/zh-Hans/app-debug.ts @@ -304,6 +304,7 @@ const translation = { press: '输入', to: '来', insertContext: '插入上下文', + optimizePromptTooltip: '在提示词生成器中优化', }, resetConfig: { title: '确认重置?',