spb/zyquo-local Public MIT
Native macOS AI chat that runs LLMs 100% locally on Apple Silicon with MLX — no cloud, no API keys.
Swift 97.2%
Shell 1.8%
Makefile 1%
1//2// MemoryAdvisor.swift3// Zyquo Local4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//89import Foundation10import MLX1112/// RAM estimation and fits/tight/won't-fit verdicts for THIS Mac.13/// Thresholds follow docs/MLX-RESEARCH.md §7: the macOS GPU-wired ceiling is14/// ~70–75 % of unified memory, so weights ≤60 % is comfortable, ≤75 % tight.15enum MemoryAdvisor {16 enum Verdict: String, Codable, Sendable {17 case fits18 case tight19 case tooLarge2021 var label: String {22 switch self {23 case .fits: "Fits"24 case .tight: "Tight"25 case .tooLarge: "Too large"26 }27 }28 }2930 /// Physical unified memory of this Mac in bytes.31 static var physicalMemoryBytes: UInt64 { HardwareGate.physicalMemory }3233 /// Estimated RAM needed to run a model: weights + KV cache + overhead.34 /// weights×1.2 covers activations/prefill working set; +1.5 GB covers a35 /// useful KV cache at moderate context.36 static func estimatedRuntimeBytes(weightsBytes: Int64) -> Int64 {37 Int64(Double(weightsBytes) * 1.2) + 1_500_000_00038 }3940 /// Verdict for a model of the given on-disk weights size.41 static func verdict(weightsBytes: Int64) -> Verdict {42 let ram = Double(physicalMemoryBytes)43 let weights = Double(weightsBytes)44 if weights <= ram * 0.60 { return .fits }45 if weights <= ram * 0.75 { return .tight }46 return .tooLarge47 }4849 /// Verdict for running two models side by side (Compare mode gate).50 static func verdict(combinedWeightsBytes: Int64) -> Verdict {51 verdict(weightsBytes: combinedWeightsBytes)52 }5354 /// Live MLX memory snapshot (bytes actively used by the loaded model).55 static var activeMemoryBytes: Int { MLX.Memory.activeMemory }56 static var peakMemoryBytes: Int { MLX.Memory.peakMemory }5758 static func resetPeakMemory() { MLX.GPU.resetPeakMemory() }5960 /// Returns cached MLX buffers to the OS — called after unloading a model.61 static func reclaimMemory() { MLX.Memory.clearCache() }62}63