feat: form not installed indicator
This commit is contained in:
parent
5ec4695e4a
commit
08cff0045d
@ -10,11 +10,15 @@ type ModelTriggerProps = {
|
|||||||
modelName: string
|
modelName: string
|
||||||
providerName: string
|
providerName: string
|
||||||
className?: string
|
className?: string
|
||||||
|
showWarnIcon?: boolean
|
||||||
|
contentClassName?: string
|
||||||
}
|
}
|
||||||
const ModelTrigger: FC<ModelTriggerProps> = ({
|
const ModelTrigger: FC<ModelTriggerProps> = ({
|
||||||
modelName,
|
modelName,
|
||||||
providerName,
|
providerName,
|
||||||
className,
|
className,
|
||||||
|
showWarnIcon,
|
||||||
|
contentClassName,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { modelProviders } = useProviderContext()
|
const { modelProviders } = useProviderContext()
|
||||||
@ -24,7 +28,7 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
|
|||||||
<div
|
<div
|
||||||
className={cn('group flex flex-grow box-content items-center p-[3px] pl-1 h-8 gap-1 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)}
|
className={cn('group flex flex-grow box-content items-center p-[3px] pl-1 h-8 gap-1 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)}
|
||||||
>
|
>
|
||||||
<div className='flex items-center w-full'>
|
<div className={cn('flex items-center w-full', contentClassName)}>
|
||||||
<div className='flex items-center py-[1px] gap-1 min-w-0 flex-1'>
|
<div className='flex items-center py-[1px] gap-1 min-w-0 flex-1'>
|
||||||
<ModelIcon
|
<ModelIcon
|
||||||
className="w-4 h-4"
|
className="w-4 h-4"
|
||||||
@ -36,9 +40,11 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='shrink-0 flex items-center justify-center'>
|
<div className='shrink-0 flex items-center justify-center'>
|
||||||
<Tooltip popupContent={t('common.modelProvider.deprecated')}>
|
{showWarnIcon && (
|
||||||
<AlertTriangle className='w-4 h-4 text-text-warning-secondary' />
|
<Tooltip popupContent={t('common.modelProvider.deprecated')}>
|
||||||
</Tooltip>
|
<AlertTriangle className='w-4 h-4 text-text-warning-secondary' />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
PortalToFollowElemContent,
|
PortalToFollowElemContent,
|
||||||
PortalToFollowElemTrigger,
|
PortalToFollowElemTrigger,
|
||||||
} from '@/app/components/base/portal-to-follow-elem'
|
} from '@/app/components/base/portal-to-follow-elem'
|
||||||
|
import classNames from '@/utils/classnames'
|
||||||
|
|
||||||
type ModelSelectorProps = {
|
type ModelSelectorProps = {
|
||||||
defaultModel?: DefaultModel
|
defaultModel?: DefaultModel
|
||||||
@ -24,6 +25,8 @@ type ModelSelectorProps = {
|
|||||||
onSelect?: (model: DefaultModel) => void
|
onSelect?: (model: DefaultModel) => void
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
scopeFeatures?: string[]
|
scopeFeatures?: string[]
|
||||||
|
deprecatedClassName?: string
|
||||||
|
showDeprecatedWarnIcon?: boolean
|
||||||
}
|
}
|
||||||
const ModelSelector: FC<ModelSelectorProps> = ({
|
const ModelSelector: FC<ModelSelectorProps> = ({
|
||||||
defaultModel,
|
defaultModel,
|
||||||
@ -33,6 +36,8 @@ const ModelSelector: FC<ModelSelectorProps> = ({
|
|||||||
onSelect,
|
onSelect,
|
||||||
readonly,
|
readonly,
|
||||||
scopeFeatures = [],
|
scopeFeatures = [],
|
||||||
|
deprecatedClassName,
|
||||||
|
showDeprecatedWarnIcon = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const {
|
const {
|
||||||
@ -64,7 +69,7 @@ const ModelSelector: FC<ModelSelectorProps> = ({
|
|||||||
placement='bottom-start'
|
placement='bottom-start'
|
||||||
offset={4}
|
offset={4}
|
||||||
>
|
>
|
||||||
<div className='relative'>
|
<div className={classNames('relative')}>
|
||||||
<PortalToFollowElemTrigger
|
<PortalToFollowElemTrigger
|
||||||
onClick={handleToggle}
|
onClick={handleToggle}
|
||||||
className='block'
|
className='block'
|
||||||
@ -86,6 +91,8 @@ const ModelSelector: FC<ModelSelectorProps> = ({
|
|||||||
modelName={defaultModel?.model || ''}
|
modelName={defaultModel?.model || ''}
|
||||||
providerName={defaultModel?.provider || ''}
|
providerName={defaultModel?.provider || ''}
|
||||||
className={triggerClassName}
|
className={triggerClassName}
|
||||||
|
showWarnIcon={showDeprecatedWarnIcon}
|
||||||
|
contentClassName={deprecatedClassName}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
|
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||||
|
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||||
|
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
||||||
|
import Indicator from '@/app/components/header/indicator'
|
||||||
|
import { type FC, useMemo } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
export type ModelBarProps = {
|
||||||
|
provider: string
|
||||||
|
model: string
|
||||||
|
} | {}
|
||||||
|
|
||||||
|
const useAllModel = () => {
|
||||||
|
const { data: textGeneration } = useModelList(ModelTypeEnum.textGeneration)
|
||||||
|
const { data: moderation } = useModelList(ModelTypeEnum.moderation)
|
||||||
|
const { data: rerank } = useModelList(ModelTypeEnum.rerank)
|
||||||
|
const { data: speech2text } = useModelList(ModelTypeEnum.speech2text)
|
||||||
|
const { data: textEmbedding } = useModelList(ModelTypeEnum.textEmbedding)
|
||||||
|
const { data: tts } = useModelList(ModelTypeEnum.tts)
|
||||||
|
const models = useMemo(() => {
|
||||||
|
return textGeneration
|
||||||
|
.concat(moderation)
|
||||||
|
.concat(rerank)
|
||||||
|
.concat(speech2text)
|
||||||
|
.concat(textEmbedding)
|
||||||
|
.concat(tts)
|
||||||
|
}, [textGeneration, moderation, rerank, speech2text, textEmbedding, tts])
|
||||||
|
if (!textGeneration || !moderation || !rerank || !speech2text || !textEmbedding || !tts)
|
||||||
|
return undefined
|
||||||
|
return models
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModelBar: FC<ModelBarProps> = (props) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const modelList = useAllModel()
|
||||||
|
if (!('provider' in props)) {
|
||||||
|
return <ModelSelector
|
||||||
|
modelList={[]}
|
||||||
|
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
|
||||||
|
defaultModel={undefined}
|
||||||
|
showDeprecatedWarnIcon={false}
|
||||||
|
readonly
|
||||||
|
deprecatedClassName='opacity-50'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
const modelInstalled = modelList?.some(
|
||||||
|
provider => provider.provider === props.provider && provider.models.some(model => model.model === props.model))
|
||||||
|
const showWarn = modelList && !modelInstalled
|
||||||
|
return modelList && <Tooltip
|
||||||
|
popupContent={t('workflow.nodes.agent.modelNotInstallTooltip')}
|
||||||
|
triggerMethod='hover'
|
||||||
|
disabled={!modelList || modelInstalled}
|
||||||
|
>
|
||||||
|
<div className='relative'>
|
||||||
|
<ModelSelector
|
||||||
|
modelList={modelList}
|
||||||
|
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
|
||||||
|
defaultModel={props}
|
||||||
|
showDeprecatedWarnIcon={false}
|
||||||
|
readonly
|
||||||
|
deprecatedClassName='opacity-50'
|
||||||
|
/>
|
||||||
|
{showWarn && <Indicator color={'red'} className='absolute -right-0.5 -top-0.5' />}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
@ -2,41 +2,19 @@ import { type FC, memo, useMemo } from 'react'
|
|||||||
import type { NodeProps } from '../../types'
|
import type { NodeProps } from '../../types'
|
||||||
import type { AgentNodeType } from './types'
|
import type { AgentNodeType } from './types'
|
||||||
import { SettingItem } from '../_base/components/setting-item'
|
import { SettingItem } from '../_base/components/setting-item'
|
||||||
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
|
||||||
import { Group, GroupLabel } from '../_base/components/group'
|
import { Group, GroupLabel } from '../_base/components/group'
|
||||||
import type { ToolIconProps } from './components/tool-icon'
|
import type { ToolIconProps } from './components/tool-icon'
|
||||||
import { ToolIcon } from './components/tool-icon'
|
import { ToolIcon } from './components/tool-icon'
|
||||||
import useConfig from './use-config'
|
import useConfig from './use-config'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { FormTypeEnum, ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||||
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
|
||||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||||
|
import { ModelBar } from './components/model-bar'
|
||||||
const useAllModel = () => {
|
|
||||||
const { data: textGeneration } = useModelList(ModelTypeEnum.textGeneration)
|
|
||||||
const { data: moderation } = useModelList(ModelTypeEnum.moderation)
|
|
||||||
const { data: rerank } = useModelList(ModelTypeEnum.rerank)
|
|
||||||
const { data: speech2text } = useModelList(ModelTypeEnum.speech2text)
|
|
||||||
const { data: textEmbedding } = useModelList(ModelTypeEnum.textEmbedding)
|
|
||||||
const { data: tts } = useModelList(ModelTypeEnum.tts)
|
|
||||||
const models = useMemo(() => {
|
|
||||||
return textGeneration
|
|
||||||
.concat(moderation)
|
|
||||||
.concat(rerank)
|
|
||||||
.concat(speech2text)
|
|
||||||
.concat(textEmbedding)
|
|
||||||
.concat(tts)
|
|
||||||
}, [textGeneration, moderation, rerank, speech2text, textEmbedding, tts])
|
|
||||||
if (!textGeneration || !moderation || !rerank || !speech2text || !textEmbedding || !tts)
|
|
||||||
return undefined
|
|
||||||
return models
|
|
||||||
}
|
|
||||||
|
|
||||||
const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
||||||
const { inputs, currentStrategy, currentStrategyStatus, pluginDetail } = useConfig(props.id, props.data)
|
const { inputs, currentStrategy, currentStrategyStatus, pluginDetail } = useConfig(props.id, props.data)
|
||||||
const renderI18nObject = useRenderI18nObject()
|
const renderI18nObject = useRenderI18nObject()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const modelList = useAllModel()
|
|
||||||
const models = useMemo(() => {
|
const models = useMemo(() => {
|
||||||
if (!inputs) return []
|
if (!inputs) return []
|
||||||
// if selected, show in node
|
// if selected, show in node
|
||||||
@ -46,6 +24,7 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
|||||||
.filter(param => param.type === FormTypeEnum.modelSelector)
|
.filter(param => param.type === FormTypeEnum.modelSelector)
|
||||||
.reduce((acc, param) => {
|
.reduce((acc, param) => {
|
||||||
const item = inputs.agent_parameters?.[param.name]?.value
|
const item = inputs.agent_parameters?.[param.name]?.value
|
||||||
|
console.log({ item })
|
||||||
if (!item) {
|
if (!item) {
|
||||||
if (param.required) {
|
if (param.required) {
|
||||||
acc.push({ param: param.name })
|
acc.push({ param: param.name })
|
||||||
@ -102,27 +81,18 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
|||||||
{inputs.agent_strategy_label}
|
{inputs.agent_strategy_label}
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
: <SettingItem label={t('workflow.nodes.agent.strategyNotSet')} />}
|
: <SettingItem label={t('workflow.nodes.agent.strategyNotSet')} />}
|
||||||
{models.length > 0 && modelList && <Group
|
<Group
|
||||||
label={<GroupLabel className='mt-1'>
|
label={<GroupLabel className='mt-1'>
|
||||||
{t('workflow.nodes.agent.model')}
|
{t('workflow.nodes.agent.model')}
|
||||||
</GroupLabel>}
|
</GroupLabel>}
|
||||||
>
|
>
|
||||||
{models.map((model) => {
|
{models.map((model) => {
|
||||||
return <ModelSelector
|
return <ModelBar
|
||||||
|
{...model}
|
||||||
key={model.param}
|
key={model.param}
|
||||||
modelList={modelList}
|
|
||||||
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
|
|
||||||
defaultModel={
|
|
||||||
'provider' in model
|
|
||||||
? {
|
|
||||||
provider: model.provider,
|
|
||||||
model: model.model,
|
|
||||||
}
|
|
||||||
: undefined}
|
|
||||||
readonly
|
|
||||||
/>
|
/>
|
||||||
})}
|
})}
|
||||||
</Group>}
|
</Group>
|
||||||
{tools.length > 0 && <Group label={<GroupLabel className='mt-1'>
|
{tools.length > 0 && <Group label={<GroupLabel className='mt-1'>
|
||||||
{t('workflow.nodes.agent.toolbox')}
|
{t('workflow.nodes.agent.toolbox')}
|
||||||
</GroupLabel>}>
|
</GroupLabel>}>
|
||||||
|
Loading…
Reference in New Issue
Block a user