@ -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 >
)
}