feat: add eval_enabled flag and format-first-then-split for eval dataset
This commit is contained in:
parent
0aea3f149d
commit
5df3a0b250
7 changed files with 23 additions and 4 deletions
|
|
@ -30,6 +30,7 @@ class TrainingBackend:
|
|||
self.step_history = []
|
||||
self.eval_loss_history = []
|
||||
self.eval_step_history = []
|
||||
self.eval_enabled = False
|
||||
self.current_theme = "light"
|
||||
|
||||
self.trainer.add_progress_callback(self._on_progress_update)
|
||||
|
|
@ -144,6 +145,7 @@ class TrainingBackend:
|
|||
self.step_history = []
|
||||
self.eval_loss_history = []
|
||||
self.eval_step_history = []
|
||||
self.eval_enabled = False
|
||||
import time
|
||||
output_dir = f"./outputs/{model_name.replace('/', '_')}_{int(time.time())}"
|
||||
|
||||
|
|
@ -215,6 +217,13 @@ class TrainingBackend:
|
|||
dataset = dataset_result
|
||||
eval_dataset = None
|
||||
|
||||
# If user set eval_steps to 0, disable evaluation entirely
|
||||
if eval_steps is not None and float(eval_steps) <= 0:
|
||||
eval_dataset = None
|
||||
|
||||
# Track whether eval is enabled for status reporting
|
||||
self.eval_enabled = eval_dataset is not None
|
||||
|
||||
if dataset is None or self.trainer.should_stop:
|
||||
logger.error("Failed to load dataset or stopped by user")
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ class TrainingStatus(BaseModel):
|
|||
"stopped"
|
||||
] = Field(..., description="Current phase of training pipeline")
|
||||
is_training_running: bool = Field(..., description="True if training loop is actively running")
|
||||
eval_enabled: bool = Field(False, description="True if evaluation dataset is configured for this training run")
|
||||
message: str = Field(..., description="Human-readable status message")
|
||||
error: Optional[str] = Field(None, description="Error details if phase is 'error'")
|
||||
details: Optional[dict] = Field(None, description="Phase-specific info, e.g. {'model_size': '8B'}")
|
||||
|
|
|
|||
|
|
@ -415,6 +415,7 @@ async def get_training_status(
|
|||
job_id=job_id,
|
||||
phase=phase,
|
||||
is_training_running=is_active,
|
||||
eval_enabled=backend.eval_enabled,
|
||||
message=status_message,
|
||||
error=error_message,
|
||||
details=details,
|
||||
|
|
|
|||
|
|
@ -148,7 +148,9 @@ function ema(data: LossHistoryItem[], alpha: number): SmoothedLossItem[] {
|
|||
|
||||
export function ChartsContent({
|
||||
metrics,
|
||||
}: { metrics: TrainingChartSeries }): ReactElement {
|
||||
isTraining,
|
||||
evalEnabled,
|
||||
}: { metrics: TrainingChartSeries; isTraining: boolean; evalEnabled: boolean }): ReactElement {
|
||||
const [smoothing, setSmoothing] = useState(0.75);
|
||||
const [showRaw, setShowRaw] = useState(true);
|
||||
const [showSmoothed, setShowSmoothed] = useState(true);
|
||||
|
|
@ -674,10 +676,10 @@ export function ChartsContent({
|
|||
className="size-5 text-muted-foreground/50"
|
||||
/>
|
||||
<p className="text-sm font-medium text-muted-foreground">
|
||||
Evaluation not configured
|
||||
{isTraining && evalEnabled ? "Waiting for first evaluation step…" : "Evaluation not configured"}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground/60">
|
||||
Set eval dataset & eval_steps to track eval loss
|
||||
{isTraining && evalEnabled ? "Chart will appear once eval_steps is reached" : "Set eval dataset & eval_steps to track eval loss"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ const SKELETON_KEYS = [
|
|||
export function ChartsSection(): ReactElement | null {
|
||||
const currentStep = useTrainingRuntimeStore((state) => state.currentStep);
|
||||
const totalSteps = useTrainingRuntimeStore((state) => state.totalSteps);
|
||||
const isTraining = useTrainingRuntimeStore((state) => state.isTrainingRunning);
|
||||
const evalEnabled = useTrainingRuntimeStore((state) => state.evalEnabled);
|
||||
const lossHistoryRaw = useTrainingRuntimeStore((state) => state.lossHistory);
|
||||
const lrHistoryRaw = useTrainingRuntimeStore((state) => state.lrHistory);
|
||||
const gradNormHistoryRaw = useTrainingRuntimeStore(
|
||||
|
|
@ -70,7 +72,7 @@ export function ChartsSection(): ReactElement | null {
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<ChartsContent metrics={series} />
|
||||
<ChartsContent metrics={series} isTraining={isTraining} evalEnabled={evalEnabled} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const initialState: TrainingRuntimeState = {
|
|||
jobId: null,
|
||||
phase: "idle",
|
||||
isTrainingRunning: false,
|
||||
evalEnabled: false,
|
||||
message: "Ready to train",
|
||||
error: null,
|
||||
isHydrating: false,
|
||||
|
|
@ -144,6 +145,7 @@ export const useTrainingRuntimeStore = create<TrainingRuntimeStore>()((set) => (
|
|||
jobId: payload.job_id || state.jobId,
|
||||
phase: payload.phase,
|
||||
isTrainingRunning: payload.is_training_running,
|
||||
evalEnabled: payload.eval_enabled ?? state.evalEnabled,
|
||||
message: payload.message,
|
||||
error: payload.error,
|
||||
startError: null,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export interface TrainingStatusResponse {
|
|||
job_id: string;
|
||||
phase: TrainingPhase;
|
||||
is_training_running: boolean;
|
||||
eval_enabled: boolean;
|
||||
message: string;
|
||||
error: string | null;
|
||||
details?: {
|
||||
|
|
@ -63,6 +64,7 @@ export interface TrainingRuntimeState {
|
|||
jobId: string | null;
|
||||
phase: TrainingPhase;
|
||||
isTrainingRunning: boolean;
|
||||
evalEnabled: boolean;
|
||||
message: string;
|
||||
error: string | null;
|
||||
isHydrating: boolean;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue