Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import pandas as pd | |
| from transformers import pipeline | |
| import torch | |
| import time | |
| import threading | |
| import os | |
| from datetime import datetime, timezone | |
| from huggingface_hub import HfApi | |
| import plotly.graph_objects as go | |
| # --- KONFIGŪRACIJA --- | |
| MODEL_NAME = "ProsusAI/finbert" | |
| TARGET_DATASET = "Vycka12/Base" | |
| HF_TOKEN = os.environ.get("HF_TOKEN") | |
| # API Raktas ir URL (Griežtai nustatyti) | |
| CRYPTOPANIC_API_KEY = "6c0f988f9e33170ccd183c6a14b34e8c2ad0867f" | |
| CRYPTOPANIC_URL = "https://cryptopanic.com/api/developer/v2/posts/" | |
| # Globalūs kintamieji | |
| news_buffer = [] | |
| stats = {"bullish": 0, "bearish": 0, "neutral": 0, "overall": "Inicijuojama...", "status": "Startuoja..."} | |
| # Krauname AI | |
| print("⌛ Kraunamas AI modelis...") | |
| try: | |
| sentiment_pipeline = pipeline("sentiment-analysis", model=MODEL_NAME) | |
| print("✅ AI paruoštas.") | |
| except Exception as e: | |
| print(f"❌ AI ERROR: {e}") | |
| sentiment_pipeline = None | |
| class SentimentSystem: | |
| def __init__(self): | |
| self.api = HfApi(token=HF_TOKEN) | |
| def fetch_and_analyze(self): | |
| global news_buffer, stats | |
| stats["status"] = "Gaunamos naujienos..." | |
| # Pataisyti parametrai - tik būtiniausi | |
| params = { | |
| "auth_token": CRYPTOPANIC_API_KEY, | |
| "kind": "news" | |
| } | |
| try: | |
| resp = requests.get(CRYPTOPANIC_URL, params=params, timeout=20) | |
| if resp.status_code == 200: | |
| data = resp.json() | |
| raw_news = data.get("results", []) | |
| if not raw_news: | |
| stats["status"] = "⚠️ API grąžino tuščią sąrašą." | |
| return | |
| temp_news = [] | |
| pos, neg, neut = 0, 0, 0 | |
| for item in raw_news: | |
| title = item.get("title", "") | |
| if not title: continue | |
| # AI Analizė | |
| if sentiment_pipeline: | |
| result = sentiment_pipeline(title[:512])[0] | |
| label = result['label'] | |
| score = result['score'] | |
| else: | |
| label, score = 'neutral', 0.5 | |
| # Emocijos | |
| if label == 'positive': | |
| status, emo = "🟢 BULLISH", "🚀" | |
| pos += 1 | |
| elif label == 'negative': | |
| status, emo = "🔴 BEARISH", "📉" | |
| neg += 1 | |
| else: | |
| status, emo = "⚪ NEUTRAL", "➖" | |
| neut += 1 | |
| # Laikas | |
| pub_time = item.get("published_at", "")[:16].replace("T", " ") | |
| temp_news.append([emo, status, title, f"{round(score*100)}%", pub_time]) | |
| stats["bullish"] = pos | |
| stats["bearish"] = neg | |
| stats["neutral"] = neut | |
| total = pos + neg + neut | |
| if total > 0: | |
| ratio = (pos - neg) / total | |
| if ratio > 0.2: stats["overall"] = "OPTIMIZMAS 📈" | |
| elif ratio < -0.2: stats["overall"] = "BAIMĖ 📉" | |
| else: stats["overall"] = "NEUTRALU ⚖️" | |
| news_buffer = temp_news | |
| stats["status"] = f"Atnaujinta: {datetime.now().strftime('%H:%M:%S')}" | |
| else: | |
| stats["status"] = f"❌ API Klaida: {resp.status_code}" | |
| except Exception as e: | |
| stats["status"] = f"❌ Klaida: {str(e)}" | |
| def create_gauge(self): | |
| total = stats["bullish"] + stats["bearish"] + stats["neutral"] | |
| val = 50 | |
| if total > 0: | |
| # Formulė: 50 + (teigiami - neigiami) * koeficientas | |
| # Jei visi teigiami -> 100, visi neigiami -> 0 | |
| net_sentiment = (stats["bullish"] - stats["bearish"]) / total | |
| val = 50 + (net_sentiment * 50) | |
| fig = go.Figure(go.Indicator( | |
| mode = "gauge+number", | |
| value = val, | |
| title = {'text': f"Rinkos Emocija: {stats['overall']}"}, | |
| gauge = { | |
| 'axis': {'range': [0, 100]}, | |
| 'bar': {'color': "black"}, | |
| 'steps': [ | |
| {'range': [0, 40], 'color': "#ff4b4b"}, | |
| {'range': [40, 60], 'color': "#ffffb2"}, | |
| {'range': [60, 100], 'color': "#00cc96"} | |
| ], | |
| } | |
| )) | |
| fig.update_layout(height=300, margin=dict(l=20, r=20, t=50, b=20)) | |
| return fig | |
| sys_analyzer = SentimentSystem() | |
| def update_loop(): | |
| # Pirmas paleidimas po 10 sek | |
| time.sleep(10) | |
| sys_analyzer.fetch_and_analyze() | |
| while True: | |
| # Atnaujiname kas 4 valandas (taupome limitą) | |
| time.sleep(14400) | |
| sys_analyzer.fetch_and_analyze() | |
| def get_ui_data(): | |
| gauge = sys_analyzer.create_gauge() | |
| cols = ["Emoji", "Verdiktas", "Antraštė", "Pasitikėjimas", "Laikas"] | |
| if not news_buffer: | |
| df = pd.DataFrame([["-", "-", "Kraunama...", "-", "-"]], columns=cols) | |
| else: | |
| df = pd.DataFrame(news_buffer, columns=cols) | |
| status_text = f"### 📊 Statistika\n**Būsena:** {stats['status']}\n**Geros:** {stats['bullish']} | **Blogos:** {stats['bearish']} | **Viso:** {stats['bullish']+stats['bearish']+stats['neutral']}" | |
| return gauge, df, status_text | |
| # --- GRADIO UI --- | |
| with gr.Blocks(title="Sentiment AI", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# 🧠 Sentiment AI Analyzer") | |
| gr.Markdown("Analizuoja realias crypto naujienas naudodamas ProsusAI FinBERT modelį.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gauge_output = gr.Plot(label="Nuotaika") | |
| with gr.Column(): | |
| status_output = gr.Markdown("Laukiama duomenų...") | |
| refresh_btn = gr.Button("🔄 Atnaujinti Dabar", variant="primary") | |
| gr.Markdown("### 📰 Naujienų srautas ir AI vertinimas") | |
| table_output = gr.Dataframe(interactive=False) | |
| # Eventai | |
| refresh_btn.click(fn=sys_analyzer.fetch_and_analyze).then( | |
| fn=get_ui_data, outputs=[gauge_output, table_output, status_output] | |
| ) | |
| # Auto-start | |
| threading.Thread(target=update_loop, daemon=True).start() | |
| # UI atnaujinimas (tik vaizdo, ne duomenų siurbimo) | |
| demo.load(get_ui_data, outputs=[gauge_output, table_output, status_output]) | |
| gr.Timer(5).tick(get_ui_data, outputs=[gauge_output, table_output, status_output]) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) | |