| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 | import { useState } from 'react'import useSWR from 'swr'import { useTranslation } from 'react-i18next'import { useContext } from 'use-context-selector'import type {  FormValue,  ProviderConfigModal,  ProviderEnum,} from './declarations'import ModelCard from './model-card'import ModelItem from './model-item'import ModelModal from './model-modal'import SystemModel from './system-model'import config from './configs'import { ConfigurableProviders } from './utils'import {  changeModelProviderPriority,  deleteModelProvider,  deleteModelProviderModel,  fetchModelProviders,  setModelProvider,} from '@/service/common'import { useToastContext } from '@/app/components/base/toast'import Confirm from '@/app/components/base/confirm/common'import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'import { useEventEmitterContextContext } from '@/context/event-emitter'import { useProviderContext } from '@/context/provider-context'import I18n from '@/context/i18n'import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'const MODEL_CARD_LIST = [  config.openai,  config.anthropic,]type DeleteModel = {  model_name: string  model_type: string}const ModelPage = () => {  const { t } = useTranslation()  const { locale } = useContext(I18n)  const {    updateModelList,    textGenerationDefaultModel,    embeddingsDefaultModel,    speech2textDefaultModel,    rerankDefaultModel,  } = useProviderContext()  const { data: providers, mutate: mutateProviders } = useSWR('/workspaces/current/model-providers', fetchModelProviders)  const [showModal, setShowModal] = useState(false)  const { notify } = useToastContext()  const { eventEmitter } = useEventEmitterContextContext()  const [modelModalConfig, setModelModalConfig] = useState<ProviderConfigModal | undefined>(undefined)  const [confirmShow, setConfirmShow] = useState(false)  const [deleteModel, setDeleteModel] = useState<DeleteModel & { providerKey: ProviderEnum }>()  const [modalMode, setModalMode] = useState('add')  let modelList = []  if (locale === 'en') {    modelList = [      config.azure_openai,      config.replicate,      config.huggingface_hub,      config.cohere,      config.zhipuai,      config.baichuan,      config.spark,      config.minimax,      config.tongyi,      config.wenxin,      config.jina,      config.chatglm,      config.xinference,      config.openllm,      config.localai,    ]  }  else {    modelList = [      config.huggingface_hub,      config.cohere,      config.zhipuai,      config.spark,      config.baichuan,      config.minimax,      config.azure_openai,      config.replicate,      config.tongyi,      config.wenxin,      config.jina,      config.chatglm,      config.xinference,      config.openllm,      config.localai,    ]  }  const handleOpenModal = (newModelModalConfig: ProviderConfigModal | undefined, editValue?: FormValue) => {    if (newModelModalConfig) {      setShowModal(true)      const defaultValue = editValue ? { ...newModelModalConfig.defaultValue, ...editValue } : newModelModalConfig.defaultValue      setModelModalConfig({        ...newModelModalConfig,        defaultValue,      })      if (editValue)        setModalMode('edit')      else        setModalMode('add')    }  }  const handleCancelModal = () => {    setShowModal(false)  }  const handleUpdateProvidersAndModelList = () => {    updateModelList(ModelType.textGeneration)    updateModelList(ModelType.embeddings)    updateModelList(ModelType.speech2text)    updateModelList(ModelType.reranking)    mutateProviders()  }  const handleSave = async (originValue?: FormValue) => {    if (originValue && modelModalConfig) {      const v = modelModalConfig.filterValue ? modelModalConfig.filterValue(originValue) : originValue      let body, url      if (ConfigurableProviders.includes(modelModalConfig.key)) {        const { model_name, model_type, ...config } = v        body = {          model_name,          model_type,          config,        }        url = `/workspaces/current/model-providers/${modelModalConfig.key}/models`      }      else {        body = {          config: v,        }        url = `/workspaces/current/model-providers/${modelModalConfig.key}`      }      try {        eventEmitter?.emit('provider-save')        const res = await setModelProvider({ url, body })        if (res.result === 'success') {          notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })          handleUpdateProvidersAndModelList()          handleCancelModal()        }        eventEmitter?.emit('')      }      catch (e) {        eventEmitter?.emit('')      }    }  }  const handleConfirm = (deleteModel: DeleteModel, providerKey: ProviderEnum) => {    setDeleteModel({ ...deleteModel, providerKey })    setConfirmShow(true)  }  const handleOperate = async ({ type, value }: Record<string, any>, provierKey: ProviderEnum) => {    if (type === 'delete') {      if (!value) {        const res = await deleteModelProvider({ url: `/workspaces/current/model-providers/${provierKey}` })        if (res.result === 'success') {          notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })          handleUpdateProvidersAndModelList()        }      }      else {        handleConfirm(value, provierKey)      }    }    if (type === 'priority') {      const res = await changeModelProviderPriority({        url: `/workspaces/current/model-providers/${provierKey}/preferred-provider-type`,        body: {          preferred_provider_type: value,        },      })      if (res.result === 'success') {        notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })        mutateProviders()      }    }  }  const handleDeleteModel = async () => {    const { model_name, model_type, providerKey } = deleteModel || {}    const res = await deleteModelProviderModel({      url: `/workspaces/current/model-providers/${providerKey}/models?model_name=${model_name}&model_type=${model_type}`,    })    if (res.result === 'success') {      notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })      setConfirmShow(false)      handleUpdateProvidersAndModelList()    }  }  const defaultModelNotConfigured = !textGenerationDefaultModel && !embeddingsDefaultModel && !speech2textDefaultModel && !rerankDefaultModel  return (    <div className='relative pt-1 -mt-2'>      <div className={`flex items-center justify-between mb-2 h-8 ${defaultModelNotConfigured && 'px-3 bg-[#FFFAEB] rounded-lg border border-[#FEF0C7]'}`}>        {          defaultModelNotConfigured            ? (              <div className='flex items-center text-xs font-medium text-gray-700'>                <AlertTriangle className='mr-1 w-3 h-3 text-[#F79009]' />                {t('common.modelProvider.notConfigured')}              </div>            )            : <div className='text-sm font-medium text-gray-800'>{t('common.modelProvider.models')}</div>        }        <SystemModel onUpdate={() => mutateProviders()} />      </div>      <div className='grid grid-cols-1 lg:grid-cols-2 gap-4 mb-6'>        {          MODEL_CARD_LIST.map((model, index) => (            <ModelCard              key={index}              modelItem={model.item}              currentProvider={providers?.[model.item.key]}              onOpenModal={editValue => handleOpenModal(model.modal, editValue)}              onOperate={v => handleOperate(v, model.item.key)}            />          ))        }      </div>      {        modelList.map((model, index) => (          <ModelItem            key={index}            modelItem={model.item}            currentProvider={providers?.[model.item.key]}            onOpenModal={editValue => handleOpenModal(model.modal, editValue)}            onOperate={v => handleOperate(v, model.item.key)}            onUpdate={mutateProviders}          />        ))      }      <ModelModal        isShow={showModal}        modelModal={modelModalConfig}        onCancel={handleCancelModal}        onSave={handleSave}        mode={modalMode}      />      <Confirm        isShow={confirmShow}        onCancel={() => setConfirmShow(false)}        title={deleteModel?.model_name || ''}        desc={t('common.modelProvider.item.deleteDesc', { modelName: deleteModel?.model_name }) || ''}        onConfirm={handleDeleteModel}        confirmWrapperClassName='!z-30'      />    </div>  )}export default ModelPage
 |