#2_jurnaling.py
import streamlit as st
import numpy as np
import pickle
import tensorflow as tf
import matplotlib.pyplot as plt
import pandas as pd
import gdown
import os
import re
from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
from nltk.corpus import stopwords
import nltk
nltk.download('stopwords')
st.set_page_config(
page_title="Analisis Journaling",
layout="wide",
initial_sidebar_state="collapsed"
)
MODEL_URL = "https://drive.google.com/uc?id=1ArBDPUBcPMdsUzH_dKwdjVEK-DyXG9qz"
TOKENIZER_URL = "https://drive.google.com/uc?id=1YVdwW-58y1Jie01MOjkd-4nY3bWFmt0E"
MODEL_PATH = "model/Pemodelan_GRU_Valid.keras"
TOKENIZER_PATH = "model/tokenizer_Valid.pkl"
os.makedirs("model", exist_ok=True)
@st.cache_resource
def load_model():
try:
if not os.path.exists(MODEL_PATH):
st.info("Mengunduh model dari Google Drive...")
gdown.download(MODEL_URL, MODEL_PATH, quiet=False)
return tf.keras.models.load_model(MODEL_PATH)
except Exception as e:
st.error(f"Gagal memuat model: {str(e)}")
st.warning("Model tidak ditemukan. Menggunakan data demo.")
return None
@st.cache_resource
def load_tokenizer():
try:
if not os.path.exists(TOKENIZER_PATH):
st.info("Mengunduh tokenizer dari Google Drive...")
gdown.download(TOKENIZER_URL, TOKENIZER_PATH, quiet=False)
with open(TOKENIZER_PATH, "rb") as handle:
return pickle.load(handle)
except Exception as e:
st.error(f"Gagal memuat tokenizer: {str(e)}")
st.warning("Tokenizer tidak ditemukan. Menggunakan data demo.")
return None
model = load_model()
tokenizer = load_tokenizer()
MAXLEN = 14
stop_words = set(stopwords.words('indonesian'))
stemmer = StemmerFactory().create_stemmer()
st.markdown("""
""", unsafe_allow_html=True)
st.markdown('
Analisis Jurnaling
', unsafe_allow_html=True)
st.markdown('', unsafe_allow_html=True)
text_input = st.text_area("", height=200, placeholder="Tuliskan isi jurnal anda di sini...")
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
st.markdown('', unsafe_allow_html=True)
analyze_button = st.button("Analisis Teks", key="analyze", use_container_width=True)
st.markdown('
', unsafe_allow_html=True)
def clean_text(text):
text = text.lower()
text = re.sub(r'http\S+', '', text)
text = re.sub(r'[^a-zA-Z\s]', '', text)
text = re.sub(r'\s+', ' ', text).strip()
words = text.split()
words = [stemmer.stem(word) for word in words if word not in stop_words]
return ' '.join(words)
def analyze_text(text):
if model is None or tokenizer is None:
return {
"emotions": {
"marah": 0.01,
"sedih": 0.02,
"jijik": 0.048,
"takut": 0.01,
"bahagia": 0.01,
"netral": 0.945,
"terkejut": 0.005
},
"dominant_emotion": "netral",
"text": text
}
clean_text_input = clean_text(text)
text_seq = tokenizer.texts_to_sequences([clean_text_input])
if not text_seq[0]:
st.warning("Teks tidak mengandung kata yang dikenali oleh model. Coba gunakan kata-kata yang lebih umum.")
return {
"emotions": {label: 0.0 for label in ["marah", "sedih", "bahagia", "takut", "jijik", "netral", "terkejut"]},
"dominant_emotion": "tidak_dikenali",
"text": text
}
text_padded = tf.keras.preprocessing.sequence.pad_sequences(text_seq, maxlen=MAXLEN, padding='post')
prediction = model.predict(text_padded, verbose=0)
predicted_class = np.argmax(prediction, axis=1)[0]
label_mapping = {0: "marah", 1: "sedih", 2: "bahagia", 3: "takut", 4: "jijik", 5: "netral", 6: "terkejut"}
emotion_label = label_mapping[predicted_class]
emotions = {}
for i, label in label_mapping.items():
emotions[label] = float(prediction[0][i])
return {
"emotions": emotions,
"dominant_emotion": emotion_label,
"text": text
}
if analyze_button:
if text_input:
result = analyze_text(text_input)
st.session_state.text_analysis_result = result
st.rerun()
else:
st.warning("Silakan masukkan teks terlebih dahulu.")
if 'text_analysis_result' in st.session_state:
result = st.session_state.text_analysis_result
st.markdown("### Hasil:")
st.markdown("#### Emosi Yang Terdeteksi:")
emotion_colors = {
"marah": "#E53935",
"sedih": "#7986CB",
"jijik": "#8BC34A",
"takut": "#FFB74D",
"bahagia": "#4CAF50",
"netral": "#9E9E9E",
"terkejut": "#1E88E5"
}
top_emotions = sorted(result["emotions"].items(), key=lambda x: x[1], reverse=True)[:3]
for emotion, score in top_emotions:
emotion_name = emotion.capitalize()
score_percent = score * 100
color = emotion_colors.get(emotion, "#FFFFFF")
st.markdown(
f'{emotion_name} {score_percent:.1f}%
',
unsafe_allow_html=True
)
st.markdown('Top 3 Emosi
', unsafe_allow_html=True)
emotions = [e[0].capitalize() for e in top_emotions]
scores = [e[1]*100 for e in top_emotions]
fig, ax = plt.subplots(figsize=(10, 4))
colors = [emotion_colors.get(emotion.lower(), "#1E88E5") for emotion in emotions]
bars = ax.barh(emotions, scores, color=colors, height=0.5)
for bar in bars:
width = bar.get_width()
ax.text(width + 1, bar.get_y() + bar.get_height()/2, f'{width:.1f}%',
va='center', fontweight='bold')
ax.set_xlim(0, 100)
ax.set_xlabel('Confidence (%)')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_color('#DDDDDD')
ax.spines['left'].set_color('#DDDDDD')
ax.tick_params(bottom=False, left=False)
ax.set_axisbelow(True)
ax.grid(axis='x', linestyle='-', alpha=0.2)
st.pyplot(fig)
positive_emotions = ["bahagia", "netral", "terkejut"]
negative_emotions = ["marah", "sedih", "jijik", "takut"]
positive_score = sum(result["emotions"][e] for e in positive_emotions) * 100
negative_score = sum(result["emotions"][e] for e in negative_emotions) * 100
st.markdown('', unsafe_allow_html=True)
st.markdown(
f'Positive Sentiment {positive_score:.1f}%
',
unsafe_allow_html=True
)
st.markdown(
f'Negative Sentiment {negative_score:.1f}%
',
unsafe_allow_html=True
)
fig2, ax2 = plt.subplots(figsize=(10, 2))
sentiments = ["Positive", "Negative"]
sentiment_scores = [positive_score, negative_score]
sentiment_colors = ["#4CAF50", "#E53935"]
bars2 = ax2.barh(sentiments, sentiment_scores, color=sentiment_colors, height=0.5)
for bar in bars2:
width = bar.get_width()
ax2.text(width + 1, bar.get_y() + bar.get_height()/2, f'{width:.1f}%',
va='center', fontweight='bold')
ax2.set_xlim(0, 100)
ax2.set_xlabel('Sentiment Score (%)')
ax2.spines['top'].set_visible(False)
ax2.spines['right'].set_visible(False)
ax2.spines['bottom'].set_color('#DDDDDD')
ax2.spines['left'].set_color('#DDDDDD')
ax2.tick_params(bottom=False, left=False)
ax2.set_axisbelow(True)
ax2.grid(axis='x', linestyle='-', alpha=0.2)
st.pyplot(fig2)
st.markdown('', unsafe_allow_html=True)
multimodal_button = st.button("Lihat Hasil Multimodal", key="multimodal", use_container_width=True)
st.markdown('
', unsafe_allow_html=True)
if multimodal_button:
st.switch_page("pages/3_hasil.py")