mirror of https://github.com/langgenius/dify.git
fix
This commit is contained in:
parent
2f0076166a
commit
4050ed8c8e
|
|
@ -53,6 +53,7 @@ export type IGetAutomaticResProps = {
|
|||
editorId?: string
|
||||
currentPrompt?: string
|
||||
isBasicMode?: boolean
|
||||
hideTryIt?: boolean
|
||||
}
|
||||
|
||||
const TryLabel: FC<{
|
||||
|
|
@ -81,6 +82,7 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
|
|||
currentPrompt,
|
||||
isBasicMode,
|
||||
onFinished,
|
||||
hideTryIt,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const localModel = localStorage.getItem('auto-gen-model')
|
||||
|
|
@ -307,7 +309,7 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
|
|||
hideDebugWithMultipleModel
|
||||
/>
|
||||
</div>
|
||||
{isBasicMode && (
|
||||
{isBasicMode && !hideTryIt && (
|
||||
<div className='mt-4'>
|
||||
<div className='flex items-center'>
|
||||
<div className='mr-3 shrink-0 text-xs font-semibold uppercase leading-[18px] text-text-tertiary'>{t('appDebug.generate.tryIt')}</div>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import Radio from '@/app/components/base/radio'
|
|||
import RadioE from '@/app/components/base/radio/ui'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import PromptEditor from '@/app/components/base/prompt-editor'
|
||||
import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
import ObjectValueList from '@/app/components/workflow/panel/chat-variable-panel/components/object-value-list'
|
||||
import ArrayValueList from '@/app/components/workflow/panel/chat-variable-panel/components/array-value-list'
|
||||
import ArrayBooleanValueList from '@/app/components/workflow/panel/chat-variable-panel/components/array-bool-list'
|
||||
|
|
@ -136,6 +136,7 @@ const BaseField = ({
|
|||
const handleChange = useCallback((value: any) => {
|
||||
if (disabled)
|
||||
return
|
||||
|
||||
field.handleChange(value)
|
||||
formOnChange?.(field.form, value)
|
||||
onChange?.(field.name, value)
|
||||
|
|
@ -340,10 +341,12 @@ const BaseField = ({
|
|||
selfProps?.enablePromptGenerator && (
|
||||
<PromptGeneratorBtn
|
||||
nodeId={selfProps?.nodeId}
|
||||
editorId={selfProps?.editorId}
|
||||
className='absolute right-0 top-[-26px]'
|
||||
onGenerated={handleChange}
|
||||
modelConfig={selfProps?.modelConfig}
|
||||
currentPrompt={value}
|
||||
isBasicMode={selfProps?.isBasicMode}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -405,11 +408,28 @@ const BaseField = ({
|
|||
type === FormTypeEnum.modelSelector && (
|
||||
<ModelParameterModal
|
||||
popupClassName='!w-[387px]'
|
||||
value={value}
|
||||
setModel={handleChange}
|
||||
mode={value?.mode}
|
||||
modelId={value?.name}
|
||||
provider={value?.provider}
|
||||
setModel={({ modelId, mode, provider }) => {
|
||||
handleChange({
|
||||
mode,
|
||||
provider,
|
||||
name: modelId,
|
||||
completion_params: value?.completion_params,
|
||||
})
|
||||
}}
|
||||
completionParams={value?.completion_params}
|
||||
onCompletionParamsChange={(params) => {
|
||||
handleChange({
|
||||
...value,
|
||||
completion_params: params,
|
||||
})
|
||||
}}
|
||||
readonly={disabled}
|
||||
scope={formSchema.scope}
|
||||
isAdvancedMode
|
||||
isInWorkflow
|
||||
hideDebugWithMultipleModel
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export const LAST_RUN_PLACEHOLDER_TEXT = '{{#last_run#}}'
|
|||
export const PRE_PROMPT_PLACEHOLDER_TEXT = '{{#pre_prompt#}}'
|
||||
export const UPDATE_DATASETS_EVENT_EMITTER = 'prompt-editor-context-block-update-datasets'
|
||||
export const UPDATE_HISTORY_EVENT_EMITTER = 'prompt-editor-history-block-update-role'
|
||||
export const UPDATE_WORKFLOW_VARIABLES_EVENT_EMITTER = 'prompt-editor-workflow-variables-block-update-variables'
|
||||
|
||||
export const checkHasContextBlock = (text: string) => {
|
||||
if (!text)
|
||||
|
|
|
|||
|
|
@ -78,9 +78,11 @@ import type {
|
|||
import {
|
||||
UPDATE_DATASETS_EVENT_EMITTER,
|
||||
UPDATE_HISTORY_EVENT_EMITTER,
|
||||
UPDATE_WORKFLOW_VARIABLES_EVENT_EMITTER,
|
||||
} from './constants'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import cn from '@/utils/classnames'
|
||||
import PromptEditorProvider from './store/provider'
|
||||
|
||||
export type PromptEditorProps = {
|
||||
instanceId?: string
|
||||
|
|
@ -176,6 +178,13 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
payload: historyBlock?.history,
|
||||
} as any)
|
||||
}, [eventEmitter, historyBlock?.history])
|
||||
useEffect(() => {
|
||||
eventEmitter?.emit({
|
||||
type: UPDATE_WORKFLOW_VARIABLES_EVENT_EMITTER,
|
||||
payload: workflowVariableBlock?.variables,
|
||||
instanceId,
|
||||
} as any)
|
||||
}, [eventEmitter, workflowVariableBlock?.variables])
|
||||
|
||||
return (
|
||||
<LexicalComposer initialConfig={{ ...initialConfig, editable }}>
|
||||
|
|
@ -267,7 +276,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
{
|
||||
workflowVariableBlock?.show && (
|
||||
<>
|
||||
<WorkflowVariableBlock {...workflowVariableBlock } />
|
||||
<WorkflowVariableBlock {...workflowVariableBlock} />
|
||||
<WorkflowVariableBlockReplacementBlock {...workflowVariableBlock} />
|
||||
</>
|
||||
)
|
||||
|
|
@ -311,4 +320,12 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
)
|
||||
}
|
||||
|
||||
export default PromptEditor
|
||||
const PromptEditorWithProvider = ({ instanceId, ...props }: PromptEditorProps) => {
|
||||
return (
|
||||
<PromptEditorProvider instanceId={instanceId}>
|
||||
<PromptEditor {...props} instanceId={instanceId} />
|
||||
</PromptEditorProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default PromptEditorWithProvider
|
||||
|
|
|
|||
|
|
@ -24,23 +24,26 @@ import Tooltip from '@/app/components/base/tooltip'
|
|||
import { isExceptionVariable } from '@/app/components/workflow/utils'
|
||||
import VarFullPathPanel from '@/app/components/workflow/nodes/_base/components/variable/var-full-path-panel'
|
||||
import { Type } from '@/app/components/workflow/nodes/llm/types'
|
||||
import type { ValueSelector, Var } from '@/app/components/workflow/types'
|
||||
import type {
|
||||
NodeOutPutVar,
|
||||
ValueSelector,
|
||||
} from '@/app/components/workflow/types'
|
||||
import {
|
||||
VariableLabelInEditor,
|
||||
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { UPDATE_WORKFLOW_VARIABLES_EVENT_EMITTER } from '../../constants'
|
||||
import { usePromptEditorStore } from '../../store/store'
|
||||
|
||||
type WorkflowVariableBlockComponentProps = {
|
||||
nodeKey: string
|
||||
variables: string[]
|
||||
workflowNodesMap: WorkflowNodesMap
|
||||
environmentVariables?: Var[]
|
||||
conversationVariables?: Var[]
|
||||
ragVariables?: Var[]
|
||||
availableVariables: NodeOutPutVar[]
|
||||
getVarType?: (payload: {
|
||||
nodeId: string,
|
||||
valueSelector: ValueSelector,
|
||||
}) => Type
|
||||
isMemorySupported?: boolean
|
||||
}
|
||||
|
||||
const WorkflowVariableBlockComponent = ({
|
||||
|
|
@ -48,13 +51,27 @@ const WorkflowVariableBlockComponent = ({
|
|||
variables,
|
||||
workflowNodesMap = {},
|
||||
getVarType,
|
||||
environmentVariables,
|
||||
conversationVariables,
|
||||
ragVariables,
|
||||
isMemorySupported,
|
||||
availableVariables: initialAvailableVariables,
|
||||
}: WorkflowVariableBlockComponentProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const instanceId = usePromptEditorStore(s => s.instanceId)
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
const [availableVariables, setAvailableVariables] = useState<NodeOutPutVar[]>(initialAvailableVariables)
|
||||
eventEmitter?.useSubscription((v: any) => {
|
||||
if (v?.type === UPDATE_WORKFLOW_VARIABLES_EVENT_EMITTER && instanceId && v.instanceId === instanceId)
|
||||
setAvailableVariables(v.payload)
|
||||
})
|
||||
const environmentVariables = availableVariables?.find(v => v.nodeId === 'env')?.vars || []
|
||||
const conversationVariables = availableVariables?.find(v => v.nodeId === 'conversation')?.vars || []
|
||||
const memoryVariables = conversationVariables?.filter(v => v.variable.startsWith('memory_block.'))
|
||||
const ragVariables = availableVariables?.reduce<any[]>((acc, curr) => {
|
||||
if (curr.nodeId === 'rag')
|
||||
acc.push(...curr.vars)
|
||||
else
|
||||
acc.push(...curr.vars.filter(v => v.isRagVariable))
|
||||
return acc
|
||||
}, [])
|
||||
const [ref, isSelected] = useSelectOrDelete(nodeKey, DELETE_WORKFLOW_VARIABLE_BLOCK_COMMAND)
|
||||
const variablesLength = variables.length
|
||||
const isRagVar = isRagVariableVar(variables)
|
||||
|
|
@ -73,27 +90,19 @@ const WorkflowVariableBlockComponent = ({
|
|||
const isMemoryVar = isMemoryVariable(variables)
|
||||
const isException = isExceptionVariable(varName, node?.type)
|
||||
|
||||
const memoryVariables = conversationVariables?.filter(v => v.variable.startsWith('memory_block.'))
|
||||
|
||||
let variableValid = true
|
||||
if (isEnv) {
|
||||
if (environmentVariables)
|
||||
variableValid = environmentVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`)
|
||||
variableValid = environmentVariables.some(v =>
|
||||
v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`)
|
||||
}
|
||||
else if (isConversationVar) {
|
||||
if (conversationVariables)
|
||||
variableValid = conversationVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`)
|
||||
variableValid = conversationVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`)
|
||||
}
|
||||
else if (isMemoryVar) {
|
||||
if (memoryVariables)
|
||||
variableValid = memoryVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`)
|
||||
|
||||
if (!isMemorySupported)
|
||||
variableValid = false
|
||||
variableValid = memoryVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}`)
|
||||
}
|
||||
else if (isRagVar) {
|
||||
if (ragVariables)
|
||||
variableValid = ragVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}.${variables?.[2] ?? ''}`)
|
||||
variableValid = ragVariables.some(v => v.variable === `${variables?.[0] ?? ''}.${variables?.[1] ?? ''}.${variables?.[2] ?? ''}`)
|
||||
}
|
||||
else {
|
||||
variableValid = !!node
|
||||
|
|
|
|||
|
|
@ -33,18 +33,9 @@ const WorkflowVariableBlock = memo(({
|
|||
onDelete,
|
||||
getVarType,
|
||||
variables: originalVariables,
|
||||
isMemorySupported,
|
||||
}: WorkflowVariableBlockType) => {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
const ragVariables = originalVariables?.reduce<any[]>((acc, curr) => {
|
||||
if (curr.nodeId === 'rag')
|
||||
acc.push(...curr.vars)
|
||||
else
|
||||
acc.push(...curr.vars.filter(v => v.isRagVariable))
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
editor.update(() => {
|
||||
editor.dispatchCommand(UPDATE_WORKFLOW_NODES_MAP, workflowNodesMap)
|
||||
|
|
@ -60,7 +51,7 @@ const WorkflowVariableBlock = memo(({
|
|||
INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND,
|
||||
(variables: string[]) => {
|
||||
editor.dispatchCommand(CLEAR_HIDE_MENU_TIMEOUT, undefined)
|
||||
const workflowVariableBlockNode = $createWorkflowVariableBlockNode(variables, workflowNodesMap, getVarType, originalVariables?.find(o => o.nodeId === 'env')?.vars || [], originalVariables?.find(o => o.nodeId === 'conversation')?.vars || [], ragVariables, isMemorySupported)
|
||||
const workflowVariableBlockNode = $createWorkflowVariableBlockNode(variables, workflowNodesMap, getVarType, originalVariables || [])
|
||||
|
||||
$insertNodes([workflowVariableBlockNode])
|
||||
if (onInsert)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { DecoratorNode } from 'lexical'
|
|||
import type { WorkflowVariableBlockType } from '../../types'
|
||||
import WorkflowVariableBlockComponent from './component'
|
||||
import type { GetVarType } from '../../types'
|
||||
import type { Var } from '@/app/components/workflow/types'
|
||||
import type { NodeOutPutVar } from '@/app/components/workflow/types'
|
||||
|
||||
export type WorkflowNodesMap = WorkflowVariableBlockType['workflowNodesMap']
|
||||
|
||||
|
|
@ -11,27 +11,21 @@ export type SerializedNode = SerializedLexicalNode & {
|
|||
variables: string[]
|
||||
workflowNodesMap: WorkflowNodesMap
|
||||
getVarType?: GetVarType
|
||||
environmentVariables?: Var[]
|
||||
conversationVariables?: Var[]
|
||||
ragVariables?: Var[]
|
||||
isMemorySupported?: boolean
|
||||
availableVariables?: NodeOutPutVar[]
|
||||
}
|
||||
|
||||
export class WorkflowVariableBlockNode extends DecoratorNode<React.JSX.Element> {
|
||||
__variables: string[]
|
||||
__workflowNodesMap: WorkflowNodesMap
|
||||
__getVarType?: GetVarType
|
||||
__environmentVariables?: Var[]
|
||||
__conversationVariables?: Var[]
|
||||
__ragVariables?: Var[]
|
||||
__isMemorySupported?: boolean
|
||||
__availableVariables?: NodeOutPutVar[]
|
||||
|
||||
static getType(): string {
|
||||
return 'workflow-variable-block'
|
||||
}
|
||||
|
||||
static clone(node: WorkflowVariableBlockNode): WorkflowVariableBlockNode {
|
||||
return new WorkflowVariableBlockNode(node.__variables, node.__workflowNodesMap, node.__getVarType, node.__key, node.__environmentVariables, node.__conversationVariables, node.__ragVariables)
|
||||
return new WorkflowVariableBlockNode(node.__variables, node.__workflowNodesMap, node.__getVarType, node.__key, node.__availableVariables)
|
||||
}
|
||||
|
||||
isInline(): boolean {
|
||||
|
|
@ -43,20 +37,14 @@ export class WorkflowVariableBlockNode extends DecoratorNode<React.JSX.Element>
|
|||
workflowNodesMap: WorkflowNodesMap,
|
||||
getVarType: any,
|
||||
key?: NodeKey,
|
||||
environmentVariables?: Var[],
|
||||
conversationVariables?: Var[],
|
||||
ragVariables?: Var[],
|
||||
isMemorySupported?: boolean,
|
||||
availableVariables?: NodeOutPutVar[],
|
||||
) {
|
||||
super(key)
|
||||
|
||||
this.__variables = variables
|
||||
this.__workflowNodesMap = workflowNodesMap
|
||||
this.__getVarType = getVarType
|
||||
this.__environmentVariables = environmentVariables
|
||||
this.__conversationVariables = conversationVariables
|
||||
this.__ragVariables = ragVariables
|
||||
this.__isMemorySupported = isMemorySupported
|
||||
this.__availableVariables = availableVariables
|
||||
}
|
||||
|
||||
createDOM(): HTMLElement {
|
||||
|
|
@ -76,16 +64,13 @@ export class WorkflowVariableBlockNode extends DecoratorNode<React.JSX.Element>
|
|||
variables={this.__variables}
|
||||
workflowNodesMap={this.__workflowNodesMap}
|
||||
getVarType={this.__getVarType!}
|
||||
environmentVariables={this.__environmentVariables}
|
||||
conversationVariables={this.__conversationVariables}
|
||||
ragVariables={this.__ragVariables}
|
||||
isMemorySupported={this.__isMemorySupported}
|
||||
availableVariables={this.__availableVariables || []}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
static importJSON(serializedNode: SerializedNode): WorkflowVariableBlockNode {
|
||||
const node = $createWorkflowVariableBlockNode(serializedNode.variables, serializedNode.workflowNodesMap, serializedNode.getVarType, serializedNode.environmentVariables, serializedNode.conversationVariables, serializedNode.ragVariables, serializedNode.isMemorySupported)
|
||||
const node = $createWorkflowVariableBlockNode(serializedNode.variables, serializedNode.workflowNodesMap, serializedNode.getVarType, serializedNode.availableVariables)
|
||||
|
||||
return node
|
||||
}
|
||||
|
|
@ -97,9 +82,7 @@ export class WorkflowVariableBlockNode extends DecoratorNode<React.JSX.Element>
|
|||
variables: this.getVariables(),
|
||||
workflowNodesMap: this.getWorkflowNodesMap(),
|
||||
getVarType: this.getVarType(),
|
||||
environmentVariables: this.getEnvironmentVariables(),
|
||||
conversationVariables: this.getConversationVariables(),
|
||||
ragVariables: this.getRagVariables(),
|
||||
availableVariables: this.getAvailableVariables(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,32 +101,17 @@ export class WorkflowVariableBlockNode extends DecoratorNode<React.JSX.Element>
|
|||
return self.__getVarType
|
||||
}
|
||||
|
||||
getEnvironmentVariables(): any {
|
||||
getAvailableVariables(): NodeOutPutVar[] {
|
||||
const self = this.getLatest()
|
||||
return self.__environmentVariables
|
||||
}
|
||||
|
||||
getConversationVariables(): any {
|
||||
const self = this.getLatest()
|
||||
return self.__conversationVariables
|
||||
}
|
||||
|
||||
getRagVariables(): any {
|
||||
const self = this.getLatest()
|
||||
return self.__ragVariables
|
||||
}
|
||||
|
||||
getIsMemorySupported() {
|
||||
const self = this.getLatest()
|
||||
return self.__isMemorySupported
|
||||
return self.__availableVariables || []
|
||||
}
|
||||
|
||||
getTextContent(): string {
|
||||
return `{{#${this.getVariables().join('.')}#}}`
|
||||
}
|
||||
}
|
||||
export function $createWorkflowVariableBlockNode(variables: string[], workflowNodesMap: WorkflowNodesMap, getVarType?: GetVarType, environmentVariables?: Var[], conversationVariables?: Var[], ragVariables?: Var[], isMemorySupported?: boolean): WorkflowVariableBlockNode {
|
||||
return new WorkflowVariableBlockNode(variables, workflowNodesMap, getVarType, undefined, environmentVariables, conversationVariables, ragVariables, isMemorySupported)
|
||||
export function $createWorkflowVariableBlockNode(variables: string[], workflowNodesMap: WorkflowNodesMap, getVarType?: GetVarType, availableVariables?: NodeOutPutVar[]): WorkflowVariableBlockNode {
|
||||
return new WorkflowVariableBlockNode(variables, workflowNodesMap, getVarType, undefined, availableVariables)
|
||||
}
|
||||
|
||||
export function $isWorkflowVariableBlockNode(
|
||||
|
|
|
|||
|
|
@ -19,16 +19,8 @@ const WorkflowVariableBlockReplacementBlock = ({
|
|||
getVarType,
|
||||
onInsert,
|
||||
variables,
|
||||
isMemorySupported,
|
||||
}: WorkflowVariableBlockType) => {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const ragVariables = variables?.reduce<any[]>((acc, curr) => {
|
||||
if (curr.nodeId === 'rag')
|
||||
acc.push(...curr.vars)
|
||||
else
|
||||
acc.push(...curr.vars.filter(v => v.isRagVariable))
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!editor.hasNodes([WorkflowVariableBlockNode]))
|
||||
|
|
@ -40,7 +32,7 @@ const WorkflowVariableBlockReplacementBlock = ({
|
|||
onInsert()
|
||||
|
||||
const nodePathString = textNode.getTextContent().slice(3, -3)
|
||||
return $applyNodeReplacement($createWorkflowVariableBlockNode(nodePathString.split('.'), workflowNodesMap, getVarType, variables?.find(o => o.nodeId === 'env')?.vars || [], variables?.find(o => o.nodeId === 'conversation')?.vars || [], ragVariables, isMemorySupported))
|
||||
return $applyNodeReplacement($createWorkflowVariableBlockNode(nodePathString.split('.'), workflowNodesMap, getVarType, variables))
|
||||
}, [onInsert, workflowNodesMap, getVarType, variables])
|
||||
|
||||
const getMatch = useCallback((text: string) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
import { createContext, useRef } from 'react'
|
||||
import { createPromptEditorStore } from './store'
|
||||
|
||||
type PromptEditorStoreApi = ReturnType<typeof createPromptEditorStore>
|
||||
|
||||
type PromptEditorContextType = PromptEditorStoreApi | undefined
|
||||
|
||||
export const PromptEditorContext = createContext<PromptEditorContextType>(undefined)
|
||||
|
||||
type PromptEditorProviderProps = {
|
||||
instanceId?: string
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const PromptEditorProvider = ({
|
||||
instanceId,
|
||||
children,
|
||||
}: PromptEditorProviderProps) => {
|
||||
const storeRef = useRef<PromptEditorStoreApi>(undefined)
|
||||
|
||||
if (!storeRef.current)
|
||||
storeRef.current = createPromptEditorStore({ instanceId })
|
||||
|
||||
return (
|
||||
<PromptEditorContext.Provider value={storeRef.current!}>
|
||||
{children}
|
||||
</PromptEditorContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default PromptEditorProvider
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { useContext } from 'react'
|
||||
import { createStore, useStore } from 'zustand'
|
||||
import { PromptEditorContext } from './provider'
|
||||
|
||||
type PromptEditorStoreProps = {
|
||||
instanceId?: string
|
||||
}
|
||||
type PromptEditorStore = {
|
||||
instanceId?: string
|
||||
}
|
||||
|
||||
export const createPromptEditorStore = ({ instanceId }: PromptEditorStoreProps) => {
|
||||
return createStore<PromptEditorStore>(() => ({
|
||||
instanceId,
|
||||
}))
|
||||
}
|
||||
|
||||
export const usePromptEditorStore = <T>(selector: (state: PromptEditorStore) => T): T => {
|
||||
const store = useContext(PromptEditorContext)
|
||||
if (!store)
|
||||
throw new Error('Missing PromptEditorContext.Provider in the tree')
|
||||
|
||||
return useStore(store, selector)
|
||||
}
|
||||
|
|
@ -129,8 +129,8 @@ export const useProviderCredentialsAndLoadBalancing = (
|
|||
// as ([Record<string, string | boolean | undefined> | undefined, ModelLoadBalancingConfig | undefined])
|
||||
}
|
||||
|
||||
export const useModelList = (type: ModelTypeEnum) => {
|
||||
const { data, mutate, isLoading } = useSWR(`/workspaces/current/models/model-types/${type}`, fetchModelList)
|
||||
export const useModelList = (type: ModelTypeEnum, enabled?: boolean) => {
|
||||
const { data, mutate, isLoading } = useSWR(enabled ? `/workspaces/current/models/model-types/${type}` : null, fetchModelList)
|
||||
|
||||
return {
|
||||
data: data?.data || [],
|
||||
|
|
@ -139,8 +139,8 @@ export const useModelList = (type: ModelTypeEnum) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const useDefaultModel = (type: ModelTypeEnum) => {
|
||||
const { data, mutate, isLoading } = useSWR(`/workspaces/current/default-model?model_type=${type}`, fetchDefaultModal)
|
||||
export const useDefaultModel = (type: ModelTypeEnum, enabled?: boolean) => {
|
||||
const { data, mutate, isLoading } = useSWR(enabled ? `/workspaces/current/default-model?model_type=${type}` : null, fetchDefaultModal)
|
||||
|
||||
return {
|
||||
data: data?.data,
|
||||
|
|
|
|||
|
|
@ -85,17 +85,11 @@ export const useNodesSyncDraft = () => {
|
|||
},
|
||||
environment_variables: environmentVariables,
|
||||
conversation_variables: conversationVariables,
|
||||
memory_blocks: memoryVariables.map(({ value_type, scope, more, node_id, model, ...rest }) => {
|
||||
memory_blocks: memoryVariables.map(({ value_type, scope, more, node_id, ...rest }) => {
|
||||
return {
|
||||
...rest,
|
||||
node_id: scope === 'node' ? node_id : undefined,
|
||||
scope,
|
||||
model: model ? {
|
||||
completion_params: model.completion_params,
|
||||
mode: model.mode,
|
||||
provider: model.provider,
|
||||
name: model.model,
|
||||
} : undefined,
|
||||
}
|
||||
}),
|
||||
hash: syncWorkflowDraftHash,
|
||||
|
|
|
|||
|
|
@ -40,12 +40,6 @@ export const useFormatMemoryVariables = () => {
|
|||
return {
|
||||
...v,
|
||||
value_type: ChatVarType.Memory,
|
||||
model: v.model ? {
|
||||
completion_params: v.model?.completion_params,
|
||||
mode: v.model?.mode,
|
||||
provider: v.model?.provider,
|
||||
model: v.model?.name,
|
||||
} : undefined,
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ export const toNodeOutputVars = (
|
|||
let nodeList = []
|
||||
if (conversationVariablesFirst) {
|
||||
nodeList = [
|
||||
...((isChatMode && conversationVariables.length > 0) ? [CHAT_VAR_NODE] : []),
|
||||
...((isChatMode && (conversationVariables.length > 0 || memoryVariables.length > 0)) ? [CHAT_VAR_NODE] : []),
|
||||
...(environmentVariables.length > 0 ? [ENV_NODE] : []),
|
||||
...sortedNodes.filter(node => SUPPORT_OUTPUT_VARS_NODE.includes(node?.data?.type)),
|
||||
...(RAG_PIPELINE_NODE.data.ragVariables.length > 0
|
||||
|
|
@ -835,7 +835,7 @@ export const toNodeOutputVars = (
|
|||
nodeList = [
|
||||
...sortedNodes.filter(node => SUPPORT_OUTPUT_VARS_NODE.includes(node?.data?.type)),
|
||||
...(environmentVariables.length > 0 ? [ENV_NODE] : []),
|
||||
...((isChatMode && conversationVariables.length > 0) ? [CHAT_VAR_NODE] : []),
|
||||
...((isChatMode && (conversationVariables.length > 0 || memoryVariables.length > 0)) ? [CHAT_VAR_NODE] : []),
|
||||
...(RAG_PIPELINE_NODE.data.ragVariables.length > 0
|
||||
? [RAG_PIPELINE_NODE]
|
||||
: []),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type Params = {
|
|||
filterVar: (payload: Var, selector: ValueSelector) => boolean
|
||||
passedInAvailableNodes?: Node[]
|
||||
conversationVariablesFirst?: boolean
|
||||
isMemorySupported?: boolean
|
||||
}
|
||||
|
||||
// TODO: loop type?
|
||||
|
|
@ -26,6 +27,7 @@ const useAvailableVarList = (nodeId: string, {
|
|||
hideChatVar,
|
||||
passedInAvailableNodes,
|
||||
conversationVariablesFirst,
|
||||
isMemorySupported,
|
||||
}: Params = {
|
||||
onlyLeafNodeVar: false,
|
||||
filterVar: () => true,
|
||||
|
|
@ -80,6 +82,11 @@ const useAvailableVarList = (nodeId: string, {
|
|||
return {
|
||||
...availableVar,
|
||||
vars: availableVar.vars.filter((v) => {
|
||||
if (!v.isMemoryVariable)
|
||||
return true
|
||||
|
||||
if (!isMemorySupported)
|
||||
return false
|
||||
if (!v.memoryVariableNodeId)
|
||||
return true
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ const ConfigPrompt: FC<Props> = ({
|
|||
onlyLeafNodeVar: false,
|
||||
filterVar,
|
||||
conversationVariablesFirst: true,
|
||||
isMemorySupported,
|
||||
})
|
||||
|
||||
const handleChatModePromptChange = useCallback((index: number) => {
|
||||
|
|
|
|||
|
|
@ -28,20 +28,11 @@ const BlockMemory = ({ id }: BlockMemoryProps) => {
|
|||
editMemoryVariable,
|
||||
handleSetEditMemoryVariable,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleDeleteConfirm,
|
||||
cacheForDeleteMemoryVariable,
|
||||
setCacheForDeleteMemoryVariable,
|
||||
} = useMemoryVariables(id)
|
||||
const [showConfirm, setShowConfirm] = useState<{
|
||||
title: string
|
||||
desc: string
|
||||
onConfirm: () => void
|
||||
} | undefined>(undefined)
|
||||
|
||||
const handleDelete = (blockId: string) => {
|
||||
setShowConfirm({
|
||||
title: t('workflow.nodes.common.memory.block.deleteConfirmTitle'),
|
||||
desc: t('workflow.nodes.common.memory.block.deleteConfirmDesc'),
|
||||
onConfirm: () => handleDelete(blockId),
|
||||
})
|
||||
}
|
||||
|
||||
if (!memoryVariablesInUsed?.length) {
|
||||
return (
|
||||
|
|
@ -87,7 +78,7 @@ const BlockMemory = ({ id }: BlockMemoryProps) => {
|
|||
editMemoryVariable?.id === memoryVariable.id && 'inline-flex',
|
||||
)}
|
||||
size='m'
|
||||
onClick={() => handleDelete(memoryVariable.id)}
|
||||
onClick={() => handleDelete(memoryVariable)}
|
||||
onMouseOver={() => setDestructiveItemId(memoryVariable.id)}
|
||||
onMouseOut={() => setDestructiveItemId(undefined)}
|
||||
>
|
||||
|
|
@ -98,13 +89,13 @@ const BlockMemory = ({ id }: BlockMemoryProps) => {
|
|||
}
|
||||
</div>
|
||||
{
|
||||
!!showConfirm && (
|
||||
!!cacheForDeleteMemoryVariable && (
|
||||
<Confirm
|
||||
isShow
|
||||
onCancel={() => setShowConfirm(undefined)}
|
||||
onConfirm={showConfirm.onConfirm}
|
||||
title={showConfirm.title}
|
||||
content={showConfirm.desc}
|
||||
onCancel={() => setCacheForDeleteMemoryVariable(undefined)}
|
||||
onConfirm={() => handleDeleteConfirm(cacheForDeleteMemoryVariable.id)}
|
||||
title={t('workflow.nodes.common.memory.deleteNodeMemoryVariableConfirmTitle', { name: cacheForDeleteMemoryVariable.name })}
|
||||
content={t('workflow.nodes.common.memory.deleteNodeMemoryVariableConfirmDesc')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { useCallback } from 'react'
|
||||
import type { MemoryVariable } from '@/app/components/workflow/types'
|
||||
import { useNodeUpdate } from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import { findUsedVarNodes } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
|
||||
export const useMemoryUsedDetector = (nodeId: string) => {
|
||||
const { getNodeData } = useNodeUpdate(nodeId)
|
||||
const getMemoryUsedDetector = useCallback((chatVar: MemoryVariable) => {
|
||||
const nodeData = getNodeData()!
|
||||
const valueSelector = ['memory_block', chatVar.node_id ? `${chatVar.node_id}_${chatVar.id}` : chatVar.id]
|
||||
return findUsedVarNodes(
|
||||
valueSelector,
|
||||
[nodeData],
|
||||
)
|
||||
}, [getNodeData])
|
||||
|
||||
return {
|
||||
getMemoryUsedDetector,
|
||||
}
|
||||
}
|
||||
|
|
@ -9,21 +9,20 @@ import {
|
|||
} from '@/app/components/workflow/store'
|
||||
import type { MemoryVariable } from '@/app/components/workflow/types'
|
||||
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
|
||||
import { useMemoryUsedDetector } from './use-memory-used-detector'
|
||||
|
||||
export const useMemoryVariables = (nodeId: string) => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
const memoryVariables = useStore(s => s.memoryVariables)
|
||||
const [editMemoryVariable, setEditMemoryVariable] = useState<MemoryVariable | undefined>(undefined)
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const { getMemoryUsedDetector } = useMemoryUsedDetector(nodeId)
|
||||
const [cacheForDeleteMemoryVariable, setCacheForDeleteMemoryVariable] = useState<MemoryVariable | undefined>(undefined)
|
||||
|
||||
const memoryVariablesInUsed = useMemo(() => {
|
||||
return memoryVariables.filter(variable => variable.node_id === nodeId)
|
||||
}, [memoryVariables, nodeId])
|
||||
|
||||
const handleDelete = (blockId: string) => {
|
||||
console.log('delete', blockId)
|
||||
}
|
||||
|
||||
const handleSave = useCallback((newMemoryVar: MemoryVariable) => {
|
||||
const { memoryVariables, setMemoryVariables } = workflowStore.getState()
|
||||
const newList = [newMemoryVar, ...memoryVariables]
|
||||
|
|
@ -47,6 +46,23 @@ export const useMemoryVariables = (nodeId: string) => {
|
|||
handleSyncWorkflowDraft()
|
||||
}
|
||||
|
||||
const handleDeleteConfirm = (memoryVariableId?: string) => {
|
||||
const { memoryVariables, setMemoryVariables } = workflowStore.getState()
|
||||
const newList = memoryVariables.filter(variable => variable.id !== memoryVariableId)
|
||||
setMemoryVariables(newList)
|
||||
handleSyncWorkflowDraft()
|
||||
setCacheForDeleteMemoryVariable(undefined)
|
||||
}
|
||||
|
||||
const handleDelete = (memoryVariable: MemoryVariable) => {
|
||||
const effectedNodes = getMemoryUsedDetector(memoryVariable)
|
||||
if (effectedNodes.length > 0) {
|
||||
setCacheForDeleteMemoryVariable(memoryVariable)
|
||||
return
|
||||
}
|
||||
handleDeleteConfirm(memoryVariable.id)
|
||||
}
|
||||
|
||||
return {
|
||||
memoryVariablesInUsed,
|
||||
handleDelete,
|
||||
|
|
@ -54,5 +70,8 @@ export const useMemoryVariables = (nodeId: string) => {
|
|||
handleSetEditMemoryVariable,
|
||||
handleEdit,
|
||||
editMemoryVariable,
|
||||
handleDeleteConfirm,
|
||||
cacheForDeleteMemoryVariable,
|
||||
setCacheForDeleteMemoryVariable,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@ import {
|
|||
} from '../linear-memory'
|
||||
import type { Memory } from '@/app/components/workflow/types'
|
||||
import { MemoryMode } from '@/app/components/workflow/types'
|
||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { useMemoryUsedDetector } from './use-memory-used-detector'
|
||||
|
||||
export const useMemory = (
|
||||
id: string,
|
||||
data: LLMNodeType,
|
||||
) => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { memory } = data
|
||||
const initCollapsed = useMemo(() => {
|
||||
if (!memory?.enabled)
|
||||
|
|
@ -27,10 +30,12 @@ export const useMemory = (
|
|||
getNodeData,
|
||||
handleNodeDataUpdate,
|
||||
} = useNodeUpdate(id)
|
||||
const [showTipsWhenMemoryModeBlockToLinear, setShowTipsWhenMemoryModeBlockToLinear] = useState(false)
|
||||
const { getMemoryUsedDetector } = useMemoryUsedDetector(id)
|
||||
|
||||
const handleMemoryTypeChange = useCallback((value: string) => {
|
||||
const nodeData = getNodeData()
|
||||
const { memory: memoryData = {} } = nodeData as any
|
||||
const { memory: memoryData = {} as Memory } = nodeData?.data as LLMNodeType
|
||||
|
||||
if (value === MemoryMode.disabled) {
|
||||
setCollapsed(true)
|
||||
|
|
@ -66,8 +71,34 @@ export const useMemory = (
|
|||
},
|
||||
})
|
||||
}
|
||||
setShowTipsWhenMemoryModeBlockToLinear(false)
|
||||
}, [getNodeData, handleNodeDataUpdate])
|
||||
|
||||
const handleMemoryTypeChangeBefore = useCallback((value: string) => {
|
||||
const nodeData = getNodeData()
|
||||
const { memory: memoryData = {} as Memory } = nodeData?.data as LLMNodeType
|
||||
const { memoryVariables } = workflowStore.getState()
|
||||
|
||||
if (memoryData.mode === MemoryMode.block && value === MemoryMode.linear && nodeData) {
|
||||
const globalMemoryVariables = memoryVariables.filter(variable => variable.scope === 'app')
|
||||
const currentNodeMemoryVariables = memoryVariables.filter(variable => variable.node_id === id)
|
||||
const allMemoryVariables = [...globalMemoryVariables, ...currentNodeMemoryVariables]
|
||||
|
||||
for (const variable of allMemoryVariables) {
|
||||
const effectedNodes = getMemoryUsedDetector(variable)
|
||||
|
||||
if (effectedNodes.length > 0) {
|
||||
setShowTipsWhenMemoryModeBlockToLinear(true)
|
||||
return
|
||||
}
|
||||
}
|
||||
handleMemoryTypeChange(value)
|
||||
}
|
||||
else {
|
||||
handleMemoryTypeChange(value)
|
||||
}
|
||||
}, [getNodeData, workflowStore, handleMemoryTypeChange])
|
||||
|
||||
const handleUpdateMemory = useCallback((memory: Memory) => {
|
||||
handleNodeDataUpdate({
|
||||
memory,
|
||||
|
|
@ -96,7 +127,10 @@ export const useMemory = (
|
|||
collapsed,
|
||||
setCollapsed,
|
||||
handleMemoryTypeChange,
|
||||
handleMemoryTypeChangeBefore,
|
||||
memoryType,
|
||||
handleUpdateMemory,
|
||||
showTipsWhenMemoryModeBlockToLinear,
|
||||
setShowTipsWhenMemoryModeBlockToLinear,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { MemoryMode } from '@/app/components/workflow/types'
|
|||
import BlockMemory from './block-memory'
|
||||
import { ActionButton } from '@/app/components/base/action-button'
|
||||
import cn from '@/utils/classnames'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
|
||||
type MemoryProps = Pick<Node, 'id' | 'data'> & {
|
||||
readonly?: boolean
|
||||
|
|
@ -38,8 +39,11 @@ const MemorySystem = ({
|
|||
collapsed,
|
||||
setCollapsed,
|
||||
handleMemoryTypeChange,
|
||||
handleMemoryTypeChangeBefore,
|
||||
memoryType,
|
||||
handleUpdateMemory,
|
||||
showTipsWhenMemoryModeBlockToLinear,
|
||||
setShowTipsWhenMemoryModeBlockToLinear,
|
||||
} = useMemory(id, data as LLMNodeType)
|
||||
|
||||
const renderTrigger = useCallback((open?: boolean) => {
|
||||
|
|
@ -87,7 +91,7 @@ const MemorySystem = ({
|
|||
</div>
|
||||
<MemorySelector
|
||||
value={memoryType}
|
||||
onSelected={handleMemoryTypeChange}
|
||||
onSelected={handleMemoryTypeChangeBefore}
|
||||
readonly={readonly}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -114,6 +118,20 @@ const MemorySystem = ({
|
|||
</Collapse>
|
||||
<Split className='mt-4' />
|
||||
</div>
|
||||
{
|
||||
showTipsWhenMemoryModeBlockToLinear && (
|
||||
<Confirm
|
||||
isShow
|
||||
type='info'
|
||||
showCancel={false}
|
||||
onCancel={() => setShowTipsWhenMemoryModeBlockToLinear(false)}
|
||||
onConfirm={() => handleMemoryTypeChange(MemoryMode.linear)}
|
||||
confirmText={t('workflow.nodes.common.memory.toLinearConfirmButton')}
|
||||
title={t('workflow.nodes.common.memory.toLinearConfirmTitle')}
|
||||
content={t('workflow.nodes.common.memory.toLinearConfirmDesc')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ type Props = {
|
|||
nodeId: string
|
||||
editorId?: string
|
||||
currentPrompt?: string
|
||||
isBasicMode?: boolean
|
||||
}
|
||||
|
||||
const PromptGeneratorBtn: FC<Props> = ({
|
||||
|
|
@ -26,6 +27,7 @@ const PromptGeneratorBtn: FC<Props> = ({
|
|||
nodeId,
|
||||
editorId,
|
||||
currentPrompt,
|
||||
isBasicMode,
|
||||
}) => {
|
||||
const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false)
|
||||
const handleAutomaticRes = useCallback((res: GenRes) => {
|
||||
|
|
@ -50,6 +52,8 @@ const PromptGeneratorBtn: FC<Props> = ({
|
|||
nodeId={nodeId}
|
||||
editorId={editorId}
|
||||
currentPrompt={currentPrompt}
|
||||
isBasicMode={isBasicMode}
|
||||
hideTryIt
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
|||
availableNodes={availableNodesWithParent}
|
||||
isSupportFileVar
|
||||
instanceId={`${id}-chat-workflow-llm-prompt-editor-user`}
|
||||
isMemorySupported={memoryType === MemoryMode.block}
|
||||
/>
|
||||
|
||||
{inputs.memory?.query_prompt_template && !inputs.memory.query_prompt_template.includes('{{#sys.query#}}') && (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiArrowDownSLine,
|
||||
RiCheckLine,
|
||||
|
|
@ -29,6 +30,7 @@ const NodeSelector: FC<Props> = ({
|
|||
onChange,
|
||||
nodeType = BlockEnum.LLM,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const filteredNodes = useStore(useShallow((s) => {
|
||||
|
|
@ -46,11 +48,14 @@ const NodeSelector: FC<Props> = ({
|
|||
>
|
||||
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
||||
{currentNode && (
|
||||
<div className={cn('flex h-8 w-[208px] cursor-pointer items-center gap-1 rounded-lg bg-components-input-bg-normal px-2 py-1 pl-3 hover:bg-state-base-hover-alt', open && 'bg-state-base-hover-alt')}>{currentNode.data?.title}</div>
|
||||
<div className={cn('flex h-8 w-[208px] cursor-pointer items-center rounded-lg bg-components-input-bg-normal px-2 py-1 pl-3 hover:bg-state-base-hover-alt', open && 'bg-state-base-hover-alt')}>
|
||||
<BlockIcon className={cn('mr-1.5 h-4 w-4 shrink-0')} type={currentNode.data?.type} />
|
||||
<div className='system-sm-regular grow truncate text-components-input-text-filled'>{currentNode.data?.title}</div>
|
||||
</div>
|
||||
)}
|
||||
{!currentNode && (
|
||||
<div className={cn('flex h-8 w-[208px] cursor-pointer items-center gap-1 rounded-lg bg-components-input-bg-normal px-2 py-1 pl-3 hover:bg-state-base-hover-alt', open && 'bg-state-base-hover-alt')}>
|
||||
<div className='system-sm-regular grow truncate text-components-input-text-placeholder'>Select node...</div>
|
||||
<div className='system-sm-regular grow truncate text-components-input-text-placeholder'>{t('workflow.chatVariable.modal.selectNode')}</div>
|
||||
<RiArrowDownSLine className='h-4 w-4 text-text-quaternary' />
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useCallback, useRef } from 'react'
|
||||
import React, { useCallback, useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import {
|
||||
|
|
@ -16,6 +16,10 @@ import { checkKeys } from '@/utils/var'
|
|||
import type { FormRefObject, FormSchema } from '@/app/components/base/form/types'
|
||||
import VariableForm from '@/app/components/base/form/form-scenarios/variable'
|
||||
import { useForm } from '../hooks'
|
||||
import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import {
|
||||
ModelTypeEnum,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
|
||||
export type ModalPropsType = {
|
||||
className?: string
|
||||
|
|
@ -46,7 +50,19 @@ const ChatVariableModal = ({
|
|||
defaultValues,
|
||||
})
|
||||
const type = useTanstackStore(form.store, (s: any) => s.values.value_type)
|
||||
const isPristine = useTanstackStore(form.store, (s: any) => s.fieldMeta?.model?.isPristine)
|
||||
const { data: defaultModel } = useDefaultModel(ModelTypeEnum.textGeneration, !chatVar && type === ChatVarType.Memory && isPristine)
|
||||
|
||||
useEffect(() => {
|
||||
if (defaultModel) {
|
||||
form.setFieldValue('model', {
|
||||
mode: 'chat',
|
||||
name: defaultModel.model,
|
||||
provider: defaultModel.provider.provider,
|
||||
completion_params: {},
|
||||
})
|
||||
}
|
||||
}, [defaultModel])
|
||||
const checkVariableName = (value: string) => {
|
||||
const { isValid, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const useForm = (chatVar?: ConversationVariable | MemoryVariable, nodeSco
|
|||
const valueSchema = useValueSchema()
|
||||
const editInJSONSchema = useEditInJSONSchema()
|
||||
const memorySchema = useMemorySchema(nodeScopeMemoryVariable)
|
||||
const memoryDefaultValues = useMemoryDefaultValues(nodeScopeMemoryVariable)
|
||||
const memoryDefaultValues = useMemoryDefaultValues(chatVar, nodeScopeMemoryVariable)
|
||||
|
||||
const formSchemas = useMemo(() => {
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -1,11 +1,42 @@
|
|||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type {
|
||||
AnyFormApi,
|
||||
} from '@tanstack/react-form'
|
||||
import { FormTypeEnum } from '@/app/components/base/form/types'
|
||||
import type { FormSchema } from '@/app/components/base/form/types'
|
||||
import { ChatVarType } from '@/app/components/workflow/panel/chat-variable-panel/type'
|
||||
import type { MemoryVariable } from '@/app/components/workflow/types'
|
||||
|
||||
export const useMemorySchema = (nodeScopeMemoryVariable?: { nodeId: string }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const getTemplateSelfFormProps = useCallback((form: AnyFormApi) => {
|
||||
const {
|
||||
node_id,
|
||||
} = form.state.values
|
||||
|
||||
return {
|
||||
enablePromptGenerator: true,
|
||||
withTopDivider: true,
|
||||
editorId: 'memory-template',
|
||||
nodeId: node_id,
|
||||
}
|
||||
}, [t])
|
||||
|
||||
const getInstructionSelfFormProps = useCallback((form: AnyFormApi) => {
|
||||
const {
|
||||
node_id,
|
||||
} = form.state.values
|
||||
|
||||
return {
|
||||
enablePromptGenerator: true,
|
||||
placeholder: t('workflow.chatVariable.modal.updateInstructionsPlaceholder'),
|
||||
editorId: 'memory-instruction',
|
||||
nodeId: node_id,
|
||||
}
|
||||
}, [t])
|
||||
|
||||
const scopeSchema = [
|
||||
{
|
||||
name: 'scope',
|
||||
|
|
@ -66,9 +97,7 @@ export const useMemorySchema = (nodeScopeMemoryVariable?: { nodeId: string }) =>
|
|||
value: [ChatVarType.Memory],
|
||||
},
|
||||
],
|
||||
selfFormProps: {
|
||||
withTopDivider: true,
|
||||
},
|
||||
selfFormProps: getTemplateSelfFormProps,
|
||||
},
|
||||
{
|
||||
name: 'instruction',
|
||||
|
|
@ -80,10 +109,7 @@ export const useMemorySchema = (nodeScopeMemoryVariable?: { nodeId: string }) =>
|
|||
value: [ChatVarType.Memory],
|
||||
},
|
||||
],
|
||||
selfFormProps: {
|
||||
enablePromptGenerator: true,
|
||||
placeholder: t('workflow.chatVariable.modal.updateInstructionsPlaceholder'),
|
||||
},
|
||||
selfFormProps: getInstructionSelfFormProps,
|
||||
},
|
||||
{
|
||||
name: 'strategy',
|
||||
|
|
@ -242,7 +268,7 @@ export const useMemorySchema = (nodeScopeMemoryVariable?: { nodeId: string }) =>
|
|||
] as FormSchema[]
|
||||
}
|
||||
|
||||
export const useMemoryDefaultValues = (nodeScopeMemoryVariable?: { nodeId: string }) => {
|
||||
export const useMemoryDefaultValues = (chatVar?: MemoryVariable, nodeScopeMemoryVariable?: { nodeId: string }) => {
|
||||
return {
|
||||
template: '',
|
||||
instruction: '',
|
||||
|
|
@ -252,8 +278,8 @@ export const useMemoryDefaultValues = (nodeScopeMemoryVariable?: { nodeId: strin
|
|||
scope: nodeScopeMemoryVariable ? 'node' : 'app',
|
||||
node_id: nodeScopeMemoryVariable?.nodeId || '',
|
||||
term: 'session',
|
||||
more: false,
|
||||
model: '',
|
||||
more: true,
|
||||
model: undefined,
|
||||
schedule_mode: 'sync',
|
||||
end_user_visible: false,
|
||||
end_user_editable: false,
|
||||
|
|
|
|||
|
|
@ -74,8 +74,20 @@ const ChatVariablePanel = () => {
|
|||
const getEffectedNodes = useCallback((chatVar: ConversationVariable | MemoryVariable) => {
|
||||
const { getNodes } = store.getState()
|
||||
const allNodes = getNodes()
|
||||
let valueSelector = []
|
||||
|
||||
if (chatVar.value_type === ChatVarType.Memory) {
|
||||
const { node_id, id } = chatVar as MemoryVariable
|
||||
valueSelector = [
|
||||
'memory_block',
|
||||
node_id ? `${node_id}_${id}` : id,
|
||||
]
|
||||
}
|
||||
else {
|
||||
valueSelector = ['conversation', chatVar.name]
|
||||
}
|
||||
return findUsedVarNodes(
|
||||
['conversation', chatVar.name],
|
||||
valueSelector,
|
||||
allNodes,
|
||||
)
|
||||
}, [store])
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ export type Var = {
|
|||
nodeId?: string
|
||||
isRagVariable?: boolean
|
||||
schemaType?: string
|
||||
isMemoryVariable?: boolean
|
||||
memoryVariableName?: string
|
||||
memoryVariableNodeId?: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ const translation = {
|
|||
memoryModel: 'Memory Model',
|
||||
updateMethod: 'Update Method',
|
||||
editableInWebApp: 'Editable in Web App',
|
||||
selectNode: 'Select node...',
|
||||
},
|
||||
storedContent: 'Stored content',
|
||||
updatedAt: 'Updated at ',
|
||||
|
|
@ -382,6 +383,11 @@ const translation = {
|
|||
desc: 'AI remembers specific information you define using custom templates',
|
||||
empty: 'Please add a memory variable in the Prompt',
|
||||
},
|
||||
deleteNodeMemoryVariableConfirmTitle: 'Delete "{{name}}"?',
|
||||
deleteNodeMemoryVariableConfirmDesc: 'This variable is currently in use. Deleting it may cause unexpected behavior. This action cannot be undone.',
|
||||
toLinearConfirmTitle: 'Cannot Enable Linear Mode',
|
||||
toLinearConfirmDesc: 'Linear mode is incompatible with memory variables. To use linear mode, please remove the memory variable from your prompt first.',
|
||||
toLinearConfirmButton: 'Got it',
|
||||
},
|
||||
memories: {
|
||||
title: 'Memories',
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ const translation = {
|
|||
memoryModel: '记忆模型',
|
||||
updateMethod: '更新方法',
|
||||
editableInWebApp: '在 Web 应用中可编辑',
|
||||
selectNode: '选择节点...',
|
||||
},
|
||||
storedContent: '存储内容',
|
||||
updatedAt: '更新时间 ',
|
||||
|
|
@ -382,6 +383,11 @@ const translation = {
|
|||
desc: 'AI 会记住你定义的特定信息',
|
||||
empty: '请在提示词中添加记忆变量以启用记忆块',
|
||||
},
|
||||
deleteNodeMemoryVariableConfirmTitle: '删除 "{{name}}"?',
|
||||
deleteNodeMemoryVariableConfirmDesc: '该变量当前正在使用。删除它可能会导致意外行为。此操作无法撤销。',
|
||||
toLinearConfirmTitle: '无法启用线性模式',
|
||||
toLinearConfirmDesc: '线性模式与记忆变量不兼容。要使用线性模式,请先从提示词中删除记忆变量。',
|
||||
toLinearConfirmButton: '知道了',
|
||||
},
|
||||
memories: {
|
||||
title: '记忆',
|
||||
|
|
|
|||
Loading…
Reference in New Issue