index.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import type { FC } from 'react'
  2. import { useState } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import type {
  5. CustomConfigrationModelFixedFields,
  6. ModelItem,
  7. ModelProvider,
  8. } from '../declarations'
  9. import { ConfigurateMethodEnum } from '../declarations'
  10. import {
  11. DEFAULT_BACKGROUND_COLOR,
  12. modelTypeFormat,
  13. } from '../utils'
  14. import ProviderIcon from '../provider-icon'
  15. import ModelBadge from '../model-badge'
  16. import CredentialPanel from './credential-panel'
  17. import QuotaPanel from './quota-panel'
  18. import ModelList from './model-list'
  19. import AddModelButton from './add-model-button'
  20. import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/arrows'
  21. import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
  22. import { fetchModelProviderModelList } from '@/service/common'
  23. import { useEventEmitterContextContext } from '@/context/event-emitter'
  24. import { IS_CE_EDITION } from '@/config'
  25. export const UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST = 'UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST'
  26. type ProviderAddedCardProps = {
  27. provider: ModelProvider
  28. onOpenModal: (configurateMethod: ConfigurateMethodEnum, currentCustomConfigrationModelFixedFields?: CustomConfigrationModelFixedFields) => void
  29. }
  30. const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
  31. provider,
  32. onOpenModal,
  33. }) => {
  34. const { t } = useTranslation()
  35. const { eventEmitter } = useEventEmitterContextContext()
  36. const [fetched, setFetched] = useState(false)
  37. const [loading, setLoading] = useState(false)
  38. const [collapsed, setCollapsed] = useState(true)
  39. const [modelList, setModelList] = useState<ModelItem[]>([])
  40. const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
  41. const systemConfig = provider.system_configuration
  42. const hasModelList = fetched && !!modelList.length
  43. const showQuota = systemConfig.enabled && ['minimax', 'spark', 'zhipuai', 'anthropic', 'openai'].includes(provider.provider) && !IS_CE_EDITION
  44. const getModelList = async (providerName: string) => {
  45. if (loading)
  46. return
  47. try {
  48. setLoading(true)
  49. const modelsData = await fetchModelProviderModelList(`/workspaces/current/model-providers/${providerName}/models`)
  50. setModelList(modelsData.data)
  51. setCollapsed(false)
  52. setFetched(true)
  53. }
  54. finally {
  55. setLoading(false)
  56. }
  57. }
  58. const handleOpenModelList = () => {
  59. if (fetched) {
  60. setCollapsed(false)
  61. return
  62. }
  63. getModelList(provider.provider)
  64. }
  65. eventEmitter?.useSubscription((v: any) => {
  66. if (v?.type === UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST && v.payload === provider.provider)
  67. getModelList(v.payload)
  68. })
  69. return (
  70. <div
  71. className='mb-2 rounded-xl border-[0.5px] border-black/5 shadow-xs'
  72. style={{ background: provider.background || DEFAULT_BACKGROUND_COLOR }}
  73. >
  74. <div className='flex pl-3 py-2 pr-2 rounded-t-xl'>
  75. <div className='grow px-1 pt-1 pb-0.5'>
  76. <ProviderIcon
  77. className='mb-2'
  78. provider={provider}
  79. />
  80. <div className='flex gap-0.5'>
  81. {
  82. provider.supported_model_types.map(modelType => (
  83. <ModelBadge key={modelType}>
  84. {modelTypeFormat(modelType)}
  85. </ModelBadge>
  86. ))
  87. }
  88. </div>
  89. </div>
  90. {
  91. showQuota && (
  92. <QuotaPanel
  93. provider={provider}
  94. />
  95. )
  96. }
  97. {
  98. configurateMethods.includes(ConfigurateMethodEnum.predefinedModel) && (
  99. <CredentialPanel
  100. onSetup={() => onOpenModal(ConfigurateMethodEnum.predefinedModel)}
  101. provider={provider}
  102. />
  103. )
  104. }
  105. </div>
  106. {
  107. collapsed && (
  108. <div className='group flex items-center justify-between pl-2 py-1.5 pr-[11px] border-t border-t-black/5 bg-white/30 text-xs font-medium text-gray-500'>
  109. <div className='group-hover:hidden pl-1 pr-1.5 h-6 leading-6'>
  110. {
  111. hasModelList
  112. ? t('common.modelProvider.modelsNum', { num: modelList.length })
  113. : t('common.modelProvider.showModels')
  114. }
  115. </div>
  116. <div
  117. className='hidden group-hover:flex items-center pl-1 pr-1.5 h-6 rounded-lg hover:bg-white cursor-pointer'
  118. onClick={handleOpenModelList}
  119. >
  120. <ChevronDownDouble className='mr-0.5 w-3 h-3' />
  121. {
  122. hasModelList
  123. ? t('common.modelProvider.showModelsNum', { num: modelList.length })
  124. : t('common.modelProvider.showModels')
  125. }
  126. {
  127. loading && (
  128. <Loading02 className='ml-0.5 animate-spin w-3 h-3' />
  129. )
  130. }
  131. </div>
  132. {
  133. configurateMethods.includes(ConfigurateMethodEnum.customizableModel) && (
  134. <AddModelButton
  135. onClick={() => onOpenModal(ConfigurateMethodEnum.customizableModel)}
  136. className='hidden group-hover:flex group-hover:text-primary-600'
  137. />
  138. )
  139. }
  140. </div>
  141. )
  142. }
  143. {
  144. !collapsed && (
  145. <ModelList
  146. provider={provider}
  147. models={modelList}
  148. onCollapse={() => setCollapsed(true)}
  149. onConfig={currentCustomConfigrationModelFixedFields => onOpenModal(ConfigurateMethodEnum.customizableModel, currentCustomConfigrationModelFixedFields)}
  150. />
  151. )
  152. }
  153. </div>
  154. )
  155. }
  156. export default ProviderAddedCard