Spaces:
Running
Running
Commit
·
0c746c9
1
Parent(s):
a6bbf63
feat: added logging
Browse files- Dockerfile +7 -5
- components/model_ingestion.py +15 -7
- components/model_loader.py +12 -4
- components/pipeline_preparer.py +15 -5
- components/predictor.py +16 -6
- main.py +10 -3
- requirements.txt +4 -0
- utils/commons.py +22 -1
Dockerfile
CHANGED
@@ -6,13 +6,15 @@ ENV PATH="/home/user/.local/bin:$PATH"
|
|
6 |
|
7 |
WORKDIR /app
|
8 |
|
|
|
|
|
|
|
9 |
COPY --chown=user ./requirements.txt requirements.txt
|
10 |
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
# Install DVC if needed (uncomment if using DVC in container)
|
15 |
RUN pip install --no-cache-dir dvc
|
16 |
|
17 |
-
|
18 |
-
|
|
|
|
6 |
|
7 |
WORKDIR /app
|
8 |
|
9 |
+
# Create logs directory
|
10 |
+
RUN mkdir -p /app/logs/running_logs && chown user:user /app/logs/running_logs
|
11 |
+
|
12 |
COPY --chown=user ./requirements.txt requirements.txt
|
13 |
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
14 |
|
15 |
+
# Install DVC
|
|
|
|
|
16 |
RUN pip install --no-cache-dir dvc
|
17 |
|
18 |
+
COPY --chown=user . /app
|
19 |
+
|
20 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
components/model_ingestion.py
CHANGED
@@ -1,14 +1,22 @@
|
|
1 |
from transformers import RobertaTokenizerFast, RobertaForSequenceClassification
|
2 |
-
from utils.commons import HUGGINGFACE_MODEL_PATH, MODEL_SAVE_PATH
|
3 |
import os
|
4 |
|
|
|
|
|
5 |
class ModelIngestor:
|
6 |
@staticmethod
|
7 |
def download_model():
|
8 |
"""Download and save the model"""
|
9 |
-
|
10 |
-
os.
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from transformers import RobertaTokenizerFast, RobertaForSequenceClassification
|
2 |
+
from utils.commons import HUGGINGFACE_MODEL_PATH, MODEL_SAVE_PATH, setup_logging
|
3 |
import os
|
4 |
|
5 |
+
logger = setup_logging("model_ingestion.log")
|
6 |
+
|
7 |
class ModelIngestor:
|
8 |
@staticmethod
|
9 |
def download_model():
|
10 |
"""Download and save the model"""
|
11 |
+
try:
|
12 |
+
if not os.path.exists(MODEL_SAVE_PATH):
|
13 |
+
os.makedirs(MODEL_SAVE_PATH)
|
14 |
+
logger.info(f"Created directory: {MODEL_SAVE_PATH}")
|
15 |
+
|
16 |
+
logger.info("Downloading tokenizer and model...")
|
17 |
+
RobertaTokenizerFast.from_pretrained(HUGGINGFACE_MODEL_PATH).save_pretrained(MODEL_SAVE_PATH)
|
18 |
+
RobertaForSequenceClassification.from_pretrained(HUGGINGFACE_MODEL_PATH).save_pretrained(MODEL_SAVE_PATH)
|
19 |
+
logger.info(f"Model and tokenizer saved to {MODEL_SAVE_PATH}")
|
20 |
+
except Exception as e:
|
21 |
+
logger.error(f"Error downloading model: {e}")
|
22 |
+
raise
|
components/model_loader.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
from transformers import RobertaTokenizerFast, RobertaForSequenceClassification
|
2 |
-
from utils.commons import MODEL_SAVE_PATH
|
|
|
|
|
3 |
|
4 |
class ModelLoader:
|
5 |
def __init__(self):
|
@@ -8,6 +10,12 @@ class ModelLoader:
|
|
8 |
|
9 |
def load_model(self):
|
10 |
"""Load model from local path"""
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from transformers import RobertaTokenizerFast, RobertaForSequenceClassification
|
2 |
+
from utils.commons import MODEL_SAVE_PATH, setup_logging
|
3 |
+
|
4 |
+
logger = setup_logging("model_loader.log")
|
5 |
|
6 |
class ModelLoader:
|
7 |
def __init__(self):
|
|
|
10 |
|
11 |
def load_model(self):
|
12 |
"""Load model from local path"""
|
13 |
+
try:
|
14 |
+
logger.info("Loading tokenizer and model...")
|
15 |
+
self.tokenizer = RobertaTokenizerFast.from_pretrained(MODEL_SAVE_PATH)
|
16 |
+
self.model = RobertaForSequenceClassification.from_pretrained(MODEL_SAVE_PATH)
|
17 |
+
logger.info("Tokenizer and model loaded successfully.")
|
18 |
+
return self.tokenizer, self.model
|
19 |
+
except Exception as e:
|
20 |
+
logger.error(f"Error loading model: {e}")
|
21 |
+
raise
|
components/pipeline_preparer.py
CHANGED
@@ -1,11 +1,21 @@
|
|
1 |
from transformers import TextClassificationPipeline
|
|
|
|
|
|
|
2 |
|
3 |
class PipelinePreparer:
|
4 |
@staticmethod
|
5 |
def prepare_pipeline(tokenizer, model):
|
6 |
"""Create text classification pipeline"""
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from transformers import TextClassificationPipeline
|
2 |
+
from utils.commons import setup_logging
|
3 |
+
|
4 |
+
logger = setup_logging("pipeline_preparer.log")
|
5 |
|
6 |
class PipelinePreparer:
|
7 |
@staticmethod
|
8 |
def prepare_pipeline(tokenizer, model):
|
9 |
"""Create text classification pipeline"""
|
10 |
+
try:
|
11 |
+
logger.info("Preparing text classification pipeline...")
|
12 |
+
pipeline = TextClassificationPipeline(
|
13 |
+
tokenizer=tokenizer,
|
14 |
+
model=model,
|
15 |
+
return_all_scores=True
|
16 |
+
)
|
17 |
+
logger.info("Pipeline prepared successfully.")
|
18 |
+
return pipeline
|
19 |
+
except Exception as e:
|
20 |
+
logger.error(f"Error preparing pipeline: {e}")
|
21 |
+
raise
|
components/predictor.py
CHANGED
@@ -1,12 +1,22 @@
|
|
|
|
|
|
|
|
|
|
1 |
class Predictor:
|
2 |
def __init__(self, pipeline):
|
3 |
self.pipeline = pipeline
|
4 |
|
5 |
def predict(self, text):
|
6 |
"""Make prediction"""
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
"
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from utils.commons import setup_logging
|
2 |
+
|
3 |
+
logger = setup_logging("predictor.log")
|
4 |
+
|
5 |
class Predictor:
|
6 |
def __init__(self, pipeline):
|
7 |
self.pipeline = pipeline
|
8 |
|
9 |
def predict(self, text):
|
10 |
"""Make prediction"""
|
11 |
+
try:
|
12 |
+
logger.info(f"Making prediction for text: {text}")
|
13 |
+
preds_list = self.pipeline(text)
|
14 |
+
best_pred = max(preds_list[0], key=lambda x: x["score"])
|
15 |
+
logger.info(f"Prediction successful: {best_pred}")
|
16 |
+
return {
|
17 |
+
"predicted_intent": best_pred["label"],
|
18 |
+
"confidence": best_pred["score"]
|
19 |
+
}
|
20 |
+
except Exception as e:
|
21 |
+
logger.error(f"Error during prediction: {e}")
|
22 |
+
raise
|
main.py
CHANGED
@@ -3,8 +3,11 @@ from pydantic import BaseModel
|
|
3 |
from components.model_loader import ModelLoader
|
4 |
from components.pipeline_preparer import PipelinePreparer
|
5 |
from components.predictor import Predictor
|
|
|
6 |
import uvicorn
|
7 |
|
|
|
|
|
8 |
app = FastAPI()
|
9 |
|
10 |
class PredictionRequest(BaseModel):
|
@@ -12,27 +15,31 @@ class PredictionRequest(BaseModel):
|
|
12 |
|
13 |
@app.on_event("startup")
|
14 |
async def startup_event():
|
15 |
-
|
16 |
try:
|
17 |
# Model initialization
|
18 |
loader = ModelLoader()
|
19 |
tokenizer, model = loader.load_model()
|
20 |
pipeline = PipelinePreparer.prepare_pipeline(tokenizer, model)
|
21 |
app.state.predictor = Predictor(pipeline)
|
22 |
-
|
23 |
except Exception as e:
|
24 |
-
|
25 |
app.state.predictor = None
|
26 |
|
27 |
@app.get("/")
|
28 |
def health_check():
|
|
|
29 |
return {"Message": "Service is healthy", "Status": "OK"}
|
30 |
|
31 |
@app.post("/predict")
|
32 |
def predict(request: PredictionRequest):
|
|
|
33 |
if not app.state.predictor:
|
|
|
34 |
return {"error": "Model not initialized"}
|
35 |
return app.state.predictor.predict(request.sentence)
|
36 |
|
37 |
if __name__ == "__main__":
|
|
|
38 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
3 |
from components.model_loader import ModelLoader
|
4 |
from components.pipeline_preparer import PipelinePreparer
|
5 |
from components.predictor import Predictor
|
6 |
+
from utils.commons import setup_logging
|
7 |
import uvicorn
|
8 |
|
9 |
+
logger = setup_logging("main.log")
|
10 |
+
|
11 |
app = FastAPI()
|
12 |
|
13 |
class PredictionRequest(BaseModel):
|
|
|
15 |
|
16 |
@app.on_event("startup")
|
17 |
async def startup_event():
|
18 |
+
logger.info("Initializing model...")
|
19 |
try:
|
20 |
# Model initialization
|
21 |
loader = ModelLoader()
|
22 |
tokenizer, model = loader.load_model()
|
23 |
pipeline = PipelinePreparer.prepare_pipeline(tokenizer, model)
|
24 |
app.state.predictor = Predictor(pipeline)
|
25 |
+
logger.info("Model initialized successfully")
|
26 |
except Exception as e:
|
27 |
+
logger.error(f"Error initializing model: {e}")
|
28 |
app.state.predictor = None
|
29 |
|
30 |
@app.get("/")
|
31 |
def health_check():
|
32 |
+
logger.info("Health check endpoint called")
|
33 |
return {"Message": "Service is healthy", "Status": "OK"}
|
34 |
|
35 |
@app.post("/predict")
|
36 |
def predict(request: PredictionRequest):
|
37 |
+
logger.info(f"Prediction request received: {request.sentence}")
|
38 |
if not app.state.predictor:
|
39 |
+
logger.error("Model not initialized")
|
40 |
return {"error": "Model not initialized"}
|
41 |
return app.state.predictor.predict(request.sentence)
|
42 |
|
43 |
if __name__ == "__main__":
|
44 |
+
logger.info("Starting FastAPI app...")
|
45 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
requirements.txt
CHANGED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastapi
|
2 |
+
uvicorn
|
3 |
+
transformers
|
4 |
+
torch
|
utils/commons.py
CHANGED
@@ -1,3 +1,24 @@
|
|
|
|
|
|
|
|
|
|
1 |
# Commonly used variables
|
2 |
HUGGINGFACE_MODEL_PATH = "bespin-global/klue-roberta-small-3i4k-intent-classification"
|
3 |
-
MODEL_SAVE_PATH = "./models"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import logging
|
3 |
+
from pathlib import Path
|
4 |
+
|
5 |
# Commonly used variables
|
6 |
HUGGINGFACE_MODEL_PATH = "bespin-global/klue-roberta-small-3i4k-intent-classification"
|
7 |
+
MODEL_SAVE_PATH = "./models"
|
8 |
+
LOG_DIR = "logs/running_logs"
|
9 |
+
|
10 |
+
# Ensure log directory exists
|
11 |
+
Path(LOG_DIR).mkdir(parents=True, exist_ok=True)
|
12 |
+
|
13 |
+
def setup_logging(log_file_name):
|
14 |
+
"""Set up logging configuration."""
|
15 |
+
log_file = os.path.join(LOG_DIR, log_file_name)
|
16 |
+
logging.basicConfig(
|
17 |
+
level=logging.INFO,
|
18 |
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
19 |
+
handlers=[
|
20 |
+
logging.FileHandler(log_file),
|
21 |
+
logging.StreamHandler()
|
22 |
+
]
|
23 |
+
)
|
24 |
+
return logging.getLogger(__name__)
|