ENTUM-AI commited on
Commit
78e1af8
Β·
verified Β·
1 Parent(s): 192673e

Upload FinBERT-Pro Financial Sentiment Gradio Space

Browse files
Files changed (2) hide show
  1. app.py +500 -0
  2. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import pipeline
3
+ import time
4
+
5
+ # ==========================================
6
+ # MODEL CONFIGURATION
7
+ # ==========================================
8
+ MODEL_NAME = "ENTUM-AI/FinBERT-Pro"
9
+
10
+ print(f"Loading model: {MODEL_NAME}...")
11
+ try:
12
+ classifier = pipeline("text-classification", model=MODEL_NAME, top_k=3)
13
+ print("Model loaded successfully!")
14
+ except Exception as e:
15
+ print(f"Error loading model: {e}")
16
+ classifier = None
17
+
18
+
19
+ # ==========================================
20
+ # PREDICTION LOGIC
21
+ # ==========================================
22
+ SENTIMENT_CONFIG = {
23
+ "Positive": {"color": "#16a34a", "bg": "#f0fdf4", "icon": "πŸ“ˆ", "bar": "#22c55e"},
24
+ "Negative": {"color": "#dc2626", "bg": "#fef2f2", "icon": "πŸ“‰", "bar": "#ef4444"},
25
+ "Neutral": {"color": "#2563eb", "bg": "#eff6ff", "icon": "βž–", "bar": "#3b82f6"},
26
+ }
27
+
28
+
29
+ def predict_single(text):
30
+ """Classify a single financial text."""
31
+ if not text or not text.strip():
32
+ return create_empty_result()
33
+
34
+ if classifier is None:
35
+ return create_error_result()
36
+
37
+ start = time.time()
38
+ results = classifier(text.strip())[0]
39
+ elapsed = (time.time() - start) * 1000
40
+
41
+ top = results[0]
42
+ return create_result_html(text.strip(), top["label"], results, elapsed)
43
+
44
+
45
+ def predict_batch(texts):
46
+ """Classify multiple financial texts (one per line)."""
47
+ if not texts or not texts.strip():
48
+ return "<p style='color:#94a3b8; text-align:center;'>Enter financial texts, one per line.</p>"
49
+
50
+ if classifier is None:
51
+ return create_error_result()
52
+
53
+ lines = [line.strip() for line in texts.strip().split("\n") if line.strip()]
54
+ if not lines:
55
+ return "<p style='color:#94a3b8; text-align:center;'>No valid texts found.</p>"
56
+
57
+ start = time.time()
58
+ all_results = classifier(lines)
59
+ elapsed = (time.time() - start) * 1000
60
+
61
+ counts = {"Positive": 0, "Negative": 0, "Neutral": 0}
62
+ html_parts = []
63
+
64
+ for text, results in zip(lines, all_results):
65
+ top = results[0]
66
+ label = top["label"]
67
+ score = top["score"]
68
+ counts[label] = counts.get(label, 0) + 1
69
+
70
+ cfg = SENTIMENT_CONFIG.get(label, SENTIMENT_CONFIG["Neutral"])
71
+ bar_width = int(score * 100)
72
+
73
+ html_parts.append(f"""
74
+ <div style="
75
+ background: {cfg['bg']};
76
+ border: 1px solid {cfg['color']}22;
77
+ border-left: 4px solid {cfg['color']};
78
+ border-radius: 12px;
79
+ padding: 16px 20px;
80
+ margin-bottom: 10px;
81
+ ">
82
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;">
83
+ <span style="color:#1e293b; font-size:14px; flex:1; margin-right:12px;">{cfg['icon']} {text}</span>
84
+ <span style="
85
+ background: {cfg['color']}15;
86
+ color: {cfg['color']};
87
+ padding: 4px 12px;
88
+ border-radius: 20px;
89
+ font-size: 12px;
90
+ font-weight: 700;
91
+ letter-spacing: 0.5px;
92
+ white-space: nowrap;
93
+ ">{label.upper()} {score:.0%}</span>
94
+ </div>
95
+ <div style="background:#e2e8f0; border-radius:6px; height:6px; overflow:hidden;">
96
+ <div style="width:{bar_width}%; height:100%; background:linear-gradient(90deg, {cfg['bar']}aa, {cfg['bar']}); border-radius:6px;"></div>
97
+ </div>
98
+ </div>
99
+ """)
100
+
101
+ # Summary card
102
+ total = len(lines)
103
+ summary = f"""
104
+ <div style="
105
+ background: #ffffff;
106
+ border: 1px solid #e2e8f0;
107
+ border-radius: 14px;
108
+ padding: 20px 24px;
109
+ margin-bottom: 16px;
110
+ text-align: center;
111
+ box-shadow: 0 1px 3px rgba(0,0,0,0.06);
112
+ ">
113
+ <span style="color:#64748b; font-size:12px; text-transform:uppercase; letter-spacing:1px;">Batch Sentiment Analysis</span>
114
+ <div style="display:flex; justify-content:center; gap:24px; margin-top:12px;">
115
+ <div>
116
+ <div style="color:#16a34a; font-size:24px; font-weight:800;">πŸ“ˆ {counts.get('Positive', 0)}</div>
117
+ <div style="color:#64748b; font-size:12px;">Positive</div>
118
+ </div>
119
+ <div>
120
+ <div style="color:#2563eb; font-size:24px; font-weight:800;">βž– {counts.get('Neutral', 0)}</div>
121
+ <div style="color:#64748b; font-size:12px;">Neutral</div>
122
+ </div>
123
+ <div>
124
+ <div style="color:#dc2626; font-size:24px; font-weight:800;">πŸ“‰ {counts.get('Negative', 0)}</div>
125
+ <div style="color:#64748b; font-size:12px;">Negative</div>
126
+ </div>
127
+ </div>
128
+ <div style="color:#94a3b8; font-size:12px; margin-top:10px;">{total} texts analyzed in {elapsed:.0f}ms</div>
129
+ </div>
130
+ """
131
+
132
+ return summary + "\n".join(html_parts)
133
+
134
+
135
+ # ==========================================
136
+ # HTML RESULT BUILDERS
137
+ # ==========================================
138
+ def create_result_html(text, top_label, all_scores, elapsed_ms):
139
+ cfg = SENTIMENT_CONFIG.get(top_label, SENTIMENT_CONFIG["Neutral"])
140
+
141
+ # Build sentiment bars for all 3 classes
142
+ bars_html = ""
143
+ for item in all_scores:
144
+ lbl = item["label"]
145
+ sc = item["score"]
146
+ c = SENTIMENT_CONFIG.get(lbl, SENTIMENT_CONFIG["Neutral"])
147
+ pct = int(sc * 100)
148
+ bars_html += f"""
149
+ <div style="margin-bottom:10px;">
150
+ <div style="display:flex; justify-content:space-between; margin-bottom:4px;">
151
+ <span style="color:#475569; font-size:13px; font-weight:600;">{c['icon']} {lbl}</span>
152
+ <span style="color:{c['color']}; font-weight:700; font-size:14px;">{sc:.1%}</span>
153
+ </div>
154
+ <div style="background:#f1f5f9; border-radius:6px; height:8px; overflow:hidden;">
155
+ <div style="width:{pct}%; height:100%; background:linear-gradient(90deg, {c['bar']}aa, {c['bar']}); border-radius:6px;"></div>
156
+ </div>
157
+ </div>
158
+ """
159
+
160
+ # Gradient background based on sentiment
161
+ if top_label == "Positive":
162
+ gradient = "linear-gradient(135deg, #dcfce7, #bbf7d0, #86efac)"
163
+ text_color = "#166534"
164
+ elif top_label == "Negative":
165
+ gradient = "linear-gradient(135deg, #fee2e2, #fecaca, #fca5a5)"
166
+ text_color = "#991b1b"
167
+ else:
168
+ gradient = "linear-gradient(135deg, #dbeafe, #bfdbfe, #93c5fd)"
169
+ text_color = "#1e40af"
170
+
171
+ top_score = all_scores[0]["score"]
172
+
173
+ return f"""
174
+ <div style="font-family: 'Inter', 'Segoe UI', sans-serif;">
175
+ <div style="
176
+ background: {gradient};
177
+ border-radius: 20px;
178
+ padding: 32px;
179
+ text-align: center;
180
+ margin-bottom: 20px;
181
+ border: 1px solid {cfg['color']}22;
182
+ box-shadow: 0 4px 24px {cfg['color']}15;
183
+ ">
184
+ <div style="font-size: 48px; margin-bottom: 8px;">{cfg['icon']}</div>
185
+ <div style="
186
+ color: {text_color};
187
+ font-size: 22px;
188
+ font-weight: 800;
189
+ letter-spacing: 2px;
190
+ margin-bottom: 6px;
191
+ ">{top_label.upper()} SENTIMENT</div>
192
+ <div style="color: {text_color}99; font-size: 14px;">Confidence: {top_score:.1%}</div>
193
+ </div>
194
+
195
+ <div style="
196
+ background: #ffffff;
197
+ border: 1px solid #e2e8f0;
198
+ border-radius: 16px;
199
+ padding: 24px;
200
+ box-shadow: 0 1px 3px rgba(0,0,0,0.06);
201
+ ">
202
+ <div style="margin-bottom: 20px;">
203
+ <span style="color: #64748b; font-size: 11px; text-transform: uppercase; letter-spacing: 1px;">Analyzed Text</span>
204
+ <div style="color: #1e293b; font-size: 15px; margin-top: 6px; font-style: italic;">"{text}"</div>
205
+ </div>
206
+
207
+ <div style="margin-bottom: 16px;">
208
+ <span style="color: #64748b; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px; display:block;">Score Breakdown</span>
209
+ {bars_html}
210
+ </div>
211
+
212
+ <div style="
213
+ display: flex;
214
+ justify-content: center;
215
+ gap: 24px;
216
+ padding-top: 12px;
217
+ border-top: 1px solid #f1f5f9;
218
+ ">
219
+ <div style="text-align: center;">
220
+ <span style="color: #94a3b8; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;">Model</span>
221
+ <div style="color: #6366f1; font-size: 13px; font-weight: 600; margin-top: 2px;">FinBERT-Pro</div>
222
+ </div>
223
+ <div style="text-align: center;">
224
+ <span style="color: #94a3b8; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;">Latency</span>
225
+ <div style="color: #0891b2; font-size: 13px; font-weight: 600; margin-top: 2px;">{elapsed_ms:.0f}ms</div>
226
+ </div>
227
+ <div style="text-align: center;">
228
+ <span style="color: #94a3b8; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;">Classes</span>
229
+ <div style="color: #d97706; font-size: 13px; font-weight: 600; margin-top: 2px;">3</div>
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </div>
234
+ """
235
+
236
+
237
+ def create_empty_result():
238
+ return """
239
+ <div style="
240
+ text-align: center;
241
+ padding: 60px 24px;
242
+ color: #94a3b8;
243
+ ">
244
+ <div style="font-size: 48px; margin-bottom: 12px;">πŸ’Ή</div>
245
+ <div style="font-size: 16px; font-weight: 600; color: #475569;">Awaiting Input</div>
246
+ <div style="font-size: 13px; margin-top: 4px;">Enter a financial text above and click <b>Analyze</b></div>
247
+ </div>
248
+ """
249
+
250
+
251
+ def create_error_result():
252
+ return """
253
+ <div style="
254
+ text-align: center;
255
+ padding: 40px 24px;
256
+ background: #fef2f2;
257
+ border-radius: 16px;
258
+ border: 1px solid #fecaca;
259
+ ">
260
+ <div style="font-size: 36px; margin-bottom: 8px;">⚠️</div>
261
+ <div style="color: #dc2626; font-size: 15px; font-weight: 600;">Model Not Available</div>
262
+ <div style="color: #64748b; font-size: 13px; margin-top: 4px;">Please wait while the model loads or try refreshing.</div>
263
+ </div>
264
+ """
265
+
266
+
267
+ # ==========================================
268
+ # CUSTOM CSS
269
+ # ==========================================
270
+ CUSTOM_CSS = """
271
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
272
+
273
+ * { font-family: 'Inter', 'Segoe UI', sans-serif !important; }
274
+
275
+ .gradio-container {
276
+ max-width: 960px !important;
277
+ margin: 0 auto !important;
278
+ background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 50%, #e2e8f0 100%) !important;
279
+ }
280
+
281
+ .main-header {
282
+ text-align: center;
283
+ padding: 40px 20px 20px;
284
+ }
285
+
286
+ .main-header h1 {
287
+ background: linear-gradient(135deg, #059669, #0891b2, #2563eb);
288
+ -webkit-background-clip: text;
289
+ -webkit-text-fill-color: transparent;
290
+ font-size: 2.5rem !important;
291
+ font-weight: 800 !important;
292
+ margin-bottom: 8px !important;
293
+ letter-spacing: -0.5px;
294
+ }
295
+
296
+ .main-header p {
297
+ color: #64748b !important;
298
+ font-size: 15px !important;
299
+ }
300
+
301
+ .model-badge {
302
+ display: inline-block;
303
+ background: linear-gradient(135deg, #ecfdf5, #e0f2fe);
304
+ border: 1px solid #a7f3d0;
305
+ color: #047857 !important;
306
+ padding: 6px 16px;
307
+ border-radius: 24px;
308
+ font-size: 13px !important;
309
+ font-weight: 600;
310
+ letter-spacing: 0.5px;
311
+ margin-top: 12px;
312
+ }
313
+
314
+ footer { display: none !important; }
315
+
316
+ .tab-nav button {
317
+ color: #64748b !important;
318
+ font-weight: 600 !important;
319
+ font-size: 14px !important;
320
+ }
321
+
322
+ .tab-nav button.selected {
323
+ color: #059669 !important;
324
+ border-color: #059669 !important;
325
+ }
326
+ """
327
+
328
+
329
+ # ==========================================
330
+ # GRADIO UI
331
+ # ==========================================
332
+ with gr.Blocks(
333
+ css=CUSTOM_CSS,
334
+ title="FinBERT-Pro β€” Financial Sentiment Analyzer",
335
+ theme=gr.themes.Soft(
336
+ primary_hue="emerald",
337
+ secondary_hue="cyan",
338
+ neutral_hue="slate",
339
+ ),
340
+ ) as demo:
341
+
342
+ # Header
343
+ gr.HTML("""
344
+ <div class="main-header">
345
+ <h1>πŸ’Ή FinBERT-Pro</h1>
346
+ <p>Financial sentiment analysis powered by <b>FinBERT</b>, fine-tuned on 3 expert-annotated datasets</p>
347
+ <span class="model-badge">🧠 ENTUM-AI / FinBERT-Pro</span>
348
+ </div>
349
+ """)
350
+
351
+ with gr.Tabs():
352
+ # --- Tab 1: Single Analysis ---
353
+ with gr.Tab("πŸ” Single Analysis"):
354
+ with gr.Row():
355
+ with gr.Column(scale=3):
356
+ single_input = gr.Textbox(
357
+ label="Financial Text",
358
+ placeholder="e.g. Stock price soars on record-breaking earnings report",
359
+ lines=2,
360
+ max_lines=4,
361
+ )
362
+ single_btn = gr.Button("⚑ Analyze Sentiment", variant="primary", size="lg")
363
+ with gr.Column(scale=4):
364
+ single_output = gr.HTML(value=create_empty_result())
365
+
366
+ gr.Examples(
367
+ examples=[
368
+ ["Stock price soars on record-breaking earnings report"],
369
+ ["Revenue decline signals weakening market position"],
370
+ ["Company announces quarterly earnings results"],
371
+ ["Shares surge 15% after strong Q3 revenue growth"],
372
+ ["Major layoffs expected as company restructures operations"],
373
+ ["The board of directors met to discuss routine operations"],
374
+ ["Bankruptcy filing raises concerns about long-term viability"],
375
+ ["Profit margins improved significantly driven by cost optimization"],
376
+ ],
377
+ inputs=single_input,
378
+ label="πŸ“‹ Try these examples",
379
+ )
380
+
381
+ single_btn.click(fn=predict_single, inputs=single_input, outputs=single_output)
382
+ single_input.submit(fn=predict_single, inputs=single_input, outputs=single_output)
383
+
384
+ # --- Tab 2: Batch Analysis ---
385
+ with gr.Tab("πŸ“Š Batch Analysis"):
386
+ gr.Markdown("Paste multiple financial texts β€” **one per line** β€” for batch sentiment classification.")
387
+ with gr.Row():
388
+ with gr.Column(scale=2):
389
+ batch_input = gr.Textbox(
390
+ label="Financial Texts (one per line)",
391
+ placeholder="Headline 1\nHeadline 2\nHeadline 3",
392
+ lines=8,
393
+ max_lines=20,
394
+ )
395
+ batch_btn = gr.Button("⚑ Analyze All", variant="primary", size="lg")
396
+ with gr.Column(scale=3):
397
+ batch_output = gr.HTML(
398
+ value="<p style='color:#94a3b8; text-align:center; padding:40px;'>Results will appear here.</p>"
399
+ )
400
+
401
+ batch_btn.click(fn=predict_batch, inputs=batch_input, outputs=batch_output)
402
+
403
+ # --- Tab 3: About ---
404
+ with gr.Tab("ℹ️ About"):
405
+ gr.HTML("""
406
+ <div style="
407
+ background: #ffffff;
408
+ border: 1px solid #e2e8f0;
409
+ border-radius: 20px;
410
+ padding: 36px;
411
+ color: #1e293b;
412
+ box-shadow: 0 1px 3px rgba(0,0,0,0.06);
413
+ ">
414
+ <h2 style="
415
+ background: linear-gradient(135deg, #059669, #0891b2);
416
+ -webkit-background-clip: text;
417
+ -webkit-text-fill-color: transparent;
418
+ font-size: 24px;
419
+ margin-bottom: 24px;
420
+ ">About FinBERT-Pro</h2>
421
+
422
+ <p style="color:#475569; font-size:14px; line-height:1.7; margin-bottom:20px;">
423
+ An improved financial sentiment model built on
424
+ <a href="https://huggingface.co/ProsusAI/finbert" style="color:#059669; text-decoration:none; font-weight:600;">ProsusAI/FinBERT</a>.
425
+ Fine-tuned on 3 expert-annotated financial datasets for more robust sentiment classification.
426
+ </p>
427
+
428
+ <table style="width:100%; border-collapse:separate; border-spacing:0 8px;">
429
+ <tr>
430
+ <td style="color:#64748b; padding:8px 16px; font-size:13px; width:35%;">Base Model</td>
431
+ <td style="color:#1e293b; padding:8px 16px; font-size:14px; font-weight:600;">ProsusAI/FinBERT (BERT-based)</td>
432
+ </tr>
433
+ <tr>
434
+ <td style="color:#64748b; padding:8px 16px; font-size:13px;">Task</td>
435
+ <td style="color:#1e293b; padding:8px 16px; font-size:14px; font-weight:600;">3-Class Sentiment (Positive / Negative / Neutral)</td>
436
+ </tr>
437
+ <tr>
438
+ <td style="color:#64748b; padding:8px 16px; font-size:13px;">Language</td>
439
+ <td style="color:#1e293b; padding:8px 16px; font-size:14px; font-weight:600;">English</td>
440
+ </tr>
441
+ <tr>
442
+ <td style="color:#64748b; padding:8px 16px; font-size:13px;">Max Input</td>
443
+ <td style="color:#1e293b; padding:8px 16px; font-size:14px; font-weight:600;">128 tokens</td>
444
+ </tr>
445
+ <tr>
446
+ <td style="color:#64748b; padding:8px 16px; font-size:13px;">License</td>
447
+ <td style="color:#1e293b; padding:8px 16px; font-size:14px; font-weight:600;">Apache 2.0</td>
448
+ </tr>
449
+ </table>
450
+
451
+ <h3 style="color:#059669; margin-top:28px; margin-bottom:12px; font-size:16px;">πŸ“Š Training Data</h3>
452
+ <p style="color:#475569; font-size:13px; line-height:1.7;">
453
+ Fine-tuned on 3 expert-annotated datasets (~14.6K total samples):
454
+ <b style="color:#047857;">FinanceInc/auditor_sentiment</b>,
455
+ <b style="color:#047857;">nickmuchi/financial-classification</b>, and
456
+ <b style="color:#047857;">warwickai/financial_phrasebank_mirror</b>.
457
+ </p>
458
+
459
+ <h3 style="color:#059669; margin-top:28px; margin-bottom:12px; font-size:16px;">πŸ” What's Different from FinBERT?</h3>
460
+ <div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; margin-top:12px;">
461
+ <div style="background:#f8fafc; border:1px solid #e2e8f0; padding:14px; border-radius:10px; font-size:13px; text-align:center;">
462
+ <span style="font-size:20px;">πŸ“š</span><br>
463
+ <b style="color:#1e293b;">Multi-Source</b><br>
464
+ <span style="color:#64748b;">3 datasets vs 1</span>
465
+ </div>
466
+ <div style="background:#f8fafc; border:1px solid #e2e8f0; padding:14px; border-radius:10px; font-size:13px; text-align:center;">
467
+ <span style="font-size:20px;">βš–οΈ</span><br>
468
+ <b style="color:#1e293b;">Class-Weighted</b><br>
469
+ <span style="color:#64748b;">Handles imbalance</span>
470
+ </div>
471
+ <div style="background:#f8fafc; border:1px solid #e2e8f0; padding:14px; border-radius:10px; font-size:13px; text-align:center;">
472
+ <span style="font-size:20px;">🎯</span><br>
473
+ <b style="color:#1e293b;">Robust</b><br>
474
+ <span style="color:#64748b;">Better generalization</span>
475
+ </div>
476
+ </div>
477
+
478
+ <h3 style="color:#059669; margin-top:28px; margin-bottom:12px; font-size:16px;">🐍 Python API</h3>
479
+ <pre style="
480
+ background:#f8fafc;
481
+ border:1px solid #e2e8f0;
482
+ border-radius:12px;
483
+ padding:20px;
484
+ color:#1e293b;
485
+ font-size:13px;
486
+ overflow-x:auto;
487
+ font-family: 'Fira Code', 'Cascadia Code', monospace !important;
488
+ "><span style="color:#059669">from</span> transformers <span style="color:#059669">import</span> pipeline
489
+
490
+ classifier = pipeline(<span style="color:#d97706">"text-classification"</span>,
491
+ model=<span style="color:#d97706">"ENTUM-AI/FinBERT-Pro"</span>)
492
+
493
+ result = classifier(<span style="color:#d97706">"Stock price soars on earnings"</span>)
494
+ <span style="color:#94a3b8"># [{'label': 'Positive', 'score': 0.99}]</span></pre>
495
+ </div>
496
+ """)
497
+
498
+
499
+ # Launch
500
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio>=4.0.0
2
+ transformers
3
+ torch