SPB Git

spb/forge-studio Public

The Instruments of LLM training — a native macOS cockpit for Forge. Train language models from scratch on Apple Silicon without a terminal.

Swift 95.7% Shell 4.3%
1.8 KB · 54 lines swift
Raw Blame History
1// Author: Simon-Pierre Boucher — contact@spboucher.ai2//3// A training run: identity, config, directories, and the state machine4// (RunSupervisor is the only mutator; every transition is persisted5// atomically by RunStore).6import Foundation78enum RunState: String, Codable, CaseIterable {9    case queued, launching, running, finishing, finished, failed, stopped1011    var isActive: Bool {12        switch self {13        case .launching, .running, .finishing: return true14        default: return false15        }16    }1718    // Legal transitions — RunSupervisor refuses anything else.19    static let transitions: [RunState: Set<RunState>] = [20        .queued: [.launching, .stopped],21        .launching: [.running, .failed, .stopped],22        .running: [.finishing, .finished, .failed, .stopped],23        .finishing: [.finished, .failed, .stopped],24        .finished: [], .failed: [], .stopped: [],25    ]26}2728struct Run: Codable, Identifiable, Equatable {29    var id: UUID = UUID()30    var name: String31    var createdAt: Date32    var state: RunState = .queued33    var config: ForgeConfig34    var datasetPath: String35    var outDirectory: String        // <workspace>/runs/<name>-<timestamp>36    var resumeCheckpoint: String?   // forge train --resume37    var pid: Int32?                 // live forge process (crash recovery)38    var lastStep: Int?39    var lastTrainLoss: Double?40    var bestValLoss: Double?41    var bestValStep: Int?42    var exitCode: Int32?43    var failureReason: String?4445    var logCSVPath: String { outDirectory + "/log.csv" }46    var runLogPath: String { outDirectory + "/run.log" }47    var configPath: String { outDirectory + "/config.json" }4849    var progress: Double {50        guard let step = lastStep, config.train.maxSteps > 0 else { return 0 }51        return min(1.0, Double(step + 1) / Double(config.train.maxSteps))52    }53}54