SreyaDvn commited on
Commit
d939482
ยท
verified ยท
1 Parent(s): 43f6086

Upload 5 files

Browse files
Files changed (5) hide show
  1. .gitignore +30 -0
  2. Dockerfile +18 -0
  3. app.py +63 -0
  4. predictor.py +46 -0
  5. requirements.txt +0 -0
.gitignore ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ignore Python cache and bytecode
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+
6
+ # Ignore virtual environment
7
+ venv/
8
+
9
+ # Ignore saved model files
10
+ saved_model/
11
+ *.safetensors
12
+ *.pt
13
+ *.bin
14
+ *.ckpt
15
+
16
+ # Ignore logs or runtime data
17
+ *.log
18
+ *.csv
19
+ *.tmp
20
+ *.DS_Store
21
+
22
+ # Ignore Jupyter Notebook checkpoints
23
+ .ipynb_checkpoints/
24
+
25
+ # Ignore environment files if sensitive
26
+ .env
27
+
28
+ *.pyc
29
+ *.pyo
30
+ *.pyd
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a slim Python image
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory inside the container
5
+ WORKDIR /app
6
+
7
+ # Copy the requirements file and install dependencies
8
+ COPY requirements.txt .
9
+ RUN pip install --upgrade pip && pip install -r requirements.txt
10
+
11
+ # Copy all app files to the container
12
+ COPY . .
13
+
14
+ # Expose the port the app will run on (Hugging Face requires 7860)
15
+ EXPOSE 7860
16
+
17
+ # Run the Flask app
18
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request
2
+ import pandas as pd
3
+ from predictor import predict_sentiment
4
+ from flask import Flask, render_template, request, redirect, url_for
5
+
6
+
7
+ app = Flask(__name__)
8
+
9
+ # ๐Ÿ”˜ Single review input route
10
+ @app.route("/")
11
+ def root():
12
+ return redirect("/sentiment-review/single")
13
+ @app.route("/sentiment-review/single", methods=["GET", "POST"])
14
+ def single_review():
15
+ prediction = None
16
+ confidence = None
17
+ review = ""
18
+
19
+ if request.method == "POST":
20
+ review = request.form.get("review", "")
21
+ if review.strip():
22
+ prediction, confidence = predict_sentiment(review)
23
+
24
+ return render_template("index.html", prediction=prediction, confidence=confidence, review=review)
25
+
26
+ # ๐Ÿ“ Batch upload route
27
+ @app.route("/sentiment-review/batch", methods=["GET", "POST"])
28
+ def batch_review():
29
+ if request.method == "POST":
30
+ if 'csvfile' not in request.files:
31
+ return render_template("batch.html", error="No file part found.")
32
+
33
+ file = request.files['csvfile']
34
+ if file.filename == "":
35
+ return render_template("batch.html", error="No selected file.")
36
+
37
+ if file and file.filename.endswith(".csv"):
38
+ try:
39
+ df = pd.read_csv(file, encoding='utf-8')
40
+ if "review" not in df.columns:
41
+ return render_template("batch.html", error="CSV must have a 'review' column.")
42
+
43
+ results = []
44
+ for i, text in enumerate(df["review"].fillna("").tolist()):
45
+ sentiment, confidence = predict_sentiment(text)
46
+ print(f"๐Ÿง  Review {i+1}: {text[:40]}... โ†’ {sentiment} ({confidence})")
47
+ results.append({
48
+ "text": text,
49
+ "sentiment": sentiment,
50
+ "confidence": confidence
51
+ })
52
+
53
+ return render_template("batch.html", results=results)
54
+
55
+ except Exception as e:
56
+ print("โŒ CSV Processing error:", e)
57
+ return render_template("batch.html", error=f"Processing error: {str(e)}")
58
+
59
+ return render_template("batch.html", error="Invalid file format. Upload .csv only.")
60
+
61
+ return render_template("batch.html")
62
+ if __name__ == "__main__":
63
+ app.run(host="0.0.0.0", port=7860, debug=False)
predictor.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # predictor.py
2
+ import torch
3
+ from transformers import BertTokenizer, BertForSequenceClassification
4
+ import re
5
+
6
+ # โœ… Load model and tokenizer from Hugging Face Hub
7
+ MODEL_NAME = "SreyaDvn/sentiment-model"
8
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
9
+
10
+ try:
11
+ print("๐Ÿš€ Loading tokenizer and model from Hugging Face Hub...")
12
+ tokenizer = BertTokenizer.from_pretrained(MODEL_NAME)
13
+ model = BertForSequenceClassification.from_pretrained(MODEL_NAME)
14
+ model.to(device)
15
+ model.eval()
16
+ print("โœ… Model & tokenizer loaded successfully from Hugging Face.")
17
+ except Exception as e:
18
+ print("โŒ Error loading model/tokenizer:", e)
19
+
20
+ # ๐Ÿ” Text cleaner
21
+ def clean_text(text):
22
+ text = str(text).lower()
23
+ text = re.sub(r"http\S+", "", text)
24
+ text = re.sub(r"@\w+", "", text)
25
+ text = re.sub(r"#\w+", "", text)
26
+ text = re.sub(r"[^\w\s]", "", text)
27
+ text = re.sub(r"\d+", "", text)
28
+ text = re.sub(r"\s+", " ", text).strip()
29
+ return text
30
+
31
+ # ๐Ÿ”ฎ Sentiment prediction
32
+ def predict_sentiment(text):
33
+ try:
34
+ cleaned = clean_text(text)
35
+ inputs = tokenizer(cleaned, return_tensors="pt", truncation=True, padding=True, max_length=128)
36
+ inputs = {k: v.to(device) for k, v in inputs.items()}
37
+ with torch.no_grad():
38
+ outputs = model(**inputs)
39
+ probs = torch.softmax(outputs.logits, dim=1).cpu().numpy()[0]
40
+ pred_class = probs.argmax()
41
+ sentiment = "Positive ๐Ÿ‘๐Ÿป" if pred_class == 1 else "Negative ๐Ÿ‘Ž๐Ÿป"
42
+ confidence = f"{probs[pred_class] * 100:.2f}%"
43
+ return sentiment, confidence
44
+ except Exception as e:
45
+ print("โŒ Prediction error:", e)
46
+ return "Error", "0.00%"
requirements.txt ADDED
Binary file (1.28 kB). View file