|
@@ -1,14 +1,17 @@
|
|
|
import type { FC } from 'react'
|
|
|
-import { Fragment, useState } from 'react'
|
|
|
+import React, { Fragment, useEffect, useState } from 'react'
|
|
|
+import useSWR from 'swr'
|
|
|
import { Popover, Transition } from '@headlessui/react'
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
import _ from 'lodash-es'
|
|
|
import cn from 'classnames'
|
|
|
+import ModelModal from '../model-modal'
|
|
|
+import cohereConfig from '../configs/cohere'
|
|
|
import s from './style.module.css'
|
|
|
-import type { BackendModel, ProviderEnum } from '@/app/components/header/account-setting/model-page/declarations'
|
|
|
+import type { BackendModel, FormValue, ProviderEnum } from '@/app/components/header/account-setting/model-page/declarations'
|
|
|
import { ModelType } from '@/app/components/header/account-setting/model-page/declarations'
|
|
|
import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
|
|
|
-import { Check, SearchLg } from '@/app/components/base/icons/src/vender/line/general'
|
|
|
+import { Check, LinkExternal01, SearchLg } from '@/app/components/base/icons/src/vender/line/general'
|
|
|
import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
|
|
|
import { AlertCircle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
|
|
|
import Tooltip from '@/app/components/base/tooltip'
|
|
@@ -20,6 +23,9 @@ import ModelModeTypeLabel from '@/app/components/app/configuration/config-model/
|
|
|
import type { ModelModeType } from '@/types/app'
|
|
|
import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes'
|
|
|
import { useModalContext } from '@/context/modal-context'
|
|
|
+import { useEventEmitterContextContext } from '@/context/event-emitter'
|
|
|
+import { fetchDefaultModal, setModelProvider } from '@/service/common'
|
|
|
+import { useToastContext } from '@/app/components/base/toast'
|
|
|
|
|
|
type Props = {
|
|
|
value: {
|
|
@@ -35,6 +41,7 @@ type Props = {
|
|
|
readonly?: boolean
|
|
|
triggerIconSmall?: boolean
|
|
|
whenEmptyGoToSetting?: boolean
|
|
|
+ onUpdate?: () => void
|
|
|
}
|
|
|
|
|
|
type ModelOption = {
|
|
@@ -59,6 +66,7 @@ const ModelSelector: FC<Props> = ({
|
|
|
readonly,
|
|
|
triggerIconSmall,
|
|
|
whenEmptyGoToSetting,
|
|
|
+ onUpdate,
|
|
|
}) => {
|
|
|
const { t } = useTranslation()
|
|
|
const { setShowAccountSettingModal } = useModalContext()
|
|
@@ -68,6 +76,7 @@ const ModelSelector: FC<Props> = ({
|
|
|
speech2textModelList,
|
|
|
rerankModelList,
|
|
|
agentThoughtModelList,
|
|
|
+ updateModelList,
|
|
|
} = useProviderContext()
|
|
|
const [search, setSearch] = useState('')
|
|
|
const modelList = supportAgentThought
|
|
@@ -98,7 +107,7 @@ const ModelSelector: FC<Props> = ({
|
|
|
})
|
|
|
: modelList
|
|
|
|
|
|
- const hasRemoved = value && !modelList.find(({ model_name, model_provider }) => model_name === value.modelName && model_provider.provider_name === value.providerName)
|
|
|
+ const hasRemoved = (value && value.modelName && value.providerName) && !modelList.find(({ model_name, model_provider }) => model_name === value.modelName && model_provider.provider_name === value.providerName)
|
|
|
|
|
|
const modelOptions: ModelOption[] = (() => {
|
|
|
const providers = _.uniq(filteredModelList.map(item => item.model_provider.provider_name))
|
|
@@ -121,6 +130,45 @@ const ModelSelector: FC<Props> = ({
|
|
|
})
|
|
|
return res
|
|
|
})()
|
|
|
+ const { eventEmitter } = useEventEmitterContextContext()
|
|
|
+ const [showRerankModal, setShowRerankModal] = useState(false)
|
|
|
+ const [shouldFetchRerankDefaultModel, setShouldFetchRerankDefaultModel] = useState(false)
|
|
|
+ const { notify } = useToastContext()
|
|
|
+ const { data: rerankDefaultModel } = useSWR(shouldFetchRerankDefaultModel ? '/workspaces/current/default-model?model_type=reranking' : null, fetchDefaultModal)
|
|
|
+ const handleOpenRerankModal = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
|
+ e.stopPropagation()
|
|
|
+ setShowRerankModal(true)
|
|
|
+ }
|
|
|
+ const handleRerankModalSave = async (originValue?: FormValue) => {
|
|
|
+ if (originValue) {
|
|
|
+ try {
|
|
|
+ eventEmitter?.emit('provider-save')
|
|
|
+ const res = await setModelProvider({
|
|
|
+ url: `/workspaces/current/model-providers/${cohereConfig.modal.key}`,
|
|
|
+ body: {
|
|
|
+ config: originValue,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ if (res.result === 'success') {
|
|
|
+ notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
|
|
+ updateModelList(ModelType.reranking)
|
|
|
+ setShowRerankModal(false)
|
|
|
+ setShouldFetchRerankDefaultModel(true)
|
|
|
+ if (onUpdate)
|
|
|
+ onUpdate()
|
|
|
+ }
|
|
|
+ eventEmitter?.emit('')
|
|
|
+ }
|
|
|
+ catch (e) {
|
|
|
+ eventEmitter?.emit('')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (rerankDefaultModel && whenEmptyGoToSetting)
|
|
|
+ onChange(rerankDefaultModel)
|
|
|
+ }, [rerankDefaultModel])
|
|
|
|
|
|
return (
|
|
|
<div className=''>
|
|
@@ -130,7 +178,7 @@ const ModelSelector: FC<Props> = ({
|
|
|
({ open }) => (
|
|
|
<>
|
|
|
{
|
|
|
- value
|
|
|
+ (value && value.modelName && value.providerName)
|
|
|
? (
|
|
|
<>
|
|
|
<ModelIcon
|
|
@@ -146,9 +194,19 @@ const ModelSelector: FC<Props> = ({
|
|
|
</div>
|
|
|
</>
|
|
|
)
|
|
|
- : (
|
|
|
- <div className='grow text-left text-sm text-gray-800 opacity-60'>{t('common.modelProvider.selectModel')}</div>
|
|
|
- )
|
|
|
+ : whenEmptyGoToSetting
|
|
|
+ ? (
|
|
|
+ <div className='grow flex items-center h-9 justify-between' onClick={handleOpenRerankModal}>
|
|
|
+ <div className='flex items-center text-[13px] font-medium text-primary-500'>
|
|
|
+ <CubeOutline className='mr-1.5 w-4 h-4' />
|
|
|
+ {t('common.modelProvider.selector.rerankTip')}
|
|
|
+ </div>
|
|
|
+ <LinkExternal01 className='w-3 h-3 text-gray-500' />
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ : (
|
|
|
+ <div className='grow text-left text-sm text-gray-800 opacity-60'>{t('common.modelProvider.selectModel')}</div>
|
|
|
+ )
|
|
|
}
|
|
|
{
|
|
|
hasRemoved && (
|
|
@@ -162,7 +220,16 @@ const ModelSelector: FC<Props> = ({
|
|
|
</Tooltip>
|
|
|
)
|
|
|
}
|
|
|
- {!readonly && <ChevronDown className={`w-4 h-4 text-gray-700 ${open ? 'opacity-100' : 'opacity-60'}`} />}
|
|
|
+ {
|
|
|
+ !readonly && !whenEmptyGoToSetting && (
|
|
|
+ <ChevronDown className={`w-4 h-4 text-gray-700 ${open ? 'opacity-100' : 'opacity-60'}`} />
|
|
|
+ )
|
|
|
+ }
|
|
|
+ {
|
|
|
+ whenEmptyGoToSetting && (value && value.modelName && value.providerName) && (
|
|
|
+ <ChevronDown className={`w-4 h-4 text-gray-700 ${open ? 'opacity-100' : 'opacity-60'}`} />
|
|
|
+ )
|
|
|
+ }
|
|
|
</>
|
|
|
)
|
|
|
}
|
|
@@ -246,21 +313,6 @@ const ModelSelector: FC<Props> = ({
|
|
|
return null
|
|
|
})
|
|
|
}
|
|
|
- {
|
|
|
- whenEmptyGoToSetting && modelList.length === 0 && (
|
|
|
- <div className='pt-6'>
|
|
|
- <div className='flex items-center justify-center mx-auto mb-2 w-12 h-12 rounded-[10px] border border-[#EAECF5]'>
|
|
|
- <CubeOutline className='w-6 h-6 text-gray-500' />
|
|
|
- </div>
|
|
|
- <div className='mb-1 text-center text-[13px] font-medium text-gray-500'>
|
|
|
- {t('common.modelProvider.selector.emptyTip')}
|
|
|
- </div>
|
|
|
- <div className='mb-6 text-center text-xs text-primary-500'>
|
|
|
- <span onClick={() => setShowAccountSettingModal({ payload: 'provider' })}>{t('common.modelProvider.selector.emptySetting')}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- )
|
|
|
- }
|
|
|
{modelList.length !== 0 && (search && filteredModelList.length === 0) && (
|
|
|
<div className='px-3 pt-1.5 h-[30px] text-center text-xs text-gray-500'>{t('common.modelProvider.noModelFound', { model: search })}</div>
|
|
|
)}
|
|
@@ -281,6 +333,13 @@ const ModelSelector: FC<Props> = ({
|
|
|
</Transition>
|
|
|
)}
|
|
|
</Popover>
|
|
|
+ <ModelModal
|
|
|
+ isShow={showRerankModal}
|
|
|
+ modelModal={cohereConfig.modal}
|
|
|
+ onCancel={() => setShowRerankModal(false)}
|
|
|
+ onSave={handleRerankModalSave}
|
|
|
+ mode={'add'}
|
|
|
+ />
|
|
|
</div>
|
|
|
)
|
|
|
}
|