File size: 4,924 Bytes
0c56445
 
 
 
 
 
 
 
 
 
 
 
 
201eb52
 
 
 
 
 
 
 
 
0c56445
201eb52
 
 
0c56445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201eb52
 
 
0c56445
201eb52
 
0c56445
201eb52
 
 
 
 
 
0c56445
 
 
 
 
 
 
 
 
 
 
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
101
102
103
104
105
106
107
108
109
import streamlit as st
import joblib
import pandas as pd
import re
import nltk
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
import os

# --- Cài đặt và tải tài nguyên NLTK (quan trọng cho môi trường Docker) ---
# Tải stopwords vào thư mục con 'nltk_data'
# Điều này giúp Dockerfile dễ dàng sao chép và NLTK tìm thấy chúng
nltk_data_path = os.path.join(os.path.dirname(__file__), 'nltk_data')

# Đảm bảo thư mục tồn tại
os.makedirs(os.path.join(nltk_data_path, 'corpora'), exist_ok=True)
# Thêm đường dẫn này để NLTK tìm kiếm
nltk.data.path.append(nltk_data_path)

# Cố gắng tải stopwords
try:
    if not os.path.exists(os.path.join(nltk_data_path, 'corpora', 'stopwords')):
        nltk.download('stopwords', download_dir=nltk_data_path)
except Exception as e:
    st.error(f"Lỗi khi tải NLTK stopwords: {e}")
    st.stop() # Dừng ứng dụng nếu không tải được

# --- Tải mô hình ---
model = None
try:
    model_path = os.path.join(os.path.dirname(__file__), 'fake_news_model.pkl')
    model = joblib.load(model_path)
    st.success("Mô hình fake_news_model.pkl đã được tải thành công!")
except Exception as e:
    st.error(f"Lỗi khi tải mô hình: {e}. Vui lòng đảm bảo file mô hình nằm cùng thư mục với app.py.")
    st.stop() # Dừng ứng dụng nếu mô hình không tải được

# --- Khởi tạo Stemmer và Stopwords ---
ps = PorterStemmer()
# Đảm bảo NLTK tìm thấy stopwords từ đường dẫn đã chỉ định
try:
    stop_words = set(stopwords.words('english'))
except Exception as e:
    st.error(f"Lỗi khi tải stop words NLTK: {e}. Đảm bảo 'stopwords' đã được tải.")
    st.stop()

# --- Hàm tiền xử lý văn bản (PHẢI GIỐNG VỚI LÚC TRAIN) ---
def preprocess_text(text):
    if not isinstance(text, str):
        return ""
    text = text.lower()
    text = re.sub('[^a-zA-Z]', ' ', text)
    words = text.split()
    words = [ps.stem(word) for word in words if word not in stop_words]
    return ' '.join(words)

# --- Giao diện Streamlit ---
st.set_page_config(page_title="Phân biệt Tin tức Thật/Giả", layout="centered")

st.title("📰 Phân biệt Tin tức Thật/Giả")
st.markdown("Sử dụng mô hình AI để phân tích và xác định liệu một tin tức là thật hay giả.")

# Ô nhập tiêu đề
title_input = st.text_input("Tiêu đề tin tức:", placeholder="Nhập tiêu đề tin tức...")

# Ô nhập nội dung
content_input = st.text_area("Nội dung tin tức:", placeholder="Nhập toàn bộ nội dung tin tức...", height=250)

# Nút Analyze
if st.button("Phân tích"):
    if not title_input and not content_input:
        st.warning("Vui lòng nhập tiêu đề hoặc nội dung tin tức để phân tích.")
    elif model is None:
        st.error("Mô hình chưa sẵn sàng để phân tích. Vui lòng kiểm tra lại lỗi tải mô hình.")
    else:
        with st.spinner("Đang phân tích tin tức..."):
            combined_text = title_input + " " + content_input
            processed_text = preprocess_text(combined_text)

            try:
                # Giả định mô hình của bạn đã được huấn luyện để nhận một danh sách các chuỗi đã tiền xử lý
                # Nếu mô hình của bạn cần một TfidfVectorizer riêng, bạn cần tải nó và chuyển đổi processed_text
                prediction = model.predict([processed_text])[0]
                prediction_proba = model.predict_proba([processed_text])[0]

                # === ĐIỀU CHỈNH LOGIC Ở ĐÂY DỰA TRÊN 1=FAKE, 0=TRUE ===
                if prediction == 1: # Nếu prediction là 1, đó là TIN GIẢ
                    result_label = "Tin tức GIẢ"
                    color = "red"
                else: # Nếu prediction là 0, đó là TIN THẬT
                    result_label = "Tin tức THẬT"
                    color = "green"
                # =======================================================

                # Lấy độ tin cậy của lớp được dự đoán
                # Nếu prediction là 1 (FAKE), lấy xác suất của lớp 1
                # Nếu prediction là 0 (TRUE), lấy xác suất của lớp 0
                confidence = round(prediction_proba[prediction] * 100, 2)


                st.subheader("Kết quả phân tích:")
                st.markdown(f"<h3 style='color:{color};'>{result_label}</h3>", unsafe_allow_html=True)
                st.info(f"Độ tin cậy: **{confidence}%**")

            except Exception as e:
                st.error(f"Đã xảy ra lỗi trong quá trình dự đoán: {e}")

st.markdown("---")
st.markdown("Ứng dụng này được phát triển để mục đích minh họa và học tập.")