GoshawkVortexAI commited on
Commit
3c0592e
·
verified ·
1 Parent(s): bf9d6aa

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -428
app.py DELETED
@@ -1,428 +0,0 @@
1
- import os
2
- import torch
3
- import gradio as gr
4
-
5
- from transformers import (
6
- AutoTokenizer,
7
- AutoModelForSequenceClassification
8
- )
9
-
10
- from peft import PeftModel
11
-
12
-
13
- # ================================================================
14
- # CONFIG
15
- # ================================================================
16
-
17
- BASE_MODEL = "distilbert-base-uncased"
18
- ADAPTER_PATH = "."
19
-
20
- MAX_LENGTH = 128
21
-
22
- LABELS = {
23
- 0: "negative",
24
- 1: "neutral",
25
- 2: "positive"
26
- }
27
-
28
-
29
- # ================================================================
30
- # DEVICE
31
- # ================================================================
32
-
33
- DEVICE = torch.device(
34
- "cuda" if torch.cuda.is_available() else "cpu"
35
- )
36
-
37
- print("=" * 60)
38
- print("INSURANCE SENTIMENT AI")
39
- print("=" * 60)
40
-
41
- print("Device:", DEVICE)
42
-
43
- if torch.cuda.is_available():
44
- print("GPU:", torch.cuda.get_device_name(0))
45
-
46
-
47
- # ================================================================
48
- # CHECK FILES
49
- # ================================================================
50
-
51
- print("\nChecking model files...")
52
-
53
- required_files = [
54
- "adapter_config.json",
55
- "adapter_model.safetensors",
56
- "tokenizer.json",
57
- "tokenizer_config.json"
58
- ]
59
-
60
- for file in required_files:
61
-
62
- path = os.path.join(
63
- ADAPTER_PATH,
64
- file
65
- )
66
-
67
- print(
68
- file,
69
- "->",
70
- "OK" if os.path.exists(path) else "MISSING"
71
- )
72
-
73
-
74
- # ================================================================
75
- # TOKENIZER
76
- # ================================================================
77
-
78
- print("\nLoading tokenizer...")
79
-
80
- tokenizer = AutoTokenizer.from_pretrained(
81
- ADAPTER_PATH,
82
- use_fast=True
83
- )
84
-
85
- print("Tokenizer loaded.")
86
-
87
-
88
- # ================================================================
89
- # BASE MODEL
90
- # ================================================================
91
-
92
- print("\nLoading base DistilBERT...")
93
-
94
- base_model = AutoModelForSequenceClassification.from_pretrained(
95
- BASE_MODEL,
96
- num_labels=3,
97
- id2label=LABELS,
98
- label2id={
99
- "negative": 0,
100
- "neutral": 1,
101
- "positive": 2
102
- },
103
- ignore_mismatched_sizes=True
104
- )
105
-
106
- print("Base model loaded.")
107
-
108
-
109
- # ================================================================
110
- # LOAD LoRA
111
- # ================================================================
112
-
113
- print("\nLoading LoRA adapter...")
114
-
115
- model = PeftModel.from_pretrained(
116
- base_model,
117
- ADAPTER_PATH
118
- )
119
-
120
- print("LoRA adapter loaded.")
121
-
122
-
123
- # ================================================================
124
- # MERGE LoRA
125
- # ================================================================
126
-
127
- print("\nMerging LoRA adapter...")
128
-
129
- try:
130
-
131
- model = model.merge_and_unload()
132
-
133
- print("LoRA merged successfully.")
134
-
135
- except Exception as e:
136
-
137
- print("Merge skipped:", str(e))
138
-
139
-
140
- # ================================================================
141
- # DEVICE
142
- # ================================================================
143
-
144
- model = model.to(DEVICE)
145
-
146
- model.eval()
147
-
148
- print("\nModel ready.")
149
-
150
-
151
- # ================================================================
152
- # PREDICTION
153
- # ================================================================
154
-
155
- def predict_sentiment(text):
156
-
157
- if text is None:
158
- return {
159
- "negative": 0.0,
160
- "neutral": 0.0,
161
- "positive": 0.0
162
- }
163
-
164
- text = str(text).strip()
165
-
166
- if not text:
167
-
168
- return {
169
- "negative": 0.0,
170
- "neutral": 0.0,
171
- "positive": 0.0
172
- }
173
-
174
- # ------------------------------------------------------------
175
- # Tokenize
176
- # ------------------------------------------------------------
177
-
178
- inputs = tokenizer(
179
- text,
180
- return_tensors="pt",
181
- truncation=True,
182
- max_length=MAX_LENGTH,
183
- padding=True
184
- )
185
-
186
- inputs = {
187
- key: value.to(DEVICE)
188
- for key, value in inputs.items()
189
- }
190
-
191
- # ------------------------------------------------------------
192
- # Inference
193
- # ------------------------------------------------------------
194
-
195
- with torch.inference_mode():
196
-
197
- outputs = model(
198
- **inputs
199
- )
200
-
201
- probabilities = torch.softmax(
202
- outputs.logits,
203
- dim=-1
204
- )[0]
205
-
206
- # ------------------------------------------------------------
207
- # Results
208
- # ------------------------------------------------------------
209
-
210
- result = {
211
- "negative": float(
212
- probabilities[0].item()
213
- ),
214
-
215
- "neutral": float(
216
- probabilities[1].item()
217
- ),
218
-
219
- "positive": float(
220
- probabilities[2].item()
221
- )
222
- }
223
-
224
- return result
225
-
226
-
227
- # ================================================================
228
- # DETAILED PREDICTION
229
- # ================================================================
230
-
231
- def analyze_news(text):
232
-
233
- if text is None or not str(text).strip():
234
-
235
- return (
236
- "Please enter an insurance news headline.",
237
- "",
238
- ""
239
- )
240
-
241
- text = str(text).strip()
242
-
243
- probabilities = predict_sentiment(text)
244
-
245
- predicted_label = max(
246
- probabilities,
247
- key=probabilities.get
248
- )
249
-
250
- confidence = (
251
- probabilities[predicted_label] * 100
252
- )
253
-
254
- result_text = (
255
- f"Prediction: {predicted_label.upper()}\n"
256
- f"Confidence: {confidence:.2f}%"
257
- )
258
-
259
- probability_text = (
260
- f"Negative: "
261
- f"{probabilities['negative'] * 100:.2f}%\n"
262
- f"Neutral: "
263
- f"{probabilities['neutral'] * 100:.2f}%\n"
264
- f"Positive: "
265
- f"{probabilities['positive'] * 100:.2f}%"
266
- )
267
-
268
- return (
269
- result_text,
270
- probability_text,
271
- text
272
- )
273
-
274
-
275
- # ================================================================
276
- # EXAMPLES
277
- # ================================================================
278
-
279
- examples = [
280
-
281
- [
282
- "Insurance companies reported strong financial results."
283
- ],
284
-
285
- [
286
- "The insurer suffered major losses after severe claims."
287
- ],
288
-
289
- [
290
- "The insurance company maintained stable operations."
291
- ],
292
-
293
- [
294
- "The insurer reported record profits and strong growth."
295
- ],
296
-
297
- [
298
- "Insurance claims increased significantly after the disaster."
299
- ]
300
- ]
301
-
302
-
303
- # ================================================================
304
- # GRADIO UI
305
- # ================================================================
306
-
307
- DESCRIPTION = """
308
- # 🛡️ Insurance Sentiment AI
309
-
310
- AI-powered sentiment analysis for **insurance news headlines**.
311
-
312
- ### Classes
313
-
314
- 🟢 **Positive** — favorable insurance/business news
315
- ⚪ **Neutral** — factual or balanced news
316
- 🔴 **Negative** — unfavorable insurance/business news
317
-
318
- Model: **DistilBERT + LoRA**
319
-
320
- Validation Macro F1: **78.06%**
321
- """
322
-
323
-
324
- with gr.Blocks(
325
- title="Insurance Sentiment AI"
326
- ) as demo:
327
-
328
- gr.Markdown(
329
- DESCRIPTION
330
- )
331
-
332
- gr.Markdown(
333
- "Enter an English insurance news headline:"
334
- )
335
-
336
- with gr.Row():
337
-
338
- with gr.Column():
339
-
340
- text_input = gr.Textbox(
341
- label="Insurance News",
342
- placeholder=(
343
- "Example: "
344
- "Insurance companies reported "
345
- "strong financial results."
346
- ),
347
- lines=5
348
- )
349
-
350
- analyze_button = gr.Button(
351
- "🔍 Analyze Sentiment",
352
- variant="primary"
353
- )
354
-
355
- with gr.Column():
356
-
357
- prediction_output = gr.Textbox(
358
- label="Prediction",
359
- lines=3
360
- )
361
-
362
- probability_output = gr.Textbox(
363
- label="Probabilities",
364
- lines=4
365
- )
366
-
367
- analyzed_text = gr.Textbox(
368
- label="Analyzed Headline",
369
- lines=3
370
- )
371
-
372
- analyze_button.click(
373
- fn=analyze_news,
374
- inputs=text_input,
375
- outputs=[
376
- prediction_output,
377
- probability_output,
378
- analyzed_text
379
- ]
380
- )
381
-
382
- text_input.submit(
383
- fn=analyze_news,
384
- inputs=text_input,
385
- outputs=[
386
- prediction_output,
387
- probability_output,
388
- analyzed_text
389
- ]
390
- )
391
-
392
- gr.Examples(
393
- examples=examples,
394
- inputs=text_input
395
- )
396
-
397
- gr.Markdown(
398
- """
399
- ---
400
-
401
- ### Model Information
402
-
403
- - **Base:** DistilBERT
404
- - **Fine-tuning:** LoRA / PEFT
405
- - **Task:** Insurance News Sentiment Classification
406
- - **Labels:** Negative / Neutral / Positive
407
- - **Validation Accuracy:** 79.75%
408
- - **Validation Macro F1:** 78.06%
409
- """
410
- )
411
-
412
-
413
- # ================================================================
414
- # LAUNCH
415
- # ================================================================
416
-
417
- if __name__ == "__main__":
418
-
419
- demo.launch(
420
- server_name="0.0.0.0",
421
- server_port=int(
422
- os.environ.get(
423
- "PORT",
424
- 7860
425
- )
426
- ),
427
- show_error=True
428
- )