Saty01 commited on
Commit
844d2b9
·
verified ·
1 Parent(s): e4a1d3e

FactChecker files(final_deploy)

Browse files
.gitattributes CHANGED
@@ -33,3 +33,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ model_training/visualizations/fake_news_wordcloud.png filter=lfs diff=lfs merge=lfs -text
37
+ model_training/visualizations/feature_importance.png filter=lfs diff=lfs merge=lfs -text
38
+ model_training/visualizations/real_news_wordcloud.png filter=lfs diff=lfs merge=lfs -text
39
+ model_training/visualizations/roc_curves.png filter=lfs diff=lfs merge=lfs -text
40
+ model_training/visualizations/text_length_distribution.png filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Docker config.
2
+ FROM python:3.9
3
+
4
+ WORKDIR /app
5
+
6
+ # Install dependencies
7
+ COPY requirements.txt .
8
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
9
+
10
+ # Download NLTK resources(location:all users)
11
+ RUN python -c "import nltk; nltk.download('punkt', download_dir='/usr/local/share/nltk_data'); nltk.download('stopwords', download_dir='/usr/local/share/nltk_data'); nltk.download('wordnet', download_dir='/usr/local/share/nltk_data')"
12
+
13
+ # Create a user
14
+ RUN useradd -m -u 1000 user
15
+ USER user
16
+ ENV PATH="/home/user/.local/bin:$PATH"
17
+ RUN python -c "import nltk; nltk.download('punkt', download_dir='/usr/local/share/nltk_data'); nltk.download('stopwords', download_dir='/usr/local/share/nltk_data'); nltk.download('wordnet', download_dir='/usr/local/share/nltk_data')"
18
+ RUN python -c "import nltk; nltk.download('punkt_tab', download_dir='/usr/local/share/nltk_data')"
19
+ ENV NLTK_DATA="/usr/local/share/nltk_data"
20
+ ##
21
+
22
+ # Copy application files
23
+ COPY --chown=user ./app.py .
24
+ COPY --chown=user ./models ./models
25
+ COPY --chown=user ./build ./build
26
+
27
+ # Command to run Flask app with gunicorn
28
+ CMD ["gunicorn", "--bind", "0.0.0.0:7860", "app:app"]
README.md CHANGED
@@ -1,12 +1,12 @@
1
- ---
2
- title: FactChecker
3
- emoji: 🏃
4
- colorFrom: red
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- short_description: 'FactChecker: Fake News Detector'
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ ---
2
+ title: FactChecker
3
+ emoji: 📚
4
+ colorFrom: pink
5
+ colorTo: red
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ short_description: 'FactChecker: Fake News Detector'
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, send_from_directory
2
+ import pickle
3
+ import torch
4
+ import re
5
+ import nltk
6
+ from nltk.corpus import stopwords
7
+ from nltk.stem import WordNetLemmatizer
8
+ from transformers import DistilBertTokenizer, DistilBertModel
9
+ import torch.nn as nn
10
+ import os
11
+ import numpy
12
+
13
+ # Download NLTK stuff
14
+ nltk.data.path.append('/usr/local/share/nltk_data')
15
+ nltk.download('punkt_tab')
16
+ nltk.download('stopwords')
17
+ nltk.download('wordnet')
18
+ nltk.download('punkt')
19
+
20
+ app = Flask(__name__, static_folder='build', static_url_path='')
21
+
22
+ # Define DistilBERT model class
23
+ class DistilBERTClassifier(nn.Module):
24
+ def __init__(self, dropout_rate=0.2):
25
+ super(DistilBERTClassifier, self).__init__()
26
+ self.distilbert = DistilBertModel.from_pretrained('distilbert-base-uncased')
27
+ self.dropout = nn.Dropout(dropout_rate)
28
+ self.classifier = nn.Linear(768, 2)
29
+
30
+ def forward(self, input_ids, attention_mask):
31
+ outputs = self.distilbert(input_ids=input_ids, attention_mask=attention_mask)
32
+ pooled_output = outputs.last_hidden_state[:, 0]
33
+ pooled_output = self.dropout(pooled_output)
34
+ logits = self.classifier(pooled_output)
35
+ return logits
36
+
37
+ # Clean text function
38
+ def clean_text(text):
39
+ text = text.lower()
40
+ text = re.sub(r'http\S+|www\S+|https\S+', '', text)
41
+ text = re.sub(r'<.*?>', '', text)
42
+ text = re.sub(r'[^\w\s]', '', text)
43
+ text = re.sub(r'\d+', '', text)
44
+
45
+ tokens = nltk.word_tokenize(text)
46
+
47
+ stop_words = set(stopwords.words('english'))
48
+ lemmatizer = WordNetLemmatizer()
49
+ tokens = [lemmatizer.lemmatize(word) for word in tokens if word not in stop_words]
50
+
51
+ cleaned_text = ' '.join(tokens)
52
+ return cleaned_text
53
+
54
+ # Load models
55
+ def load_models():
56
+ # Set device
57
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
58
+
59
+ # TF-IDF vectorizer
60
+ with open('models/tfidf_vectorizer.pkl', 'rb') as f:
61
+ tfidf_vectorizer = pickle.load(f)
62
+
63
+ # Logistic Regression
64
+ with open('models/lr_model.pkl', 'rb') as f:
65
+ lr_model = pickle.load(f)
66
+
67
+ # random Forest
68
+ with open('models/rf_model.pkl', 'rb') as f:
69
+ rf_model = pickle.load(f)
70
+
71
+ # load DistilBERT
72
+ tokenizer = DistilBertTokenizer.from_pretrained('distilbert-base-uncased')
73
+ distilbert_model = DistilBERTClassifier()
74
+ distilbert_model.load_state_dict(torch.load('models/distilbert_model.pt', map_location=device))
75
+ distilbert_model.to(device)
76
+ distilbert_model.eval()
77
+
78
+ return tfidf_vectorizer, lr_model, rf_model, distilbert_model, tokenizer, device
79
+
80
+ # Load models at startup
81
+ tfidf_vectorizer, lr_model, rf_model, distilbert_model, tokenizer, device = load_models()
82
+
83
+ @app.route('/')
84
+ def serve():
85
+ return send_from_directory(app.static_folder, 'index.html')
86
+
87
+ @app.route('/api/analyze', methods=['POST'])
88
+ def analyze():
89
+ data = request.get_json()
90
+
91
+ if not data or 'text' not in data or 'model' not in data:
92
+ return jsonify({'error': 'Missing required fields'}), 400
93
+ news_text = data['text']
94
+ model_option = data['model']
95
+
96
+ if not news_text:
97
+ return jsonify({'error': 'Text cannot be empty'}), 400
98
+
99
+ # Clean text
100
+ cleaned_text = clean_text(news_text)
101
+
102
+ results = {}
103
+
104
+ # Using Logistic Regression
105
+ if model_option in ["lr", "all"]:
106
+ text_tfidf = tfidf_vectorizer.transform([cleaned_text])
107
+ lr_pred = lr_model.predict(text_tfidf)[0]
108
+ lr_prob = lr_model.predict_proba(text_tfidf)[0]
109
+ results["Logistic Regression"] = {
110
+ "prediction": "Real" if lr_pred == 1 else "Fake",
111
+ "fake_prob": float(lr_prob[0]),
112
+ "real_prob": float(lr_prob[1])
113
+ }
114
+
115
+ # Using Random Forest
116
+ if model_option in ["rf", "all"]:
117
+ text_tfidf = tfidf_vectorizer.transform([cleaned_text])
118
+ rf_pred = rf_model.predict(text_tfidf)[0]
119
+ rf_prob = rf_model.predict_proba(text_tfidf)[0]
120
+ results["Random Forest"] = {
121
+ "prediction": "Real" if rf_pred == 1 else "Fake",
122
+ "fake_prob": float(rf_prob[0]),
123
+ "real_prob": float(rf_prob[1])
124
+ }
125
+
126
+ # Using DistilBERT
127
+ if model_option in ["distilbert", "all"]:
128
+ encoding = tokenizer(
129
+ cleaned_text,
130
+ truncation=True,
131
+ padding='max_length',
132
+ max_length=128,
133
+ return_tensors='pt'
134
+ )
135
+
136
+ with torch.no_grad():
137
+ input_ids = encoding['input_ids'].to(device)
138
+ attention_mask = encoding['attention_mask'].to(device)
139
+ outputs = distilbert_model(input_ids=input_ids, attention_mask=attention_mask)
140
+ print("Raw model output:", outputs.cpu().numpy())
141
+ probs = torch.softmax(outputs, dim=1).cpu().numpy()[0]
142
+ print("After softmax:", probs)
143
+
144
+ print(f"Text: {cleaned_text[:50]}...")
145
+ print(f"Probabilities: Real={probs[0]:.4f}, Fake={probs[1]:.4f}")
146
+
147
+ distilbert_pred = 1 if probs[1] > probs[0] else 0
148
+ results["DistilBERT"] = {
149
+ "prediction": "Real" if distilbert_pred == 1 else "Fake",
150
+ "fake_prob": float(probs[0]),
151
+ "real_prob": float(probs[1])
152
+ }
153
+
154
+ # Calculate overall results for "all models" option
155
+ if model_option == "all":
156
+ real_votes = sum(1 for model, result in results.items() if result["prediction"] == "Real")
157
+ fake_votes = len(results) - real_votes
158
+ overall_verdict = "Real" if real_votes >= fake_votes else "Fake"
159
+ results["Overall"] = {
160
+ "prediction": overall_verdict,
161
+ "real_votes": real_votes,
162
+ "fake_votes": fake_votes,
163
+ "total_models": len(results)
164
+ }
165
+
166
+ return jsonify({'results': results})
167
+
168
+ if __name__ == '__main__':
169
+ port = int(os.environ.get('PORT', 7860))
170
+ app.run(host='0.0.0.0', port=port)
build/asset-manifest.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "files": {
3
+ "main.css": "/static/css/main.b34208b9.css",
4
+ "main.js": "/static/js/main.c63a58f2.js",
5
+ "index.html": "/index.html",
6
+ "main.b34208b9.css.map": "/static/css/main.b34208b9.css.map",
7
+ "main.c63a58f2.js.map": "/static/js/main.c63a58f2.js.map"
8
+ },
9
+ "entrypoints": [
10
+ "static/css/main.b34208b9.css",
11
+ "static/js/main.c63a58f2.js"
12
+ ]
13
+ }
build/index.html ADDED
@@ -0,0 +1 @@
 
 
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/logo.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>FactChecker</title><script defer="defer" src="/static/js/main.c63a58f2.js"></script><link href="/static/css/main.b34208b9.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
build/logo.ico ADDED
build/logo.png ADDED
build/manifest.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "short_name": "React App",
3
+ "name": "Create React App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
build/robots.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
build/static/css/main.b34208b9.css ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}*{box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;margin:0;padding:0}body{background-color:#f5f7fa;color:#333}.app{align-items:center;display:flex;justify-content:center;min-height:100vh;padding:20px}.container{max-width:600px;width:100%}.card{background-color:#fff;border-radius:12px;box-shadow:0 4px 20px #0000000d;overflow:hidden}.card-header{align-items:center;border-bottom:1px solid #f0f0f0;display:flex;justify-content:center;padding:24px 20px}h1{color:#333;font-size:18px;font-weight:600}form{padding:20px}textarea{border:1px solid #e8e8e8;border-radius:8px;color:#555;font-size:16px;height:150px;margin-bottom:16px;outline:none;padding:16px;resize:none;transition:border-color .2s;width:100%}textarea:focus{border-color:#4f8df8}textarea::placeholder{color:#aaa}.model-select{margin-bottom:16px}select{-webkit-appearance:none;appearance:none;background-color:#fff;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m1 1 5 5 5-5' stroke='%23888' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");background-position:right 16px center;background-repeat:no-repeat;border:1px solid #e8e8e8;border-radius:8px;color:#555;cursor:pointer;font-size:16px;outline:none;padding:12px 16px;width:100%}select:focus{border-color:#4f8df8}button{background-color:#4f8df8;border:none;border-radius:8px;color:#fff;cursor:pointer;font-size:16px;font-weight:600;padding:16px;transition:background-color .2s;width:100%}button:hover{background-color:#3a7fe5}button:disabled{background-color:#a5c4ff;cursor:not-allowed}.error{background-color:#ffefef;border-radius:8px;color:#e74c3c;font-size:14px;margin-top:16px;padding:12px}.results{padding:20px}.results h2{color:#333;font-size:18px;font-weight:600;margin-bottom:20px}.result-item{background-color:#f9f9f9;border-radius:8px;margin-bottom:16px;padding:16px}.result-item.real{border-left:4px solid #2ecc71}.result-item.fake{border-left:4px solid #e74c3c}.result-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:12px}.result-header h3{color:#333;font-size:16px;font-weight:600}.prediction-badge{border-radius:20px;font-size:14px;font-weight:600;padding:6px 12px}.real .prediction-badge{background-color:#e8f7f0;color:#2ecc71}.fake .prediction-badge{background-color:#fdeae8;color:#e74c3c}.confidence{margin-top:12px}.confidence-bar{background-color:#f0f0f0;border-radius:6px;height:12px;margin-bottom:8px;overflow:hidden}.confidence-fill{background-color:#4f8df8;border-radius:6px;height:100%;position:relative}.confidence-fill span{color:#fff;font-size:12px;font-weight:600;position:absolute;right:8px;top:-3px}.confidence p{color:#888;font-size:12px;text-align:right}.back-button{background-color:#e9ecef;color:#495057;margin-top:16px}.back-button:hover{background-color:#dee2e6}.logo-image{height:50px;object-fit:contain;width:50px}.icon{align-items:center;display:flex}
2
+ /*# sourceMappingURL=main.b34208b9.css.map*/
build/static/css/main.b34208b9.css.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"static/css/main.b34208b9.css","mappings":"AAAA,KAKI,kCAAmC,CACnC,iCAAkC,CAJlC,mIAEY,CAHZ,QAMF,CAEA,KACE,uEAEF,CCZF,EAGE,qBAAsB,CACtB,wHAC8D,CAJ9D,QAAS,CACT,SAIF,CAEA,KACE,wBAAyB,CACzB,UACF,CAEA,KAGE,kBAAmB,CAFnB,YAAa,CACb,sBAAuB,CAEvB,gBAAiB,CACjB,YACF,CAEA,WAEE,eAAgB,CADhB,UAEF,CAEA,MACE,qBAAuB,CACvB,kBAAmB,CACnB,+BAA0C,CAC1C,eACF,CAEA,aAEE,kBAAmB,CAGnB,+BAAgC,CAJhC,YAAa,CAEb,sBAAuB,CACvB,iBAEF,CAMA,GAGE,UAAW,CAFX,cAAe,CACf,eAEF,CAEA,KACE,YACF,CAEA,SAIE,wBAAyB,CACzB,iBAAkB,CAGlB,UAAW,CADX,cAAe,CALf,YAAa,CAOb,kBAAmB,CACnB,YAAa,CAPb,YAAa,CAGb,WAAY,CAKZ,2BAA6B,CAV7B,UAWF,CAEA,eACE,oBACF,CAEA,sBACE,UACF,CAEA,cACE,kBACF,CAEA,OASE,uBAAgB,CAAhB,eAAgB,CAFhB,qBAAuB,CAGvB,qOAA+O,CAE/O,qCAAsC,CADtC,2BAA4B,CAR5B,wBAAyB,CACzB,iBAAkB,CAElB,UAAW,CAOX,cAAe,CARf,cAAe,CAGf,YAAa,CANb,iBAAkB,CADlB,UAaF,CAEA,aACE,oBACF,CAEA,OAKE,wBAAyB,CAFzB,WAAY,CACZ,iBAAkB,CAElB,UAAY,CAGZ,cAAe,CAFf,cAAe,CACf,eAAgB,CANhB,YAAa,CAQb,+BAAiC,CATjC,UAUF,CAEA,aACE,wBACF,CAEA,gBACE,wBAAyB,CACzB,kBACF,CAEA,OAIE,wBAAyB,CADzB,iBAAkB,CAElB,aAAc,CACd,cAAe,CALf,eAAgB,CAChB,YAKF,CAGA,SACE,YACF,CAEA,YAIE,UAAW,CAHX,cAAe,CAEf,eAAgB,CADhB,kBAGF,CAEA,aAGE,wBAAyB,CADzB,iBAAkB,CAElB,kBAAmB,CAHnB,YAIF,CAEA,kBACE,6BACF,CAEA,kBACE,6BACF,CAEA,eAGE,kBAAmB,CAFnB,YAAa,CACb,6BAA8B,CAE9B,kBACF,CAEA,kBAGE,UAAW,CAFX,cAAe,CACf,eAEF,CAEA,kBAEE,kBAAmB,CACnB,cAAe,CACf,eAAgB,CAHhB,gBAIF,CAEA,wBACE,wBAAyB,CACzB,aACF,CAEA,wBACE,wBAAyB,CACzB,aACF,CAEA,YACE,eACF,CAEA,gBAEE,wBAAyB,CACzB,iBAAkB,CAFlB,WAAY,CAIZ,iBAAkB,CADlB,eAEF,CAEA,iBAEE,wBAAyB,CACzB,iBAAkB,CAFlB,WAAY,CAGZ,iBACF,CAEA,sBAME,UAAY,CAFZ,cAAe,CACf,eAAgB,CAJhB,iBAAkB,CAClB,SAAU,CACV,QAIF,CAEA,cAEE,UAAW,CADX,cAAe,CAEf,gBACF,CAEA,aAEE,wBAAyB,CACzB,aAAc,CAFd,eAGF,CAEA,mBACE,wBACF,CAEA,YAEE,WAAY,CACZ,kBAAmB,CAFnB,UAGF,CAEA,MAEE,kBAAmB,CADnB,YAEF","sources":["index.css","App.css"],"sourcesContent":["body {\r\n margin: 0;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\r\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\r\n sans-serif;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n }\r\n \r\n code {\r\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\r\n monospace;\r\n }","* {\r\n margin: 0;\r\n padding: 0;\r\n box-sizing: border-box;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,\r\n Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n}\r\n\r\nbody {\r\n background-color: #f5f7fa;\r\n color: #333;\r\n}\r\n\r\n.app {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n min-height: 100vh;\r\n padding: 20px;\r\n}\r\n\r\n.container {\r\n width: 100%;\r\n max-width: 600px;\r\n}\r\n\r\n.card {\r\n background-color: white;\r\n border-radius: 12px;\r\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);\r\n overflow: hidden;\r\n}\r\n\r\n.card-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 24px 20px;\r\n border-bottom: 1px solid #f0f0f0;\r\n}\r\n\r\n/* .icon {\r\n margin-right: 12px;\r\n} */\r\n\r\nh1 {\r\n font-size: 18px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\nform {\r\n padding: 20px;\r\n}\r\n\r\ntextarea {\r\n width: 100%;\r\n height: 150px;\r\n padding: 16px;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 8px;\r\n resize: none;\r\n font-size: 16px;\r\n color: #555;\r\n margin-bottom: 16px;\r\n outline: none;\r\n transition: border-color 0.2s;\r\n}\r\n\r\ntextarea:focus {\r\n border-color: #4F8DF8;\r\n}\r\n\r\ntextarea::placeholder {\r\n color: #aaa;\r\n}\r\n\r\n.model-select {\r\n margin-bottom: 16px;\r\n}\r\n\r\nselect {\r\n width: 100%;\r\n padding: 12px 16px;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 8px;\r\n font-size: 16px;\r\n color: #555;\r\n background-color: white;\r\n outline: none;\r\n appearance: none;\r\n background-image: url(\"data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%23888888' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\");\r\n background-repeat: no-repeat;\r\n background-position: right 16px center;\r\n cursor: pointer;\r\n}\r\n\r\nselect:focus {\r\n border-color: #4F8DF8;\r\n}\r\n\r\nbutton {\r\n width: 100%;\r\n padding: 16px;\r\n border: none;\r\n border-radius: 8px;\r\n background-color: #4F8DF8;\r\n color: white;\r\n font-size: 16px;\r\n font-weight: 600;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\nbutton:hover {\r\n background-color: #3a7fe5;\r\n}\r\n\r\nbutton:disabled {\r\n background-color: #a5c4ff;\r\n cursor: not-allowed;\r\n}\r\n\r\n.error {\r\n margin-top: 16px;\r\n padding: 12px;\r\n border-radius: 8px;\r\n background-color: #ffefef;\r\n color: #e74c3c;\r\n font-size: 14px;\r\n}\r\n\r\n/* Results styling */\r\n.results {\r\n padding: 20px;\r\n}\r\n\r\n.results h2 {\r\n font-size: 18px;\r\n margin-bottom: 20px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.result-item {\r\n padding: 16px;\r\n border-radius: 8px;\r\n background-color: #f9f9f9;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.result-item.real {\r\n border-left: 4px solid #2ecc71;\r\n}\r\n\r\n.result-item.fake {\r\n border-left: 4px solid #e74c3c;\r\n}\r\n\r\n.result-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.result-header h3 {\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.prediction-badge {\r\n padding: 6px 12px;\r\n border-radius: 20px;\r\n font-size: 14px;\r\n font-weight: 600;\r\n}\r\n\r\n.real .prediction-badge {\r\n background-color: #e8f7f0;\r\n color: #2ecc71;\r\n}\r\n\r\n.fake .prediction-badge {\r\n background-color: #fdeae8;\r\n color: #e74c3c;\r\n}\r\n\r\n.confidence {\r\n margin-top: 12px;\r\n}\r\n\r\n.confidence-bar {\r\n height: 12px;\r\n background-color: #f0f0f0;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.confidence-fill {\r\n height: 100%;\r\n background-color: #4F8DF8;\r\n border-radius: 6px;\r\n position: relative;\r\n}\r\n\r\n.confidence-fill span {\r\n position: absolute;\r\n right: 8px;\r\n top: -3px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: white;\r\n}\r\n\r\n.confidence p {\r\n font-size: 12px;\r\n color: #888;\r\n text-align: right;\r\n}\r\n\r\n.back-button {\r\n margin-top: 16px;\r\n background-color: #e9ecef;\r\n color: #495057;\r\n}\r\n\r\n.back-button:hover {\r\n background-color: #dee2e6;\r\n}\r\n\r\n.logo-image {\r\n width: 50px; \r\n height: 50px;\r\n object-fit: contain;\r\n}\r\n\r\n.icon {\r\n display: flex;\r\n align-items: center;\r\n}"],"names":[],"sourceRoot":""}
build/static/js/main.c63a58f2.js ADDED
The diff for this file is too large to render. See raw diff
 
