mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 01:26:33 +08:00
form
This commit is contained in:
parent
158da1ce6e
commit
01f0ee339e
@ -13,6 +13,7 @@ type CollapseProps = {
|
|||||||
onCollapse?: (collapsed: boolean) => void
|
onCollapse?: (collapsed: boolean) => void
|
||||||
operations?: ReactNode
|
operations?: ReactNode
|
||||||
hideCollapseIcon?: boolean
|
hideCollapseIcon?: boolean
|
||||||
|
triggerClassName?: string
|
||||||
}
|
}
|
||||||
const Collapse = ({
|
const Collapse = ({
|
||||||
disabled,
|
disabled,
|
||||||
@ -22,6 +23,7 @@ const Collapse = ({
|
|||||||
onCollapse,
|
onCollapse,
|
||||||
operations,
|
operations,
|
||||||
hideCollapseIcon,
|
hideCollapseIcon,
|
||||||
|
triggerClassName,
|
||||||
}: CollapseProps) => {
|
}: CollapseProps) => {
|
||||||
const [collapsedLocal, setCollapsedLocal] = useState(true)
|
const [collapsedLocal, setCollapsedLocal] = useState(true)
|
||||||
const collapsedMerged = collapsed !== undefined ? collapsed : collapsedLocal
|
const collapsedMerged = collapsed !== undefined ? collapsed : collapsedLocal
|
||||||
@ -42,7 +44,7 @@ const Collapse = ({
|
|||||||
<>
|
<>
|
||||||
<div className='group/collapse flex items-center'>
|
<div className='group/collapse flex items-center'>
|
||||||
<div
|
<div
|
||||||
className='ml-4 flex grow items-center'
|
className={cn('ml-4 flex grow items-center', triggerClassName)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
setCollapsedLocal(!collapsedMerged)
|
setCollapsedLocal(!collapsedMerged)
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { useCallback } from 'react'
|
||||||
|
import { useStoreApi } from 'reactflow'
|
||||||
import { useNodeDataUpdate } from '@/app/components/workflow/hooks'
|
import { useNodeDataUpdate } from '@/app/components/workflow/hooks'
|
||||||
import type { CommonNodeType } from '@/app/components/workflow/types'
|
import type { CommonNodeType } from '@/app/components/workflow/types'
|
||||||
const useNodeCrud = <T>(id: string, data: CommonNodeType<T>) => {
|
const useNodeCrud = <T>(id: string, data: CommonNodeType<T>) => {
|
||||||
@ -16,4 +18,28 @@ const useNodeCrud = <T>(id: string, data: CommonNodeType<T>) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useNodeUpdate = (id: string) => {
|
||||||
|
const store = useStoreApi()
|
||||||
|
const { handleNodeDataUpdateWithSyncDraft } = useNodeDataUpdate()
|
||||||
|
|
||||||
|
const getNodeData = useCallback(() => {
|
||||||
|
const { getNodes } = store.getState()
|
||||||
|
const nodes = getNodes()
|
||||||
|
|
||||||
|
return nodes.find(node => node.id === id)
|
||||||
|
}, [store, id])
|
||||||
|
|
||||||
|
const handleNodeDataUpdate = useCallback((data: Partial<CommonNodeType>) => {
|
||||||
|
handleNodeDataUpdateWithSyncDraft({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}, [id, handleNodeDataUpdateWithSyncDraft])
|
||||||
|
|
||||||
|
return {
|
||||||
|
getNodeData,
|
||||||
|
handleNodeDataUpdate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default useNodeCrud
|
export default useNodeCrud
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
|
import type { LLMNodeType } from '../../types'
|
||||||
|
import { useNodeUpdate } from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||||
|
|
||||||
|
export const useMemory = (
|
||||||
|
id: string,
|
||||||
|
data: LLMNodeType,
|
||||||
|
) => {
|
||||||
|
const { memory } = data
|
||||||
|
const initCollapsed = useMemo(() => {
|
||||||
|
if (!memory?.enabled)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}, [memory])
|
||||||
|
const [collapsed, setCollapsed] = useState(initCollapsed)
|
||||||
|
const { getNodeData } = useNodeUpdate(id)
|
||||||
|
|
||||||
|
const handleMemoryTypeChange = useCallback((value: string) => {
|
||||||
|
const nodeData = getNodeData()
|
||||||
|
console.log('nodeData', nodeData)
|
||||||
|
|
||||||
|
if (value === 'disabled')
|
||||||
|
console.log('disabled')
|
||||||
|
if (value === 'linear')
|
||||||
|
setCollapsed(true)
|
||||||
|
if (value === 'block')
|
||||||
|
setCollapsed(true)
|
||||||
|
}, [getNodeData])
|
||||||
|
|
||||||
|
return {
|
||||||
|
collapsed,
|
||||||
|
setCollapsed,
|
||||||
|
handleMemoryTypeChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
memo,
|
||||||
|
} from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Collapse from '@/app/components/workflow/nodes/_base/components/collapse'
|
||||||
|
import type {
|
||||||
|
Node,
|
||||||
|
} from '@/app/components/workflow/types'
|
||||||
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
|
import MemorySelector from './memory-selector'
|
||||||
|
import LinearMemory from './linear-memory'
|
||||||
|
import type { Memory } from '@/app/components/workflow/types'
|
||||||
|
import type { LLMNodeType } from '../../types'
|
||||||
|
import { useMemory } from './hooks'
|
||||||
|
|
||||||
|
type MemoryProps = Pick<Node, 'id' | 'data'>
|
||||||
|
const MemorySystem = ({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: MemoryProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { memory } = data as LLMNodeType
|
||||||
|
const {
|
||||||
|
collapsed,
|
||||||
|
setCollapsed,
|
||||||
|
handleMemoryTypeChange,
|
||||||
|
} = useMemory(id, data as LLMNodeType)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='py-4'>
|
||||||
|
<Collapse
|
||||||
|
disabled={!memory?.enabled}
|
||||||
|
collapsed={collapsed}
|
||||||
|
onCollapse={setCollapsed}
|
||||||
|
hideCollapseIcon
|
||||||
|
triggerClassName='ml-0 system-sm-semibold-uppercase'
|
||||||
|
trigger={
|
||||||
|
collapseIcon => (
|
||||||
|
<div className='flex grow items-center justify-between'>
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<div className='system-sm-semibold-uppercase mr-0.5 text-text-secondary'>
|
||||||
|
{t('workflow.nodes.common.errorHandle.title')}
|
||||||
|
</div>
|
||||||
|
<Tooltip
|
||||||
|
popupContent={t('workflow.nodes.common.errorHandle.tip')}
|
||||||
|
triggerClassName='w-4 h-4'
|
||||||
|
/>
|
||||||
|
{collapseIcon}
|
||||||
|
</div>
|
||||||
|
<MemorySelector
|
||||||
|
value='linear'
|
||||||
|
onSelected={handleMemoryTypeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
(memory?.mode === 'linear' || !memory?.mode) && !collapsed && (
|
||||||
|
<LinearMemory
|
||||||
|
payload={memory as Memory}
|
||||||
|
onChange={() => {
|
||||||
|
console.log('onChange')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
</Collapse>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(MemorySystem)
|
||||||
@ -0,0 +1,179 @@
|
|||||||
|
import {
|
||||||
|
memo,
|
||||||
|
useCallback,
|
||||||
|
} from 'react'
|
||||||
|
import { produce } from 'immer'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Switch from '@/app/components/base/switch'
|
||||||
|
import Slider from '@/app/components/base/slider'
|
||||||
|
import Input from '@/app/components/base/input'
|
||||||
|
import type { Memory } from '@/app/components/workflow/types'
|
||||||
|
import { MemoryRole } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
|
const WINDOW_SIZE_MIN = 1
|
||||||
|
const WINDOW_SIZE_MAX = 100
|
||||||
|
const WINDOW_SIZE_DEFAULT = 50
|
||||||
|
const MEMORY_DEFAULT: Memory = {
|
||||||
|
window: { enabled: false, size: WINDOW_SIZE_DEFAULT },
|
||||||
|
query_prompt_template: '{{#sys.query#}}\n\n{{#sys.files#}}',
|
||||||
|
}
|
||||||
|
type RoleItemProps = {
|
||||||
|
readonly: boolean
|
||||||
|
title: string
|
||||||
|
value: string
|
||||||
|
onChange: (value: string) => void
|
||||||
|
}
|
||||||
|
const RoleItem = ({
|
||||||
|
readonly,
|
||||||
|
title,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
}: RoleItemProps) => {
|
||||||
|
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
onChange(e.target.value)
|
||||||
|
}, [onChange])
|
||||||
|
return (
|
||||||
|
<div className='flex items-center justify-between'>
|
||||||
|
<div className='text-[13px] font-normal text-text-secondary'>{title}</div>
|
||||||
|
<Input
|
||||||
|
readOnly={readonly}
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
className='h-8 w-[200px]'
|
||||||
|
type='text' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinearMemoryProps = {
|
||||||
|
payload: Memory
|
||||||
|
readonly?: boolean
|
||||||
|
onChange: (payload: Memory) => void
|
||||||
|
canSetRoleName?: boolean
|
||||||
|
}
|
||||||
|
const LinearMemory = ({
|
||||||
|
payload,
|
||||||
|
readonly,
|
||||||
|
onChange,
|
||||||
|
canSetRoleName,
|
||||||
|
}: LinearMemoryProps) => {
|
||||||
|
const i18nPrefix = 'workflow.nodes.common.memory'
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const handleWindowEnabledChange = useCallback((enabled: boolean) => {
|
||||||
|
const newPayload = produce(payload || MEMORY_DEFAULT, (draft) => {
|
||||||
|
if (!draft.window)
|
||||||
|
draft.window = { enabled: false, size: WINDOW_SIZE_DEFAULT }
|
||||||
|
|
||||||
|
draft.window.enabled = enabled
|
||||||
|
})
|
||||||
|
|
||||||
|
onChange(newPayload)
|
||||||
|
}, [payload, onChange])
|
||||||
|
|
||||||
|
const handleWindowSizeChange = useCallback((size: number | string) => {
|
||||||
|
const newPayload = produce(payload || MEMORY_DEFAULT, (draft) => {
|
||||||
|
if (!draft.window)
|
||||||
|
draft.window = { enabled: true, size: WINDOW_SIZE_DEFAULT }
|
||||||
|
let limitedSize: null | string | number = size
|
||||||
|
if (limitedSize === '') {
|
||||||
|
limitedSize = null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
limitedSize = Number.parseInt(limitedSize as string, 10)
|
||||||
|
if (Number.isNaN(limitedSize))
|
||||||
|
limitedSize = WINDOW_SIZE_DEFAULT
|
||||||
|
|
||||||
|
if (limitedSize < WINDOW_SIZE_MIN)
|
||||||
|
limitedSize = WINDOW_SIZE_MIN
|
||||||
|
|
||||||
|
if (limitedSize > WINDOW_SIZE_MAX)
|
||||||
|
limitedSize = WINDOW_SIZE_MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
draft.window.size = limitedSize as number
|
||||||
|
})
|
||||||
|
onChange(newPayload)
|
||||||
|
}, [payload, onChange])
|
||||||
|
|
||||||
|
const handleBlur = useCallback(() => {
|
||||||
|
if (!payload)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (payload.window.size === '' || payload.window.size === null)
|
||||||
|
handleWindowSizeChange(WINDOW_SIZE_DEFAULT)
|
||||||
|
}, [handleWindowSizeChange, payload])
|
||||||
|
const handleRolePrefixChange = useCallback((role: MemoryRole) => {
|
||||||
|
return (value: string) => {
|
||||||
|
const newPayload = produce(payload || MEMORY_DEFAULT, (draft) => {
|
||||||
|
if (!draft.role_prefix) {
|
||||||
|
draft.role_prefix = {
|
||||||
|
user: '',
|
||||||
|
assistant: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draft.role_prefix[role] = value
|
||||||
|
})
|
||||||
|
onChange(newPayload)
|
||||||
|
}
|
||||||
|
}, [payload, onChange])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='flex justify-between'>
|
||||||
|
<div className='flex h-8 items-center space-x-2'>
|
||||||
|
<Switch
|
||||||
|
defaultValue={payload?.window?.enabled}
|
||||||
|
onChange={handleWindowEnabledChange}
|
||||||
|
size='md'
|
||||||
|
disabled={readonly}
|
||||||
|
/>
|
||||||
|
<div className='system-xs-medium-uppercase text-text-tertiary'>{t(`${i18nPrefix}.windowSize`)}</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex h-8 items-center space-x-2'>
|
||||||
|
<Slider
|
||||||
|
className='w-[144px]'
|
||||||
|
value={(payload.window?.size || WINDOW_SIZE_DEFAULT) as number}
|
||||||
|
min={WINDOW_SIZE_MIN}
|
||||||
|
max={WINDOW_SIZE_MAX}
|
||||||
|
step={1}
|
||||||
|
onChange={handleWindowSizeChange}
|
||||||
|
disabled={readonly || !payload.window?.enabled}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={(payload.window?.size || WINDOW_SIZE_DEFAULT) as number}
|
||||||
|
wrapperClassName='w-12'
|
||||||
|
className='appearance-none pr-0'
|
||||||
|
type='number'
|
||||||
|
min={WINDOW_SIZE_MIN}
|
||||||
|
max={WINDOW_SIZE_MAX}
|
||||||
|
step={1}
|
||||||
|
onChange={e => handleWindowSizeChange(e.target.value)}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
disabled={readonly || !payload.window?.enabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{canSetRoleName && (
|
||||||
|
<div className='mt-4'>
|
||||||
|
<div className='text-xs font-medium uppercase leading-6 text-text-tertiary'>{t(`${i18nPrefix}.conversationRoleName`)}</div>
|
||||||
|
<div className='mt-1 space-y-2'>
|
||||||
|
<RoleItem
|
||||||
|
readonly={!!readonly}
|
||||||
|
title={t(`${i18nPrefix}.user`)}
|
||||||
|
value={payload.role_prefix?.user || ''}
|
||||||
|
onChange={handleRolePrefixChange(MemoryRole.user)}
|
||||||
|
/>
|
||||||
|
<RoleItem
|
||||||
|
readonly={!!readonly}
|
||||||
|
title={t(`${i18nPrefix}.assistant`)}
|
||||||
|
value={payload.role_prefix?.assistant || ''}
|
||||||
|
onChange={handleRolePrefixChange(MemoryRole.assistant)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(LinearMemory)
|
||||||
@ -0,0 +1,99 @@
|
|||||||
|
import {
|
||||||
|
memo,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import {
|
||||||
|
RiArrowDownSLine,
|
||||||
|
RiCheckLine,
|
||||||
|
} from '@remixicon/react'
|
||||||
|
import {
|
||||||
|
PortalToFollowElem,
|
||||||
|
PortalToFollowElemContent,
|
||||||
|
PortalToFollowElemTrigger,
|
||||||
|
} from '@/app/components/base/portal-to-follow-elem'
|
||||||
|
import Button from '@/app/components/base/button'
|
||||||
|
|
||||||
|
type MemorySelectorProps = {
|
||||||
|
value: string
|
||||||
|
onSelected: (value: string) => void
|
||||||
|
}
|
||||||
|
const MemorySelector = ({
|
||||||
|
value,
|
||||||
|
onSelected,
|
||||||
|
}: MemorySelectorProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
value: 'disabled',
|
||||||
|
label: t('workflow.nodes.common.memory.disabled.title'),
|
||||||
|
description: t('workflow.nodes.common.memory.disabled.desc'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'linear',
|
||||||
|
label: t('workflow.nodes.common.memory.linear.title'),
|
||||||
|
description: t('workflow.nodes.common.memory.linear.desc'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'block',
|
||||||
|
label: t('workflow.nodes.common.memory.block.title'),
|
||||||
|
description: t('workflow.nodes.common.memory.block.desc'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const selectedOption = options.find(option => option.value === value)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PortalToFollowElem
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
placement='bottom-end'
|
||||||
|
offset={4}
|
||||||
|
>
|
||||||
|
<PortalToFollowElemTrigger onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.nativeEvent.stopImmediatePropagation()
|
||||||
|
setOpen(v => !v)
|
||||||
|
}}>
|
||||||
|
<Button
|
||||||
|
size='small'
|
||||||
|
>
|
||||||
|
{selectedOption?.label}
|
||||||
|
<RiArrowDownSLine className='h-3.5 w-3.5' />
|
||||||
|
</Button>
|
||||||
|
</PortalToFollowElemTrigger>
|
||||||
|
<PortalToFollowElemContent className='z-[11]'>
|
||||||
|
<div className='w-[280px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg'>
|
||||||
|
{
|
||||||
|
options.map(option => (
|
||||||
|
<div
|
||||||
|
key={option.value}
|
||||||
|
className='flex cursor-pointer rounded-lg p-2 pr-3 hover:bg-state-base-hover'
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.nativeEvent.stopImmediatePropagation()
|
||||||
|
onSelected(option.value)
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='mr-1 w-4 shrink-0'>
|
||||||
|
{
|
||||||
|
value === option.value && (
|
||||||
|
<RiCheckLine className='h-4 w-4 text-text-accent' />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className='grow'>
|
||||||
|
<div className='system-sm-semibold mb-0.5 text-text-secondary'>{option.label}</div>
|
||||||
|
<div className='system-xs-regular text-text-tertiary'>{option.description}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</PortalToFollowElemContent>
|
||||||
|
</PortalToFollowElem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(MemorySelector)
|
||||||
@ -21,6 +21,7 @@ import Switch from '@/app/components/base/switch'
|
|||||||
import { RiAlertFill, RiQuestionLine } from '@remixicon/react'
|
import { RiAlertFill, RiQuestionLine } from '@remixicon/react'
|
||||||
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
|
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
|
||||||
import Toast from '@/app/components/base/toast'
|
import Toast from '@/app/components/base/toast'
|
||||||
|
import MemorySystem from './components/memory-system'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.nodes.llm'
|
const i18nPrefix = 'workflow.nodes.llm'
|
||||||
|
|
||||||
@ -224,7 +225,11 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
|||||||
readonly={readOnly}
|
readonly={readOnly}
|
||||||
config={{ data: inputs.memory }}
|
config={{ data: inputs.memory }}
|
||||||
onChange={handleMemoryChange}
|
onChange={handleMemoryChange}
|
||||||
canSetRoleName={isCompletionModel}
|
canSetRoleName={!isCompletionModel}
|
||||||
|
/>
|
||||||
|
<MemorySystem
|
||||||
|
id={id}
|
||||||
|
data={data}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React, { useCallback, useRef } from 'react'
|
import React, { useCallback, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useContext } from 'use-context-selector'
|
import { useContext } from 'use-context-selector'
|
||||||
|
import { v4 as uuid4 } from 'uuid'
|
||||||
import {
|
import {
|
||||||
useForm as useTanstackForm,
|
useForm as useTanstackForm,
|
||||||
useStore as useTanstackStore,
|
useStore as useTanstackStore,
|
||||||
@ -63,26 +64,27 @@ const ChatVariableModal = ({
|
|||||||
}) || { isCheckValidated: false, values: {} }
|
}) || { isCheckValidated: false, values: {} }
|
||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
type,
|
value_type,
|
||||||
value,
|
value,
|
||||||
|
editInJSON,
|
||||||
|
...rest
|
||||||
} = values
|
} = values
|
||||||
console.log(values, 'xxx')
|
|
||||||
if (!isCheckValidated)
|
if (!isCheckValidated)
|
||||||
return
|
return
|
||||||
if (!checkVariableName(name))
|
if (!checkVariableName(name))
|
||||||
return
|
return
|
||||||
if (!chatVar && varList.some(chatVar => chatVar.name === name))
|
if (!chatVar && varList.some(chatVar => chatVar.name === name))
|
||||||
return notify({ type: 'error', message: 'name is existed' })
|
return notify({ type: 'error', message: 'name is existed' })
|
||||||
if (type === ChatVarType.Object && value.some((item: any) => !item.key && !!item.value))
|
if (value_type === ChatVarType.Object && value.some((item: any) => !item.key && !!item.value))
|
||||||
return notify({ type: 'error', message: 'object key can not be empty' })
|
return notify({ type: 'error', message: 'object key can not be empty' })
|
||||||
|
|
||||||
// onSave({
|
onSave({
|
||||||
// id: chatVar ? chatVar.id : uuid4(),
|
id: chatVar ? chatVar.id : uuid4(),
|
||||||
// name,
|
name,
|
||||||
// value_type: type,
|
value_type,
|
||||||
// value: values,
|
value: editInJSON ? JSON.parse(value) : value,
|
||||||
// description,
|
...rest,
|
||||||
// })
|
})
|
||||||
onClose()
|
onClose()
|
||||||
}, [onClose, notify, t, varList, chatVar, checkVariableName])
|
}, [onClose, notify, t, varList, chatVar, checkVariableName])
|
||||||
|
|
||||||
|
|||||||
@ -173,7 +173,7 @@ export type ConversationVariable = {
|
|||||||
name: string
|
name: string
|
||||||
value_type: ChatVarType
|
value_type: ChatVarType
|
||||||
value: any
|
value: any
|
||||||
description: string
|
description?: string
|
||||||
} & MemoryVariable
|
} & MemoryVariable
|
||||||
|
|
||||||
export type GlobalVariable = {
|
export type GlobalVariable = {
|
||||||
@ -259,12 +259,15 @@ export type RolePrefix = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type Memory = {
|
export type Memory = {
|
||||||
|
enabled?: boolean
|
||||||
role_prefix?: RolePrefix
|
role_prefix?: RolePrefix
|
||||||
window: {
|
window: {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
size: number | string | null
|
size: number | string | null
|
||||||
}
|
}
|
||||||
query_prompt_template: string
|
query_prompt_template: string
|
||||||
|
block_id?: string
|
||||||
|
mode?: 'linear' | 'block'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum VarType {
|
export enum VarType {
|
||||||
|
|||||||
@ -340,6 +340,18 @@ const translation = {
|
|||||||
conversationRoleName: 'Conversation Role Name',
|
conversationRoleName: 'Conversation Role Name',
|
||||||
user: 'User prefix',
|
user: 'User prefix',
|
||||||
assistant: 'Assistant prefix',
|
assistant: 'Assistant prefix',
|
||||||
|
disabled: {
|
||||||
|
title: 'Disabled',
|
||||||
|
desc: 'AI won\'t remember anything from previous conversations',
|
||||||
|
},
|
||||||
|
linear: {
|
||||||
|
title: 'Linear',
|
||||||
|
desc: 'AI remembers the conversation flow and previous messages in order',
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
title: 'Memory Block',
|
||||||
|
desc: 'AI remembers specific information you define using custom templates',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
memories: {
|
memories: {
|
||||||
title: 'Memories',
|
title: 'Memories',
|
||||||
|
|||||||
@ -340,6 +340,18 @@ const translation = {
|
|||||||
conversationRoleName: '对话角色名',
|
conversationRoleName: '对话角色名',
|
||||||
user: '用户前缀',
|
user: '用户前缀',
|
||||||
assistant: '助手前缀',
|
assistant: '助手前缀',
|
||||||
|
disabled: {
|
||||||
|
title: '禁用',
|
||||||
|
desc: 'AI 不会记住任何之前的对话',
|
||||||
|
},
|
||||||
|
linear: {
|
||||||
|
title: '线性',
|
||||||
|
desc: 'AI 会记住对话的顺序和之前的消息',
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
title: '记忆块',
|
||||||
|
desc: 'AI 会记住你定义的特定信息',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
memories: {
|
memories: {
|
||||||
title: '记忆',
|
title: '记忆',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user