Spaces:
Paused
Paused
File size: 8,225 Bytes
4abf821 5be262b 4abf821 e92f1ba 4abf821 61e63b0 4abf821 61e63b0 d61c890 61e63b0 4abf821 5be262b 4abf821 2aa5eb6 f2b649d 5be262b 4abf821 5be262b 4abf821 5be262b 4abf821 93dd654 5be262b 93dd654 5be262b 93dd654 d61c890 fee972c 93dd654 fee972c 5be262b d61c890 fee972c d61c890 fee972c d61c890 5be262b d61c890 5be262b d61c890 93dd654 e0bd111 5be262b e0bd111 93dd654 5be262b 93dd654 4abf821 5be262b d61c890 5be262b d61c890 5be262b d61c890 5be262b d61c890 5be262b e92f1ba 5be262b 4abf821 5be262b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | import os
import logging
from flask import Flask, jsonify
from flask_cors import CORS
import whisper
from dotenv import load_dotenv
from .agents.text_extractor import TextExtractorAgent
from .agents.phi_scrubber import PHIScrubberAgent
from .agents.phi_scrubber import MedicalTextUtils
from .agents.summarizer import SummarizerAgent
from .agents.medical_data_extractor import MedicalDataExtractorAgent
from .agents.medical_data_extractor import MedicalDocDataExtractorAgent
import torch
# Load environment variables
load_dotenv()
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.StreamHandler(),
logging.FileHandler('/tmp/app.log')
]
)
app = Flask(__name__)
CORS(app)
# Configure upload directory
UPLOAD_DIR = '/data/uploads'
os.makedirs(UPLOAD_DIR, exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_DIR
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 100 MB max file size
# Set cache directories
CACHE_DIRS = {
'HF_HOME': '/tmp/huggingface',
'TRANSFORMERS_CACHE': '/tmp/huggingface',
'XDG_CACHE_HOME': '/tmp',
'TORCH_HOME': '/tmp/torch',
'WHISPER_CACHE': '/tmp/whisper'
}
for env_var, path in CACHE_DIRS.items():
os.environ[env_var] = path
os.makedirs(path, exist_ok=True)
# Model loaders
class LazyModelLoader:
def __init__(self, model_name, model_type, fallback_model=None):
self.model_name = model_name
self.model_type = model_type
self.fallback_model = fallback_model
self._model = None
self._tokenizer = None
self._pipeline = None
def load(self):
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM, AutoModelForSeq2SeqLM
if self._pipeline is None:
try:
logging.info(f"Loading {self.model_name}...")
# Clear GPU memory
import torch
torch.cuda.empty_cache()
# Load tokenizer with proper error handling
try:
self._tokenizer = AutoTokenizer.from_pretrained(
self.model_name,
trust_remote_code=True,
cache_dir=os.environ.get('TRANSFORMERS_CACHE', '/tmp/huggingface')
)
except Exception as e:
logging.error(f"Failed to load tokenizer: {str(e)}")
if self.fallback_model:
logging.info(f"Trying fallback model tokenizer: {self.fallback_model}")
self._tokenizer = AutoTokenizer.from_pretrained(
self.fallback_model,
trust_remote_code=True,
cache_dir=os.environ.get('TRANSFORMERS_CACHE', '/tmp/huggingface')
)
else:
raise
# Load model with memory optimizations
try:
if self.model_type == "text-generation":
self._model = AutoModelForCausalLM.from_pretrained(
self.model_name,
trust_remote_code=True,
device_map="auto",
low_cpu_mem_usage=True,
torch_dtype=torch.float16,
cache_dir=os.environ.get('TRANSFORMERS_CACHE', '/tmp/huggingface')
)
else:
self._model = AutoModelForSeq2SeqLM.from_pretrained(
self.model_name,
trust_remote_code=True,
device_map="auto",
low_cpu_mem_usage=True,
torch_dtype=torch.float16,
cache_dir=os.environ.get('TRANSFORMERS_CACHE', '/tmp/huggingface')
)
except Exception as e:
logging.error(f"Failed to load model: {str(e)}")
if self.fallback_model:
logging.info(f"Trying fallback model: {self.fallback_model}")
self._model = AutoModelForSeq2SeqLM.from_pretrained(
self.fallback_model,
trust_remote_code=True,
device_map="auto",
low_cpu_mem_usage=True,
torch_dtype=torch.float16,
cache_dir=os.environ.get('TRANSFORMERS_CACHE', '/tmp/huggingface')
)
else:
raise
# Create pipeline after model is loaded
self._pipeline = pipeline(
task=self.model_type,
model=self._model,
tokenizer=self._tokenizer,
device_map="auto"
)
logging.info(f"Successfully loaded {self.model_name}")
return self._pipeline
except Exception as e:
if self.fallback_model:
logging.warning(f"Failed to load {self.model_name}, falling back to {self.fallback_model}")
self.model_name = self.fallback_model
return self.load()
logging.error(f"Failed to load {self.model_name}: {str(e)}", exc_info=True)
raise
return self._pipeline
class WhisperModelLoader:
_instance = None
def __init__(self):
self._model = None
@staticmethod
def get_instance():
if WhisperModelLoader._instance is None:
WhisperModelLoader._instance = WhisperModelLoader()
return WhisperModelLoader._instance
def load(self):
if self._model is None:
try:
logging.info("Loading Whisper model...")
self._model = whisper.load_model(
"tiny", # Using tiny model for better memory usage
download_root=os.environ.get('WHISPER_CACHE', '/tmp/whisper')
)
logging.info("Whisper model loaded successfully")
except Exception as e:
logging.error(f"Failed to load Whisper model: {str(e)}", exc_info=True)
raise
return self._model
def transcribe(self, audio_path):
model = self.load()
return model.transcribe(audio_path)
# Initialize agents
try:
# Use smaller models for Hugging Face Spaces
medalpaca_model_loader = LazyModelLoader(
"facebook/bart-base", # Start with a smaller model
"text-generation",
fallback_model="facebook/bart-large-cnn"
)
summarization_model_loader = LazyModelLoader(
"facebook/bart-base",
"summarization",
fallback_model="facebook/bart-large-cnn"
)
# Initialize agents with lazy loading
text_extractor_agent = TextExtractorAgent()
phi_scrubber_agent = PHIScrubberAgent()
medical_data_extractor_agent = MedicalDataExtractorAgent(medalpaca_model_loader)
summarizer_agent = SummarizerAgent(summarization_model_loader)
# Pass all agents and models to routes
agents = {
"text_extractor": text_extractor_agent,
"phi_scrubber": phi_scrubber_agent,
"summarizer": summarizer_agent,
"medical_data_extractor": medical_data_extractor_agent,
"whisper_model": WhisperModelLoader.get_instance()
}
from .api.routes import register_routes
register_routes(app, agents)
except Exception as e:
logging.error(f"Failed to initialize application: {str(e)}", exc_info=True)
raise
@app.errorhandler(Exception)
def handle_error(error):
logging.error(f"Unhandled error: {str(error)}", exc_info=True)
return jsonify({
"error": str(error),
"status": "error"
}), 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860, debug=False) |