build/static/js/main.c63a58f2.js.LICENSE.txt ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license React
3
+ * react-dom-client.production.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ /**
12
+ * @license React
13
+ * react-dom.production.js
14
+ *
15
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ */
20
+
21
+ /**
22
+ * @license React
23
+ * react-jsx-runtime.production.js
24
+ *
25
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
26
+ *
27
+ * This source code is licensed under the MIT license found in the
28
+ * LICENSE file in the root directory of this source tree.
29
+ */
30
+
31
+ /**
32
+ * @license React
33
+ * react.production.js
34
+ *
35
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
36
+ *
37
+ * This source code is licensed under the MIT license found in the
38
+ * LICENSE file in the root directory of this source tree.
39
+ */
40
+
41
+ /**
42
+ * @license React
43
+ * scheduler.production.js
44
+ *
45
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
46
+ *
47
+ * This source code is licensed under the MIT license found in the
48
+ * LICENSE file in the root directory of this source tree.
49
+ */
build/static/js/main.c63a58f2.js.map ADDED
The diff for this file is too large to render. See raw diff
 
model_training/model_training.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
model_training/visualizations/class_distribution.png ADDED
model_training/visualizations/distilbert_confusion_matrix.png ADDED
model_training/visualizations/fake_news_wordcloud.png ADDED

