ibraheem15 commited on
Commit
a1099ee
·
1 Parent(s): 3fa282f

Refactor Dockerfile for multi-stage builds and enhance main.py with CORS middleware and updated model

Browse files
Files changed (2) hide show
  1. Dockerfile +28 -16
  2. main.py +12 -2
Dockerfile CHANGED
@@ -1,24 +1,36 @@
1
- # Dockerfile
2
-
3
- # Use a lean official Python image
4
- FROM python:3.10-slim
5
-
6
- # Set working directory
7
  WORKDIR /app
 
 
8
 
9
- # Copy requirements and install dependencies
10
- COPY requirements.txt /app/
11
-
12
  RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu
13
-
14
  RUN pip install --no-cache-dir -r requirements.txt
15
 
16
- # Copy the application code
 
 
 
 
 
 
17
  COPY main.py /app/
 
 
18
  COPY tests/ /app/tests/
19
- # The port is often fixed by the cloud host (e.g., 7860 for HF Spaces)
20
- # We use 8000 as a standard, and the cloud host will map its port to this one.
21
- EXPOSE 8000
22
 
23
- # Command to run the application using Uvicorn
24
- CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
 
 
 
 
 
 
 
 
 
1
+ # STAGE 1: Base (Heavy Dependencies)
2
+ FROM python:3.10-slim as base
 
 
 
 
3
  WORKDIR /app
4
+ # Install system deps if needed (e.g., usually needed for cv2 or weird numpy versions)
5
+ # RUN apt-get update && apt-get install -y --no-install-recommends gcc libgomp1
6
 
7
+ COPY requirements.txt .
8
+ # 1. Install Torch (Heavy - Cached in this layer)
 
9
  RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu
10
+ # 2. Install other Prod deps
11
  RUN pip install --no-cache-dir -r requirements.txt
12
 
13
+ # STAGE 2: Test (Needs App Code + Tests)
14
+ FROM base as test
15
+ # 1. Install Test Tools
16
+ RUN pip install pytest flake8 httpx
17
+
18
+ # 2. COPY THE APP CODE (Crucial Step!)
19
+ # The tests need to import 'main', so main.py must be here.
20
  COPY main.py /app/
21
+
22
+ # 3. Copy Tests
23
  COPY tests/ /app/tests/
 
 
 
24
 
25
+ ENV PYTHONPATH=/app
26
+ # 4. Run Linting and Tests
27
+ RUN flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
28
+ RUN pytest tests/
29
+
30
+ # STAGE 3: Production (Final Image)
31
+ FROM base as prod
32
+ # We start fresh from 'base'. The junk from 'test' stage is gone.
33
+ COPY main.py /app/
34
+ # Note: We do NOT copy tests/ here to keep prod image smaller
35
+ EXPOSE 8000
36
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
main.py CHANGED
@@ -1,12 +1,13 @@
1
  # main.py
2
  from fastapi import FastAPI, HTTPException
 
3
  from pydantic import BaseModel
4
  from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
5
  from contextlib import asynccontextmanager
6
  import torch
7
 
8
  # --- MLOps Configuration ---
9
- HF_MODEL_NAME = "roshana1s/spam-message-classifier"
10
  CLASSIFIER_PIPELINE = None
11
 
12
  # Pydantic model for request body
@@ -45,6 +46,14 @@ app = FastAPI(
45
  lifespan=lifespan
46
  )
47
 
 
 
 
 
 
 
 
 
48
  @app.get("/")
49
  def health_check():
50
  return {"status": "ok", "model_loaded": CLASSIFIER_PIPELINE is not None}
@@ -55,7 +64,8 @@ def predict_spam(item: Message):
55
  raise HTTPException(status_code=503, detail="Model is not ready.")
56
 
57
  try:
58
- results = CLASSIFIER_PIPELINE(item.text)
 
59
  label = results[0]['label']
60
  score = results[0]['score']
61
  output_label = "spam" if label == 'LABEL_1' else "ham"
 
1
  # main.py
2
  from fastapi import FastAPI, HTTPException
3
+ from fastapi.middleware.cors import CORSMiddleware
4
  from pydantic import BaseModel
5
  from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
6
  from contextlib import asynccontextmanager
7
  import torch
8
 
9
  # --- MLOps Configuration ---
10
+ HF_MODEL_NAME = "mrm8488/bert-tiny-finetuned-sms-spam-detection"
11
  CLASSIFIER_PIPELINE = None
12
 
13
  # Pydantic model for request body
 
46
  lifespan=lifespan
47
  )
48
 
49
+ app.add_middleware(
50
+ CORSMiddleware,
51
+ allow_origins=["*"],
52
+ allow_credentials=True,
53
+ allow_methods=["*"],
54
+ allow_headers=["*"],
55
+ )
56
+
57
  @app.get("/")
58
  def health_check():
59
  return {"status": "ok", "model_loaded": CLASSIFIER_PIPELINE is not None}
 
64
  raise HTTPException(status_code=503, detail="Model is not ready.")
65
 
66
  try:
67
+ print(f"Received text for prediction: {item.text}")
68
+ results = CLASSIFIER_PIPELINE(item.text, truncation=True, max_length=512)
69
  label = results[0]['label']
70
  score = results[0]['score']
71
  output_label = "spam" if label == 'LABEL_1' else "ham"