Yk8746 commited on
Commit
8175a64
·
1 Parent(s): 52cbc54
history.csv ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ review,sentiment
2
+ its a superb movie,positive
3
+ its a crap,negative
4
+ "its somewhat okay
5
+ ",neutral
6
+ The climax is wawa,neutral
7
+ The climax is fantastic,positive
8
+ the color of product is bullshit,negative
9
+ the story is a scrap,negative
10
+ its a fantastic movie,positive
11
+ the movie is bullshit,negative
12
+ move is kind of okay,positive
13
+ its an above average movie,positive
14
+ its okay,neutral
15
+ its below average,negative
16
+ its above average,neutral
17
+ The product is entirely destructed\,negative
requirements.txt CHANGED
@@ -1,3 +1,6 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
1
+ transformers>=4.30.0
2
+ datasets>=2.12.0
3
+ pandas>=1.3.0
4
+ scikit-learn>=1.0.0
5
+ torch>=1.10.0
6
+ streamlit>=1.20.0
sentiment_model/config.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "distilbert-base-uncased",
3
+ "activation": "gelu",
4
+ "architectures": [
5
+ "DistilBertForSequenceClassification"
6
+ ],
7
+ "attention_dropout": 0.1,
8
+ "dim": 768,
9
+ "dropout": 0.1,
10
+ "hidden_dim": 3072,
11
+ "id2label": {
12
+ "0": "LABEL_0",
13
+ "1": "LABEL_1",
14
+ "2": "LABEL_2"
15
+ },
16
+ "initializer_range": 0.02,
17
+ "label2id": {
18
+ "LABEL_0": 0,
19
+ "LABEL_1": 1,
20
+ "LABEL_2": 2
21
+ },
22
+ "max_position_embeddings": 512,
23
+ "model_type": "distilbert",
24
+ "n_heads": 12,
25
+ "n_layers": 6,
26
+ "pad_token_id": 0,
27
+ "problem_type": "single_label_classification",
28
+ "qa_dropout": 0.1,
29
+ "seq_classif_dropout": 0.2,
30
+ "sinusoidal_pos_embds": false,
31
+ "tie_weights_": true,
32
+ "torch_dtype": "float32",
33
+ "transformers_version": "4.49.0",
34
+ "vocab_size": 30522
35
+ }
sentiment_model/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9422fd567a5f50cc403e0a56a08831a6bb38c89235b836141a38f222801675ea
3
+ size 267835644
sentiment_model/special_tokens_map.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "[CLS]",
3
+ "mask_token": "[MASK]",
4
+ "pad_token": "[PAD]",
5
+ "sep_token": "[SEP]",
6
+ "unk_token": "[UNK]"
7
+ }
sentiment_model/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
sentiment_model/tokenizer_config.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "100": {
12
+ "content": "[UNK]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "101": {
20
+ "content": "[CLS]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "102": {
28
+ "content": "[SEP]",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "103": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "clean_up_tokenization_spaces": false,
45
+ "cls_token": "[CLS]",
46
+ "do_lower_case": true,
47
+ "extra_special_tokens": {},
48
+ "mask_token": "[MASK]",
49
+ "model_max_length": 512,
50
+ "pad_token": "[PAD]",
51
+ "sep_token": "[SEP]",
52
+ "strip_accents": null,
53
+ "tokenize_chinese_chars": true,
54
+ "tokenizer_class": "DistilBertTokenizer",
55
+ "unk_token": "[UNK]"
56
+ }
sentiment_model/vocab.txt ADDED
The diff for this file is too large to render. See raw diff
 
