feat(settings): refactor LLM model management UI and components
This commit is contained in:
@@ -1 +1 @@
|
|||||||
<svg id="_层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274.37 172.76"><defs><style>.cls-2{fill:#36cfd1}.cls-3{fill:#624aff}</style></defs><g id="_层_1-2"><path class="cls-3" d="M24.78 73.55h25.65V99.2H24.78zm99.14 25.66h25.65v25.65h-25.65zm76.95 25.65h-25.65v22.19h47.84V99.21h-22.19v25.65z"/><path class="cls-2" d="M149.57 73.55h25.65V99.2h-25.65zM24.78 47.9h25.65v25.65H24.78z"/><path class="cls-3" d="M223.06 73.55h25.65V99.2h-25.65z"/><path class="cls-2" d="M223.06 47.9h25.65v25.65h-25.65z"/><path class="cls-3" d="M175.22 25.71V47.9h25.65v25.65h22.19V25.71h-47.84z"/><path class="cls-2" d="M98.27 73.55h25.65V99.2H98.27z"/><path class="cls-3" d="M72.62 47.9h25.65V25.71H50.43v47.84h22.19V47.9zm0 51.31H50.43v47.84h47.84v-22.19H72.62V99.21z"/><path style="fill:none" d="M0 0h274.37v172.76H0z"/></g></svg>
|
<svg id="layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274.37 172.76"><defs><style>.cls-2{fill:#36cfd1}.cls-3{fill:#624aff}</style></defs><g id="layer_1-2"><path class="cls-3" d="M24.78 73.55h25.65V99.2H24.78zm99.14 25.66h25.65v25.65h-25.65zm76.95 25.65h-25.65v22.19h47.84V99.21h-22.19v25.65z"/><path class="cls-2" d="M149.57 73.55h25.65V99.2h-25.65zM24.78 47.9h25.65v25.65H24.78z"/><path class="cls-3" d="M223.06 73.55h25.65V99.2h-25.65z"/><path class="cls-2" d="M223.06 47.9h25.65v25.65h-25.65z"/><path class="cls-3" d="M175.22 25.71V47.9h25.65v25.65h22.19V25.71h-47.84z"/><path class="cls-2" d="M98.27 73.55h25.65V99.2H98.27z"/><path class="cls-3" d="M72.62 47.9h25.65V25.71H50.43v47.84h22.19V47.9zm0 51.31H50.43v47.84h47.84v-22.19H72.62V99.21z"/><path style="fill:none" d="M0 0h274.37v172.76H0z"/></g></svg>
|
||||||
|
Before Width: | Height: | Size: 821 B After Width: | Height: | Size: 822 B |
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg id="_图层_2" data-name="图层 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 111.08 53.12">
|
<svg id="layer_2" data-name="layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 111.08 53.12">
|
||||||
<defs>
|
<defs>
|
||||||
<style>
|
<style>
|
||||||
.cls-1 {
|
.cls-1 {
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</defs>
|
</defs>
|
||||||
<g id="_图层_1-2" data-name="图层 1">
|
<g id="layer_1-2" data-name="layer 1">
|
||||||
<path class="cls-1" d="M106.25,0h-48.3c-2.67,0-4.83,2.16-4.83,4.83v14.49c0,2.67-2.16,4.83-4.83,4.83H4.83c-2.67,0-4.83,2.16-4.83,4.83v19.32c0,2.67,2.16,4.83,4.83,4.83h48.3c2.67,0,4.83-2.16,4.83-4.83v-14.49c0-2.67,2.16-4.83,4.83-4.83h43.47c2.67,0,4.83-2.16,4.83-4.83V4.83c0-2.67-2.16-4.83-4.83-4.83Z"/>
|
<path class="cls-1" d="M106.25,0h-48.3c-2.67,0-4.83,2.16-4.83,4.83v14.49c0,2.67-2.16,4.83-4.83,4.83H4.83c-2.67,0-4.83,2.16-4.83,4.83v19.32c0,2.67,2.16,4.83,4.83,4.83h48.3c2.67,0,4.83-2.16,4.83-4.83v-14.49c0-2.67,2.16-4.83,4.83-4.83h43.47c2.67,0,4.83-2.16,4.83-4.83V4.83c0-2.67-2.16-4.83-4.83-4.83Z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 595 B After Width: | Height: | Size: 589 B |
@@ -1,28 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
<svg id="layer_1" data-name="layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 283.46 283.46">
|
viewBox="0 0 283.46 283.46">
|
||||||
<defs>
|
<defs>
|
||||||
<style>
|
<style>
|
||||||
.cls-1 {
|
.cls-1 {
|
||||||
fill: url(#_未命名的渐变_5-2);
|
fill: url(#gradient_5-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cls-2 {
|
.cls-2 {
|
||||||
fill: url(#_未命名的渐变_9);
|
fill: url(#gradient_9);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cls-3 {
|
.cls-3 {
|
||||||
fill: url(#_未命名的渐变_5);
|
fill: url(#gradient_5);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<linearGradient id="_未命名的渐变_5" data-name="未命名的渐变 5" x1="27.03" y1="287.05" x2="253.15" y2="1.14"
|
<linearGradient id="gradient_5" data-name="gradient 5" x1="27.03" y1="287.05" x2="253.15" y2="1.14"
|
||||||
gradientUnits="userSpaceOnUse">
|
gradientUnits="userSpaceOnUse">
|
||||||
<stop offset="0" stop-color="#e9a85e" />
|
<stop offset="0" stop-color="#e9a85e" />
|
||||||
<stop offset="1" stop-color="#f52b76" />
|
<stop offset="1" stop-color="#f52b76" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<linearGradient id="_未命名的渐变_5-2" data-name="未命名的渐变 5" x1="25.96" y1="286.21" x2="252.09" y2=".3"
|
<linearGradient id="gradient_5-2" data-name="gradient 5" x1="25.96" y1="286.21" x2="252.09" y2=".3"
|
||||||
xlink:href="#_未命名的渐变_5" />
|
xlink:href="#gradient_5" />
|
||||||
<linearGradient id="_未命名的渐变_9" data-name="未命名的渐变 9" x1="-474.33" y1="476.58" x2="-160.37" y2="476.58"
|
<linearGradient id="gradient_9" data-name="gradient 9" x1="-474.33" y1="476.58" x2="-160.37" y2="476.58"
|
||||||
gradientTransform="translate(669.07 -75.9) rotate(33.75)" gradientUnits="userSpaceOnUse">
|
gradientTransform="translate(669.07 -75.9) rotate(33.75)" gradientUnits="userSpaceOnUse">
|
||||||
<stop offset="0" stop-color="#6a0cf5" />
|
<stop offset="0" stop-color="#6a0cf5" />
|
||||||
<stop offset="1" stop-color="#ab66f3" />
|
<stop offset="1" stop-color="#ab66f3" />
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -6,7 +6,7 @@ const svgPath = '/src/assets/svg'
|
|||||||
|
|
||||||
interface AppSvgIconProps extends SvgIconProps {
|
interface AppSvgIconProps extends SvgIconProps {
|
||||||
name: string;
|
name: string;
|
||||||
point: 'llm' | 'chunk' | 'file' | 'default';
|
point?: 'llm' | 'chunk' | 'file' | 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPointPath = (point: AppSvgIconProps['point']) => {
|
const getPointPath = (point: AppSvgIconProps['point']) => {
|
||||||
|
|||||||
@@ -1,12 +1,100 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import {
|
||||||
|
Settings as SettingsIcon,
|
||||||
|
} from '@mui/icons-material'
|
||||||
|
import { LlmSvgIcon } from "@/components/AppSvgIcon";
|
||||||
|
import { IconMap, type LLMFactory } from "@/constants/llm";
|
||||||
|
import type { IFactory } from "@/interfaces/database/llm";
|
||||||
|
import { Box, Button, Card, CardContent, Chip, Typography } from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
function LLMFactoryCard() {
|
// 模型类型标签颜色映射
|
||||||
return (
|
export const MODEL_TYPE_COLORS: Record<string, string> = {
|
||||||
<Box>
|
'LLM': '#1976d2',
|
||||||
<Typography variant="h6" gutterBottom>
|
'TEXT EMBEDDING': '#388e3c',
|
||||||
</Typography>
|
'TEXT RE-RANK': '#f57c00',
|
||||||
</Box>
|
'TTS': '#7b1fa2',
|
||||||
)
|
'SPEECH2TEXT': '#c2185b',
|
||||||
|
'IMAGE2TEXT': '#5d4037',
|
||||||
|
'MODERATION': '#455a64',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 模型工厂卡片组件
|
||||||
|
interface ModelFactoryCardProps {
|
||||||
|
factory: IFactory;
|
||||||
|
onConfigure: (factory: IFactory) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LLMFactoryCard;
|
const LLMFactoryCard: React.FC<ModelFactoryCardProps> = ({
|
||||||
|
factory,
|
||||||
|
onConfigure,
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
// 获取工厂图标名称
|
||||||
|
const getFactoryIconName = (factoryName: LLMFactory) => {
|
||||||
|
return IconMap[factoryName] || 'default';
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card sx={{
|
||||||
|
mb: 2,
|
||||||
|
border: '1px solid #e0e0e0',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column'
|
||||||
|
}}>
|
||||||
|
<CardContent sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
textAlign: 'left',
|
||||||
|
gap: 2,
|
||||||
|
flex: 1,
|
||||||
|
}}>
|
||||||
|
{/* 图标 */}
|
||||||
|
<LlmSvgIcon
|
||||||
|
name={getFactoryIconName(factory.name as LLMFactory)}
|
||||||
|
sx={{ width: 48, height: 48, color: 'primary.main' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 标题 */}
|
||||||
|
<Typography variant="h6" component="div" sx={{ fontWeight: 'bold' }}>
|
||||||
|
{factory.name}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* 标签 */}
|
||||||
|
<Box display="flex" flexWrap="wrap" gap={0.5} justifyContent="left">
|
||||||
|
{factory.model_types.map((type) => (
|
||||||
|
<Chip
|
||||||
|
key={type}
|
||||||
|
label={type.toUpperCase()}
|
||||||
|
size="small"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: MODEL_TYPE_COLORS[type.toUpperCase()] || '#757575',
|
||||||
|
color: 'white',
|
||||||
|
fontSize: '0.65rem',
|
||||||
|
height: '20px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* 配置按钮 */}
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
onClick={() => onConfigure(factory)}
|
||||||
|
sx={{
|
||||||
|
mt: 'auto',
|
||||||
|
color: 'primary.main',
|
||||||
|
alignSelf: 'center',
|
||||||
|
width: 'fit-content'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加模型
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LLMFactoryCard
|
||||||
@@ -9,266 +9,27 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
Collapse,
|
Collapse,
|
||||||
Grid,
|
Grid,
|
||||||
Divider,
|
|
||||||
Dialog,
|
|
||||||
DialogTitle,
|
|
||||||
DialogContent,
|
|
||||||
DialogActions,
|
|
||||||
FormControl,
|
|
||||||
InputLabel,
|
|
||||||
Select,
|
|
||||||
MenuItem,
|
|
||||||
Alert,
|
Alert,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
Accordion,
|
||||||
|
AccordionSummary,
|
||||||
|
AccordionDetails,
|
||||||
|
Divider,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import {
|
import {
|
||||||
ExpandMore as ExpandMoreIcon,
|
ExpandMore as ExpandMoreIcon,
|
||||||
ExpandLess as ExpandLessIcon,
|
ExpandLess as ExpandLessIcon,
|
||||||
Settings as SettingsIcon,
|
|
||||||
Delete as DeleteIcon,
|
|
||||||
Edit as EditIcon,
|
Edit as EditIcon,
|
||||||
Add as AddIcon,
|
Delete as DeleteIcon,
|
||||||
Visibility as VisibilityIcon,
|
|
||||||
VisibilityOff as VisibilityOffIcon,
|
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
import { useLlmModelSetting } from '@/hooks/setting-hooks';
|
import { useLlmModelSetting } from '@/hooks/setting-hooks';
|
||||||
import { useModelDialogs } from './hooks/useModelDialogs';
|
import { useModelDialogs } from './hooks/useModelDialogs';
|
||||||
import { LlmSvgIcon } from '@/components/AppSvgIcon';
|
import AppSvgIcon, { LlmSvgIcon } from '@/components/AppSvgIcon';
|
||||||
import { LLM_FACTORY_LIST, IconMap, type LLMFactory } from '@/constants/llm';
|
import { LLM_FACTORY_LIST, IconMap, type LLMFactory } from '@/constants/llm';
|
||||||
import type { IFactory, IMyLlmModel, ILlmItem } from '@/interfaces/database/llm';
|
import type { IFactory, IMyLlmModel, ILlmItem } from '@/interfaces/database/llm';
|
||||||
|
import LLMFactoryCard, { MODEL_TYPE_COLORS } from './components/LLMFactoryCard';
|
||||||
|
|
||||||
// 模型类型标签颜色映射
|
|
||||||
const MODEL_TYPE_COLORS: Record<string, string> = {
|
|
||||||
'LLM': '#1976d2',
|
|
||||||
'TEXT EMBEDDING': '#388e3c',
|
|
||||||
'TEXT RE-RANK': '#f57c00',
|
|
||||||
'TTS': '#7b1fa2',
|
|
||||||
'SPEECH2TEXT': '#c2185b',
|
|
||||||
'IMAGE2TEXT': '#5d4037',
|
|
||||||
'MODERATION': '#455a64',
|
|
||||||
};
|
|
||||||
|
|
||||||
// 模型工厂卡片组件
|
|
||||||
interface ModelFactoryCardProps {
|
|
||||||
factory: IFactory;
|
|
||||||
myModels: ILlmItem[];
|
|
||||||
onConfigure: (factory: IFactory) => void;
|
|
||||||
onDeleteFactory: (factoryName: string) => void;
|
|
||||||
onDeleteModel: (factoryName: string, modelName: string) => void;
|
|
||||||
onEditModel: (factory: IFactory, model: ILlmItem) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ModelFactoryCard: React.FC<ModelFactoryCardProps> = ({
|
|
||||||
factory,
|
|
||||||
myModels,
|
|
||||||
onConfigure,
|
|
||||||
onDeleteFactory,
|
|
||||||
onDeleteModel,
|
|
||||||
onEditModel,
|
|
||||||
}) => {
|
|
||||||
const [expanded, setExpanded] = useState(false);
|
|
||||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
|
||||||
|
|
||||||
const handleExpandClick = () => {
|
|
||||||
setExpanded(!expanded);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteFactory = () => {
|
|
||||||
onDeleteFactory(factory.name);
|
|
||||||
setShowDeleteConfirm(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取工厂图标名称
|
|
||||||
const getFactoryIconName = (factoryName: LLMFactory) => {
|
|
||||||
return IconMap[factoryName] || 'default';
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Card sx={{ mb: 2, border: '1px solid #e0e0e0' }}>
|
|
||||||
<CardContent>
|
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
|
||||||
<Box display="flex" alignItems="center" gap={2}>
|
|
||||||
<LlmSvgIcon
|
|
||||||
name={getFactoryIconName(factory.name as LLMFactory)}
|
|
||||||
sx={{ width: 40, height: 40, color: 'primary.main' }}/>
|
|
||||||
<Box>
|
|
||||||
<Typography variant="h6" component="div">
|
|
||||||
{factory.name}
|
|
||||||
</Typography>
|
|
||||||
<Box display="flex" gap={1} mt={1}>
|
|
||||||
{factory.model_types.map((type) => (
|
|
||||||
<Chip
|
|
||||||
key={type}
|
|
||||||
label={type.toUpperCase()}
|
|
||||||
size="small"
|
|
||||||
sx={{
|
|
||||||
backgroundColor: MODEL_TYPE_COLORS[type.toUpperCase()] || '#757575',
|
|
||||||
color: 'white',
|
|
||||||
fontSize: '0.7rem',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box display="flex" alignItems="center" gap={1}>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
size="small"
|
|
||||||
startIcon={<SettingsIcon />}
|
|
||||||
onClick={() => onConfigure(factory)}
|
|
||||||
>
|
|
||||||
配置
|
|
||||||
</Button>
|
|
||||||
{myModels.length > 0 && (
|
|
||||||
<IconButton onClick={handleExpandClick}>
|
|
||||||
{expanded ? <ExpandLessIcon /> : <ExpandMoreIcon />}
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
<IconButton
|
|
||||||
color="error"
|
|
||||||
onClick={() => setShowDeleteConfirm(true)}
|
|
||||||
>
|
|
||||||
<DeleteIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Collapse in={expanded} timeout="auto" unmountOnExit>
|
|
||||||
<Divider sx={{ my: 2 }} />
|
|
||||||
<Typography variant="subtitle2" gutterBottom>
|
|
||||||
已配置的模型 ({myModels.length})
|
|
||||||
</Typography>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
{myModels.map((model) => (
|
|
||||||
<Grid size={{ xs: 12, sm: 6, md: 4 }} key={model.name}>
|
|
||||||
<Card variant="outlined" sx={{ p: 2 }}>
|
|
||||||
<Box display="flex" justifyContent="space-between" alignItems="start">
|
|
||||||
<Box>
|
|
||||||
<Typography variant="body2" fontWeight="bold">
|
|
||||||
{model.name}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption" color="text.secondary">
|
|
||||||
{model.type}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption" display="block" color="text.secondary">
|
|
||||||
Max Tokens: {model.max_tokens}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption" display="block" color="text.secondary">
|
|
||||||
Used: {model.used_token}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
onClick={() => onEditModel(factory, model)}
|
|
||||||
>
|
|
||||||
<EditIcon fontSize="small" />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
color="error"
|
|
||||||
onClick={() => onDeleteModel(factory.name, model.name)}
|
|
||||||
>
|
|
||||||
<DeleteIcon fontSize="small" />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Card>
|
|
||||||
</Grid>
|
|
||||||
))}
|
|
||||||
</Grid>
|
|
||||||
</Collapse>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* 删除确认对话框 */}
|
|
||||||
<Dialog open={showDeleteConfirm} onClose={() => setShowDeleteConfirm(false)}>
|
|
||||||
<DialogTitle>确认删除</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
<Typography>
|
|
||||||
确定要删除模型工厂 "{factory.name}" 吗?这将删除该工厂下的所有模型配置。
|
|
||||||
</Typography>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={() => setShowDeleteConfirm(false)}>取消</Button>
|
|
||||||
<Button onClick={handleDeleteFactory} color="error" variant="contained">
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 系统默认模型设置组件
|
|
||||||
interface SystemModelSettingProps {
|
|
||||||
myLlm: Record<string, IMyLlmModel> | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SystemModelSetting: React.FC<SystemModelSettingProps> = ({ myLlm }) => {
|
|
||||||
const [defaultModel, setDefaultModel] = useState('');
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
|
|
||||||
// 获取所有可用的聊天模型
|
|
||||||
const chatModels = myLlm ? Object.values(myLlm).flatMap(group =>
|
|
||||||
group.llm.filter(model => model.type.toLowerCase().includes('chat') || model.type.toLowerCase().includes('llm'))
|
|
||||||
) : [];
|
|
||||||
|
|
||||||
const handleSaveDefaultModel = async () => {
|
|
||||||
if (!defaultModel) return;
|
|
||||||
|
|
||||||
setLoading(true);
|
|
||||||
try {
|
|
||||||
// TODO: 调用设置系统默认模型的 API
|
|
||||||
console.log('Setting default model:', defaultModel);
|
|
||||||
// await userService.setSystemDefaultModel({ model: defaultModel });
|
|
||||||
} catch (error) {
|
|
||||||
console.error('设置默认模型失败:', error);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card sx={{ mb: 3 }}>
|
|
||||||
<CardContent>
|
|
||||||
<Typography variant="h6" gutterBottom>
|
|
||||||
系统默认 LLM 模型
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
|
||||||
设置系统默认使用的大语言模型,用于对话和文本生成任务。
|
|
||||||
</Typography>
|
|
||||||
<Box display="flex" gap={2} alignItems="center" mt={2}>
|
|
||||||
<FormControl sx={{ minWidth: 300 }}>
|
|
||||||
<InputLabel>选择默认模型</InputLabel>
|
|
||||||
<Select
|
|
||||||
value={defaultModel}
|
|
||||||
label="选择默认模型"
|
|
||||||
onChange={(e) => setDefaultModel(e.target.value)}
|
|
||||||
>
|
|
||||||
{chatModels.map((model) => (
|
|
||||||
<MenuItem key={`${model.name}-${model.type}`} value={model.name}>
|
|
||||||
{model.name} ({model.type})
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
onClick={handleSaveDefaultModel}
|
|
||||||
disabled={!defaultModel || loading}
|
|
||||||
startIcon={loading ? <CircularProgress size={16} /> : undefined}
|
|
||||||
>
|
|
||||||
保存设置
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 主页面组件
|
// 主页面组件
|
||||||
function ModelsPage() {
|
function ModelsPage() {
|
||||||
@@ -336,19 +97,20 @@ function ModelsPage() {
|
|||||||
管理您的 LLM 模型工厂和个人模型配置
|
管理您的 LLM 模型工厂和个人模型配置
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/* 系统默认模型设置 */}
|
|
||||||
<SystemModelSetting myLlm={myLlm} />
|
|
||||||
|
|
||||||
{/* My LLM 部分 */}
|
{/* My LLM 部分 */}
|
||||||
{/* <Box mb={4}>
|
<Box mb={4} mt={2}>
|
||||||
<Typography variant="h5" gutterBottom>
|
|
||||||
我的 LLM 模型
|
|
||||||
</Typography>
|
|
||||||
{!myLlm || Object.keys(myLlm).length === 0 ? (
|
{!myLlm || Object.keys(myLlm).length === 0 ? (
|
||||||
<Alert severity="info">
|
<Alert severity="info">
|
||||||
您还没有配置任何 LLM 模型。请在下方的模型工厂中进行配置。
|
您还没有配置任何 LLM 模型。请在下方的模型工厂中进行配置。
|
||||||
</Alert>
|
</Alert>
|
||||||
) : (
|
) : (
|
||||||
|
<Accordion defaultExpanded>
|
||||||
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
|
<Typography variant="h5" gutterBottom>
|
||||||
|
我的 LLM 模型
|
||||||
|
</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{Object.entries(myLlm).map(([factoryName, group]) => (
|
{Object.entries(myLlm).map(([factoryName, group]) => (
|
||||||
<Grid size={12} key={factoryName}>
|
<Grid size={12} key={factoryName}>
|
||||||
@@ -423,29 +185,36 @@ function ModelsPage() {
|
|||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
)}
|
)}
|
||||||
</Box> */}
|
</Box>
|
||||||
|
|
||||||
{/* LLM Factory 部分 */}
|
{/* LLM Factory 部分 */}
|
||||||
<Box>
|
<Box>
|
||||||
|
<Accordion defaultExpanded>
|
||||||
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
<Typography variant="h5" gutterBottom>
|
<Typography variant="h5" gutterBottom>
|
||||||
LLM 模型工厂
|
LLM 模型工厂
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
<AppSvgIcon name='arxiv' />
|
||||||
配置各种 AI 服务提供商的模型
|
</AccordionSummary>
|
||||||
</Typography>
|
<AccordionDetails>
|
||||||
|
<Grid container spacing={2}>
|
||||||
{llmFactory.map((factory) => (
|
{
|
||||||
<ModelFactoryCard
|
llmFactory.map((factory) => (
|
||||||
|
<Grid size={{ xs: 6, sm: 4, md: 3 }} key={factory.name}>
|
||||||
|
<LLMFactoryCard
|
||||||
key={factory.name}
|
key={factory.name}
|
||||||
factory={factory}
|
factory={factory}
|
||||||
myModels={getModelsForFactory(factory.name as LLMFactory)}
|
|
||||||
onConfigure={handleConfigureFactory}
|
onConfigure={handleConfigureFactory}
|
||||||
onDeleteFactory={handleDeleteFactory}
|
|
||||||
onDeleteModel={handleDeleteModel}
|
|
||||||
onEditModel={handleEditModel}
|
|
||||||
/>
|
/>
|
||||||
))}
|
</Grid>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Grid>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* 模型配置对话框 */}
|
{/* 模型配置对话框 */}
|
||||||
|
|||||||
@@ -5,7 +5,15 @@ import svgr from "vite-plugin-svgr";
|
|||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), svgr()],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
svgr({
|
||||||
|
svgrOptions: {
|
||||||
|
icon: true,
|
||||||
|
prettier: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.resolve(__dirname, './src'),
|
'@': path.resolve(__dirname, './src'),
|
||||||
|
|||||||
Reference in New Issue
Block a user