File size: 3,383 Bytes
6eb3a6c
13a39f1
 
 
 
 
 
 
 
 
 
 
 
24b360d
13a39f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6eb3a6c
13a39f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import streamlit as st
import numpy as np
import tensorflow as tf
from transformers import RobertaTokenizerFast, TFRobertaModel

MAX_LEN = 96
MODEL_PATH = "src/roberta_fold_1.h5" 

#MODEL ARCHITECTURE
def build_model():
    ids = tf.keras.layers.Input((MAX_LEN,), dtype=tf.int32, name="input_ids")
    att = tf.keras.layers.Input((MAX_LEN,), dtype=tf.int32, name="attention_mask")

    roberta = TFRobertaModel.from_pretrained('roberta-base', from_pt=True)
    x = roberta(ids, attention_mask=att)[0]
    x1 = tf.keras.layers.Dropout(0.1)(x) 
    start_logits = tf.keras.layers.Dense(1)(x1)
    start_logits = tf.keras.layers.Flatten()(start_logits)
    end_logits = tf.keras.layers.Dense(1)(x1)
    end_logits = tf.keras.layers.Flatten()(end_logits)
    
    model = tf.keras.Model(inputs=[ids, att], outputs=[start_logits, end_logits])
    return model

#MODEL
@st.cache_resource
def load_model_and_tokenizer():
    tokenizer = RobertaTokenizerFast.from_pretrained('roberta-base')
    model = build_model()
    model.load_weights(MODEL_PATH)
    return model, tokenizer

with st.spinner('Loading model and tokenizer... Please wait.'):
    model, tokenizer = load_model_and_tokenizer()

#PREDICTION 
def predict_sentiment(tweet, sentiment):
    # Preprocessing
    tweet = " " + " ".join(str(tweet).split())
    # Tokenization
    enc = tokenizer.encode_plus(
        sentiment, 
        tweet,
        add_special_tokens=True,
        max_length=MAX_LEN,
        padding='max_length',
        truncation=True,
        return_attention_mask=True)
    
    input_ids = np.array([enc['input_ids']])
    attention_mask = np.array([enc['attention_mask']])
    # Inference
    preds = model.predict([input_ids, attention_mask])
    start_logits = preds[0]
    end_logits = preds[1]
    
    idx_start = np.argmax(start_logits)
    idx_end = np.argmax(end_logits)
    # Decoding
    if sentiment == "neutral" or len(tweet.split()) < 2:
        return tweet.strip()
    # Validation check
    if idx_start > idx_end:
        return tweet.strip()
    else:
        text_tokens = tokenizer.decode(enc['input_ids'][idx_start:idx_end+1])
        return text_tokens.strip()

#INTERFACE
st.title("🐦 Tweet Sentiment Extraction")
st.markdown("""
This AI model analyzes a tweet and extracts the **specific phrase or word** that supports the selected sentiment.
*Built with TensorFlow & RoBERTa*
""")

#Inputs
col1, col2 = st.columns([1, 2])
with col1:
    sentiment = st.selectbox(
        "Select Sentiment:", 
        ["positive", "negative", "neutral"])
with col2:
    text = st.text_area(
        "Enter Tweet:", 
        value="This movie was really fantastic and I loved it!",
        height=100)
#Prediction
if st.button("Extract Phrase", type="primary"):
    if text:
        result = predict_sentiment(text, sentiment)
        st.write("### Result:")
        # Highlight Logic for Visualization
        if result in text and len(result) > 2:
            highlighted_text = text.replace(result, f"<span style='background-color: #ffd700; color: black; padding: 2px; font-weight: bold; border-radius: 3px;'>{result}</span>")
            st.markdown(f"**Context:** {highlighted_text}", unsafe_allow_html=True)
        else:
            st.markdown(f"**Context:** {text}")  
        st.success(f"Extracted Text: **{result}**")
    else:
        st.warning("Please enter a tweet to analyze.")