File size: 5,291 Bytes
66028cc
 
 
 
 
 
1180a53
66028cc
 
4e05a46
a66d87f
66028cc
 
1180a53
66028cc
 
 
 
 
 
 
 
 
 
4e05a46
 
 
1a42889
 
 
 
66028cc
 
 
4e05a46
66028cc
4e05a46
1a42889
 
 
66028cc
 
1180a53
66028cc
 
1180a53
66028cc
 
 
 
 
 
 
 
 
 
 
 
 
 
1180a53
 
66028cc
1180a53
 
66028cc
 
1180a53
d0873ef
1180a53
 
 
 
 
 
66028cc
 
1180a53
66028cc
 
 
1180a53
66028cc
 
 
 
 
 
 
1180a53
66028cc
 
 
 
1180a53
66028cc
 
 
 
 
1180a53
66028cc
 
 
 
 
1180a53
66028cc
 
 
 
 
 
 
1180a53
66028cc
 
 
a66d87f
 
 
 
 
 
 
 
1180a53
 
a66d87f
 
 
 
 
 
 
1180a53
a66d87f
 
 
 
 
 
1180a53
a66d87f
 
 
 
 
 
 
 
1180a53
a66d87f
 
1180a53
66028cc
1180a53
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import os
from fastapi import FastAPI, Request, Form
from pydantic import BaseModel
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from datasets import load_from_disk
import torch
import random
import subprocess
import json

# Caricamento del modello e dei dati se già scaricati
MODEL = "cardiffnlp/twitter-roberta-base-sentiment-latest"
TWEET_PROCESSED_PATH = "data/processed/tweet_eval_tokenized"
YT_PROCESSED_PATH = "data/processed/youtube_tokenized"

tokenizer = AutoTokenizer.from_pretrained(MODEL)
model = AutoModelForSequenceClassification.from_pretrained(MODEL)


labels = ["negative", "neutral", "positive"]


# TWEET EVAL
if not os.path.exists(TWEET_PROCESSED_PATH):
    print(f"Dataset Tweet Eval non trovato in {TWEET_PROCESSED_PATH}. Lo genero...")

    if not os.environ.get("SKIP_DATA_PREP"):
        if not os.path.exists(TWEET_PROCESSED_PATH):
            subprocess.run(["python", "src/data_preparation.py", "tweet_eval"], check=True)
tweet_eval = load_from_disk(TWEET_PROCESSED_PATH)


# YOUTUBE COMMENTS
if not os.path.exists(YT_PROCESSED_PATH):
    print(f" Dataset YouTube non trovato in {YT_PROCESSED_PATH}. Lo genero...")
    if not os.environ.get("SKIP_DATA_PREP"):
        if not os.path.exists(YT_PROCESSED_PATH):
            subprocess.run(["python", "src/data_preparation.py", "youtube"], check=True)
youtube_ds = load_from_disk(YT_PROCESSED_PATH)

app = FastAPI(title="Sentiment Analysis API")
templates = Jinja2Templates(directory="app_templates/")


class TextInput(BaseModel):
    text: str


def predict_sentiment(text: str):
    inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
    with torch.no_grad():
        outputs = model(**inputs)
        probs = torch.nn.functional.softmax(outputs.logits, dim=-1)
        pred = torch.argmax(probs, dim=1).item()
        confidence = probs[0][pred].item()
    return {"label": labels[pred], "confidence": round(confidence, 3)}


@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})


@app.get("/random_tweet", response_class=HTMLResponse)
def random_tweet(request: Request):
    #  sample = random.choice(tweet_eval["test"])
    sample = tweet_eval["test"][random.randrange(len(tweet_eval["test"]))]
    text = (
        sample["text"]
        if "text" in sample
        else tokenizer.decode(sample["input_ids"], skip_special_tokens=True)
    )

    result = predict_sentiment(text)

    true_label = labels[sample["label"]]

    return templates.TemplateResponse(
        "random_tweet.html",
        {"request": request, "text": text, "true_label": true_label, "result": result},
    )


@app.get("/predict", response_class=HTMLResponse)
def predict_page(request: Request):
    return templates.TemplateResponse("predict.html", {"request": request, "result": None})


@app.post("/predict", response_class=HTMLResponse)
def predict_text(request: Request, text: str = Form(...)):
    result = predict_sentiment(text)
    return templates.TemplateResponse(
        "predict.html", {"request": request, "text": text, "result": result}
    )


@app.get("/random_youtube_comment", response_class=HTMLResponse)
def random_youtube_comment(request: Request):
    sample = random.choice(youtube_ds["train"])

    text = sample["text"] if "text" in sample else sample["text"]
    true_label = sample["label"] if "label" in sample else "N/A"

    if isinstance(true_label, int):

        label_map = {0: "negative", 1: "neutral", 2: "positive"}
        true_label = label_map.get(true_label, "N/A")

    result = predict_sentiment(text)

    return templates.TemplateResponse(
        "random_youtube.html",
        {"request": request, "text": text, "true_label": true_label, "result": result},
    )


@app.get("/admin", response_class=HTMLResponse)
async def admin_dashboard(request: Request):
    """Pagina principale dell'area admin."""
    metrics = None
    metrics_path = "reports/metrics.json"
    if os.path.exists(metrics_path):
        with open(metrics_path, "r") as f:
            metrics = json.load(f)
    return templates.TemplateResponse("admin.html", {"request": request, "metrics": metrics})


@app.post("/admin/train")
async def retrain_model():
    """Lancia lo script di training."""
    subprocess.run(["python", "src/train.py"], check=True)
    return {"status": "Training completato"}


@app.post("/admin/monitor")
async def run_monitoring():
    """Esegue il monitoring e aggiorna metrics.json."""
    subprocess.run(["python", "src/monitoring.py"], check=True)
    return {"status": "Monitoring completato"}


@app.get("/admin/metrics", response_class=HTMLResponse)
def view_metrics(request: Request):
    """Visualizza i risultati del monitoring in forma tabellare e grafica."""
    metrics_path = "reports/metrics.json"
    metrics = None
    if os.path.exists(metrics_path):
        with open(metrics_path, "r") as f:
            metrics = json.load(f)
    return templates.TemplateResponse("metrics.html", {"request": request, "metrics": metrics})


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)