import streamlit as st import pandas as pd import numpy as np from GoogleNews import GoogleNews from transformers import pipeline import plotly.express as px import plotly.graph_objects as go import dateparser from datetime import datetime, timedelta # --- SYSTEM CONFIG --- st.set_page_config( page_title="VBI Terminal: Strategic AI", page_icon="🛡️", layout="wide", initial_sidebar_state="collapsed" ) # --- PROFESSIONAL UI (Cyberpunk/Terminal Style) --- st.markdown(""" """, unsafe_allow_html=True) # --- AI ENGINE --- @st.cache_resource def load_neural_engine(): """Load Zero-Shot Classification Model""" return pipeline("zero-shot-classification", model="facebook/bart-large-mnli") analyzer = load_neural_engine() # --- INTELLIGENCE ENGINE --- def calculate_source_weight(source_name): """Assigns weight based on source credibility (Heuristic)""" source_name = str(source_name).lower() if any(x in source_name for x in ['reuters', 'bloomberg', 'forbes', 'tengrinews', 'zakon', 'kapital']): return 2.0 # High Impact Tier 1 elif any(x in source_name for x in ['blog', 'reddit', 'twitter', 'post']): return 0.8 # Low Impact / High Noise return 1.0 # Standard def fetch_intelligence(query, region, depth, mode): """Fetches real-time data using OSINT techniques.""" lang_set = 'en' gn = GoogleNews(lang=lang_set, region=region) gn.clear() # Advanced Query Logic final_query = query if mode == "Social Buzz (Risk)": final_query = f'{query} AND ("scandal" OR "fail" OR "crash" OR "complaint" OR "leak" OR "reddit" OR "opinion")' elif mode == "Financial Intel": final_query = f'{query} AND ("stock" OR "profit" OR "loss" OR "quarter" OR "ipo" OR "revenue")' gn.search(final_query) results = gn.result() if len(results) < depth: gn.getpage(2) results += gn.result() clean_data = [] seen_titles = set() for item in results[:depth]: title = item.get('title', '') if title in seen_titles: continue seen_titles.add(title) raw_date = item.get('date', '') parsed_date = dateparser.parse(raw_date) if not parsed_date: parsed_date = datetime.now() source_label = item.get('media', 'Unknown Node') weight = calculate_source_weight(source_label) clean_data.append({ "Timestamp": parsed_date, "Source": source_label, "Headline": title, "Link": item.get('link', '#'), "Weight": weight }) return clean_data # --- STRATEGIC ADVISOR MODULE --- def generate_ai_advice(rep_index, top_risk, volatility, sentiment_ratio): """Generates text-based strategy based on metrics.""" advice = [] status = "STABLE" css_class = "advisor-box" # 1. Reputation Assessment if rep_index < 40: status = "CRITICAL" css_class = "warning-box" advice.append(f"🚨 **CRISIS MODE ACTIVATED:** Reputation Index ({round(rep_index)}%) is critically low. Immediate PR intervention required.") elif rep_index < 60: status = "VOLATILE" advice.append(f"⚠️ **Caution:** Brand sentiment is mixed ({round(rep_index)}%). Monitor closely.") else: advice.append(f"✅ **Healthy:** Strong market perception ({round(rep_index)}%). Focus on maintaining momentum.") # 2. Risk Specific Strategy if top_risk == "Legal/Compliance": advice.append("⚖️ **Legal Vector:** High volume of legal discussions detected. Prepare official statements regarding compliance/lawsuits immediately.") elif top_risk == "Technical Failure": advice.append("🔧 **Ops Vector:** Technical complaints are trending. Issue a transparency report on uptime/fixes to reassure customers.") elif top_risk == "Financial Risk": advice.append("📉 **Market Vector:** Financial anxiety detected. IR (Investor Relations) should release clarifying data.") elif top_risk == "PR Crisis": advice.append("📣 **PR Vector:** Viral negativity detected. Do not ignore. Use 'Recall & Reframe' strategy.") # 3. Volatility Check if volatility > 0.3: advice.append("🌊 **High Volatility:** Opinions are shifting rapidly. Avoid controversial statements for 48h.") return status, "\n\n".join(advice), css_class # --- SIDEBAR --- with st.sidebar: st.header("🛰️ VBI: COMMAND") target_region = st.selectbox("Geo-Node", ["KZ", "US", "GB", "RU"], index=0) source_mode = st.radio("Signal Mode:", ["Corporate News", "Social Buzz (Risk)", "Financial Intel"]) scan_depth = st.slider("Depth", 10, 60, 30) st.divider() st.markdown("Created by **VBI Intelligence**") # --- MAIN LAYOUT --- st.title("🛡️ VBI: Strategic Brand Intelligence") st.markdown("`v2.0` | Neural OSINT & Automated Strategy Generation") col_search, col_btn = st.columns([4, 1]) with col_search: target_query = st.text_input("TARGET ENTITY:", placeholder="e.g. FlyArystan, Kaspi, KazMunayGas") with col_btn: st.write("") st.write("") start_btn = st.button("🚀 INITIATE SCAN", use_container_width=True) if start_btn and target_query: with st.spinner(f"🛰️ Intercepting signals for '{target_query}'..."): # 1. Fetch raw_data = fetch_intelligence(target_query, target_region, scan_depth, source_mode) if not raw_data: st.error("No signals detected. System Standby.") else: # 2. Process processed_data = [] risk_vectors = ["Legal/Compliance", "Financial Risk", "Technical Failure", "Market Expansion", "PR Crisis", "Customer Service"] sentiment_cats = ["Positive", "Negative", "Neutral"] prog = st.progress(0) for i, item in enumerate(raw_data): # Neural Analysis risk_out = analyzer(item['Headline'], candidate_labels=risk_vectors) sent_out = analyzer(item['Headline'], candidate_labels=sentiment_cats) # Logic: If Risk Score is low, it might be just General News top_risk = risk_out['labels'][0] if risk_out['scores'][0] < 0.4: top_risk = "General Noise" # Weighted Score Calculation sent_score = 1 if sent_out['labels'][0] == 'Positive' else -1 if sent_out['labels'][0] == 'Negative' else 0 weighted_impact = sent_score * item['Weight'] processed_data.append({ "Time": item['Timestamp'], "Source": item['Source'], "Headline": item['Headline'], "Risk Category": top_risk, "Risk Conf": risk_out['scores'][0], "Sentiment": sent_out['labels'][0], "Impact Score": weighted_impact }) prog.progress((i + 1) / len(raw_data)) prog.empty() df = pd.DataFrame(processed_data).sort_values(by='Time') # --- ANALYTICS ENGINE --- total_impact = df['Impact Score'].sum() total_weight = df['Impact Score'].abs().sum() if df['Impact Score'].abs().sum() != 0 else 1 # Reputation Index (0-100) rep_index = 50 + ((total_impact / len(df)) * 50) rep_index = max(0, min(100, rep_index)) # Clamp 0-100 # Volatility (Std Dev of Impact) volatility = df['Impact Score'].std() # Top Risk top_risk_cat = df['Risk Category'].value_counts().idxmax() # Advice Generation status, strategy_text, css_style = generate_ai_advice(rep_index, top_risk_cat, volatility, 0) # --- DASHBOARD --- # 1. STRATEGIC ADVISOR BLOCK st.markdown(f"""

