File size: 5,537 Bytes
0573fbf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9426218
 
 
 
 
 
 
 
 
0573fbf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import React from 'react';
import { Paper, Box, Typography, LinearProgress, Grid, Alert } from '@mui/material';
import { Activity as ActivityIcon } from 'lucide-react';
import LossChart from './LossChart';
import { trainingMonitorStyles } from '../theme';

export default function TrainingMonitor({
    trainingProgress,
    trainingStatus,
    trainingError,
    trainingConfig,
    indicatorState,
}) {
    const getProgressColor = () => {
        if (trainingError) return 'error';
        if (trainingProgress === 100) return 'success';
        return 'primary';
    };

    const status = indicatorState?.status || 'idle';
    const label = indicatorState?.label || 'Idle';
    const animate = indicatorState?.animate || false;

    return (
        <Paper sx={trainingMonitorStyles.rootPaper}>
            <Box sx={trainingMonitorStyles.headerRow}>
                <Box sx={trainingMonitorStyles.headerTitleWrap}>
                    <Box component="span" sx={trainingMonitorStyles.headerIcon}>
                        <ActivityIcon size={20} />
                    </Box>
                    <Typography variant="h6" sx={trainingMonitorStyles.headerTitle}>
                        Training Monitor
                    </Typography>
                </Box>
                <Box sx={trainingMonitorStyles.statusInline}>
                    <Box sx={trainingMonitorStyles.statusDot(status, animate)} />
                    <Typography variant="caption" sx={trainingMonitorStyles.statusText(status)}>
                        {label}
                    </Typography>
                </Box>
            </Box>

            <Box sx={trainingMonitorStyles.progressSection}>
                <Box sx={trainingMonitorStyles.progressHeader}>
                    <Typography variant="body2">Progress</Typography>
                    <Typography variant="body2">{trainingProgress}%</Typography>
                </Box>
                <LinearProgress
                    variant="determinate"
                    value={trainingProgress}
                    color={getProgressColor()}
                    sx={trainingMonitorStyles.progressBar}
                />
            </Box>

            {trainingStatus?.device_info && (
                <Box sx={trainingMonitorStyles.deviceSection}>
                    <Typography variant="body2" color="textSecondary">
                        <strong>{
                            trainingStatus.device_info.type === 'cuda' ? 'CUDA' :
                                trainingStatus.device_info.type === 'mps' ? 'MPS' : 'CPU'
                        }</strong>
                        {' · '}{trainingStatus.device_info.device}
                        {trainingStatus.device_info.memory_gb
                            ? ` · ${trainingStatus.device_info.memory_gb.toFixed(1)} GB`
                            : ''}
                    </Typography>
                </Box>
            )}

            <Grid container spacing={2} sx={trainingMonitorStyles.metricsGrid}>
                <Grid item xs={12} sm={6}>
                    <Typography variant="body2" color="textSecondary">Current Epoch</Typography>
                    <Typography variant="body1">
                        {trainingStatus?.current_epoch !== undefined ?
                            `${trainingStatus.current_epoch + 1} / ${trainingConfig.epochs}` :
                            '0 / ' + trainingConfig.epochs}
                    </Typography>
                </Grid>
                <Grid item xs={12} sm={6}>
                    <Typography variant="body2" color="textSecondary">Global Step / Total Steps</Typography>
                    <Typography variant="body1" color="primary">
                        {trainingStatus?.global_step !== undefined && trainingStatus?.total_steps !== undefined ?
                            `${trainingStatus.global_step} / ${trainingStatus.total_steps}` :
                            'N/A'}
                    </Typography>
                </Grid>
                <Grid item xs={12} sm={6}>
                    <Typography variant="body2" color="textSecondary">Checkpoints Saved</Typography>
                    <Typography variant="body1">
                        {trainingStatus?.checkpoints_saved || 0}
                    </Typography>
                </Grid>
                <Grid item xs={12} sm={6}>
                    <Typography variant="body2" color="textSecondary">Current Loss</Typography>
                    <Typography variant="body1">
                        {trainingStatus?.loss ? parseFloat(trainingStatus.loss).toFixed(4) : 'N/A'}
                    </Typography>
                </Grid>
            </Grid>

            {trainingStatus?.loss_history && trainingStatus.loss_history.length > 0 && (
                <Box sx={trainingMonitorStyles.lossSection}>
                    <Typography variant="body2" color="textSecondary" gutterBottom>
                        <strong>Loss History</strong>
                    </Typography>
                    <Box sx={trainingMonitorStyles.lossChartBox}>
                        <LossChart data={trainingStatus.loss_history} />
                    </Box>
                </Box>
            )}

            {trainingError && (
                <Alert severity="error" sx={trainingMonitorStyles.errorAlert}>
                    <Typography variant="body2">
                        <strong>Training Error:</strong> {trainingError}
                    </Typography>
                </Alert>
            )}
        </Paper>
    );
}