Spaces:
Sleeping
Sleeping
Prathamesh Sutar
commited on
Commit
Β·
f0663fb
1
Parent(s):
f4d6026
Deployment optimized
Browse files- Dockerfile +5 -1
- api.py +32 -0
- app.py +2 -1
- classifier.py +11 -2
Dockerfile
CHANGED
|
@@ -33,13 +33,17 @@ RUN python -c "import os; os.environ['HF_HOME']='/app/.cache'; from ner import g
|
|
| 33 |
RUN python -c "import os; os.environ['HF_HOME']='/app/.cache'; from sentiment import get_emotion_classifier; get_emotion_classifier()"
|
| 34 |
RUN python -c "import os; os.environ['HF_HOME']='/app/.cache'; from translate import get_translator; get_translator()"
|
| 35 |
|
| 36 |
-
# Create startup script
|
| 37 |
RUN echo '#!/bin/bash\n\
|
| 38 |
export HF_HOME=/app/.cache\n\
|
| 39 |
export TRANSFORMERS_CACHE=/app/.cache\n\
|
| 40 |
export HF_HUB_CACHE=/app/.cache\n\
|
| 41 |
echo "π Starting FastAPI server on port 8000..."\n\
|
| 42 |
python -m uvicorn api:app --host 0.0.0.0 --port 8000 &\n\
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
echo "π Starting Gradio web interface on port 7860..."\n\
|
| 44 |
python app.py' > start_services.sh
|
| 45 |
|
|
|
|
| 33 |
RUN python -c "import os; os.environ['HF_HOME']='/app/.cache'; from sentiment import get_emotion_classifier; get_emotion_classifier()"
|
| 34 |
RUN python -c "import os; os.environ['HF_HOME']='/app/.cache'; from translate import get_translator; get_translator()"
|
| 35 |
|
| 36 |
+
# Create startup script with model pre-loading
|
| 37 |
RUN echo '#!/bin/bash\n\
|
| 38 |
export HF_HOME=/app/.cache\n\
|
| 39 |
export TRANSFORMERS_CACHE=/app/.cache\n\
|
| 40 |
export HF_HUB_CACHE=/app/.cache\n\
|
| 41 |
echo "π Starting FastAPI server on port 8000..."\n\
|
| 42 |
python -m uvicorn api:app --host 0.0.0.0 --port 8000 &\n\
|
| 43 |
+
echo "β³ Waiting for FastAPI to start..."\n\
|
| 44 |
+
sleep 10\n\
|
| 45 |
+
echo "π₯ Warming up models..."\n\
|
| 46 |
+
curl -X POST http://localhost:8000/warmup || echo "Warmup failed, continuing..."\n\
|
| 47 |
echo "π Starting Gradio web interface on port 7860..."\n\
|
| 48 |
python app.py' > start_services.sh
|
| 49 |
|
api.py
CHANGED
|
@@ -73,6 +73,38 @@ def health():
|
|
| 73 |
"""Alternative health check endpoint"""
|
| 74 |
return health_check()
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
# Main analysis endpoint
|
| 77 |
@app.post("/analyze", response_model=TweetAnalysisResponse)
|
| 78 |
async def analyze_tweets(request: TweetAnalysisRequest):
|
|
|
|
| 73 |
"""Alternative health check endpoint"""
|
| 74 |
return health_check()
|
| 75 |
|
| 76 |
+
@app.post("/warmup")
|
| 77 |
+
async def warmup_models():
|
| 78 |
+
"""Pre-load all models to reduce first request time"""
|
| 79 |
+
try:
|
| 80 |
+
logger.info("Starting model warmup...")
|
| 81 |
+
|
| 82 |
+
# Pre-load all models
|
| 83 |
+
from classifier import get_classifier
|
| 84 |
+
from ner import get_ner_pipeline
|
| 85 |
+
from sentiment import get_emotion_classifier
|
| 86 |
+
from translate import get_translator
|
| 87 |
+
|
| 88 |
+
classifier = get_classifier()
|
| 89 |
+
ner = get_ner_pipeline()
|
| 90 |
+
emotion_clf = get_emotion_classifier()
|
| 91 |
+
translator = get_translator()
|
| 92 |
+
|
| 93 |
+
# Test with sample data
|
| 94 |
+
test_text = "Test tweet for model warmup"
|
| 95 |
+
classifier(test_text, ["test", "not test"])
|
| 96 |
+
if ner:
|
| 97 |
+
ner(test_text)
|
| 98 |
+
emotion_clf(test_text)
|
| 99 |
+
translator(test_text)
|
| 100 |
+
|
| 101 |
+
logger.info("Model warmup completed successfully")
|
| 102 |
+
return {"status": "success", "message": "All models loaded and ready"}
|
| 103 |
+
|
| 104 |
+
except Exception as e:
|
| 105 |
+
logger.error(f"Model warmup failed: {str(e)}")
|
| 106 |
+
return {"status": "error", "message": str(e)}
|
| 107 |
+
|
| 108 |
# Main analysis endpoint
|
| 109 |
@app.post("/analyze", response_model=TweetAnalysisResponse)
|
| 110 |
async def analyze_tweets(request: TweetAnalysisRequest):
|
app.py
CHANGED
|
@@ -42,8 +42,9 @@ def run_pipeline(limit=20, hazard_type=None, location=None, days_back=1):
|
|
| 42 |
logger.info(f"Fetched {len(tweets)} tweets")
|
| 43 |
|
| 44 |
# Process tweets: translate -> classify -> analyze
|
|
|
|
| 45 |
results = classify_tweets(tweets)
|
| 46 |
-
logger.info(f"Processed {len(results)} tweets (translated, classified, and analyzed)")
|
| 47 |
|
| 48 |
# Store hazardous tweets in database (optional)
|
| 49 |
try:
|
|
|
|
| 42 |
logger.info(f"Fetched {len(tweets)} tweets")
|
| 43 |
|
| 44 |
# Process tweets: translate -> classify -> analyze
|
| 45 |
+
logger.info("π Processing tweets (this may take 1-2 minutes for first request)...")
|
| 46 |
results = classify_tweets(tweets)
|
| 47 |
+
logger.info(f"β
Processed {len(results)} tweets (translated, classified, and analyzed)")
|
| 48 |
|
| 49 |
# Store hazardous tweets in database (optional)
|
| 50 |
try:
|
classifier.py
CHANGED
|
@@ -7,7 +7,15 @@ import json
|
|
| 7 |
|
| 8 |
model_name = "cross-encoder/nli-deberta-v3-base"
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
def classify_with_model(tweet_text):
|
| 13 |
"""
|
|
@@ -17,7 +25,8 @@ def classify_with_model(tweet_text):
|
|
| 17 |
if not tweet_text or not tweet_text.strip():
|
| 18 |
return 0
|
| 19 |
candidate_labels = ["report of an ocean hazard", "not an ocean hazard"]
|
| 20 |
-
|
|
|
|
| 21 |
top_label = result['labels'][0]
|
| 22 |
top_score = result['scores'][0]
|
| 23 |
if top_label == "report of an ocean hazard" and top_score > 0.75:
|
|
|
|
| 7 |
|
| 8 |
model_name = "cross-encoder/nli-deberta-v3-base"
|
| 9 |
|
| 10 |
+
# Lazy loading - only load when needed
|
| 11 |
+
classifier = None
|
| 12 |
+
|
| 13 |
+
def get_classifier():
|
| 14 |
+
"""Lazy load classifier to avoid startup delay"""
|
| 15 |
+
global classifier
|
| 16 |
+
if classifier is None:
|
| 17 |
+
classifier = pipeline("zero-shot-classification", model=model_name, framework="pt")
|
| 18 |
+
return classifier
|
| 19 |
|
| 20 |
def classify_with_model(tweet_text):
|
| 21 |
"""
|
|
|
|
| 25 |
if not tweet_text or not tweet_text.strip():
|
| 26 |
return 0
|
| 27 |
candidate_labels = ["report of an ocean hazard", "not an ocean hazard"]
|
| 28 |
+
classifier_instance = get_classifier()
|
| 29 |
+
result = classifier_instance(tweet_text, candidate_labels)
|
| 30 |
top_label = result['labels'][0]
|
| 31 |
top_score = result['scores'][0]
|
| 32 |
if top_label == "report of an ocean hazard" and top_score > 0.75:
|