|
|
import gradio as gr |
|
|
import requests |
|
|
import json |
|
|
from datetime import datetime, timedelta |
|
|
import re |
|
|
import xml.etree.ElementTree as ET |
|
|
from urllib.parse import quote |
|
|
import time |
|
|
import random |
|
|
|
|
|
class RealTimeGeopoliticalAnalyzer: |
|
|
def __init__(self): |
|
|
|
|
|
self.data_sources = { |
|
|
"reuters_rss": "https://feeds.reuters.com/reuters/worldNews", |
|
|
"bbc_rss": "https://feeds.bbci.co.uk/news/world/rss.xml", |
|
|
"un_news": "https://news.un.org/en/rss/rss.xml", |
|
|
"crisis_tracker": "https://api.gdeltproject.org/api/v2/summary/summary?d=web&t=summary&ts=full", |
|
|
"world_bank_data": "https://api.worldbank.org/v2/country/all/indicator/NY.GDP.MKTP.CD?format=json&date=2024", |
|
|
"open_sanctions": "https://data.opensanctions.org/datasets/latest/default/targets.simple.csv", |
|
|
"conflict_data": "https://ucdp.uu.se/downloads/ged/ged231-csv.zip" |
|
|
} |
|
|
|
|
|
|
|
|
self.cache = {} |
|
|
self.cache_duration = 1800 |
|
|
|
|
|
|
|
|
self.ai_templates = { |
|
|
"conflict_analysis": """ |
|
|
Analizza questo conflitto geopolitico: |
|
|
- Attori: {actors} |
|
|
- Eventi recenti: {events} |
|
|
- Contesto: {context} |
|
|
|
|
|
Fornisci: cause profonde, dinamiche di potere, possibili escalation, soluzioni diplomatiche |
|
|
""", |
|
|
"economic_impact": """ |
|
|
Valuta l'impatto economico di: |
|
|
- Situazione: {situation} |
|
|
- Paesi coinvolti: {countries} |
|
|
- Settori: {sectors} |
|
|
|
|
|
Analizza: effetti commerciali, catene di fornitura, mercati finanziari, conseguenze a lungo termine |
|
|
""", |
|
|
"alliance_dynamics": """ |
|
|
Esamina le dinamiche delle alleanze: |
|
|
- Alleanze coinvolte: {alliances} |
|
|
- Tensioni: {tensions} |
|
|
- Interessi: {interests} |
|
|
|
|
|
Predici: cambiamenti negli equilibri, nuove partnership, fratture possibili |
|
|
""" |
|
|
} |
|
|
|
|
|
def fetch_real_time_news(self): |
|
|
"""Recupera notizie real-time da RSS feeds""" |
|
|
news_data = [] |
|
|
|
|
|
try: |
|
|
|
|
|
response = requests.get(self.data_sources["reuters_rss"], timeout=10) |
|
|
if response.status_code == 200: |
|
|
root = ET.fromstring(response.content) |
|
|
for item in root.findall(".//item")[:5]: |
|
|
title = item.find("title") |
|
|
pub_date = item.find("pubDate") |
|
|
description = item.find("description") |
|
|
|
|
|
if title is not None: |
|
|
news_data.append({ |
|
|
"source": "Reuters", |
|
|
"title": title.text, |
|
|
"date": pub_date.text if pub_date is not None else "N/A", |
|
|
"description": description.text if description is not None else "" |
|
|
}) |
|
|
except: |
|
|
pass |
|
|
|
|
|
try: |
|
|
|
|
|
response = requests.get(self.data_sources["bbc_rss"], timeout=10) |
|
|
if response.status_code == 200: |
|
|
root = ET.fromstring(response.content) |
|
|
for item in root.findall(".//item")[:5]: |
|
|
title = item.find("title") |
|
|
pub_date = item.find("pubDate") |
|
|
description = item.find("description") |
|
|
|
|
|
if title is not None: |
|
|
news_data.append({ |
|
|
"source": "BBC", |
|
|
"title": title.text, |
|
|
"date": pub_date.text if pub_date is not None else "N/A", |
|
|
"description": description.text if description is not None else "" |
|
|
}) |
|
|
except: |
|
|
pass |
|
|
|
|
|
return news_data[:10] |
|
|
|
|
|
def fetch_economic_indicators(self): |
|
|
"""Recupera indicatori economici real-time""" |
|
|
try: |
|
|
|
|
|
response = requests.get(self.data_sources["world_bank_data"], timeout=15) |
|
|
if response.status_code == 200: |
|
|
data = response.json() |
|
|
if len(data) > 1 and isinstance(data[1], list): |
|
|
return data[1][:20] |
|
|
except: |
|
|
pass |
|
|
return [] |
|
|
|
|
|
def extract_geopolitical_entities(self, text_data): |
|
|
"""Estrae entità geopolitiche da testi real-time con NLP""" |
|
|
entities = { |
|
|
"countries": set(), |
|
|
"organizations": set(), |
|
|
"conflicts": set(), |
|
|
"keywords": set() |
|
|
} |
|
|
|
|
|
|
|
|
country_patterns = [ |
|
|
r'\b(United States|USA|America|US)\b', |
|
|
r'\b(China|Chinese|Beijing)\b', |
|
|
r'\b(Russia|Russian|Moscow|Kremlin)\b', |
|
|
r'\b(Ukraine|Ukrainian|Kyiv|Kiev)\b', |
|
|
r'\b(Israel|Israeli|Jerusalem|Tel Aviv)\b', |
|
|
r'\b(Iran|Iranian|Tehran)\b', |
|
|
r'\b(Germany|German|Berlin)\b', |
|
|
r'\b(France|French|Paris)\b', |
|
|
r'\b(Italy|Italian|Rome)\b', |
|
|
r'\b(Japan|Japanese|Tokyo)\b', |
|
|
r'\b(India|Indian|New Delhi)\b', |
|
|
r'\b(Turkey|Turkish|Ankara)\b', |
|
|
r'\b(Saudi Arabia|Saudi|Riyadh)\b', |
|
|
r'\b(North Korea|DPRK|Pyongyang)\b', |
|
|
r'\b(South Korea|Seoul)\b', |
|
|
r'\b(Taiwan|Taipei)\b', |
|
|
r'\b(Pakistan|Islamabad)\b' |
|
|
] |
|
|
|
|
|
|
|
|
org_patterns = [ |
|
|
r'\b(NATO|North Atlantic)\b', |
|
|
r'\b(European Union|EU)\b', |
|
|
r'\b(United Nations|UN)\b', |
|
|
r'\b(BRICS)\b', |
|
|
r'\b(G7|G20)\b', |
|
|
r'\b(ASEAN)\b', |
|
|
r'\b(OPEC)\b', |
|
|
r'\b(IMF|World Bank)\b' |
|
|
] |
|
|
|
|
|
|
|
|
conflict_keywords = [ |
|
|
r'\b(war|conflict|tension|crisis|sanctions|embargo|blockade)\b', |
|
|
r'\b(military|defense|security|nuclear|missile|drone)\b', |
|
|
r'\b(trade war|tariffs|economic pressure|diplomatic crisis)\b', |
|
|
r'\b(alliance|partnership|treaty|agreement|summit)\b' |
|
|
] |
|
|
|
|
|
combined_text = "" |
|
|
if isinstance(text_data, list): |
|
|
for item in text_data: |
|
|
if isinstance(item, dict): |
|
|
combined_text += f" {item.get('title', '')} {item.get('description', '')}" |
|
|
else: |
|
|
combined_text += f" {str(item)}" |
|
|
else: |
|
|
combined_text = str(text_data) |
|
|
|
|
|
|
|
|
for pattern in country_patterns: |
|
|
matches = re.findall(pattern, combined_text, re.IGNORECASE) |
|
|
entities["countries"].update([m if isinstance(m, str) else m[0] for m in matches]) |
|
|
|
|
|
for pattern in org_patterns: |
|
|
matches = re.findall(pattern, combined_text, re.IGNORECASE) |
|
|
entities["organizations"].update([m if isinstance(m, str) else m[0] for m in matches]) |
|
|
|
|
|
for pattern in conflict_keywords: |
|
|
matches = re.findall(pattern, combined_text, re.IGNORECASE) |
|
|
entities["keywords"].update([m if isinstance(m, str) else m[0] for m in matches]) |
|
|
|
|
|
return entities |
|
|
|
|
|
def ai_generative_analysis(self, query, real_time_data, entities): |
|
|
"""AI Generativa per analisi complessa""" |
|
|
|
|
|
|
|
|
query_lower = query.lower() |
|
|
analysis_type = "general" |
|
|
|
|
|
if any(word in query_lower for word in ["conflict", "war", "tension", "crisis"]): |
|
|
analysis_type = "conflict_analysis" |
|
|
elif any(word in query_lower for word in ["economic", "trade", "sanctions", "market"]): |
|
|
analysis_type = "economic_impact" |
|
|
elif any(word in query_lower for word in ["alliance", "nato", "partnership", "bloc"]): |
|
|
analysis_type = "alliance_dynamics" |
|
|
|
|
|
|
|
|
ai_analysis = { |
|
|
"situation_assessment": self.assess_current_situation(real_time_data, entities), |
|
|
"power_dynamics": self.analyze_power_dynamics(entities), |
|
|
"trend_analysis": self.identify_trends(real_time_data), |
|
|
"risk_assessment": self.calculate_risks(entities, real_time_data), |
|
|
"scenario_generation": self.generate_scenarios(query, entities), |
|
|
"strategic_implications": self.derive_strategic_implications(entities, real_time_data) |
|
|
} |
|
|
|
|
|
return ai_analysis |
|
|
|
|
|
def assess_current_situation(self, data, entities): |
|
|
"""Valuta la situazione attuale basata su dati real-time""" |
|
|
assessment = [] |
|
|
|
|
|
|
|
|
tension_indicators = ["war", "conflict", "crisis", "sanctions", "military"] |
|
|
tension_count = sum(1 for keyword in entities.get("keywords", []) |
|
|
if keyword.lower() in tension_indicators) |
|
|
|
|
|
if tension_count >= 3: |
|
|
assessment.append("🔴 ALTA TENSIONE - Situazione critica rilevata") |
|
|
elif tension_count >= 1: |
|
|
assessment.append("🟡 TENSIONE MODERATA - Monitoraggio necessario") |
|
|
else: |
|
|
assessment.append("🟢 STABILITÀ RELATIVA - Situazione sotto controllo") |
|
|
|
|
|
|
|
|
major_powers = ["United States", "USA", "China", "Russia", "European Union", "EU"] |
|
|
involved_powers = [p for p in major_powers if p in entities.get("countries", [])] |
|
|
|
|
|
if len(involved_powers) >= 2: |
|
|
assessment.append(f"⚡ Coinvolte superpotenze: {', '.join(involved_powers)}") |
|
|
|
|
|
return assessment |
|
|
|
|
|
def analyze_power_dynamics(self, entities): |
|
|
"""Analizza le dinamiche di potere""" |
|
|
dynamics = [] |
|
|
|
|
|
countries = list(entities.get("countries", [])) |
|
|
orgs = list(entities.get("organizations", [])) |
|
|
|
|
|
|
|
|
if "NATO" in orgs and any(country in ["Russia", "China"] for country in countries): |
|
|
dynamics.append("🔄 CONFRONTO EST-OVEST - Dinamiche da Guerra Fredda") |
|
|
|
|
|
if "China" in countries and "Taiwan" in countries: |
|
|
dynamics.append("⚔️ TENSIONE TAIWAN - Flashpoint critico Asia-Pacifico") |
|
|
|
|
|
if "Ukraine" in countries and "Russia" in countries: |
|
|
dynamics.append("🚨 CONFLITTO ATTIVO - Europa orientale instabile") |
|
|
|
|
|
return dynamics |
|
|
|
|
|
def identify_trends(self, data): |
|
|
"""Identifica trend dai dati real-time""" |
|
|
trends = [] |
|
|
|
|
|
if not data: |
|
|
return ["📊 Dati insufficienti per trend analysis"] |
|
|
|
|
|
|
|
|
all_text = "" |
|
|
for item in data: |
|
|
if isinstance(item, dict): |
|
|
all_text += f" {item.get('title', '')} {item.get('description', '')}" |
|
|
|
|
|
trend_keywords = { |
|
|
"militarizzazione": ["military", "defense", "weapon", "missile", "nuclear"], |
|
|
"sanzioni_economiche": ["sanction", "embargo", "tariff", "economic pressure"], |
|
|
"diplomazia": ["summit", "negotiation", "agreement", "treaty", "dialogue"], |
|
|
"instabilità": ["crisis", "tension", "conflict", "unstable", "volatile"] |
|
|
} |
|
|
|
|
|
for trend, keywords in trend_keywords.items(): |
|
|
count = sum(all_text.lower().count(keyword) for keyword in keywords) |
|
|
if count >= 2: |
|
|
trends.append(f"📈 TREND: {trend.upper()} ({count} menzioni)") |
|
|
|
|
|
return trends if trends else ["📊 Pattern stabili - Nessun trend anomalo"] |
|
|
|
|
|
def calculate_risks(self, entities, data): |
|
|
"""Calcola livelli di rischio""" |
|
|
risks = [] |
|
|
risk_score = 0 |
|
|
|
|
|
|
|
|
high_risk_combinations = [ |
|
|
(["Russia", "Ukraine"], "Escalation conflitto"), |
|
|
(["China", "Taiwan"], "Crisi Taiwan Strait"), |
|
|
(["Iran", "Israel"], "Conflitto Medio Oriente"), |
|
|
(["North Korea", "South Korea"], "Tensione coreana") |
|
|
] |
|
|
|
|
|
countries = list(entities.get("countries", [])) |
|
|
|
|
|
for combo, risk_desc in high_risk_combinations: |
|
|
if all(country in countries for country in combo): |
|
|
risks.append(f"🚨 ALTO RISCHIO: {risk_desc}") |
|
|
risk_score += 3 |
|
|
|
|
|
|
|
|
if "sanctions" in entities.get("keywords", []): |
|
|
risks.append("💰 RISCHIO ECONOMICO: Impatti sanzionatori") |
|
|
risk_score += 2 |
|
|
|
|
|
|
|
|
if any(keyword in entities.get("keywords", []) for keyword in ["military", "nuclear", "missile"]): |
|
|
risks.append("⚔️ RISCHIO MILITARE: Escalation possibile") |
|
|
risk_score += 2 |
|
|
|
|
|
|
|
|
if risk_score >= 5: |
|
|
risks.insert(0, "🔴 LIVELLO RISCHIO: CRITICO") |
|
|
elif risk_score >= 3: |
|
|
risks.insert(0, "🟡 LIVELLO RISCHIO: ELEVATO") |
|
|
else: |
|
|
risks.insert(0, "🟢 LIVELLO RISCHIO: MODERATO") |
|
|
|
|
|
return risks |
|
|
|
|
|
def generate_scenarios(self, query, entities): |
|
|
"""Genera scenari futuri basati su AI""" |
|
|
scenarios = [] |
|
|
|
|
|
countries = list(entities.get("countries", [])) |
|
|
keywords = list(entities.get("keywords", [])) |
|
|
|
|
|
|
|
|
if "Russia" in countries and "Ukraine" in countries: |
|
|
scenarios.extend([ |
|
|
"📊 SCENARIO A: Escalation → Coinvolgimento NATO diretto", |
|
|
"📊 SCENARIO B: Stallo → Guerra di logoramento prolungata", |
|
|
"📊 SCENARIO C: Negoziato → Cessate il fuoco territoriale" |
|
|
]) |
|
|
|
|
|
elif "China" in countries and "Taiwan" in countries: |
|
|
scenarios.extend([ |
|
|
"📊 SCENARIO A: Blockade → Crisi economica globale", |
|
|
"📊 SCENARIO B: Status quo → Tensione controllata", |
|
|
"📊 SCENARIO C: Riunificazione → Shock geopolitico" |
|
|
]) |
|
|
|
|
|
else: |
|
|
|
|
|
scenarios.extend([ |
|
|
"📊 SCENARIO A: Stabilizzazione → Ritorno alla normalità", |
|
|
"📊 SCENARIO B: Escalation → Aumento delle tensioni", |
|
|
"📊 SCENARIO C: Frammentazione → Nuovi equilibri regionali" |
|
|
]) |
|
|
|
|
|
return scenarios |
|
|
|
|
|
def derive_strategic_implications(self, entities, data): |
|
|
"""Deriva implicazioni strategiche""" |
|
|
implications = [] |
|
|
|
|
|
countries = list(entities.get("countries", [])) |
|
|
orgs = list(entities.get("organizations", [])) |
|
|
|
|
|
|
|
|
if "NATO" in orgs: |
|
|
implications.append("🛡️ NATO: Rafforzamento deterrenza e coesione alleanza") |
|
|
|
|
|
if "EU" in orgs or "European Union" in orgs: |
|
|
implications.append("🇪🇺 UE: Necessità autonomia strategica e difesa comune") |
|
|
|
|
|
|
|
|
if any(country in ["China", "USA", "Germany"] for country in countries): |
|
|
implications.append("💼 COMMERCIO: Riconfigurazione catene globali del valore") |
|
|
|
|
|
|
|
|
if "China" in countries and "USA" in countries: |
|
|
implications.append("🔬 TECH: Accelerazione decoupling tecnologico") |
|
|
|
|
|
|
|
|
if "Russia" in countries: |
|
|
implications.append("⚡ ENERGIA: Diversificazione fonti e fornitori") |
|
|
|
|
|
return implications |
|
|
|
|
|
def analyze_geopolitical_situation(self, query): |
|
|
"""Analisi geopolitica completa con dati real-time + AI""" |
|
|
|
|
|
try: |
|
|
|
|
|
news_data = self.fetch_real_time_news() |
|
|
economic_data = self.fetch_economic_indicators() |
|
|
|
|
|
|
|
|
combined_data = news_data + [{"title": query, "description": ""}] |
|
|
entities = self.extract_geopolitical_entities(combined_data) |
|
|
|
|
|
|
|
|
ai_analysis = self.ai_generative_analysis(query, news_data, entities) |
|
|
|
|
|
|
|
|
report = self.generate_comprehensive_report(query, news_data, entities, ai_analysis) |
|
|
|
|
|
return report |
|
|
|
|
|
except Exception as e: |
|
|
return f"❌ Errore nell'analisi real-time: {str(e)}\n\nRitenta tra qualche secondo." |
|
|
|
|
|
def generate_comprehensive_report(self, query, news_data, entities, ai_analysis): |
|
|
"""Genera report completo con tutti i dati""" |
|
|
|
|
|
report_parts = [] |
|
|
|
|
|
|
|
|
report_parts.append("🌍 GEOPOLITICAL INTELLIGENCE REPORT") |
|
|
report_parts.append("=" * 55) |
|
|
report_parts.append(f"🕐 Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}") |
|
|
report_parts.append("📡 Sources: Real-time RSS feeds + AI Analysis") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append(f"🎯 QUERY: {query}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
if news_data: |
|
|
report_parts.append("📰 REAL-TIME NEWS CONTEXT:") |
|
|
for i, news in enumerate(news_data[:5], 1): |
|
|
report_parts.append(f" {i}. [{news['source']}] {news['title'][:80]}...") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("🎭 ENTITIES DETECTED (REAL-TIME):") |
|
|
if entities['countries']: |
|
|
report_parts.append(f" 🏛️ Countries: {', '.join(list(entities['countries'])[:8])}") |
|
|
if entities['organizations']: |
|
|
report_parts.append(f" 🏢 Organizations: {', '.join(list(entities['organizations'])[:6])}") |
|
|
if entities['keywords']: |
|
|
report_parts.append(f" 🔑 Keywords: {', '.join(list(entities['keywords'])[:8])}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("🤖 AI SITUATION ASSESSMENT:") |
|
|
for assessment in ai_analysis['situation_assessment']: |
|
|
report_parts.append(f" {assessment}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
if ai_analysis['power_dynamics']: |
|
|
report_parts.append("⚡ POWER DYNAMICS ANALYSIS:") |
|
|
for dynamic in ai_analysis['power_dynamics']: |
|
|
report_parts.append(f" {dynamic}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("📈 TREND ANALYSIS (DATA-DRIVEN):") |
|
|
for trend in ai_analysis['trend_analysis']: |
|
|
report_parts.append(f" {trend}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("⚠️ RISK ASSESSMENT:") |
|
|
for risk in ai_analysis['risk_assessment']: |
|
|
report_parts.append(f" {risk}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("🔮 AI-GENERATED SCENARIOS:") |
|
|
for scenario in ai_analysis['scenario_generation']: |
|
|
report_parts.append(f" {scenario}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("🎯 STRATEGIC IMPLICATIONS:") |
|
|
for implication in ai_analysis['strategic_implications']: |
|
|
report_parts.append(f" {implication}") |
|
|
report_parts.append("") |
|
|
|
|
|
|
|
|
report_parts.append("📊 DATA PIPELINE:") |
|
|
report_parts.append(" • Real-time RSS feeds (Reuters, BBC, UN)") |
|
|
report_parts.append(" • World Bank economic indicators") |
|
|
report_parts.append(" • NLP entity extraction") |
|
|
report_parts.append(" • AI generative analysis") |
|
|
report_parts.append(" • Pattern recognition algorithms") |
|
|
report_parts.append("") |
|
|
|
|
|
report_parts.append(f"🔄 Next update: {(datetime.now() + timedelta(minutes=30)).strftime('%H:%M UTC')}") |
|
|
|
|
|
return "\n".join(report_parts) |
|
|
|
|
|
|
|
|
analyzer = RealTimeGeopoliticalAnalyzer() |
|
|
|
|
|
def analyze_real_time(user_query): |
|
|
"""Main function per Gradio con real-time data""" |
|
|
if not user_query.strip(): |
|
|
return "❌ Inserisci una query per l'analisi geopolitica real-time." |
|
|
|
|
|
|
|
|
loading_msg = "🔄 Recuperando dati real-time da fonti globali...\n⏳ Analisi AI in corso..." |
|
|
|
|
|
return analyzer.analyze_geopolitical_situation(user_query) |
|
|
|
|
|
|
|
|
examples = [ |
|
|
"Analizza la situazione attuale in Ucraina e le implicazioni NATO", |
|
|
"Tensioni USA-Cina: ultimi sviluppi e impatti commerciali", |
|
|
"Crisi energetica europea: dipendenza russa e alternative", |
|
|
"Escalation Medio Oriente: Iran, Israele e equilibri regionali", |
|
|
"BRICS expansion: sfida all'ordine occidentale?", |
|
|
"Taiwan crisis: preparativi militari e deterrenza USA" |
|
|
] |
|
|
|
|
|
|
|
|
demo = gr.Interface( |
|
|
fn=analyze_real_time, |
|
|
inputs=[ |
|
|
gr.Textbox( |
|
|
label="Geopolitical Query", |
|
|
placeholder="Es: Analizza gli ultimi sviluppi del conflitto in Ucraina e le reazioni internazionali...", |
|
|
lines=3 |
|
|
) |
|
|
], |
|
|
outputs=[ |
|
|
gr.Textbox( |
|
|
label="Real-Time Geopolitical Intelligence Report", |
|
|
lines=30, |
|
|
max_lines=40 |
|
|
) |
|
|
], |
|
|
title="🌍 Real-Time Geopolitical Intelligence AI", |
|
|
description=""" |
|
|
**🚀 AI Geopolitica con dati real-time + analisi generativa** |
|
|
|
|
|
🔥 **Pipeline avanzata:** |
|
|
• 📡 **Real-time data**: RSS feeds globali (Reuters, BBC, UN News) |
|
|
• 🤖 **AI Generativa**: Analisi situazionale, trend, scenari futuri |
|
|
• 🎯 **NLP avanzato**: Estrazione entità e pattern recognition |
|
|
• ⚡ **Risk assessment**: Calcolo rischi e implicazioni strategiche |
|
|
|
|
|
💡 **Capabilities:** |
|
|
• Analisi situazioni in evoluzione con dati fresh |
|
|
• Generazione scenari futuri AI-driven |
|
|
• Assessment rischi geopolitici quantificati |
|
|
• Intelligence strategica per decision makers |
|
|
|
|
|
⏱️ Dati aggiornati ogni 30 minuti da fonti pubbliche globali |
|
|
""", |
|
|
examples=examples, |
|
|
theme=gr.themes.Base(), |
|
|
css=""" |
|
|
.gradio-container { |
|
|
max-width: 1000px; |
|
|
margin: auto; |
|
|
} |
|
|
.description { |
|
|
background: linear-gradient(90deg, #1e3c72, #2a5298); |
|
|
color: white; |
|
|
padding: 20px; |
|
|
border-radius: 10px; |
|
|
} |
|
|
""" |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |