model-list-item.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { memo, useCallback } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { useDebounceFn } from 'ahooks'
  4. import type { CustomConfigurationModelFixedFields, ModelItem, ModelProvider } from '../declarations'
  5. import { ConfigurationMethodEnum, ModelStatusEnum } from '../declarations'
  6. import ModelBadge from '../model-badge'
  7. import ModelIcon from '../model-icon'
  8. import ModelName from '../model-name'
  9. import classNames from '@/utils/classnames'
  10. import Button from '@/app/components/base/button'
  11. import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
  12. import { Settings01 } from '@/app/components/base/icons/src/vender/line/general'
  13. import Switch from '@/app/components/base/switch'
  14. import Tooltip from '@/app/components/base/tooltip'
  15. import { useProviderContext, useProviderContextSelector } from '@/context/provider-context'
  16. import { disableModel, enableModel } from '@/service/common'
  17. import { Plan } from '@/app/components/billing/type'
  18. import { useAppContext } from '@/context/app-context'
  19. export type ModelListItemProps = {
  20. model: ModelItem
  21. provider: ModelProvider
  22. isConfigurable: boolean
  23. onConfig: (currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields) => void
  24. onModifyLoadBalancing?: (model: ModelItem) => void
  25. }
  26. const ModelListItem = ({ model, provider, isConfigurable, onConfig, onModifyLoadBalancing }: ModelListItemProps) => {
  27. const { t } = useTranslation()
  28. const { plan } = useProviderContext()
  29. const modelLoadBalancingEnabled = useProviderContextSelector(state => state.modelLoadBalancingEnabled)
  30. const { isCurrentWorkspaceManager } = useAppContext()
  31. const toggleModelEnablingStatus = useCallback(async (enabled: boolean) => {
  32. if (enabled)
  33. await enableModel(`/workspaces/current/model-providers/${provider.provider}/models/enable`, { model: model.model, model_type: model.model_type })
  34. else
  35. await disableModel(`/workspaces/current/model-providers/${provider.provider}/models/disable`, { model: model.model, model_type: model.model_type })
  36. }, [model.model, model.model_type, provider.provider])
  37. const { run: debouncedToggleModelEnablingStatus } = useDebounceFn(toggleModelEnablingStatus, { wait: 500 })
  38. const onEnablingStateChange = useCallback(async (value: boolean) => {
  39. debouncedToggleModelEnablingStatus(value)
  40. }, [debouncedToggleModelEnablingStatus])
  41. return (
  42. <div
  43. key={model.model}
  44. className={classNames(
  45. 'group flex items-center pl-2 pr-2.5 h-8 rounded-lg',
  46. isConfigurable && 'hover:bg-gray-50',
  47. model.deprecated && 'opacity-60',
  48. )}
  49. >
  50. <ModelIcon
  51. className='shrink-0 mr-2'
  52. provider={provider}
  53. modelName={model.model}
  54. />
  55. <ModelName
  56. className='grow text-sm font-normal text-gray-900'
  57. modelItem={model}
  58. showModelType
  59. showMode
  60. showContextSize
  61. >
  62. {modelLoadBalancingEnabled && !model.deprecated && model.load_balancing_enabled && (
  63. <ModelBadge className='ml-1 uppercase text-indigo-600 border-indigo-300'>
  64. <Balance className='w-3 h-3 mr-0.5' />
  65. {t('common.modelProvider.loadBalancingHeadline')}
  66. </ModelBadge>
  67. )}
  68. </ModelName>
  69. <div className='shrink-0 flex items-center'>
  70. {
  71. model.fetch_from === ConfigurationMethodEnum.customizableModel
  72. ? (isCurrentWorkspaceManager && (
  73. <Button
  74. className='hidden group-hover:flex h-7'
  75. onClick={() => onConfig({ __model_name: model.model, __model_type: model.model_type })}
  76. >
  77. <Settings01 className='mr-[5px] w-3.5 h-3.5' />
  78. {t('common.modelProvider.config')}
  79. </Button>
  80. ))
  81. : (isCurrentWorkspaceManager && (modelLoadBalancingEnabled || plan.type === Plan.sandbox) && !model.deprecated && [ModelStatusEnum.active, ModelStatusEnum.disabled].includes(model.status))
  82. ? (
  83. <Button
  84. className='opacity-0 group-hover:opacity-100 h-[28px] transition-opacity'
  85. onClick={() => onModifyLoadBalancing?.(model)}
  86. >
  87. <Balance className='mr-1 w-[14px] h-[14px]' />
  88. {t('common.modelProvider.configLoadBalancing')}
  89. </Button>
  90. )
  91. : null
  92. }
  93. {
  94. model.deprecated
  95. ? (
  96. <Tooltip
  97. popupContent={
  98. <span className='font-semibold'>{t('common.modelProvider.modelHasBeenDeprecated')}</span>} offset={{ mainAxis: 4 }
  99. }
  100. needsDelay
  101. >
  102. <Switch defaultValue={false} disabled size='md' />
  103. </Tooltip>
  104. )
  105. : (isCurrentWorkspaceManager && (
  106. <Switch
  107. className='ml-2'
  108. defaultValue={model?.status === ModelStatusEnum.active}
  109. disabled={![ModelStatusEnum.active, ModelStatusEnum.disabled].includes(model.status)}
  110. size='md'
  111. onChange={onEnablingStateChange}
  112. />
  113. ))
  114. }
  115. </div>
  116. </div>
  117. )
  118. }
  119. export default memo(ModelListItem)