feat: model load balancing (#4926)

This commit is contained in:
Nite Knite
2024-06-05 00:13:29 +08:00
committed by GitHub
parent d1dbbc1e33
commit 37f292ea91
58 changed files with 1896 additions and 304 deletions

View File

@@ -11,12 +11,14 @@ import type {
CredentialFormSchema,
CredentialFormSchemaRadio,
CredentialFormSchemaSelect,
CustomConfigrationModelFixedFields,
CustomConfigurationModelFixedFields,
FormValue,
ModelLoadBalancingConfig,
ModelLoadBalancingConfigEntry,
ModelProvider,
} from '../declarations'
import {
ConfigurateMethodEnum,
ConfigurationMethodEnum,
CustomConfigurationStatusEnum,
FormTypeEnum,
} from '../declarations'
@@ -28,11 +30,12 @@ import {
} from '../utils'
import {
useLanguage,
useProviderCrenditialsFormSchemasValue,
useProviderCredentialsAndLoadBalancing,
} from '../hooks'
import ProviderIcon from '../provider-icon'
import { useValidate } from '../../key-validator/hooks'
import { ValidatedStatus } from '../../key-validator/declarations'
import ModelLoadBalancingConfigs from '../provider-added-card/model-load-balancing-configs'
import Form from './Form'
import Button from '@/app/components/base/button'
import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
@@ -47,8 +50,8 @@ import ConfirmCommon from '@/app/components/base/confirm/common'
type ModelModalProps = {
provider: ModelProvider
configurateMethod: ConfigurateMethodEnum
currentCustomConfigrationModelFixedFields?: CustomConfigrationModelFixedFields
configurateMethod: ConfigurationMethodEnum
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
onCancel: () => void
onSave: () => void
}
@@ -56,16 +59,20 @@ type ModelModalProps = {
const ModelModal: FC<ModelModalProps> = ({
provider,
configurateMethod,
currentCustomConfigrationModelFixedFields,
currentCustomConfigurationModelFixedFields,
onCancel,
onSave,
}) => {
const providerFormSchemaPredefined = configurateMethod === ConfigurateMethodEnum.predefinedModel
const formSchemasValue = useProviderCrenditialsFormSchemasValue(
const providerFormSchemaPredefined = configurateMethod === ConfigurationMethodEnum.predefinedModel
const {
credentials: formSchemasValue,
loadBalancing: originalConfig,
mutate,
} = useProviderCredentialsAndLoadBalancing(
provider.provider,
configurateMethod,
providerFormSchemaPredefined && provider.custom_configuration.status === CustomConfigurationStatusEnum.active,
currentCustomConfigrationModelFixedFields,
currentCustomConfigurationModelFixedFields,
)
const isEditMode = !!formSchemasValue
const { t } = useTranslation()
@@ -73,13 +80,29 @@ const ModelModal: FC<ModelModalProps> = ({
const language = useLanguage()
const [loading, setLoading] = useState(false)
const [showConfirm, setShowConfirm] = useState(false)
const [draftConfig, setDraftConfig] = useState<ModelLoadBalancingConfig>()
const originalConfigMap = useMemo(() => {
if (!originalConfig)
return {}
return originalConfig?.configs.reduce((prev, config) => {
if (config.id)
prev[config.id] = config
return prev
}, {} as Record<string, ModelLoadBalancingConfigEntry>)
}, [originalConfig])
useEffect(() => {
if (originalConfig && !draftConfig)
setDraftConfig(originalConfig)
}, [draftConfig, originalConfig])
const formSchemas = useMemo(() => {
return providerFormSchemaPredefined
? provider.provider_credential_schema.credential_form_schemas
: [
genModelTypeFormSchema(provider.supported_model_types),
genModelNameFormSchema(provider.model_credential_schema?.model),
...provider.model_credential_schema.credential_form_schemas,
...(draftConfig?.enabled ? [] : provider.model_credential_schema.credential_form_schemas),
]
}, [
providerFormSchemaPredefined,
@@ -87,15 +110,14 @@ const ModelModal: FC<ModelModalProps> = ({
provider.supported_model_types,
provider.model_credential_schema?.credential_form_schemas,
provider.model_credential_schema?.model,
draftConfig?.enabled,
])
const [
requiredFormSchemas,
secretFormSchemas,
defaultFormSchemaValue,
showOnVariableMap,
] = useMemo(() => {
const requiredFormSchemas: CredentialFormSchema[] = []
const secretFormSchemas: CredentialFormSchema[] = []
const defaultFormSchemaValue: Record<string, string | number> = {}
const showOnVariableMap: Record<string, string[]> = {}
@@ -103,9 +125,6 @@ const ModelModal: FC<ModelModalProps> = ({
if (formSchema.required)
requiredFormSchemas.push(formSchema)
if (formSchema.type === FormTypeEnum.secretInput)
secretFormSchemas.push(formSchema)
if (formSchema.default)
defaultFormSchemaValue[formSchema.variable] = formSchema.default
@@ -136,22 +155,21 @@ const ModelModal: FC<ModelModalProps> = ({
return [
requiredFormSchemas,
secretFormSchemas,
defaultFormSchemaValue,
showOnVariableMap,
]
}, [formSchemas])
const initialFormSchemasValue = useMemo(() => {
const initialFormSchemasValue: Record<string, string | number> = useMemo(() => {
return {
...defaultFormSchemaValue,
...formSchemasValue,
}
} as unknown as Record<string, string | number>
}, [formSchemasValue, defaultFormSchemaValue])
const [value, setValue] = useState(initialFormSchemasValue)
useEffect(() => {
setValue(initialFormSchemasValue)
}, [initialFormSchemasValue])
const [validate, validating, validatedStatusState] = useValidate(value)
const [_, validating, validatedStatusState] = useValidate(value)
const filteredRequiredFormSchemas = requiredFormSchemas.filter((requiredFormSchema) => {
if (requiredFormSchema.show_on.length && requiredFormSchema.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
return true
@@ -161,32 +179,63 @@ const ModelModal: FC<ModelModalProps> = ({
return false
})
const getSecretValues = useCallback((v: FormValue) => {
return secretFormSchemas.reduce((prev, next) => {
if (v[next.variable] === initialFormSchemasValue[next.variable])
prev[next.variable] = '[__HIDDEN__]'
return prev
}, {} as Record<string, string>)
}, [initialFormSchemasValue, secretFormSchemas])
const handleValueChange = (v: FormValue) => {
setValue(v)
}
const extendedSecretFormSchemas = useMemo(
() =>
(providerFormSchemaPredefined
? provider.provider_credential_schema.credential_form_schemas
: [
genModelTypeFormSchema(provider.supported_model_types),
genModelNameFormSchema(provider.model_credential_schema?.model),
...provider.model_credential_schema.credential_form_schemas,
]).filter(({ type }) => type === FormTypeEnum.secretInput),
[
provider.model_credential_schema?.credential_form_schemas,
provider.model_credential_schema?.model,
provider.provider_credential_schema?.credential_form_schemas,
provider.supported_model_types,
providerFormSchemaPredefined,
],
)
const encodeSecretValues = useCallback((v: FormValue) => {
const result = { ...v }
extendedSecretFormSchemas.forEach(({ variable }) => {
if (result[variable] === formSchemasValue?.[variable])
result[variable] = '[__HIDDEN__]'
})
return result
}, [extendedSecretFormSchemas, formSchemasValue])
const encodeConfigEntrySecretValues = useCallback((entry: ModelLoadBalancingConfigEntry) => {
const result = { ...entry }
extendedSecretFormSchemas.forEach(({ variable }) => {
if (entry.id && result.credentials[variable] === originalConfigMap[entry.id]?.credentials?.[variable])
result.credentials[variable] = '[__HIDDEN__]'
})
return result
}, [extendedSecretFormSchemas, originalConfigMap])
const handleSave = async () => {
try {
setLoading(true)
const res = await saveCredentials(
providerFormSchemaPredefined,
provider.provider,
encodeSecretValues(value),
{
...value,
...getSecretValues(value),
...draftConfig,
enabled: Boolean(draftConfig?.enabled),
configs: draftConfig?.configs.map(encodeConfigEntrySecretValues) || [],
},
)
if (res.result === 'success') {
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
mutate()
onSave()
onCancel()
}
@@ -207,6 +256,7 @@ const ModelModal: FC<ModelModalProps> = ({
)
if (res.result === 'success') {
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
mutate()
onSave()
onCancel()
}
@@ -217,7 +267,7 @@ const ModelModal: FC<ModelModalProps> = ({
}
const renderTitlePrefix = () => {
const prefix = configurateMethod === ConfigurateMethodEnum.customizableModel ? t('common.operation.add') : t('common.operation.setup')
const prefix = configurateMethod === ConfigurationMethodEnum.customizableModel ? t('common.operation.add') : t('common.operation.setup')
return `${prefix} ${provider.label[language] || provider.label.en_US}`
}
@@ -232,6 +282,7 @@ const ModelModal: FC<ModelModalProps> = ({
<div className='text-xl font-semibold text-gray-900'>{renderTitlePrefix()}</div>
<ProviderIcon provider={provider} />
</div>
<Form
value={value}
onChange={handleValueChange}
@@ -241,7 +292,17 @@ const ModelModal: FC<ModelModalProps> = ({
showOnVariableMap={showOnVariableMap}
isEditMode={isEditMode}
/>
<div className='sticky bottom-0 flex justify-between items-center py-6 flex-wrap gap-y-2 bg-white'>
<div className='mt-1 mb-4 border-t-[0.5px] border-t-gray-100' />
<ModelLoadBalancingConfigs withSwitch {...{
draftConfig,
setDraftConfig,
provider,
currentCustomConfigurationModelFixedFields,
configurationMethod: configurateMethod,
}} />
<div className='sticky bottom-0 flex justify-between items-center mt-2 -mx-2 pt-4 px-2 pb-6 flex-wrap gap-y-2 bg-white z-10'>
{
(provider.help && (provider.help.title || provider.help.url))
? (
@@ -278,7 +339,11 @@ const ModelModal: FC<ModelModalProps> = ({
className='h-9 text-sm font-medium'
type='primary'
onClick={handleSave}
disabled={loading || filteredRequiredFormSchemas.some(item => value[item.variable] === undefined)}
disabled={
loading
|| filteredRequiredFormSchemas.some(item => value[item.variable] === undefined)
|| (draftConfig?.enabled && (draftConfig?.configs.filter(config => config.enabled).length ?? 0) < 2)
}
>
{t('common.operation.save')}
</Button>