perf: model provider show; perf: get init data buffer (#3459)

* pr code

* perf: model table show

* perf: model provider show

* perf: get init data buffer

* perf: get init data buffer

* perf: icon
This commit is contained in:
Archer
2024-12-24 15:12:07 +08:00
committed by GitHub
parent f646ef8595
commit 108e1b92ef
59 changed files with 558 additions and 329 deletions

View File

@@ -61,7 +61,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
// System hook
const { data, refetch: refetchUnRead } = useQuery(['getUnreadCount'], getUnreadCount, {
enabled: !!userInfo && !!feConfigs.isPlus,
refetchInterval: 10000
refetchInterval: 30000
});
const unread = data?.unReadCount || 0;
const importantInforms = data?.importantInforms || [];

View File

@@ -83,9 +83,10 @@ const Navbar = ({ unread }: { unread: number }) => {
'/account/team',
'/account/usage',
'/account/apikey',
'/account/individuation',
'/account/setting',
'/account/inform',
'/account/promotion'
'/account/promotion',
'/account/model'
]
}
],

View File

@@ -55,9 +55,10 @@ const NavbarPhone = ({ unread }: { unread: number }) => {
'/account/team',
'/account/usage',
'/account/apikey',
'/account/individuation',
'/account/setting',
'/account/inform',
'/account/promotion'
'/account/promotion',
'/account/model'
],
unread
}

View File

@@ -12,8 +12,8 @@ import { ModelProviderList } from '@fastgpt/global/core/ai/provider';
import MultipleRowSelect from '@fastgpt/web/components/common/MySelect/MultipleRowSelect';
import { getModelFromList } from '@fastgpt/global/core/ai/model';
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
type Props = SelectProps & {
@@ -103,7 +103,7 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => {
/>
</MyTooltip>
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Box>
);
};
@@ -212,7 +212,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) =>
/>
</MyTooltip>
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Box>
);
};

View File