Git LFS Details

  • SHA256: 0efbdc3a3b9e7c2485fccffb75107a17ae820aa310151c00ffe3e0c4acc788dd
  • Pointer size: 132 Bytes
  • Size of remote file: 1.53 MB
model_training/visualizations/feature_importance.png ADDED

Git LFS Details

  • SHA256: 842508752fd83e145688ef8ae92ce5e8a1d4105cfc5eeeb06e439e5cb1207aa8
  • Pointer size: 131 Bytes
  • Size of remote file: 148 kB
model_training/visualizations/lr_confusion_matrix.png ADDED
model_training/visualizations/model_comparison.png ADDED
model_training/visualizations/real_news_wordcloud.png ADDED

Git LFS Details

  • SHA256: a50c137d1379cca5a5f0447a9740d6936a2c7ad3f4466c834a42356a5849121c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.42 MB
model_training/visualizations/rf_confusion_matrix.png ADDED
model_training/visualizations/roc_curves.png ADDED

Git LFS Details

  • SHA256: 2ef1c56f7fcc9e1789f5fdb441feb036e479ab1c6fe4248bfb267751650937af
  • Pointer size: 131 Bytes
  • Size of remote file: 220 kB
model_training/visualizations/text_length_distribution.png ADDED

Git LFS Details

  • SHA256: 4f1c0a35ecc63c1cfebeb23990b1d4b6195c335b56d7072248f4a71c16929823
  • Pointer size: 131 Bytes
  • Size of remote file: 101 kB
models/distilbert_model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0181662839f9ed56480b01882d344bb0f3ea133fe154a184562e089651dc413f
3
+ size 265499424
models/lr_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:abbb63f0866d81b83fbddf21308879f1f4d475f24b337050c0a9e31f9bccbc8b
3
+ size 80784
models/rf_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:04577df8c9f96e29bc7614f16f72f733de4e0a41288b4211e1d05a80bfbd29d0
3
+ size 53206112
models/tfidf_vectorizer.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7eba5171ee839fc50cf4d5eed7bf3e5e1d6a7822cd6cbe00b0e368fa77ad070f
3
+ size 372373
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ flask==2.0.1
2
+ werkzeug==2.0.3
3
+ torch==2.6.0
4
+ transformers==4.49.0
5
+ scikit-learn==1.6.1
6
+ nltk==3.9.1
7
+ regex==2023.6.3
8
+ numpy==2.0.2
9
+ gunicorn==20.1.0
10
+ matplotlib==3.7.2