#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('
TULISKAN EKSPRESIMU DENGAN KATA-KATA
', 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")