218 lines
6.6 KiB
TypeScript
218 lines
6.6 KiB
TypeScript
|
|
import {
|
||
|
|
Box,
|
||
|
|
Button,
|
||
|
|
Card,
|
||
|
|
CardContent,
|
||
|
|
Grid,
|
||
|
|
LinearProgress,
|
||
|
|
Table,
|
||
|
|
TableBody,
|
||
|
|
TableCell,
|
||
|
|
TableContainer,
|
||
|
|
TableHead,
|
||
|
|
TableRow,
|
||
|
|
Typography,
|
||
|
|
styled
|
||
|
|
} from '@mui/material';
|
||
|
|
|
||
|
|
const StyledCard = styled(Card)({
|
||
|
|
height: '100%',
|
||
|
|
display: 'flex',
|
||
|
|
flexDirection: 'column',
|
||
|
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
|
||
|
|
borderRadius: '8px',
|
||
|
|
});
|
||
|
|
|
||
|
|
const CardTitle = styled(Typography)({
|
||
|
|
fontSize: '1rem',
|
||
|
|
fontWeight: 'bold',
|
||
|
|
marginBottom: '16px',
|
||
|
|
});
|
||
|
|
|
||
|
|
const MetricsContainer = styled(Box)({
|
||
|
|
display: 'flex',
|
||
|
|
justifyContent: 'space-between',
|
||
|
|
marginBottom: '16px',
|
||
|
|
});
|
||
|
|
|
||
|
|
const Metric = styled(Box)({
|
||
|
|
display: 'flex',
|
||
|
|
flexDirection: 'column',
|
||
|
|
});
|
||
|
|
|
||
|
|
const MetricValue = styled(Typography)({
|
||
|
|
fontSize: '1.5rem',
|
||
|
|
fontWeight: 'bold',
|
||
|
|
});
|
||
|
|
|
||
|
|
const MetricLabel = styled(Typography)({
|
||
|
|
fontSize: '0.75rem',
|
||
|
|
color: '#666',
|
||
|
|
});
|
||
|
|
|
||
|
|
const ProgressContainer = styled(Box)({
|
||
|
|
marginBottom: '16px',
|
||
|
|
});
|
||
|
|
|
||
|
|
const ProgressLabel = styled(Box)({
|
||
|
|
display: 'flex',
|
||
|
|
justifyContent: 'space-between',
|
||
|
|
fontSize: '0.65rem',
|
||
|
|
marginBottom: '4px',
|
||
|
|
});
|
||
|
|
|
||
|
|
const StyledLinearProgress = styled(LinearProgress)({
|
||
|
|
height: '8px',
|
||
|
|
borderRadius: '4px',
|
||
|
|
});
|
||
|
|
|
||
|
|
const StatusPill = styled(Box)<{ status?: string }>(({ status }) => ({
|
||
|
|
display: 'inline-block',
|
||
|
|
padding: '4px 8px',
|
||
|
|
borderRadius: '12px',
|
||
|
|
fontSize: '0.65rem',
|
||
|
|
fontWeight: 'bold',
|
||
|
|
backgroundColor: status === 'OK' ? '#e6f7ed' : '#ffebee',
|
||
|
|
color: status === 'OK' ? '#00a389' : '#d32f2f',
|
||
|
|
}));
|
||
|
|
|
||
|
|
const InlineNote = styled('span')({
|
||
|
|
fontSize: '0.75rem',
|
||
|
|
color: '#666',
|
||
|
|
fontWeight: 'normal',
|
||
|
|
marginLeft: '4px',
|
||
|
|
});
|
||
|
|
|
||
|
|
// 模拟数据
|
||
|
|
const recentQueries = [
|
||
|
|
{ query: 'How to reset device firmware?', latency: 732, source: 'manual.pdf', time: '09:21', status: 'OK' },
|
||
|
|
{ query: 'List authentication failure codes', latency: 801, source: 'auth_guide.html', time: '09:18', status: 'OK' },
|
||
|
|
{ query: 'Can we purge stale vectors?', latency: 915, source: 'system_kb', time: '09:10', status: 'OK' },
|
||
|
|
{ query: 'Explain retrieval scoring logic', latency: 845, source: 'design_notes', time: '08:57', status: 'OK' },
|
||
|
|
{ query: 'Pipeline concurrency limits?', latency: 1042, source: 'ops_doc', time: '08:43', status: 'OK' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const Home = () => {
|
||
|
|
return (
|
||
|
|
<Box>
|
||
|
|
<Grid container spacing={3}>
|
||
|
|
{/* Knowledge Base Status Card */}
|
||
|
|
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
|
||
|
|
<StyledCard>
|
||
|
|
<CardContent>
|
||
|
|
<CardTitle>Knowledge Base Status</CardTitle>
|
||
|
|
<MetricsContainer>
|
||
|
|
<Metric>
|
||
|
|
<MetricLabel>Documents</MetricLabel>
|
||
|
|
<MetricValue>4,218</MetricValue>
|
||
|
|
</Metric>
|
||
|
|
<Metric>
|
||
|
|
<MetricLabel>Sources</MetricLabel>
|
||
|
|
<MetricValue>17</MetricValue>
|
||
|
|
</Metric>
|
||
|
|
<Metric>
|
||
|
|
<MetricLabel>Vectors</MetricLabel>
|
||
|
|
<MetricValue>1.2M</MetricValue>
|
||
|
|
</Metric>
|
||
|
|
</MetricsContainer>
|
||
|
|
|
||
|
|
<ProgressContainer>
|
||
|
|
<ProgressLabel>
|
||
|
|
<span>Sync Progress</span>
|
||
|
|
<span>62%</span>
|
||
|
|
</ProgressLabel>
|
||
|
|
<StyledLinearProgress variant="determinate" value={62} />
|
||
|
|
</ProgressContainer>
|
||
|
|
|
||
|
|
<Button
|
||
|
|
variant="contained"
|
||
|
|
fullWidth
|
||
|
|
sx={{
|
||
|
|
backgroundColor: '#1a1a2e',
|
||
|
|
'&:hover': { backgroundColor: '#2a2a3e' }
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
Create New Knowledge Base
|
||
|
|
</Button>
|
||
|
|
</CardContent>
|
||
|
|
</StyledCard>
|
||
|
|
</Grid>
|
||
|
|
|
||
|
|
{/* Recent Activity Card */}
|
||
|
|
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
|
||
|
|
<StyledCard>
|
||
|
|
<CardContent>
|
||
|
|
<CardTitle>
|
||
|
|
Recent Activity <InlineNote>(latest 24h)</InlineNote>
|
||
|
|
</CardTitle>
|
||
|
|
<Box sx={{ fontSize: '0.7rem', lineHeight: 1.8 }}>
|
||
|
|
<Box>152 user queries processed</Box>
|
||
|
|
<Box>87 new documents ingested</Box>
|
||
|
|
<Box>4 pipeline adjustments</Box>
|
||
|
|
</Box>
|
||
|
|
<Box sx={{ marginTop: 'auto', fontSize: '0.65rem', opacity: 0.75, mt: 2 }}>
|
||
|
|
Latency stable at p95 820ms
|
||
|
|
</Box>
|
||
|
|
</CardContent>
|
||
|
|
</StyledCard>
|
||
|
|
</Grid>
|
||
|
|
|
||
|
|
{/* Model Overview Card */}
|
||
|
|
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
|
||
|
|
<StyledCard>
|
||
|
|
<CardContent>
|
||
|
|
<CardTitle>Model Overview</CardTitle>
|
||
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '0.4rem', fontSize: '0.7rem' }}>
|
||
|
|
<Box>Embedding Model: <strong>text-embedding-3-large</strong></Box>
|
||
|
|
<Box>Generator: <strong>gpt-4o-mini</strong></Box>
|
||
|
|
<Box>Reranker: <strong>cross-encoder-v2</strong></Box>
|
||
|
|
<Box>Chunking: 512 tokens</Box>
|
||
|
|
<Box>Retriever Top-K: 8</Box>
|
||
|
|
</Box>
|
||
|
|
<StatusPill status="OK" sx={{ mt: 1 }}>Healthy</StatusPill>
|
||
|
|
</CardContent>
|
||
|
|
</StyledCard>
|
||
|
|
</Grid>
|
||
|
|
|
||
|
|
{/* Recent RAG Queries Table */}
|
||
|
|
<Grid size={12}>
|
||
|
|
<StyledCard>
|
||
|
|
<CardContent>
|
||
|
|
<CardTitle>
|
||
|
|
Recent RAG Queries <InlineNote>(latest 5)</InlineNote>
|
||
|
|
</CardTitle>
|
||
|
|
<TableContainer>
|
||
|
|
<Table size="small">
|
||
|
|
<TableHead>
|
||
|
|
<TableRow>
|
||
|
|
<TableCell>Query</TableCell>
|
||
|
|
<TableCell>Latency (ms)</TableCell>
|
||
|
|
<TableCell>Source</TableCell>
|
||
|
|
<TableCell>Time</TableCell>
|
||
|
|
<TableCell>Status</TableCell>
|
||
|
|
</TableRow>
|
||
|
|
</TableHead>
|
||
|
|
<TableBody>
|
||
|
|
{recentQueries.map((row, index) => (
|
||
|
|
<TableRow key={index}>
|
||
|
|
<TableCell>{row.query}</TableCell>
|
||
|
|
<TableCell>{row.latency}</TableCell>
|
||
|
|
<TableCell>{row.source}</TableCell>
|
||
|
|
<TableCell>{row.time}</TableCell>
|
||
|
|
<TableCell>
|
||
|
|
<StatusPill status={row.status}>{row.status}</StatusPill>
|
||
|
|
</TableCell>
|
||
|
|
</TableRow>
|
||
|
|
))}
|
||
|
|
</TableBody>
|
||
|
|
</Table>
|
||
|
|
</TableContainer>
|
||
|
|
</CardContent>
|
||
|
|
</StyledCard>
|
||
|
|
</Grid>
|
||
|
|
</Grid>
|
||
|
|
</Box>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default Home;
|