@@ -33,8 +33,8 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import dynamic from 'next/dynamic';
import InputSlider from '@fastgpt/web/components/common/MySlider/InputSlider';
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
const FlexItemStyles: FlexProps = {
@@ -328,7 +328,7 @@ const AIChatSettingsModal = ({
</Button>
</ModalFooter>
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</MyModal>
);
};

View File

@@ -0,0 +1,251 @@
import {
Box,
Flex,
HStack,
ModalBody,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr
} from '@chakra-ui/react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import React, { useMemo, useRef, useState } from 'react';
import {
ModelProviderList,
ModelProviderIdType,
getModelProvider
} from '@fastgpt/global/core/ai/provider';
import MySelect from '@fastgpt/web/components/common/MySelect';
import { modelTypeList, ModelTypeEnum } from '@fastgpt/global/core/ai/model';
import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTag from '@fastgpt/web/components/common/Tag/index';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
const ModelTable = () => {
const { t } = useTranslation();
const [provider, setProvider] = useState<ModelProviderIdType | ''>('');
const providerList = useRef<{ label: any; value: ModelProviderIdType | '' }[]>([
{ label: t('common:common.All'), value: '' },
...ModelProviderList.map((item) => ({
label: (
<HStack>
<Avatar src={item.avatar} w={'1rem'} />
<Box>{t(item.name as any)}</Box>
</HStack>
),
value: item.id
}))
]);
const [modelType, setModelType] = useState<ModelTypeEnum | ''>('');
const selectModelTypeList = useRef<{ label: string; value: ModelTypeEnum | '' }[]>([
{ label: t('common:common.All'), value: '' },
...modelTypeList.map((item) => ({ label: t(item.label), value: item.value }))
]);
const [search, setSearch] = useState('');
const { llmModelList, audioSpeechModelList, vectorModelList, whisperModel } = useSystemStore();
const modelList = useMemo(() => {
const formatLLMModelList = llmModelList.map((item) => ({
...item,
typeLabel: t('common:model.type.chat'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
</Box>
{`${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
),
tagColor: 'blue'
}));
const formatVectorModelList = vectorModelList.map((item) => ({
...item,
typeLabel: t('common:model.type.embedding'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K Tokens`}
</Flex>
),
tagColor: 'yellow'
}));
const formatAudioSpeechModelList = audioSpeechModelList.map((item) => ({
...item,
typeLabel: t('common:model.type.tts'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{item.charsPointsPrice}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 1K ${t('common:unit.character')}`}
</Flex>
),
tagColor: 'green'
}));
const formatWhisperModel = {
...whisperModel,
typeLabel: t('common:model.type.stt'),
priceLabel: (
<Flex color={'myGray.700'}>
<Box fontWeight={'bold'} color={'myGray.900'} mr={0.5}>
{whisperModel.charsPointsPrice}
</Box>
{` ${t('common:support.wallet.subscription.point')} / 60${t('common:unit.seconds')}`}
</Flex>
),
tagColor: 'purple'
};
const list = (() => {
if (modelType === ModelTypeEnum.chat) return formatLLMModelList;
if (modelType === ModelTypeEnum.embedding) return formatVectorModelList;
if (modelType === ModelTypeEnum.tts) return formatAudioSpeechModelList;
if (modelType === ModelTypeEnum.stt) return [formatWhisperModel];
return [
...formatLLMModelList,
...formatVectorModelList,
...formatAudioSpeechModelList,
formatWhisperModel
];
})();
const formatList = list.map((item) => {
const provider = getModelProvider(item.provider);
return {
name: item.name,
avatar: provider.avatar,
providerId: provider.id,
providerName: t(provider.name as any),
typeLabel: item.typeLabel,
priceLabel: item.priceLabel,
order: provider.order,
tagColor: item.tagColor
};
});
formatList.sort((a, b) => a.order - b.order);
const filterList = formatList.filter((item) => {
const providerFilter = provider ? item.providerId === provider : true;
const regx = new RegExp(search, 'i');
const nameFilter = search ? regx.test(item.name) : true;
return providerFilter && nameFilter;
});
return filterList;
}, [
provider,
modelType,
llmModelList,
vectorModelList,
audioSpeechModelList,
whisperModel,
t,
search
]);
return (
<Flex flexDirection={'column'} h={'100%'}>
<Flex>
<HStack flexShrink={0}>
<Box fontSize={'sm'} color={'myGray.900'}>
{t('common:model.provider')}
</Box>
<MySelect
w={'200px'}
bg={'myGray.50'}
value={provider}
onchange={setProvider}
list={providerList.current}
/>
</HStack>
<HStack flexShrink={0} ml={6}>
<Box fontSize={'sm'} color={'myGray.900'}>
{t('common:model.model_type')}
</Box>
<MySelect
w={'150px'}
bg={'myGray.50'}
value={modelType}
onchange={setModelType}
list={selectModelTypeList.current}
/>
</HStack>
<Box flex={1} />
<Box flex={'0 0 250px'}>
<SearchInput
bg={'myGray.50'}
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder={t('common:model.search_name_placeholder')}
/>
</Box>
</Flex>
<TableContainer mt={5} flex={'1 0 0'} h={0} overflowY={'auto'}>
<Table>
<Thead>
<Tr color={'myGray.600'}>
<Th fontSize={'xs'}>{t('common:model.name')}</Th>
<Th fontSize={'xs'}>{t('common:model.model_type')}</Th>
<Th fontSize={'xs'}>{t('common:model.billing')}</Th>
</Tr>
</Thead>
<Tbody>
{modelList.map((item) => (
<Tr key={item.name} _hover={{ bg: 'myGray.50' }}>
<Td fontSize={'sm'}>
<MyTooltip title={item.providerName}>
<HStack>
<Avatar src={item.avatar} w={'1.2rem'} />
<Box color={'myGray.900'}>{item.name}</Box>
</HStack>
</MyTooltip>
</Td>
<Td>
<MyTag colorSchema={item.tagColor as any}>{item.typeLabel}</MyTag>
</Td>
<Td fontSize={'sm'}>{item.priceLabel}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</Flex>
);
};
export default ModelTable;
export const ModelPriceModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation();
return (
<MyModal
isCentered
iconSrc="/imgs/modal/bill.svg"
title={t('common:support.wallet.subscription.Ai points')}
isOpen
onClose={onClose}
w={'100%'}
h={'100%'}
maxW={'90vw'}
maxH={'90vh'}
>
<ModalBody flex={'1 0 0'}>
<ModelTable />
</ModalBody>
</MyModal>
);
};

View File

@@ -8,8 +8,8 @@ import { useTranslation } from 'next-i18next';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import dynamic from 'next/dynamic';
const AiPointsModal = dynamic(() =>
import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal)
const ModelPriceModal = dynamic(() =>
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
);
const StandardPlanContentList = ({
@@ -127,7 +127,7 @@ const StandardPlanContentList = ({
<Box color={'myGray.600'}>{t('common:support.wallet.subscription.web_site_sync')}</Box>
</Flex>
)}
{isOpenAiPointsModal && <AiPointsModal onClose={onCloseAiPointsModal} />}
{isOpenAiPointsModal && <ModelPriceModal onClose={onCloseAiPointsModal} />}
</Grid>
) : null;
};