mirror of https://github.com/langgenius/dify.git
select memory var in popup
This commit is contained in:
parent
7e9375ce7e
commit
57624979e4
|
|
@ -80,6 +80,9 @@ import {
|
|||
UPDATE_HISTORY_EVENT_EMITTER,
|
||||
} from './constants'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
} from '@/app/components/workflow/types'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type PromptEditorProps = {
|
||||
|
|
@ -106,6 +109,8 @@ export type PromptEditorProps = {
|
|||
lastRunBlock?: LastRunBlockType
|
||||
isSupportFileVar?: boolean
|
||||
isMemorySupported?: boolean
|
||||
memoryVarInNode?: ConversationVariable[]
|
||||
memoryVarInApp?: ConversationVariable[]
|
||||
}
|
||||
|
||||
const PromptEditor: FC<PromptEditorProps> = ({
|
||||
|
|
@ -132,6 +137,8 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
lastRunBlock,
|
||||
isSupportFileVar,
|
||||
isMemorySupported,
|
||||
memoryVarInNode = [],
|
||||
memoryVarInApp = [],
|
||||
}) => {
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
const initialConfig = {
|
||||
|
|
@ -203,7 +210,11 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
{isMemorySupported && (
|
||||
<MemoryPopupPlugin instanceId={instanceId} />
|
||||
<MemoryPopupPlugin
|
||||
instanceId={instanceId}
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
)}
|
||||
<ComponentPickerBlock
|
||||
triggerString='/'
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
useState,
|
||||
} from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
autoUpdate,
|
||||
flip,
|
||||
|
|
@ -21,6 +22,12 @@ import {
|
|||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/add-memory-button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import VariableIcon from '@/app/components/workflow/nodes/_base/components/variable/variable-label/base/variable-icon'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
} from '@/app/components/workflow/types'
|
||||
import { INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND } from '../workflow-variable-block'
|
||||
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
|
|
@ -28,13 +35,18 @@ export type MemoryPopupProps = {
|
|||
className?: string
|
||||
container?: Element | null
|
||||
instanceId?: string
|
||||
memoryVarInNode: ConversationVariable[]
|
||||
memoryVarInApp: ConversationVariable[]
|
||||
}
|
||||
|
||||
export default function MemoryPopupPlugin({
|
||||
className,
|
||||
container,
|
||||
instanceId,
|
||||
memoryVarInNode,
|
||||
memoryVarInApp,
|
||||
}: MemoryPopupProps) {
|
||||
const { t } = useTranslation()
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
|
||||
|
|
@ -124,6 +136,11 @@ export default function MemoryPopupPlugin({
|
|||
openPortal()
|
||||
})
|
||||
|
||||
const handleSelectVariable = useCallback((variable: string[]) => {
|
||||
editor.dispatchCommand(INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND, variable)
|
||||
closePortal()
|
||||
}, [editor, closePortal])
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerUpdateListener(({ editorState }) => {
|
||||
editorState.read(() => {
|
||||
|
|
@ -155,22 +172,68 @@ export default function MemoryPopupPlugin({
|
|||
return null
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
ref={(node) => {
|
||||
portalRef.current = node
|
||||
refs.setFloating(node)
|
||||
}}
|
||||
className={cn(
|
||||
useContainer ? '' : 'z-[999999]',
|
||||
'absolute rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-sm',
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
...floatingStyles,
|
||||
visibility: isPositioned ? 'visible' : 'hidden',
|
||||
}}
|
||||
>
|
||||
Memory Popup
|
||||
<div className='h-0 w-0'>
|
||||
<div
|
||||
ref={(node) => {
|
||||
portalRef.current = node
|
||||
refs.setFloating(node)
|
||||
}}
|
||||
className={cn(
|
||||
useContainer ? '' : 'z-[999999]',
|
||||
'absolute rounded-xl shadow-lg backdrop-blur-sm',
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
...floatingStyles,
|
||||
visibility: isPositioned ? 'visible' : 'hidden',
|
||||
}}
|
||||
>
|
||||
<div className='w-[261px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur'>
|
||||
{memoryVarInNode.length > 0 && (
|
||||
<>
|
||||
<div className='flex items-center gap-1 pb-1 pt-2.5'>
|
||||
<Divider className='!h-px !w-3 bg-divider-subtle' />
|
||||
<div className='system-2xs-medium-uppercase shrink-0 text-text-tertiary'>{t('workflow.nodes.llm.memory.currentNodeLabel')}</div>
|
||||
<Divider className='!h-px grow bg-divider-subtle' />
|
||||
</div>
|
||||
<div className='p-1'>
|
||||
{memoryVarInNode.map(variable => (
|
||||
<div key={variable.id} className='flex cursor-pointer items-center gap-1 rounded-md px-3 py-1 hover:bg-state-base-hover' onClick={() => handleSelectVariable(['conversation', variable.name])}>
|
||||
<VariableIcon
|
||||
isMemoryVariable
|
||||
variables={['conversation', variable.name]}
|
||||
className='text-util-colors-teal-teal-700'
|
||||
/>
|
||||
<div title={variable.name} className='system-sm-medium shrink-0 truncate text-text-secondary'>{variable.name}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{memoryVarInApp.length > 0 && (
|
||||
<>
|
||||
<div className='flex items-center gap-1 pb-1 pt-2.5'>
|
||||
<Divider className='!h-px !w-3 bg-divider-subtle' />
|
||||
<div className='system-2xs-medium-uppercase shrink-0 text-text-tertiary'>{t('workflow.nodes.llm.memory.conversationScopeLabel')}</div>
|
||||
<Divider className='!h-px grow bg-divider-subtle' />
|
||||
</div>
|
||||
<div className='p-1'>
|
||||
{memoryVarInApp.map(variable => (
|
||||
<div key={variable.id} className='flex cursor-pointer items-center gap-1 rounded-md px-3 py-1 hover:bg-state-base-hover' onClick={() => handleSelectVariable(['conversation', variable.name])}>
|
||||
<VariableIcon
|
||||
isMemoryVariable
|
||||
variables={['conversation', variable.name]}
|
||||
className='text-util-colors-teal-teal-700'
|
||||
/>
|
||||
<div title={variable.name} className='system-sm-medium shrink-0 truncate text-text-secondary'>{variable.name}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div>{t('workflow.nodes.llm.memory.createButton')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
containerEl,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
|
|||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { useWorkflowVariableType } from '@/app/components/workflow/hooks'
|
||||
import AddMemoryButton, { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from './add-memory-button'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
} from '@/app/components/workflow/types'
|
||||
|
||||
type Props = {
|
||||
className?: string
|
||||
|
|
@ -81,6 +84,8 @@ type Props = {
|
|||
titleClassName?: string
|
||||
required?: boolean
|
||||
isMemorySupported?: boolean
|
||||
memoryVarInNode?: ConversationVariable[]
|
||||
memoryVarInApp?: ConversationVariable[]
|
||||
}
|
||||
|
||||
const Editor: FC<Props> = ({
|
||||
|
|
@ -121,6 +126,8 @@ const Editor: FC<Props> = ({
|
|||
editorContainerClassName,
|
||||
required,
|
||||
isMemorySupported,
|
||||
memoryVarInNode = [],
|
||||
memoryVarInApp = [],
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
|
|
@ -301,6 +308,8 @@ const Editor: FC<Props> = ({
|
|||
editable={!readOnly}
|
||||
isSupportFileVar={isSupportFileVar}
|
||||
isMemorySupported
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
{/* to patch Editor not support dynamic change editable status */}
|
||||
{readOnly && <div className='absolute inset-0 z-10'></div>}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ import Editor from '@/app/components/workflow/nodes/_base/components/prompt/edit
|
|||
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { PromptRole } from '@/models/debug'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
} from '@/app/components/workflow/types'
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.llm'
|
||||
|
||||
|
|
@ -39,6 +42,8 @@ type Props = {
|
|||
varList: Variable[]
|
||||
handleAddVariable: (payload: any) => void
|
||||
modelConfig?: ModelConfig
|
||||
memoryVarInNode?: ConversationVariable[]
|
||||
memoryVarInApp?: ConversationVariable[]
|
||||
}
|
||||
|
||||
const roleOptions = [
|
||||
|
|
@ -81,6 +86,8 @@ const ConfigPromptItem: FC<Props> = ({
|
|||
varList,
|
||||
handleAddVariable,
|
||||
modelConfig,
|
||||
memoryVarInNode = [],
|
||||
memoryVarInApp = [],
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
|
@ -157,6 +164,8 @@ const ConfigPromptItem: FC<Props> = ({
|
|||
</>
|
||||
}
|
||||
isMemorySupported
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import cn from '@/utils/classnames'
|
|||
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
|
||||
import AddButton from '@/app/components/workflow/nodes/_base/components/add-button'
|
||||
import { DragHandle } from '@/app/components/base/icons/src/vender/line/others'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
} from '@/app/components/workflow/types'
|
||||
|
||||
const i18nPrefix = 'workflow.nodes.llm'
|
||||
|
||||
|
|
@ -35,6 +38,8 @@ type Props = {
|
|||
handleAddVariable: (payload: any) => void
|
||||
modelConfig: ModelConfig
|
||||
memoryVarSortFn?: (a: string, b: string) => number
|
||||
memoryVarInNode?: ConversationVariable[]
|
||||
memoryVarInApp?: ConversationVariable[]
|
||||
}
|
||||
|
||||
const ConfigPrompt: FC<Props> = ({
|
||||
|
|
@ -51,6 +56,8 @@ const ConfigPrompt: FC<Props> = ({
|
|||
handleAddVariable,
|
||||
modelConfig,
|
||||
memoryVarSortFn,
|
||||
memoryVarInNode,
|
||||
memoryVarInApp,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
|
@ -208,6 +215,8 @@ const ConfigPrompt: FC<Props> = ({
|
|||
varList={varList}
|
||||
handleAddVariable={handleAddVariable}
|
||||
modelConfig={modelConfig}
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
|||
filterJinja2InputVar,
|
||||
handleReasoningFormatChange,
|
||||
memoryVarSortFn,
|
||||
memoryVarInNode,
|
||||
memoryVarInApp,
|
||||
} = useConfig(id, data)
|
||||
const { memoryType } = useMemory(id, data)
|
||||
|
||||
|
|
@ -157,6 +159,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
|||
handleAddVariable={handleAddVariable}
|
||||
modelConfig={model}
|
||||
memoryVarSortFn={memoryVarSortFn}
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import produce from 'immer'
|
||||
import { EditionType, VarType } from '../../types'
|
||||
import type { Memory, PromptItem, ValueSelector, Var, Variable } from '../../types'
|
||||
|
|
@ -18,10 +18,12 @@ import {
|
|||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import { checkHasContextBlock, checkHasHistoryBlock, checkHasQueryBlock } from '@/app/components/base/prompt-editor/constants'
|
||||
import useInspectVarsCrud from '@/app/components/workflow/hooks/use-inspect-vars-crud'
|
||||
import { ChatVarType } from '@/app/components/workflow/panel/chat-variable-panel/type'
|
||||
|
||||
const useConfig = (id: string, payload: LLMNodeType) => {
|
||||
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
||||
const isChatMode = useIsChatMode()
|
||||
const conversationVariables = useStore(s => s.conversationVariables)
|
||||
|
||||
const defaultConfig = useStore(s => s.nodesDefaultConfigs)?.[payload.type]
|
||||
const [defaultRolePrefix, setDefaultRolePrefix] = useState<{ user: string; assistant: string }>({ user: '', assistant: '' })
|
||||
|
|
@ -342,6 +344,20 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
|||
return a.localeCompare(b)
|
||||
}, [inputs.memory?.block_id])
|
||||
|
||||
const memoryVarInNode = useMemo(() => {
|
||||
const idsInNode = inputs.memory?.block_id || []
|
||||
return conversationVariables
|
||||
.filter(varItem => varItem.value_type === ChatVarType.Memory)
|
||||
.filter(varItem => idsInNode.includes(varItem.id))
|
||||
}, [inputs.memory?.block_id, conversationVariables])
|
||||
|
||||
const memoryVarInApp = useMemo(() => {
|
||||
const idsInApp = inputs.memory?.block_id || []
|
||||
return conversationVariables
|
||||
.filter(varItem => varItem.value_type === ChatVarType.Memory)
|
||||
.filter(varItem => !idsInApp.includes(varItem.id))
|
||||
}, [inputs.memory?.block_id, conversationVariables])
|
||||
|
||||
return {
|
||||
readOnly,
|
||||
isChatMode,
|
||||
|
|
@ -376,6 +392,8 @@ const useConfig = (id: string, payload: LLMNodeType) => {
|
|||
filterJinja2InputVar,
|
||||
handleReasoningFormatChange,
|
||||
memoryVarSortFn,
|
||||
memoryVarInNode,
|
||||
memoryVarInApp,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -526,6 +526,9 @@ const translation = {
|
|||
promptEditorPlaceholder2: 'Type \'/\' to insert variable',
|
||||
memory: {
|
||||
addButton: 'Add Memory',
|
||||
currentNodeLabel: 'Current Node scope',
|
||||
conversationScopeLabel: 'Conversation scope',
|
||||
createButton: 'Create memory variable',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
|
|
|
|||
|
|
@ -526,6 +526,9 @@ const translation = {
|
|||
promptEditorPlaceholder2: '输入 \'/\' 插入变量',
|
||||
memory: {
|
||||
addButton: '添加记忆',
|
||||
currentNodeLabel: '当前节点范围',
|
||||
conversationScopeLabel: '会话范围',
|
||||
createButton: '创建记忆变量',
|
||||
},
|
||||
},
|
||||
knowledgeRetrieval: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue