refactor(vision): share Python config between detection and training

Extracts TRAINING_PYTHON, TRAINING_SCRIPTS_DIR, and PYTHON_ENV to a
shared config.ts file. Both hardware detection and training now import
from the same source, making it impossible for them to diverge.

This ensures hardware detection always shows exactly what training
will use.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2026-01-06 07:12:51 -06:00
parent 276c9db5af
commit bd77b5ac22
3 changed files with 43 additions and 18 deletions

View File

@@ -0,0 +1,34 @@
import path from 'path'
/**
* Shared configuration for vision training.
*
* CRITICAL: Both hardware detection and training MUST use the same Python
* environment so that hardware detection accurately reflects what training
* will actually use.
*/
const cwd = process.cwd()
/**
* Path to the Python executable used for ALL vision training operations.
* This venv has tensorflow-metal installed for Apple Silicon GPU support.
*/
export const TRAINING_PYTHON = path.join(
cwd,
'scripts/train-column-classifier/.venv/bin/python'
)
/**
* Path to the training scripts directory
*/
export const TRAINING_SCRIPTS_DIR = path.join(cwd, 'scripts/train-column-classifier')
/**
* Common environment variables for Python subprocesses
*/
export const PYTHON_ENV = {
...process.env,
PYTHONUNBUFFERED: '1',
PYTHONWARNINGS: 'ignore::FutureWarning', // Suppress keras warning
}

View File

@@ -1,5 +1,6 @@
import { spawn } from 'child_process'
import path from 'path'
import { PYTHON_ENV, TRAINING_PYTHON, TRAINING_SCRIPTS_DIR } from '../config'
/**
* Hardware detection result from Python/TensorFlow
@@ -38,23 +39,17 @@ export async function GET(): Promise<Response> {
try {
const cwd = path.resolve(process.cwd())
const scriptPath = path.join(cwd, 'scripts/train-column-classifier/detect_hardware.py')
const scriptPath = path.join(TRAINING_SCRIPTS_DIR, 'detect_hardware.py')
const result = await new Promise<HardwareInfo>((resolve, reject) => {
let stdout = ''
let stderr = ''
let hasError = false
// Use the venv Python with tensorflow-metal for proper GPU detection
const venvPython = path.join(cwd, 'scripts/train-column-classifier/.venv/bin/python')
const childProcess = spawn(venvPython, [scriptPath], {
// Use shared Python config - same as training uses
const childProcess = spawn(TRAINING_PYTHON, [scriptPath], {
cwd,
env: {
...process.env,
PYTHONUNBUFFERED: '1',
PYTHONWARNINGS: 'ignore::FutureWarning', // Suppress keras warning
},
env: PYTHON_ENV,
})
childProcess.stdout?.on('data', (data: Buffer) => {

View File

@@ -1,5 +1,6 @@
import { spawn, type ChildProcess } from 'child_process'
import path from 'path'
import { PYTHON_ENV, TRAINING_PYTHON } from '../config'
/**
* Training configuration options
@@ -94,17 +95,12 @@ export async function POST(request: Request): Promise<Response> {
},
})
// Spawn Python process using the venv with tensorflow-metal for GPU support
// Spawn Python process - uses shared config so hardware detection matches
const cwd = path.resolve(process.cwd())
const venvPython = path.join(cwd, 'scripts/train-column-classifier/.venv/bin/python')
activeProcess = spawn(venvPython, args, {
activeProcess = spawn(TRAINING_PYTHON, args, {
cwd,
env: {
...process.env,
PYTHONUNBUFFERED: '1',
PYTHONWARNINGS: 'ignore::FutureWarning', // Suppress keras warning
},
env: PYTHON_ENV,
})
// Handle stdout (JSON progress events)