mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-02-02 00:25:06 +08:00
Refactor(setting-model): Refactor the model management interface and optimize the component structure. #10703 (#10905)
### What problem does this PR solve? Refactor(setting-model): Refactor the model management interface and optimize the component structure. #10703 ### Type of change - [x] Refactoring
This commit is contained in:
@ -1,47 +1,16 @@
|
||||
import { ReactComponent as MoreModelIcon } from '@/assets/svg/more-model.svg';
|
||||
import { LlmIcon } from '@/components/svg-icon';
|
||||
import { useTheme } from '@/components/theme-provider';
|
||||
import { LLMFactory } from '@/constants/llm';
|
||||
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
||||
import {
|
||||
LlmItem,
|
||||
useFetchMyLlmListDetailed,
|
||||
useSelectLlmList,
|
||||
} from '@/hooks/llm-hooks';
|
||||
import { getRealModelName } from '@/utils/llm-util';
|
||||
import {
|
||||
CloseCircleOutlined,
|
||||
EditOutlined,
|
||||
SettingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Collapse,
|
||||
CollapseProps,
|
||||
Divider,
|
||||
Flex,
|
||||
List,
|
||||
Row,
|
||||
Space,
|
||||
Spin,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { CircleHelp } from 'lucide-react';
|
||||
import { LlmItem, useFetchMyLlmListDetailed } from '@/hooks/llm-hooks';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import SettingTitle from '../components/setting-title';
|
||||
import { isLocalLlmFactory } from '../utils';
|
||||
import ApiKeyModal from './api-key-modal';
|
||||
import AzureOpenAIModal from './azure-openai-modal';
|
||||
import BedrockModal from './bedrock-modal';
|
||||
import SystemSetting from './components/system-setting';
|
||||
import { AvailableModels } from './components/un-add-model';
|
||||
import { UsedModel } from './components/used-model';
|
||||
import FishAudioModal from './fish-audio-modal';
|
||||
import GoogleModal from './google-modal';
|
||||
import {
|
||||
useHandleDeleteFactory,
|
||||
useHandleDeleteLlm,
|
||||
useSubmitApiKey,
|
||||
useSubmitAzure,
|
||||
useSubmitBedrock,
|
||||
@ -56,164 +25,15 @@ import {
|
||||
useSubmityiyan,
|
||||
} from './hooks';
|
||||
import HunyuanModal from './hunyuan-modal';
|
||||
import styles from './index.less';
|
||||
import TencentCloudModal from './next-tencent-modal';
|
||||
import OllamaModal from './ollama-modal';
|
||||
import SparkModal from './spark-modal';
|
||||
import SystemModelSettingModal from './system-model-setting-modal';
|
||||
import VolcEngineModal from './volcengine-modal';
|
||||
import YiyanModal from './yiyan-modal';
|
||||
|
||||
const { Text } = Typography;
|
||||
interface IModelCardProps {
|
||||
item: LlmItem;
|
||||
clickApiKey: (llmFactory: string) => void;
|
||||
handleEditModel: (model: any, factory: LlmItem) => void;
|
||||
}
|
||||
|
||||
type TagType =
|
||||
| 'LLM'
|
||||
| 'TEXT EMBEDDING'
|
||||
| 'TEXT RE-RANK'
|
||||
| 'TTS'
|
||||
| 'SPEECH2TEXT'
|
||||
| 'IMAGE2TEXT'
|
||||
| 'MODERATION';
|
||||
|
||||
const sortTags = (tags: string) => {
|
||||
const orderMap: Record<TagType, number> = {
|
||||
LLM: 1,
|
||||
'TEXT EMBEDDING': 2,
|
||||
'TEXT RE-RANK': 3,
|
||||
TTS: 4,
|
||||
SPEECH2TEXT: 5,
|
||||
IMAGE2TEXT: 6,
|
||||
MODERATION: 7,
|
||||
};
|
||||
|
||||
return tags
|
||||
.split(',')
|
||||
.map((tag) => tag.trim())
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(orderMap[a as TagType] || 999) - (orderMap[b as TagType] || 999),
|
||||
);
|
||||
};
|
||||
|
||||
const ModelCard = ({ item, clickApiKey, handleEditModel }: IModelCardProps) => {
|
||||
const { visible, switchVisible } = useSetModalState();
|
||||
const { t } = useTranslate('setting');
|
||||
const { theme } = useTheme();
|
||||
const { handleDeleteLlm } = useHandleDeleteLlm(item.name);
|
||||
const { handleDeleteFactory } = useHandleDeleteFactory(item.name);
|
||||
|
||||
const handleApiKeyClick = () => {
|
||||
clickApiKey(item.name);
|
||||
};
|
||||
|
||||
const handleShowMoreClick = () => {
|
||||
switchVisible();
|
||||
};
|
||||
|
||||
return (
|
||||
<List.Item>
|
||||
<Card
|
||||
className={theme === 'dark' ? styles.addedCardDark : styles.addedCard}
|
||||
>
|
||||
<Row align={'middle'}>
|
||||
<Col span={12}>
|
||||
<Flex gap={'middle'} align="center">
|
||||
<LlmIcon name={item.name} />
|
||||
<Flex vertical gap={'small'}>
|
||||
<b>{item.name}</b>
|
||||
<Flex wrap="wrap">
|
||||
{sortTags(item.tags).map((tag, index) => (
|
||||
<Tag
|
||||
key={index}
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
margin: '1px',
|
||||
paddingInline: '4px',
|
||||
}}
|
||||
>
|
||||
{tag}
|
||||
</Tag>
|
||||
))}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Col>
|
||||
<Col span={12} className={styles.factoryOperationWrapper}>
|
||||
<Space size={'middle'}>
|
||||
<Button onClick={handleApiKeyClick}>
|
||||
<Flex align="center" gap={4}>
|
||||
{isLocalLlmFactory(item.name) ||
|
||||
item.name === LLMFactory.VolcEngine ||
|
||||
item.name === LLMFactory.TencentHunYuan ||
|
||||
item.name === LLMFactory.XunFeiSpark ||
|
||||
item.name === LLMFactory.BaiduYiYan ||
|
||||
item.name === LLMFactory.FishAudio ||
|
||||
item.name === LLMFactory.TencentCloud ||
|
||||
item.name === LLMFactory.GoogleCloud ||
|
||||
item.name === LLMFactory.AzureOpenAI
|
||||
? t('addTheModel')
|
||||
: 'API-Key'}
|
||||
<SettingOutlined />
|
||||
</Flex>
|
||||
</Button>
|
||||
<Button onClick={handleShowMoreClick}>
|
||||
<Flex align="center" gap={4}>
|
||||
{visible ? t('hideModels') : t('showMoreModels')}
|
||||
<MoreModelIcon />
|
||||
</Flex>
|
||||
</Button>
|
||||
<Button type={'text'} onClick={handleDeleteFactory}>
|
||||
<Flex align="center">
|
||||
<CloseCircleOutlined style={{ color: '#D92D20' }} />
|
||||
</Flex>
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
{visible && (
|
||||
<List
|
||||
size="small"
|
||||
dataSource={item.llm}
|
||||
className={styles.llmList}
|
||||
renderItem={(model) => (
|
||||
<List.Item>
|
||||
<Space>
|
||||
{getRealModelName(model.name)}
|
||||
<Tag color="#b8b8b8">{model.type}</Tag>
|
||||
{isLocalLlmFactory(item.name) && (
|
||||
<Tooltip title={t('edit', { keyPrefix: 'common' })}>
|
||||
<Button
|
||||
type={'text'}
|
||||
onClick={() => handleEditModel(model, item)}
|
||||
>
|
||||
<EditOutlined style={{ color: '#1890ff' }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('delete', { keyPrefix: 'common' })}>
|
||||
<Button type={'text'} onClick={handleDeleteLlm(model.name)}>
|
||||
<CloseCircleOutlined style={{ color: '#D92D20' }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
</List.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const UserSettingModel = () => {
|
||||
const { factoryList, myLlmList: llmList, loading } = useSelectLlmList();
|
||||
const ModelProviders = () => {
|
||||
const { saveSystemModelSettingLoading, onSystemSettingSavingOk } =
|
||||
useSubmitSystemModelSetting();
|
||||
const { data: detailedLlmList } = useFetchMyLlmListDetailed();
|
||||
const { theme } = useTheme();
|
||||
const {
|
||||
saveApiKeyLoading,
|
||||
initialApiKey,
|
||||
@ -224,14 +44,6 @@ const UserSettingModel = () => {
|
||||
hideApiKeyModal,
|
||||
showApiKeyModal,
|
||||
} = useSubmitApiKey();
|
||||
const {
|
||||
saveSystemModelSettingLoading,
|
||||
onSystemSettingSavingOk,
|
||||
systemSettingVisible,
|
||||
hideSystemSettingModal,
|
||||
showSystemSettingModal,
|
||||
} = useSubmitSystemModelSetting();
|
||||
const { t } = useTranslate('setting');
|
||||
const {
|
||||
llmAddingVisible,
|
||||
hideLlmAddingModal,
|
||||
@ -342,6 +154,7 @@ const UserSettingModel = () => {
|
||||
|
||||
const handleAddModel = useCallback(
|
||||
(llmFactory: string) => {
|
||||
console.log('handleAddModel', llmFactory);
|
||||
if (isLocalLlmFactory(llmFactory)) {
|
||||
showLlmAddingModal(llmFactory);
|
||||
} else if (llmFactory in ModalMap) {
|
||||
@ -378,116 +191,21 @@ const UserSettingModel = () => {
|
||||
},
|
||||
[showApiKeyModal, showLlmAddingModal, ModalMap, detailedLlmList],
|
||||
);
|
||||
|
||||
const items: CollapseProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
label: t('addedModels'),
|
||||
children: (
|
||||
<List
|
||||
grid={{ gutter: 16, column: 1 }}
|
||||
dataSource={llmList}
|
||||
renderItem={(item) => (
|
||||
<ModelCard
|
||||
item={item}
|
||||
clickApiKey={handleAddModel}
|
||||
handleEditModel={handleEditModel}
|
||||
></ModelCard>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: (
|
||||
<div className="flex items-center gap-2">
|
||||
{t('modelsToBeAdded')}
|
||||
<Tooltip title={t('modelsToBeAddedTooltip')}>
|
||||
<CircleHelp className="size-4" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
),
|
||||
children: (
|
||||
<List
|
||||
grid={{
|
||||
gutter: {
|
||||
xs: 8,
|
||||
sm: 10,
|
||||
md: 12,
|
||||
lg: 16,
|
||||
xl: 20,
|
||||
xxl: 24,
|
||||
},
|
||||
xs: 1,
|
||||
sm: 1,
|
||||
md: 2,
|
||||
lg: 3,
|
||||
xl: 4,
|
||||
xxl: 8,
|
||||
}}
|
||||
dataSource={factoryList}
|
||||
renderItem={(item) => (
|
||||
<List.Item>
|
||||
<Card
|
||||
className={
|
||||
theme === 'dark'
|
||||
? styles.toBeAddedCardDark
|
||||
: styles.toBeAddedCard
|
||||
}
|
||||
>
|
||||
<Flex vertical gap={'middle'}>
|
||||
<LlmIcon name={item.name} imgClass="h-12 w-auto" />
|
||||
<Flex vertical gap={'middle'}>
|
||||
<b>
|
||||
<Text ellipsis={{ tooltip: item.name }}>{item.name}</Text>
|
||||
</b>
|
||||
<Flex wrap="wrap" style={{ minHeight: '50px' }}>
|
||||
{sortTags(item.tags).map((tag, index) => (
|
||||
<Tag
|
||||
key={index}
|
||||
style={{
|
||||
fontSize: '8px',
|
||||
margin: '1px',
|
||||
paddingInline: '4px',
|
||||
height: '22px',
|
||||
}}
|
||||
>
|
||||
{tag}
|
||||
</Tag>
|
||||
))}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Divider className={styles.modelDivider}></Divider>
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleAddModel(item.name)}
|
||||
className={styles.addButton}
|
||||
>
|
||||
{t('addTheModel')}
|
||||
</Button>
|
||||
</Card>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="xx" className="w-full space-y-6">
|
||||
<Spin spinning={loading}>
|
||||
<section className={styles.modelContainer}>
|
||||
<SettingTitle
|
||||
title={t('model')}
|
||||
description={t('modelDescription')}
|
||||
showRightButton
|
||||
clickButton={showSystemSettingModal}
|
||||
></SettingTitle>
|
||||
<Divider></Divider>
|
||||
<Collapse defaultActiveKey={['1', '2']} ghost items={items} />
|
||||
</section>
|
||||
</Spin>
|
||||
<div className="flex w-full">
|
||||
<section className="flex flex-col gap-4 w-3/5 px-5 border-r border-border-button overflow-auto scrollbar-auto">
|
||||
<SystemSetting
|
||||
onOk={onSystemSettingSavingOk}
|
||||
loading={saveSystemModelSettingLoading}
|
||||
/>
|
||||
<UsedModel
|
||||
handleAddModel={handleAddModel}
|
||||
handleEditModel={handleEditModel}
|
||||
/>
|
||||
</section>
|
||||
<section className="flex flex-col w-2/5 overflow-auto scrollbar-auto">
|
||||
<AvailableModels handleAddModel={handleAddModel} />
|
||||
</section>
|
||||
<ApiKeyModal
|
||||
visible={apiKeyVisible}
|
||||
hideModal={hideApiKeyModal}
|
||||
@ -497,14 +215,6 @@ const UserSettingModel = () => {
|
||||
onOk={onApiKeySavingOk}
|
||||
llmFactory={llmFactory}
|
||||
></ApiKeyModal>
|
||||
{systemSettingVisible && (
|
||||
<SystemModelSettingModal
|
||||
visible={systemSettingVisible}
|
||||
onOk={onSystemSettingSavingOk}
|
||||
hideModal={hideSystemSettingModal}
|
||||
loading={saveSystemModelSettingLoading}
|
||||
></SystemModelSettingModal>
|
||||
)}
|
||||
<OllamaModal
|
||||
visible={llmAddingVisible}
|
||||
hideModal={hideLlmAddingModal}
|
||||
@ -577,8 +287,7 @@ const UserSettingModel = () => {
|
||||
loading={AzureAddingLoading}
|
||||
llmFactory={LLMFactory.AzureOpenAI}
|
||||
></AzureOpenAIModal>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserSettingModel;
|
||||
export default ModelProviders;
|
||||
|
||||
Reference in New Issue
Block a user