streamlit_app.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import torch
4
+ from transformers import DistilBertTokenizerFast, DistilBertForSequenceClassification
5
+ import pandas as pd
6
+
7
+ # Set page config for a modern look
8
+ title = "AI Sentiment Classifier"
9
+ st.set_page_config(page_title=title, layout="centered")
10
+
11
+ # Custom CSS for high-tech look
12
+ st.markdown(
13
+ """
14
+ <style>
15
+ body {
16
+ background-color: #181A1B;
17
+ }
18
+ .main {
19
+ background-color: #23272A;
20
+ border-radius: 12px;
21
+ padding: 2rem 2rem 1.5rem 2rem;
22
+ box-shadow: 0 4px 32px 0 rgba(0,0,0,0.25);
23
+ }
24
+ .stTextArea textarea {
25
+ background-color: #23272A !important;
26
+ color: #F8F8F2 !important;
27
+ font-size: 1.1rem;
28
+ border-radius: 8px;
29
+ }
30
+ .stButton>button {
31
+ background: linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%);
32
+ color: #181A1B;
33
+ font-weight: bold;
34
+ border-radius: 8px;
35
+ border: none;
36
+ font-size: 1.1rem;
37
+ padding: 0.5rem 1.5rem;
38
+ }
39
+ .sentiment-box {
40
+ background: #23272A;
41
+ border: 2px solid #00C9FF;
42
+ border-radius: 10px;
43
+ padding: 1.2rem;
44
+ margin-top: 1.5rem;
45
+ text-align: center;
46
+ font-size: 1.3rem;
47
+ color: #00C9FF;
48
+ font-weight: bold;
49
+ letter-spacing: 1px;
50
+ box-shadow: 0 2px 16px 0 rgba(0,201,255,0.10);
51
+ }
52
+ </style>
53
+ """,
54
+ unsafe_allow_html=True,
55
+ )
56
+
57
+ st.markdown(f"<h1 style='text-align:center; color:#00C9FF; margin-bottom:0.2em'>{title}</h1>", unsafe_allow_html=True)
58
+ st.markdown("<h4 style='text-align:center; color:#F8F8F2; margin-top:0'>Classify the sentiment of your product or movie review instantly.</h4>", unsafe_allow_html=True)
59
+
60
+ st.markdown("""
61
+ <div class="main">
62
+ """, unsafe_allow_html=True)
63
+
64
+ review = st.text_area("Enter your review:", height=120, key="review_input")
65
+
66
+ # Load model and tokenizer only once
67
+ @st.cache_resource
68
+ def load_model():
69
+ model_dir = './sentiment_model'
70
+ tokenizer = DistilBertTokenizerFast.from_pretrained(model_dir)
71
+ model = DistilBertForSequenceClassification.from_pretrained(model_dir)
72
+ model.eval()
73
+ return tokenizer, model
74
+
75
+ tokenizer, model = load_model()
76
+
77
+ sentiment = None
78
+ show_result = False
79
+
80
+ if st.button("Analyze Sentiment"):
81
+ if review.strip():
82
+ # Tokenize and predict
83
+ inputs = tokenizer([review], padding=True, truncation=True, max_length=128, return_tensors='pt')
84
+ with torch.no_grad():
85
+ outputs = model(input_ids=inputs['input_ids'], attention_mask=inputs['attention_mask'])
86
+ pred = torch.argmax(outputs.logits, dim=1).item()
87
+ sentiment_map = {0: "negative", 1: "neutral", 2: "positive"}
88
+ sentiment = sentiment_map.get(pred, "unknown")
89
+ color = {"positive": "#00FFB3", "neutral": "#FFD600", "negative": "#FF4B4B"}[sentiment]
90
+ st.markdown(f"<div class='sentiment-box' style='color:{color};border-color:{color}'>Sentiment: {sentiment.capitalize()}</div>", unsafe_allow_html=True)
91
+ show_result = True
92
+ # Save to local history file
93
+ history_file = "history.csv"
94
+ file_exists = os.path.isfile(history_file)
95
+ import csv
96
+ with open(history_file, mode="a", newline='', encoding="utf-8") as f:
97
+ writer = csv.writer(f)
98
+ if not file_exists:
99
+ writer.writerow(["review", "sentiment"])
100
+ writer.writerow([review, sentiment])
101
+ else:
102
+ st.warning("Please enter a review to analyze.")
103
+
104
+ # Show history table
105
+ st.markdown("<hr style='margin:2em 0 1em 0;border:1px solid #222;'>", unsafe_allow_html=True)
106
+ st.subheader("Review History")
107
+ # Clear History Button
108
+ if st.button("Clear History 🗑️"):
109
+ history_file = "history.csv"
110
+ if os.path.isfile(history_file):
111
+ os.remove(history_file)
112
+ st.success("Review history cleared.")
113
+ st.experimental_rerun()
114
+
115
+ history_file = "history.csv"
116
+ if os.path.isfile(history_file):
117
+ try:
118
+ df = pd.read_csv(history_file)
119
+ if not df.empty:
120
+ st.dataframe(df[::-1].reset_index(drop=True), use_container_width=True)
121
+ else:
122
+ st.info("No review history yet.")
123
+ except Exception:
124
+ st.info("No review history yet.")
125
+ else:
126
+ st.info("No review history yet.")
127
+
128
+ st.markdown("""
129
+ </div>
130
+ """, unsafe_allow_html=True)