from flask import Flask, render_template, request, jsonify import joblib import sys import traceback import pandas as pd import re app = Flask(__name__) # ----------------------------- # Load kamus CSV (delimiter ;) # ----------------------------- kamus_df = pd.read_csv('kamus_normalize.csv', sep=';') kamus_df.columns = kamus_df.columns.str.strip() # hilangkan spasi di nama kolom kamus = dict(zip(kamus_df['BEFORE'], kamus_df['AFTER'])) # ----------------------------- # Preprocessing function # ----------------------------- def preprocess(text): text = text.lower() for k, v in kamus.items(): text = text.replace(k, v) text = re.sub(r'[^a-z\s]', '', text) text = re.sub(r'\s+', ' ', text).strip() return text # ----------------------------- # Load model, vectorizer, LabelEncoder # ----------------------------- try: print("Python version:", sys.version) print("Loading TF-IDF vectorizer...") # Jika vectorizer pernah pakai custom analyzer, definisikan identity dulu: # def identity(x): return x vectorizer = joblib.load('tfidf_vectorizer.pkl') print("Vectorizer loaded:", type(vectorizer)) print("Loading Naive Bayes model...") model = joblib.load('nb_classifier.pkl') print("Model loaded:", type(model)) print("Loading LabelEncoder...") le = joblib.load('label_encoder.pkl') print("LabelEncoder loaded:", type(le)) except FileNotFoundError as e: print(f"Error: {e}") raise except Exception as e: print(f"Error loading models: {str(e)}") traceback.print_exc() raise # ----------------------------- # Routes # ----------------------------- @app.route('/') def home(): return render_template('index.html') @app.route('/analyze', methods=['POST']) def analyze(): if request.method == 'POST': try: text = request.form['text'] print(f"Received text: {text}") # Preprocess input text_clean = preprocess(text) print(f"Preprocessed text: {text_clean}") # Transform and predict X = vectorizer.transform([text_clean]) pred_encoded = model.predict(X)[0] pred_label = le.inverse_transform([pred_encoded])[0] # output string print(f"Predicted label: {pred_label}") # Get prediction probabilities probs = model.predict_proba(X)[0] # Ambil index probabilitas positif/negatif labels = le.inverse_transform(range(len(probs))) # misal ['negatif', 'positif'] neg_idx = list(labels).index('negatif') pos_idx = list(labels).index('positif') # Map ke key JS yang sesuai prob_percentages = { 'Positive': f"{probs[pos_idx]*100:.2f}%", 'Negative': f"{probs[neg_idx]*100:.2f}%"} # Pastikan sentimen dikirim bahasa Inggris untuk JS pred_label_lower = pred_label.lower().strip() if pred_label_lower == 'positif': sentiment_str = 'Positive' else: sentiment_str = 'Negative' # Map probabilities to correct labels (hanya negatif/positif) # label_order = le.inverse_transform(range(len(probs))) # ['negatif', 'positif'] # prob_percentages = {label.capitalize(): f"{prob*100:.2f}%" for label, prob in zip(label_order, probs)} return jsonify({ 'sentiment': pred_label.capitalize(), 'probabilities': prob_percentages }) except Exception as e: print(f"Error during analysis: {str(e)}") traceback.print_exc() return jsonify({'error': str(e)}), 500 # ----------------------------- # Run Flask # ----------------------------- if __name__ == '__main__': app.run(debug=True)