feat[bert]: Basic logic
Browse files- docker-compose.yml +7 -0
- ml-service/Dockerfile +8 -0
- ml-service/app.py +34 -0
- ml-service/classifier.py +22 -0
- ml-service/download_model.py +11 -0
- ml-service/model.py +16 -0
- ml-service/nlp.py +8 -0
docker-compose.yml
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
version: '3
|
2 |
+
|
3 |
+
services:
|
4 |
+
ml-service:
|
5 |
+
build: ./ml-service
|
6 |
+
ports:
|
7 |
+
- 6000:6000
|
ml-service/Dockerfile
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10.8-slim
|
2 |
+
LABEL description="Sentiment classifier of tweets service"
|
3 |
+
WORKDIR /app
|
4 |
+
COPY requirements.txt /app/requirements.txt
|
5 |
+
RUN pip install -r requirements.txt
|
6 |
+
COPY . /app/
|
7 |
+
EXPOSE 6000
|
8 |
+
CMD ["python", "app.py"]
|
ml-service/app.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# app.py
|
2 |
+
from fastapi import FastAPI, APIRouter
|
3 |
+
import uvicorn
|
4 |
+
from classifier import Classifier
|
5 |
+
from model import Model
|
6 |
+
from nlp import NLP
|
7 |
+
import logging
|
8 |
+
|
9 |
+
logging.basicConfig(level = logging.INFO)
|
10 |
+
|
11 |
+
# Create the FastAPI instance
|
12 |
+
app = FastAPI()
|
13 |
+
nlp = NLP()
|
14 |
+
router = APIRouter()
|
15 |
+
classifier = Classifier()
|
16 |
+
|
17 |
+
# Define the required routes
|
18 |
+
@router.get("/")
|
19 |
+
async def home():
|
20 |
+
return {"message": "Machine Learning service"}
|
21 |
+
|
22 |
+
@router.post("/sentiment")
|
23 |
+
async def data(data: dict):
|
24 |
+
try:
|
25 |
+
input_text = data["text"]
|
26 |
+
res = nlp.sentiment_analysis(classifier, input_text)
|
27 |
+
return res
|
28 |
+
except Exception as e:
|
29 |
+
log.error("Something went wrong")
|
30 |
+
|
31 |
+
app.include_router(router)
|
32 |
+
|
33 |
+
if __name__ == "__main__":
|
34 |
+
uvicorn.run("app:app", reload=True, port=6000, host="0.0.0.0")
|
ml-service/classifier.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# classifier.py
|
2 |
+
from scipy.special import softmax
|
3 |
+
from model import Model
|
4 |
+
import numpy as np
|
5 |
+
|
6 |
+
class Classifier:
|
7 |
+
def __init__(self):
|
8 |
+
self.model = Model.load_model()
|
9 |
+
self.tokenizer = Model.load_tokenizer()
|
10 |
+
|
11 |
+
def get_sentiment_label_and_score(self, text: str):
|
12 |
+
result = {}
|
13 |
+
labels = ["Negative", "Neutral", "Positive"]
|
14 |
+
encoded_input = self.tokenizer(text, return_tensors='pt')
|
15 |
+
output = self.model(**encoded_input)
|
16 |
+
scores = output[0][0]jj.detach().numpy()
|
17 |
+
scores = softmax(scores)
|
18 |
+
ranking = np.argsort(scores)
|
19 |
+
ranking = ranking[::-1]
|
20 |
+
result["label"] = str(labels[ranking[0]])
|
21 |
+
result["score"] = np.round(float(scores[ranking[0]]), 4)
|
22 |
+
return result
|
ml-service/download_model.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from transformers import AutoModelForSequenceClassification, TFAutoModelForSequenceClassification, AutoTokenize
|
2 |
+
|
3 |
+
# download the model
|
4 |
+
MODEL = "cardiffnlp/twitter-roberta-base-sentiment"
|
5 |
+
tokenizer = AutoTokenizer.from_pretrained(MODEL)
|
6 |
+
model = AutoModelForSequenceClassification.from_pretrained(MODEL)
|
7 |
+
|
8 |
+
# save the model
|
9 |
+
save_dir = "ml-service/models/roberta-base"
|
10 |
+
tokenizer.save_pretrained(save_dir)
|
11 |
+
model.save_pretrained(save_dir)
|
ml-service/model.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# model.py
|
2 |
+
from transformers import AutoModelForSequenceClassification, TFAutoModelForSequenceClassification, AutoTokenize
|
3 |
+
|
4 |
+
class Model:
|
5 |
+
"""A model class to lead the model and tokenizer"""
|
6 |
+
|
7 |
+
def __init__(self) -> None:
|
8 |
+
pass
|
9 |
+
|
10 |
+
def load_model():
|
11 |
+
model = AutoModelForSequenceClassification.from_pretrained("./models/roberta-base/")
|
12 |
+
return model
|
13 |
+
|
14 |
+
def load_tokenizer():
|
15 |
+
tokenizer = AutoTokenize.from_pretrained("./models/roberta-base/")
|
16 |
+
return tokenizer
|
ml-service/nlp.py
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# nlp.py
|
2 |
+
from classifier import Classifier
|
3 |
+
|
4 |
+
classifier = Classifier()
|
5 |
+
|
6 |
+
def sentiment_analysis(self, text:str, classifier):
|
7 |
+
sentiment = classifier.get_sentiment_label_and_score(text)
|
8 |
+
return sentiment
|