feat: implement RAG dashboard with MUI and react-router
Add new RAG dashboard feature including: - Main application layout with header and sidebar - Multiple pages (Home, KnowledgeBase, PipelineConfig, Dashboard, MCP) - Theme configuration and styling - Routing setup with protected routes - Login page and authentication flow - Various UI components and mock data for dashboard views
This commit is contained in:
349
src/pages/PipelineConfig.tsx
Normal file
349
src/pages/PipelineConfig.tsx
Normal file
@@ -0,0 +1,349 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Card,
|
||||
CardContent,
|
||||
Grid,
|
||||
Button,
|
||||
Switch,
|
||||
FormControlLabel,
|
||||
Slider,
|
||||
TextField,
|
||||
Select,
|
||||
MenuItem,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Chip,
|
||||
Divider,
|
||||
Alert,
|
||||
LinearProgress,
|
||||
} from '@mui/material';
|
||||
import {
|
||||
Settings as SettingsIcon,
|
||||
PlayArrow as PlayIcon,
|
||||
Stop as StopIcon,
|
||||
Refresh as RefreshIcon,
|
||||
Save as SaveIcon,
|
||||
} from '@mui/icons-material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
const PageContainer = styled(Box)(({ theme }) => ({
|
||||
padding: '1.5rem',
|
||||
backgroundColor: '#F8F9FA',
|
||||
minHeight: 'calc(100vh - 60px)',
|
||||
}));
|
||||
|
||||
const PageHeader = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: '1.5rem',
|
||||
}));
|
||||
|
||||
const ConfigCard = styled(Card)(({ theme }) => ({
|
||||
marginBottom: '1.5rem',
|
||||
border: '1px solid #E5E5E5',
|
||||
}));
|
||||
|
||||
const ConfigSection = styled(Box)(({ theme }) => ({
|
||||
marginBottom: '1.5rem',
|
||||
'&:last-child': {
|
||||
marginBottom: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
const StatusIndicator = styled(Box)<{ status: 'running' | 'stopped' | 'error' }>(({ status, theme }) => ({
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5rem',
|
||||
padding: '0.25rem 0.75rem',
|
||||
borderRadius: '12px',
|
||||
fontSize: '0.875rem',
|
||||
fontWeight: 500,
|
||||
backgroundColor:
|
||||
status === 'running' ? '#E8F5E8' :
|
||||
status === 'stopped' ? '#F8F9FA' : '#F8D7DA',
|
||||
color:
|
||||
status === 'running' ? '#155724' :
|
||||
status === 'stopped' ? '#666' : '#721C24',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
width: '8px',
|
||||
height: '8px',
|
||||
borderRadius: '50%',
|
||||
backgroundColor:
|
||||
status === 'running' ? '#28A745' :
|
||||
status === 'stopped' ? '#6C757D' : '#DC3545',
|
||||
},
|
||||
}));
|
||||
|
||||
const PipelineConfig: React.FC = () => {
|
||||
const [pipelineStatus, setPipelineStatus] = useState<'running' | 'stopped' | 'error'>('stopped');
|
||||
const [config, setConfig] = useState({
|
||||
enabled: false,
|
||||
chunkSize: 512,
|
||||
chunkOverlap: 50,
|
||||
embeddingModel: 'text-embedding-ada-002',
|
||||
retrievalTopK: 5,
|
||||
temperature: 0.7,
|
||||
maxTokens: 2048,
|
||||
systemPrompt: '你是一个专业的AI助手,请基于提供的知识库内容回答用户问题。',
|
||||
});
|
||||
|
||||
const handleConfigChange = (key: string, value: any) => {
|
||||
setConfig(prev => ({ ...prev, [key]: value }));
|
||||
};
|
||||
|
||||
const handleStartPipeline = () => {
|
||||
setPipelineStatus('running');
|
||||
};
|
||||
|
||||
const handleStopPipeline = () => {
|
||||
setPipelineStatus('stopped');
|
||||
};
|
||||
|
||||
const handleSaveConfig = () => {
|
||||
// 保存配置逻辑
|
||||
console.log('保存配置:', config);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageHeader>
|
||||
<Box>
|
||||
<Typography variant="h4" fontWeight={600} color="#333">
|
||||
RAG Pipeline 配置
|
||||
</Typography>
|
||||
<Box display="flex" alignItems="center" gap={2} mt={1}>
|
||||
<StatusIndicator status={pipelineStatus}>
|
||||
{pipelineStatus === 'running' ? '运行中' :
|
||||
pipelineStatus === 'stopped' ? '已停止' : '错误'}
|
||||
</StatusIndicator>
|
||||
{pipelineStatus === 'running' && (
|
||||
<LinearProgress sx={{ width: '200px', height: '6px', borderRadius: '3px' }} />
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box display="flex" gap={1}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<SaveIcon />}
|
||||
onClick={handleSaveConfig}
|
||||
>
|
||||
保存配置
|
||||
</Button>
|
||||
{pipelineStatus === 'running' ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
startIcon={<StopIcon />}
|
||||
onClick={handleStopPipeline}
|
||||
>
|
||||
停止
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="contained"
|
||||
startIcon={<PlayIcon />}
|
||||
onClick={handleStartPipeline}
|
||||
>
|
||||
启动
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</PageHeader>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<ConfigCard>
|
||||
<CardContent>
|
||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||
<SettingsIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||
基础配置
|
||||
</Typography>
|
||||
|
||||
<ConfigSection>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={config.enabled}
|
||||
onChange={(e) => handleConfigChange('enabled', e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="启用 RAG Pipeline"
|
||||
/>
|
||||
</ConfigSection>
|
||||
|
||||
<ConfigSection>
|
||||
<Typography gutterBottom>文档分块大小</Typography>
|
||||
<Slider
|
||||
value={config.chunkSize}
|
||||
onChange={(_, value) => handleConfigChange('chunkSize', value)}
|
||||
min={128}
|
||||
max={2048}
|
||||
step={64}
|
||||
marks={[
|
||||
{ value: 128, label: '128' },
|
||||
{ value: 512, label: '512' },
|
||||
{ value: 1024, label: '1024' },
|
||||
{ value: 2048, label: '2048' },
|
||||
]}
|
||||
valueLabelDisplay="on"
|
||||
/>
|
||||
</ConfigSection>
|
||||
|
||||
<ConfigSection>
|
||||
<Typography gutterBottom>分块重叠 (%)</Typography>
|
||||
<Slider
|
||||
value={config.chunkOverlap}
|
||||
onChange={(_, value) => handleConfigChange('chunkOverlap', value)}
|
||||
min={0}
|
||||
max={50}
|
||||
step={5}
|
||||
valueLabelDisplay="on"
|
||||
/>
|
||||
</ConfigSection>
|
||||
|
||||
<ConfigSection>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>嵌入模型</InputLabel>
|
||||
<Select
|
||||
value={config.embeddingModel}
|
||||
onChange={(e) => handleConfigChange('embeddingModel', e.target.value)}
|
||||
label="嵌入模型"
|
||||
>
|
||||
<MenuItem value="text-embedding-ada-002">text-embedding-ada-002</MenuItem>
|
||||
<MenuItem value="text-embedding-3-small">text-embedding-3-small</MenuItem>
|
||||
<MenuItem value="text-embedding-3-large">text-embedding-3-large</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</ConfigSection>
|
||||
</CardContent>
|
||||
</ConfigCard>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} md={6}>
|
||||
<ConfigCard>
|
||||
<CardContent>
|
||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||
检索与生成配置
|
||||
</Typography>
|
||||
|
||||
<ConfigSection>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="检索文档数量 (Top-K)"
|
||||
type="number"
|
||||
value={config.retrievalTopK}
|
||||
onChange={(e) => handleConfigChange('retrievalTopK', parseInt(e.target.value))}
|
||||
inputProps={{ min: 1, max: 20 }}
|
||||
/>
|
||||
</ConfigSection>
|
||||
|
||||
<ConfigSection>
|
||||
<Typography gutterBottom>生成温度</Typography>
|
||||
<Slider
|
||||
value={config.temperature}
|
||||
onChange={(_, value) => handleConfigChange('temperature', value)}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
marks={[
|
||||
{ value: 0, label: '0' },
|
||||
{ value: 0.5, label: '0.5' },
|
||||
{ value: 1, label: '1' },
|
||||
]}
|
||||
valueLabelDisplay="on"
|
||||
/>
|
||||
</ConfigSection>
|
||||
|
||||
<ConfigSection>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="最大输出Token数"
|
||||
type="number"
|
||||
value={config.maxTokens}
|
||||
onChange={(e) => handleConfigChange('maxTokens', parseInt(e.target.value))}
|
||||
inputProps={{ min: 256, max: 4096 }}
|
||||
/>
|
||||
</ConfigSection>
|
||||
|
||||
<ConfigSection>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="系统提示词"
|
||||
multiline
|
||||
rows={4}
|
||||
value={config.systemPrompt}
|
||||
onChange={(e) => handleConfigChange('systemPrompt', e.target.value)}
|
||||
/>
|
||||
</ConfigSection>
|
||||
</CardContent>
|
||||
</ConfigCard>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<ConfigCard>
|
||||
<CardContent>
|
||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||
Pipeline 状态监控
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||
<Typography variant="h4" color="primary" fontWeight={600}>
|
||||
1,234
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
已处理文档
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||
<Typography variant="h4" color="success.main" fontWeight={600}>
|
||||
98.5%
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
成功率
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||
<Typography variant="h4" color="warning.main" fontWeight={600}>
|
||||
2.3s
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
平均响应时间
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||
<Typography variant="h4" color="info.main" fontWeight={600}>
|
||||
156
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
今日查询数
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{pipelineStatus === 'error' && (
|
||||
<Alert severity="error" sx={{ mt: 2 }}>
|
||||
Pipeline 运行出现错误,请检查配置和日志。
|
||||
</Alert>
|
||||
)}
|
||||
</CardContent>
|
||||
</ConfigCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default PipelineConfig;
|
||||
Reference in New Issue
Block a user