Files
Thomas Hallock 22e3a3a543 feat(vision): display actual training hardware on train page
Adds hardware detection that queries TensorFlow to determine exactly
which device will be used for training:

- New Python script detect_hardware.py queries TensorFlow for available
  devices (GPU/Metal/CPU)
- New API endpoint GET /api/vision-training/hardware runs the script
  and caches results for 1 hour
- Training page shows hardware prominently before the "Start Training"
  button with GPU/CPU badge, TensorFlow version, and system memory

On Apple Silicon Macs, shows chip type (e.g., "Apple M3 Pro GPU (Metal)")
On NVIDIA systems, shows GPU name from CUDA
Falls back to CPU with processor info if no GPU available

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 06:41:14 -06:00

140 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""
Detect available training hardware by querying TensorFlow.
This script outputs JSON with information about what hardware
TensorFlow will use for training.
"""
import json
import os
import platform
import sys
# Suppress TensorFlow logging during detection
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
def get_hardware_info() -> dict:
"""Detect available hardware for TensorFlow training."""
result = {
"available": False,
"device": "unknown",
"deviceName": "Unknown",
"deviceType": "unknown",
"details": {},
"error": None,
}
# Get system info
result["details"]["platform"] = platform.system()
result["details"]["machine"] = platform.machine()
result["details"]["processor"] = platform.processor()
try:
import tensorflow as tf
result["details"]["tensorflowVersion"] = tf.__version__
# List all physical devices
gpus = tf.config.list_physical_devices('GPU')
cpus = tf.config.list_physical_devices('CPU')
# Check for Apple Silicon Metal (MPS)
# TensorFlow on Apple Silicon uses 'GPU' device type with Metal
is_apple_silicon = (
platform.system() == "Darwin" and
platform.machine() == "arm64"
)
if gpus:
# GPU available (could be NVIDIA CUDA or Apple Metal)
gpu = gpus[0]
result["available"] = True
result["deviceType"] = "gpu"
if is_apple_silicon:
result["device"] = "metal"
result["deviceName"] = "Apple Silicon GPU (Metal)"
# Try to get chip info from system_profiler
try:
import subprocess
sp_output = subprocess.check_output(
["system_profiler", "SPHardwareDataType", "-json"],
text=True,
timeout=5
)
sp_data = json.loads(sp_output)
hardware = sp_data.get("SPHardwareDataType", [{}])[0]
chip_type = hardware.get("chip_type", "")
if chip_type:
result["deviceName"] = f"{chip_type} GPU (Metal)"
result["details"]["chipType"] = chip_type
# Get memory info
memory = hardware.get("physical_memory", "")
if memory:
result["details"]["systemMemory"] = memory
except Exception:
pass # Use default name
else:
# Likely NVIDIA GPU
result["device"] = "cuda"
result["deviceName"] = gpu.name
result["details"]["gpuCount"] = len(gpus)
# Try to get more GPU details
try:
gpu_details = tf.config.experimental.get_device_details(gpu)
if gpu_details:
result["details"]["gpuDetails"] = gpu_details
except Exception:
pass
elif cpus:
# CPU only
result["available"] = True
result["device"] = "cpu"
result["deviceType"] = "cpu"
result["deviceName"] = "CPU"
# Get CPU info
if is_apple_silicon:
try:
import subprocess
sp_output = subprocess.check_output(
["system_profiler", "SPHardwareDataType", "-json"],
text=True,
timeout=5
)
sp_data = json.loads(sp_output)
hardware = sp_data.get("SPHardwareDataType", [{}])[0]
chip_type = hardware.get("chip_type", "")
if chip_type:
result["deviceName"] = f"{chip_type} CPU"
result["details"]["chipType"] = chip_type
except Exception:
pass
else:
# Try to get CPU name on other systems
cpu_name = platform.processor()
if cpu_name:
result["deviceName"] = cpu_name
else:
result["error"] = "No compute devices found"
except ImportError as e:
result["error"] = f"TensorFlow not installed: {e}"
except Exception as e:
result["error"] = f"Error detecting hardware: {e}"
return result
if __name__ == "__main__":
info = get_hardware_info()
print(json.dumps(info))