🧠 AI Strategic Advisor: {status}

{strategy_text}
""", unsafe_allow_html=True) st.divider() # 2. KEY METRICS m1, m2, m3, m4 = st.columns(4) m1.metric("Reputation Index", f"{round(rep_index, 1)}%", delta="Weighted Impact") m2.metric("Signal Volume", len(df)) m3.metric("Primary Threat", top_risk_cat, delta_color="off") m4.metric("Volatility", f"{round(volatility, 2)}", help="Higher means less stable opinions") # 3. VISUALIZATIONS st.subheader("📊 Visual Intelligence") tab1, tab2 = st.tabs(["📈 Trend Dynamics", "🛡️ Risk Matrix"]) with tab1: # Rolling Average Trend df['MA'] = df['Impact Score'].rolling(window=3).mean() fig_trend = go.Figure() fig_trend.add_trace(go.Scatter(x=df['Time'], y=df['Impact Score'], mode='markers', name='Raw Signal', marker=dict(color='#94a3b8'))) fig_trend.add_trace(go.Scatter(x=df['Time'], y=df['MA'], mode='lines', name='Reputation Trend', line=dict(color='#38bdf8', width=3))) fig_trend.update_layout(title="Reputation Stability Over Time", template="plotly_dark", paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)') st.plotly_chart(fig_trend, use_container_width=True) with tab2: c1, c2 = st.columns(2) with c1: fig_pie = px.pie(df, names='Sentiment', title="Sentiment Distribution", color='Sentiment', color_discrete_map={"Positive": "#10b981", "Negative": "#ef4444", "Neutral": "#64748b"}) fig_pie.update_layout(template="plotly_dark", paper_bgcolor='rgba(0,0,0,0)') st.plotly_chart(fig_pie, use_container_width=True) with c2: risk_counts = df['Risk Category'].value_counts().reset_index() risk_counts.columns = ['Risk', 'Count'] fig_bar = px.bar(risk_counts, x='Count', y='Risk', orientation='h', title="Risk Vectors", color='Count', color_continuous_scale='Redor') fig_bar.update_layout(template="plotly_dark", paper_bgcolor='rgba(0,0,0,0)') st.plotly_chart(fig_bar, use_container_width=True) # 4. INTELLIGENCE LOG st.subheader("📡 Decrypted Signal Log") def highlight_risk(val): color = '#ef4444' if val in ['Legal/Compliance', 'Technical Failure', 'PR Crisis'] else '#cbd5e1' return f'color: {color}' display_df = df[['Time', 'Source', 'Headline', 'Risk Category', 'Sentiment', 'Impact Score']].copy() st.dataframe( display_df.style.map(highlight_risk, subset=['Risk Category']), use_container_width=True, height=400 )