hjsu
Browse files- Dockerfile +2 -1
- audio_utils.py +24 -0
- fastapi_app.py +22 -21
- requirements.txt +4 -1
Dockerfile
CHANGED
|
@@ -2,4 +2,5 @@ FROM python:3.10-slim
|
|
| 2 |
COPY . /app
|
| 3 |
WORKDIR /app
|
| 4 |
RUN pip install -r requirements.txt
|
| 5 |
-
|
|
|
|
|
|
| 2 |
COPY . /app
|
| 3 |
WORKDIR /app
|
| 4 |
RUN pip install -r requirements.txt
|
| 5 |
+
RUN apt-get update && apt-get install -y ffmpeg
|
| 6 |
+
CMD ["uvicorn", "fastapi_app:app", "--host", "0.0.0.0", "--port", "7860"]
|
audio_utils.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import noisereduce as nr
|
| 3 |
+
import soundfile as sf
|
| 4 |
+
from pydub import AudioSegment
|
| 5 |
+
import io
|
| 6 |
+
|
| 7 |
+
def preprocess_audio(file_bytes):
|
| 8 |
+
# Charger l'audio
|
| 9 |
+
audio = AudioSegment.from_file(io.BytesIO(file_bytes))
|
| 10 |
+
# Convertir en mono, 16kHz
|
| 11 |
+
audio = audio.set_channels(1).set_frame_rate(16000)
|
| 12 |
+
# Exporter en wav bytes
|
| 13 |
+
wav_io = io.BytesIO()
|
| 14 |
+
audio.export(wav_io, format='wav')
|
| 15 |
+
wav_io.seek(0)
|
| 16 |
+
# Charger en numpy
|
| 17 |
+
y, sr = sf.read(wav_io)
|
| 18 |
+
# Réduction de bruit
|
| 19 |
+
y_denoised = nr.reduce_noise(y=y, sr=sr)
|
| 20 |
+
# Sauvegarder en wav bytes
|
| 21 |
+
out_io = io.BytesIO()
|
| 22 |
+
sf.write(out_io, y_denoised, sr, format='WAV')
|
| 23 |
+
out_io.seek(0)
|
| 24 |
+
return out_io
|
fastapi_app.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
| 2 |
"""
|
| 3 |
Medical AI Assistant - FastAPI Only Version
|
| 4 |
Simplified endpoints for backend integration with Swagger UI
|
|
|
|
|
|
|
| 5 |
"""
|
| 6 |
|
| 7 |
from fastapi import FastAPI, HTTPException, File, UploadFile, BackgroundTasks
|
|
@@ -62,15 +64,15 @@ async def load_models():
|
|
| 62 |
|
| 63 |
@asynccontextmanager
|
| 64 |
async def lifespan(app: FastAPI):
|
| 65 |
-
"""Application lifespan management"""
|
| 66 |
try:
|
| 67 |
await load_models()
|
| 68 |
-
|
| 69 |
except Exception as e:
|
| 70 |
logger.error(f"❌ Error during startup: {str(e)}", exc_info=True)
|
| 71 |
-
raise
|
| 72 |
-
|
| 73 |
-
|
| 74 |
|
| 75 |
# Custom OpenAPI schema
|
| 76 |
def custom_openapi():
|
|
@@ -594,21 +596,20 @@ async def validation_exception_handler(request, exc):
|
|
| 594 |
}
|
| 595 |
)
|
| 596 |
|
| 597 |
-
# =========================================================================
|
| 598 |
# STARTUP MESSAGE
|
| 599 |
-
# =========================================================================
|
| 600 |
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
| 611 |
-
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
)
|
|
|
|
| 2 |
"""
|
| 3 |
Medical AI Assistant - FastAPI Only Version
|
| 4 |
Simplified endpoints for backend integration with Swagger UI
|
| 5 |
+
|
| 6 |
+
This file is Hugging Face Spaces compatible: the FastAPI app is exposed as 'app' at the module level.
|
| 7 |
"""
|
| 8 |
|
| 9 |
from fastapi import FastAPI, HTTPException, File, UploadFile, BackgroundTasks
|
|
|
|
| 64 |
|
| 65 |
@asynccontextmanager
|
| 66 |
async def lifespan(app: FastAPI):
|
| 67 |
+
"""Application lifespan management (robust for Hugging Face Spaces)"""
|
| 68 |
try:
|
| 69 |
await load_models()
|
| 70 |
+
logger.info("✅ Models loaded in lifespan.")
|
| 71 |
except Exception as e:
|
| 72 |
logger.error(f"❌ Error during startup: {str(e)}", exc_info=True)
|
| 73 |
+
# Do not raise, just log. App will start but endpoints will return 503 if models are missing.
|
| 74 |
+
yield
|
| 75 |
+
logger.info("🔄 Shutting down...")
|
| 76 |
|
| 77 |
# Custom OpenAPI schema
|
| 78 |
def custom_openapi():
|
|
|
|
| 596 |
}
|
| 597 |
)
|
| 598 |
|
| 599 |
+
# =========================================================================
|
| 600 |
# STARTUP MESSAGE
|
| 601 |
+
# =========================================================================
|
| 602 |
|
| 603 |
+
# The following block is removed for Hugging Face Spaces compatibility:
|
| 604 |
+
# if __name__ == "__main__":
|
| 605 |
+
# import uvicorn
|
| 606 |
+
# print("🩺 Starting Medical AI Assistant API...")
|
| 607 |
+
# print("📚 Documentation available at: http://localhost:8000/docs")
|
| 608 |
+
# print("🔄 Alternative docs at: http://localhost:8000/redoc")
|
| 609 |
+
# uvicorn.run(
|
| 610 |
+
# app,
|
| 611 |
+
# host="0.0.0.0",
|
| 612 |
+
# port=8000,
|
| 613 |
+
# log_level="info",
|
| 614 |
+
# reload=False
|
| 615 |
+
# )
|
|
|
requirements.txt
CHANGED
|
@@ -36,4 +36,7 @@ pytest==7.4.3
|
|
| 36 |
pytest-asyncio==0.21.1
|
| 37 |
|
| 38 |
# Optional: For production deployment
|
| 39 |
-
gunicorn==21.2.0
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
pytest-asyncio==0.21.1
|
| 37 |
|
| 38 |
# Optional: For production deployment
|
| 39 |
+
gunicorn==21.2.0
|
| 40 |
+
|
| 41 |
+
noisereduce==3.0.1
|
| 42 |
+
pydub==0.25.1
|