UdasriHasindu commited on
Commit
d352a67
·
1 Parent(s): 586d5d0

load models from hugging face in first run

Browse files
ml/__init__.py ADDED
File without changes
ml/model_predictor.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import joblib
2
+ import os
3
+ import numpy as np
4
+ import pandas as pd
5
+ from huggingface_hub import hf_hub_download
6
+
7
+ MODEL_REPO = "xplorers/parkinsons-updrs-model"
8
+ MODEL_DIR = "/tmp/models"
9
+
10
+ # In-memory cache — models are loaded once at startup, reused for every request
11
+ _cache = {}
12
+
13
+ def _download_and_cache():
14
+ """Download models from HF Hub and cache in memory. Runs once at startup."""
15
+ if _cache:
16
+ return # already loaded
17
+
18
+ os.makedirs(MODEL_DIR, exist_ok=True)
19
+
20
+ filenames = ["ensemble_model.pkl", "feature_names.pkl", "scaler.pkl"]
21
+ for filename in filenames:
22
+ hf_hub_download(
23
+ repo_id=MODEL_REPO,
24
+ filename=filename,
25
+ repo_type="model",
26
+ local_dir=MODEL_DIR,
27
+ token=os.getenv("HF_TOKEN"), # needed if your HF model repo is private
28
+ )
29
+
30
+ _cache["model"] = joblib.load(os.path.join(MODEL_DIR, "ensemble_model.pkl"))
31
+ _cache["feature_names"] = joblib.load(os.path.join(MODEL_DIR, "feature_names.pkl"))
32
+ _cache["scaler"] = joblib.load(os.path.join(MODEL_DIR, "scaler.pkl"))
33
+ print("Models loaded into memory from HF Hub.")
34
+
35
+
36
+ def predict_parkinson(features: dict) -> float:
37
+ """
38
+ Predict Parkinson's motor UPDRS score from patient features.
39
+ Uses cached models — no disk read on each request.
40
+ """
41
+ try:
42
+ model = _cache["model"]
43
+ feature_names = _cache["feature_names"]
44
+ scaler = _cache["scaler"]
45
+
46
+ print(f"Expected features: {feature_names}")
47
+ print(f"Received features: {list(features.keys())}")
48
+
49
+ missing_features = [name for name in feature_names if name not in features]
50
+ if missing_features:
51
+ raise ValueError(f"Missing required features: {missing_features}")
52
+
53
+ for name in feature_names:
54
+ value = features[name]
55
+ if pd.isna(value) or np.isinf(value):
56
+ print(f"Warning: Feature '{name}' has invalid value: {value}, replacing with 0.0")
57
+ features[name] = 0.0
58
+
59
+ input_values = [features[name] for name in feature_names]
60
+ input_df = pd.DataFrame([input_values], columns=feature_names)
61
+
62
+ scaled_features = scaler.transform(input_df)
63
+ updrs_prediction = model.predict(scaled_features)[0]
64
+
65
+ return float(updrs_prediction)
66
+
67
+ except KeyError:
68
+ raise RuntimeError("Models not loaded. Ensure startup lifespan ran successfully.")
69
+ except Exception as e:
70
+ raise Exception(f"Prediction error: {e}")
71
+
72
+
73
+ def get_required_features():
74
+ try:
75
+ return list(_cache["feature_names"])
76
+ except KeyError:
77
+ return [
78
+ 'age', 'sex', 'test_time', 'Jitter(%)', 'Jitter(Abs)', 'Jitter:RAP',
79
+ 'Jitter:PPQ5', 'Jitter:DDP', 'Shimmer', 'Shimmer(dB)', 'Shimmer:APQ3',
80
+ 'Shimmer:APQ5', 'Shimmer:APQ11', 'Shimmer:DDA', 'NHR', 'HNR',
81
+ 'RPDE', 'DFA', 'PPE'
82
+ ]
services/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+
services/voice_analyze_service.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from utils.file_handler import save_temp_file
3
+ from ml.model_predictor import predict_parkinson
4
+ from utils.voice_data_extraction import extract_voice_features
5
+
6
+ async def process_audio_and_predict(audio_file, basic_info):
7
+ print("PROCESSING IN SERVICE:")
8
+ print(f"Received basic_info: {basic_info}")
9
+ print(f"Audio file object: {type(audio_file)}")
10
+
11
+ temp_file_path = await save_temp_file(audio_file)
12
+
13
+ try:
14
+ voice_features = extract_voice_features(temp_file_path)
15
+
16
+ patient_name = basic_info['name']
17
+
18
+ # exclude name
19
+ prediction_features = {k: v for k, v in basic_info.items() if k != 'name'}
20
+
21
+ # Encode sex: male=1, female=0
22
+ if 'sex' in prediction_features:
23
+ prediction_features['sex'] = 1 if prediction_features['sex'].lower() == 'male' else 0
24
+
25
+ feature_data = {**prediction_features, **voice_features}
26
+
27
+ print("CALLING ML MODEL...")
28
+ prediction = predict_parkinson(feature_data)
29
+
30
+ final_result = {"prediction": prediction, "patient": patient_name}
31
+ print(f"FINAL RESULT: {final_result}")
32
+
33
+ return final_result
34
+ finally:
35
+ # Always clean up the temp file from disk
36
+ if temp_file_path and os.path.exists(temp_file_path):
37
+ os.remove(temp_file_path)
38
+ print(f"Cleaned up temp file: {temp_file_path}")