Sync local codebase to Hugging Face
Browse files- main/requirements.txt +12 -12
- requirements.txt +12 -12
- webserver/app.py +36 -5
- webserver/train_service.py +12 -4
main/requirements.txt
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
-
matplotlib==3.
|
| 2 |
-
numpy==
|
| 3 |
-
optuna==4.
|
| 4 |
-
pandas==
|
| 5 |
-
|
| 6 |
-
scipy==1.
|
| 7 |
-
seaborn==0.13.
|
| 8 |
-
timm==
|
| 9 |
-
torch==2.
|
| 10 |
-
torchvision==0.
|
| 11 |
-
tqdm==4.
|
| 12 |
-
|
|
|
|
| 1 |
+
matplotlib==3.8.4
|
| 2 |
+
numpy==1.26.4
|
| 3 |
+
optuna==4.1.1
|
| 4 |
+
pandas==2.2.3
|
| 5 |
+
scikit-learn==1.5.2
|
| 6 |
+
scipy==1.14.1
|
| 7 |
+
seaborn==0.13.1
|
| 8 |
+
timm==0.9.16
|
| 9 |
+
torch==2.3.1
|
| 10 |
+
torchvision==0.18.1
|
| 11 |
+
tqdm==4.66.5
|
| 12 |
+
umap-learn==0.5.7
|
requirements.txt
CHANGED
|
@@ -2,15 +2,15 @@ fastapi
|
|
| 2 |
uvicorn
|
| 3 |
python-multipart
|
| 4 |
jinja2
|
| 5 |
-
matplotlib==3.
|
| 6 |
-
numpy==
|
| 7 |
-
optuna==4.
|
| 8 |
-
pandas==
|
| 9 |
-
scikit-learn
|
| 10 |
-
scipy==1.
|
| 11 |
-
seaborn==0.13.
|
| 12 |
-
timm==
|
| 13 |
-
torch==2.
|
| 14 |
-
torchvision==0.
|
| 15 |
-
tqdm==4.
|
| 16 |
-
umap-learn==0.5.
|
|
|
|
| 2 |
uvicorn
|
| 3 |
python-multipart
|
| 4 |
jinja2
|
| 5 |
+
matplotlib==3.8.4
|
| 6 |
+
numpy==1.26.4
|
| 7 |
+
optuna==4.1.1
|
| 8 |
+
pandas==2.2.3
|
| 9 |
+
scikit-learn==1.5.2
|
| 10 |
+
scipy==1.14.1
|
| 11 |
+
seaborn==0.13.1
|
| 12 |
+
timm==0.9.16
|
| 13 |
+
torch==2.3.1
|
| 14 |
+
torchvision==0.18.1
|
| 15 |
+
tqdm==4.66.5
|
| 16 |
+
umap-learn==0.5.7
|
webserver/app.py
CHANGED
|
@@ -35,14 +35,26 @@ os.makedirs(PREDICTIONS_DIR, exist_ok=True)
|
|
| 35 |
app = FastAPI(title="Raman Fine-Tune Webserver")
|
| 36 |
templates = Jinja2Templates(directory=TEMPLATE_DIR)
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
JOB_MANAGER = None
|
| 43 |
JOBS = {}
|
|
|
|
| 44 |
JOB_PROCESSES = {}
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
|
| 48 |
def _save_upload(file_obj: UploadFile, dst_path: str):
|
|
@@ -223,6 +235,25 @@ def _reap_job_process(job_id: str, process: multiprocessing.Process):
|
|
| 223 |
JOB_PROCESSES.pop(job_id, None)
|
| 224 |
|
| 225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
@app.get("/")
|
| 227 |
def index(request: Request):
|
| 228 |
return templates.TemplateResponse(request, "index.html", {"request": request})
|
|
|
|
| 35 |
app = FastAPI(title="Raman Fine-Tune Webserver")
|
| 36 |
templates = Jinja2Templates(directory=TEMPLATE_DIR)
|
| 37 |
|
| 38 |
+
# Initialize multiprocessing with fallback for constrained environments
|
| 39 |
+
try:
|
| 40 |
+
if multiprocessing.current_process().name == "MainProcess":
|
| 41 |
+
JOB_MANAGER = multiprocessing.Manager()
|
| 42 |
+
JOBS = JOB_MANAGER.dict()
|
| 43 |
+
else:
|
| 44 |
+
JOB_MANAGER = None
|
| 45 |
+
JOBS = {}
|
| 46 |
+
except Exception as e:
|
| 47 |
+
print(f"Warning: multiprocessing.Manager() failed: {e}. Using local dict instead.")
|
| 48 |
JOB_MANAGER = None
|
| 49 |
JOBS = {}
|
| 50 |
+
|
| 51 |
JOB_PROCESSES = {}
|
| 52 |
+
|
| 53 |
+
try:
|
| 54 |
+
JOB_CONTEXT = multiprocessing.get_context("spawn")
|
| 55 |
+
except Exception as e:
|
| 56 |
+
print(f"Warning: spawn context not available: {e}. Using default context.")
|
| 57 |
+
JOB_CONTEXT = multiprocessing
|
| 58 |
|
| 59 |
|
| 60 |
def _save_upload(file_obj: UploadFile, dst_path: str):
|
|
|
|
| 235 |
JOB_PROCESSES.pop(job_id, None)
|
| 236 |
|
| 237 |
|
| 238 |
+
@app.on_event("startup")
|
| 239 |
+
async def startup_event():
|
| 240 |
+
import sys
|
| 241 |
+
print("[STARTUP] Application initializing...")
|
| 242 |
+
print(f"[STARTUP] Python version: {sys.version}")
|
| 243 |
+
print(f"[STARTUP] PyTorch: {torch.__version__}")
|
| 244 |
+
print(f"[STARTUP] CUDA available: {torch.cuda.is_available()}")
|
| 245 |
+
if torch.cuda.is_available():
|
| 246 |
+
print(f"[STARTUP] CUDA device: {torch.cuda.get_device_name(0)}")
|
| 247 |
+
print(f"[STARTUP] JOB_MANAGER: {'multiprocessing.Manager' if JOB_MANAGER else 'local dict'}")
|
| 248 |
+
print(f"[STARTUP] JOB_CONTEXT: {type(JOB_CONTEXT).__name__}")
|
| 249 |
+
print("[STARTUP] Application ready!")
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
@app.get("/health")
|
| 253 |
+
def health_check():
|
| 254 |
+
return {"status": "ok", "cuda": torch.cuda.is_available()}
|
| 255 |
+
|
| 256 |
+
|
| 257 |
@app.get("/")
|
| 258 |
def index(request: Request):
|
| 259 |
return templates.TemplateResponse(request, "index.html", {"request": request})
|
webserver/train_service.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import json
|
| 2 |
import os
|
|
|
|
| 3 |
import traceback
|
| 4 |
from dataclasses import dataclass
|
| 5 |
from datetime import datetime
|
|
@@ -16,10 +17,10 @@ from webserver.preprocess_utils import augment_small_trainset, preprocess_raman_
|
|
| 16 |
# Make project root importable when the web server runs from ./webserver
|
| 17 |
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
| 18 |
MAIN_DIR = os.path.join(ROOT_DIR, "main")
|
| 19 |
-
if ROOT_DIR not in
|
| 20 |
-
|
| 21 |
-
if MAIN_DIR not in
|
| 22 |
-
|
| 23 |
|
| 24 |
from main.Ramandataset import RamanDataset
|
| 25 |
from main.Raman_Task import (
|
|
@@ -220,6 +221,11 @@ def predict_with_checkpoint(checkpoint_path: str, spectra: np.ndarray, wavenumbe
|
|
| 220 |
|
| 221 |
def run_finetune_job(job_id: str, input_paths: dict, run_dir: str, config: TrainConfig, jobs: dict):
|
| 222 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
_update_job(
|
| 224 |
jobs,
|
| 225 |
job_id,
|
|
@@ -231,9 +237,11 @@ def run_finetune_job(job_id: str, input_paths: dict, run_dir: str, config: Train
|
|
| 231 |
total_epochs=config.epochs,
|
| 232 |
)
|
| 233 |
|
|
|
|
| 234 |
spectral = np.load(input_paths["spectral"], allow_pickle=True)
|
| 235 |
labels = np.load(input_paths["labels"], allow_pickle=True)
|
| 236 |
wavenumbers = np.load(input_paths["wavenumbers"], allow_pickle=True)
|
|
|
|
| 237 |
|
| 238 |
_update_job(jobs, job_id, message="Preprocessing (crop/pad/interpolate/normalize)...", progress=5, phase="preprocessing")
|
| 239 |
processed_x, processed_labels, target_w = preprocess_raman_dataset(
|
|
|
|
| 1 |
import json
|
| 2 |
import os
|
| 3 |
+
import sys
|
| 4 |
import traceback
|
| 5 |
from dataclasses import dataclass
|
| 6 |
from datetime import datetime
|
|
|
|
| 17 |
# Make project root importable when the web server runs from ./webserver
|
| 18 |
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
| 19 |
MAIN_DIR = os.path.join(ROOT_DIR, "main")
|
| 20 |
+
if ROOT_DIR not in sys.path:
|
| 21 |
+
sys.path.insert(0, ROOT_DIR)
|
| 22 |
+
if MAIN_DIR not in sys.path:
|
| 23 |
+
sys.path.insert(0, MAIN_DIR)
|
| 24 |
|
| 25 |
from main.Ramandataset import RamanDataset
|
| 26 |
from main.Raman_Task import (
|
|
|
|
| 221 |
|
| 222 |
def run_finetune_job(job_id: str, input_paths: dict, run_dir: str, config: TrainConfig, jobs: dict):
|
| 223 |
try:
|
| 224 |
+
print(f"[JOB {job_id}] Starting fine-tune job...")
|
| 225 |
+
print(f"[JOB {job_id}] Input paths: {input_paths}")
|
| 226 |
+
print(f"[JOB {job_id}] Run directory: {run_dir}")
|
| 227 |
+
print(f"[JOB {job_id}] Config: epochs={config.epochs}, batch_size={config.batch_size}")
|
| 228 |
+
|
| 229 |
_update_job(
|
| 230 |
jobs,
|
| 231 |
job_id,
|
|
|
|
| 237 |
total_epochs=config.epochs,
|
| 238 |
)
|
| 239 |
|
| 240 |
+
print(f"[JOB {job_id}] Loading spectral data...")
|
| 241 |
spectral = np.load(input_paths["spectral"], allow_pickle=True)
|
| 242 |
labels = np.load(input_paths["labels"], allow_pickle=True)
|
| 243 |
wavenumbers = np.load(input_paths["wavenumbers"], allow_pickle=True)
|
| 244 |
+
print(f"[JOB {job_id}] Data loaded: spectral {spectral.shape}, labels {labels.shape}, wavenumbers {wavenumbers.shape}")
|
| 245 |
|
| 246 |
_update_job(jobs, job_id, message="Preprocessing (crop/pad/interpolate/normalize)...", progress=5, phase="preprocessing")
|
| 247 |
processed_x, processed_labels, target_w = preprocess_raman_dataset(
|