import streamlit as st
import pandas as pd
from typing import Union, List, Dict
from groq import Groq
import os
from duckduckgo_search import DDGS
# Set page configuration with fullscreen layout and custom theme
st.set_page_config(
page_title="Z-Alpha News Analysis",
layout="wide",
initial_sidebar_state="collapsed",
page_icon="🔍"
)
# Execute JavaScript to make the app fullscreen on load
st.markdown("""
""", unsafe_allow_html=True)
# Enhanced CSS for a more beautiful Google DeepMind-inspired styling with green background
st.markdown("""
""", unsafe_allow_html=True)
class DuckDuckGoSearch:
"""
Custom DuckDuckGo search implementation with robust error handling and result processing.
Uses the duckduckgo_search library to fetch and format news results.
"""
def __init__(self):
# Initialize the DuckDuckGo search session
self.ddgs = DDGS()
def __call__(self, query: str, max_results: int = 5) -> str:
try:
# Perform the search and get results
# The news method is more appropriate for recent news analysis
search_results = list(self.ddgs.news(
query,
max_results=max_results,
region='wt-wt', # Worldwide results
safesearch='on'
))
if not search_results:
return "No results found. Try modifying your search query."
# Format the results into a readable string
formatted_results = []
for idx, result in enumerate(search_results, 1):
# Extract available fields with fallbacks for missing data
title = result.get('title', 'No title available')
snippet = result.get('body', result.get('snippet', 'No description available'))
source = result.get('source', 'Unknown source')
url = result.get('url', result.get('link', 'No link available'))
date = result.get('date', 'Date not available')
# Format each result with available information
formatted_results.append(
f"{idx}. Title: {title}\n"
f" Date: {date}\n"
f" Source: {source}\n"
f" Summary: {snippet}\n"
f" URL: {url}\n"
)
return "\n".join(formatted_results)
except Exception as e:
# Provide detailed error information for debugging
error_msg = f"Search error: {str(e)}\nTry again with a different search term or check your internet connection."
print(f"DuckDuckGo search error: {str(e)}") # For logging
return error_msg
class GroqLLM:
"""
LLM interface using Groq's LLama model.
Handles API communication and response processing.
"""
def __init__(self, model_name="llama-3.1-8B-Instant"):
self.client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
self.model_name = model_name
def __call__(self, prompt: Union[str, dict, List[Dict]]) -> str:
try:
# Convert prompt to string if it's a complex structure
prompt_str = str(prompt) if isinstance(prompt, (dict, list)) else prompt
# Make API call to Groq
completion = self.client.chat.completions.create(
model=self.model_name,
messages=[{
"role": "user",
"content": prompt_str
}],
temperature=0.7,
max_tokens=1024,
stream=False
)
return completion.choices[0].message.content if completion.choices else "Error: No response generated"
except Exception as e:
error_msg = f"Error generating response: {str(e)}"
print(error_msg) # For logging
return error_msg
def create_analysis_prompt(topic: str, search_results: str) -> str:
"""
Creates a detailed prompt for news analysis, structuring the request
to get comprehensive and well-organized results from the LLM.
"""
return f"""Analyze the following news information about {topic}.
Search Results: {search_results}
Please provide a comprehensive analysis including:
1. Key Points Summary:
- Main events and developments
- Critical updates and changes
2. Stakeholder Analysis:
- Primary parties involved
- Their roles and positions
3. Impact Assessment:
- Immediate implications
- Potential long-term effects
- Broader context and significance
4. Multiple Perspectives:
- Different viewpoints on the issue
- Areas of agreement and contention
5. Fact Check & Reliability:
- Verification of major claims
- Consistency across sources
- Source credibility assessment
Please format the analysis in a clear, journalistic style with section headers."""
def log_agent_activity(prompt: str, result: str, agent_name: str):
"""
Creates an expandable log of agent activities in the Streamlit interface
for transparency and debugging purposes.
"""
with st.expander("🔍 View Agent Activity Log"):
st.markdown("
", unsafe_allow_html=True)
# Animated header with branded logo and description
st.markdown("""
Z-Agent News Analysis
Intelligent news analysis powered by AI. Get comprehensive insights and multiple perspectives on any topic.
""", unsafe_allow_html=True)
# Main content area
st.markdown('
', unsafe_allow_html=True)
# Initialize the components
try:
# Initialize LLM and search tool
llm = GroqLLM()
search_tool = DuckDuckGoSearch()
# Input section with enhanced design
st.markdown("
News Topic Analysis
", unsafe_allow_html=True)
news_topic = st.text_input(
"What news topic would you like to analyze?",
placeholder="E.g., Recent developments in renewable energy, Tech industry layoffs, Global climate agreements...",
key="news_topic_input"
)
# Analysis options in a cleaner layout
st.markdown("", unsafe_allow_html=True)
st.markdown("
""", unsafe_allow_html=True)
except Exception as e:
st.error(f"""
An error occurred during analysis: {str(e)}
""", unsafe_allow_html=True)
elif analyze_button:
# This handles the case when analyze button is clicked but no topic is entered
st.warning("""
Please enter a news topic to analyze.
""", unsafe_allow_html=True)
# Tips and usage guidance section - displayed when no analysis is in progress
if not analyze_button or not news_topic:
st.markdown('
', unsafe_allow_html=True)
st.markdown("
Tips for Better Results
", unsafe_allow_html=True)
st.markdown("""
💡
Be specific with your topic. Instead of "climate change", try "recent climate legislation in the EU".
🔍
Adjust search depth to find the right balance between comprehensive coverage and analysis speed.
📊
Choose the right analysis type based on your needs:
Comprehensive: Full analysis with multiple perspectives
Quick Summary: Brief overview of key points
Technical: Detailed analysis with industry-specific terminology
Simplified: Easy-to-understand breakdown of complex topics
⏱️
Select an appropriate time period based on how recent you want the news to be.
""", unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
# Example topics for quick selection
st.markdown('
', unsafe_allow_html=True)
st.markdown("
Try These Topics
", unsafe_allow_html=True)
col1, col2, col3 = st.columns(3)
with col1:
if st.button("🌍 Climate Change Policies"):
st.session_state.news_topic_input = "Recent climate change policies and agreements"
st.experimental_rerun()
with col2:
if st.button("💰 Cryptocurrency Trends"):
st.session_state.news_topic_input = "Latest developments in cryptocurrency markets"
st.experimental_rerun()
with col3:
if st.button("🔬 AI Research Breakthroughs"):
st.session_state.news_topic_input = "Recent breakthroughs in artificial intelligence research"
st.experimental_rerun()
st.markdown('
', unsafe_allow_html=True)
# Footer with attribution and version info
st.markdown("""
""", unsafe_allow_html=True)
except Exception as e:
# Global error handling to catch any unforeseen issues
st.error(f"""
Application Error: {str(e)}
""", unsafe_allow_html=True)
st.markdown("""
Troubleshooting Tips:
Check your API keys for Groq LLM in environment variables
Ensure you have internet connection for DuckDuckGo searches
Try refreshing the page or restarting the application
""", unsafe_allow_html=True)
# Add a hidden feature to reset the application state
if st.sidebar.button("Reset Application", key="reset_app"):
for key in st.session_state.keys():
del st.session_state[key]
st.experimental_rerun()
# Optional: Add a feedback mechanism
with st.sidebar:
st.markdown("### Feedback")
feedback = st.text_area("Share your thoughts or report issues", placeholder="Your feedback helps us improve...")
if st.button("Submit Feedback"):
st.success("Thank you for your feedback!")
# In a production app, you would save this feedback to a database