Sigrid De los Santos
App is ready
c319a1e
import os
import sys
import tempfile
import time
import itertools
import streamlit as st
import pandas as pd
import requests
import openai
from threading import Thread
# Add 'src' to Python path
sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
from main import run_pipeline
st.set_page_config(page_title="πŸ“° AI News Analyzer", layout="wide")
st.title("🧠 AI-Powered Investing News Analyzer")
# === API Key Input ===
st.subheader("πŸ” API Keys")
openai_api_key = st.text_input("OpenAI API Key", type="password").strip()
tavily_api_key = st.text_input("Tavily API Key", type="password").strip()
# === Topic Input ===
st.subheader("πŸ“ˆ Topics of Interest")
topics_data = []
with st.form("topics_form"):
topic_count = st.number_input("How many topics?", min_value=1, max_value=10, value=1, step=1)
for i in range(topic_count):
col1, col2 = st.columns(2)
with col1:
topic = st.text_input(f"Topic {i+1}", key=f"topic_{i}")
with col2:
days = st.number_input(f"Timespan (days)", min_value=1, max_value=30, value=7, key=f"days_{i}")
topics_data.append({"topic": topic, "timespan_days": days})
submitted = st.form_submit_button("Run Analysis")
# === Tabs Setup ===
tab_report, tab_articles, tab_insights = st.tabs(["πŸ“ Report", "πŸ“‹ Articles", "πŸ“Š Insights"])
if submitted:
if not openai_api_key or not tavily_api_key or not all([td['topic'] for td in topics_data]):
st.warning("Please fill in all fields.")
else:
# Reset old results
articles_df = pd.DataFrame()
insights_df = pd.DataFrame()
html_paths = []
os.environ["OPENAI_API_KEY"] = openai_api_key
os.environ["TAVILY_API_KEY"] = tavily_api_key
df = pd.DataFrame(topics_data)
with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp_csv:
df.to_csv(tmp_csv.name, index=False)
csv_path = tmp_csv.name
spinner_box = st.empty()
log_box = st.empty()
logs = []
rotating = True
def log(msg):
logs.append(msg)
log_box.code("\n".join(logs))
# === Rotating UI Messages ===
def rotating_messages():
messages = itertools.cycle([
"πŸ” Searching financial news...",
"🧠 Running AI analysis...",
"πŸ“Š Evaluating sentiment...",
"πŸ“ Generating report...",
"πŸ’Ή Finalizing insights..."
])
while rotating:
spinner_box.markdown(f"⏳ {next(messages)}")
time.sleep(1.5)
rotator_thread = Thread(target=rotating_messages)
rotator_thread.start()
try:
# Check API Keys
try:
client = openai.OpenAI(api_key=openai_api_key)
client.models.list()
log("βœ… OpenAI API key is valid.")
except Exception as e:
log(f"❌ OpenAI API Key Error: {e}")
rotating = False
rotator_thread.join()
st.stop()
try:
response = requests.post(
"https://api.tavily.com/search",
headers={"Authorization": f"Bearer {tavily_api_key}"},
json={"query": "test", "days": 1, "max_results": 1}
)
if response.status_code == 200:
log("βœ… Tavily API key is valid.")
else:
log(f"❌ Tavily Key Error: {response.status_code} {response.text}")
rotating = False
rotator_thread.join()
st.stop()
except Exception as e:
log(f"❌ Tavily API Key Error: {e}")
rotating = False
rotator_thread.join()
st.stop()
with st.spinner("⏳ Running analysis..."):
html_paths, articles_df, insights_df = run_pipeline(csv_path, tavily_api_key, progress_callback=log)
rotating = False
rotator_thread.join()
spinner_box.success("βœ… Analysis complete!")
# === Report Tab ===
with tab_report:
st.subheader("πŸ“ Latest Report")
if html_paths:
latest_report = html_paths[-1]
with open(latest_report, 'r', encoding='utf-8') as f:
html_content = f.read()
# Download button for HTML report
st.download_button(
label="⬇️ Download Report (HTML)",
data=html_content,
file_name=os.path.basename(latest_report),
mime="text/html"
)
st.components.v1.html(html_content, height=600, scrolling=True)
else:
st.error("❌ No reports were generated.")
# === Articles Tab ===
with tab_articles:
st.subheader("πŸ“‹ Articles Table")
if not articles_df.empty:
st.dataframe(
articles_df[["Title", "URL", "Priority", "Sentiment", "Confidence", "Signal", "Date"]],
use_container_width=True
)
st.download_button(
label="⬇️ Download Articles CSV",
data=articles_df.to_csv(index=False).encode("utf-8"),
file_name="articles.csv",
mime="text/csv"
)
else:
st.info("No articles available.")
# === Insights Tab ===
with tab_insights:
st.subheader("πŸ“Š Investment Insights")
if not insights_df.empty:
st.dataframe(insights_df, use_container_width=True)
st.download_button(
label="⬇️ Download Insights CSV",
data=insights_df.to_csv(index=False).encode("utf-8"),
file_name="insights.csv",
mime="text/csv"
)
else:
st.info("No insights available.")
except Exception as e:
rotating = False
rotator_thread.join()
spinner_box.error("❌ Failed.")
log_box.error(f"❌ Error: {e}")
# import os
# import sys
# import tempfile
# import time
# import streamlit as st
# import pandas as pd
# import requests
# import openai
# sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
# from main import run_pipeline
# st.set_page_config(page_title="πŸ“° AI News Analyzer", layout="wide")
# st.title("🧠 AI-Powered Investing News Analyzer")
# # === API Key Input ===
# st.subheader("πŸ” API Keys")
# openai_api_key = st.text_input("OpenAI API Key", type="password").strip()
# tavily_api_key = st.text_input("Tavily API Key", type="password").strip()
# # === Topic Input ===
# st.subheader("πŸ“ˆ Topics of Interest")
# topics_data = []
# with st.form("topics_form"):
# topic_count = st.number_input("How many topics?", min_value=1, max_value=10, value=1, step=1)
# for i in range(topic_count):
# col1, col2 = st.columns(2)
# with col1:
# topic = st.text_input(f"Topic {i+1}", key=f"topic_{i}")
# with col2:
# days = st.number_input(f"Timespan (days)", min_value=1, max_value=30, value=7, key=f"days_{i}")
# topics_data.append({"topic": topic, "timespan_days": days})
# submitted = st.form_submit_button("Run Analysis")
# # === Tabs Setup ===
# tab_report, tab_articles, tab_insights, tab_debug = st.tabs(["πŸ“ Report", "πŸ“‹ Articles", "πŸ“Š Insights", "πŸ›  Debug"])
# if submitted:
# if not openai_api_key or not tavily_api_key or not all([td['topic'] for td in topics_data]):
# st.warning("Please fill in all fields.")
# else:
# articles_df = pd.DataFrame()
# insights_df = pd.DataFrame()
# html_paths = []
# os.environ["OPENAI_API_KEY"] = openai_api_key
# os.environ["TAVILY_API_KEY"] = tavily_api_key
# df = pd.DataFrame(topics_data)
# with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp_csv:
# df.to_csv(tmp_csv.name, index=False)
# csv_path = tmp_csv.name
# spinner_box = st.empty()
# log_box = st.empty()
# logs = []
# def log(msg):
# logs.append(msg)
# log_box.code("\n".join(logs))
# try:
# spinner_box.markdown("⏳ Checking API keys...")
# # === Check OpenAI Key ===
# try:
# client = openai.OpenAI(api_key=openai_api_key)
# client.models.list()
# log("βœ… OpenAI API key is valid.")
# except Exception as e:
# log(f"❌ OpenAI API Key Error: {e}")
# st.stop()
# # === Check Tavily Key ===
# try:
# response = requests.post(
# "https://api.tavily.com/search",
# headers={"Authorization": f"Bearer {tavily_api_key}"},
# json={"query": "test", "days": 1, "max_results": 1}
# )
# if response.status_code == 200:
# log("βœ… Tavily API key is valid.")
# else:
# log(f"❌ Tavily Key Error: {response.status_code} {response.text}")
# st.stop()
# except Exception as e:
# log(f"❌ Tavily API Key Error: {e}")
# st.stop()
# spinner_box.markdown("⏳ Running analysis pipeline...")
# html_paths, articles_df, insights_df = run_pipeline(csv_path, tavily_api_key, progress_callback=log)
# spinner_box.success("βœ… Analysis complete!")
# # === Report Tab ===
# with tab_report:
# if html_paths:
# for path in html_paths:
# with open(path, 'r', encoding='utf-8') as f:
# html_content = f.read()
# st.components.v1.html(html_content, height=600, scrolling=True)
# else:
# st.error("❌ No reports were generated.")
# # === Articles Tab ===
# with tab_articles:
# st.subheader("πŸ“‹ Articles Table")
# if not articles_df.empty:
# st.dataframe(articles_df[["Title", "URL", "Summary", "Priority", "Sentiment", "Confidence", "Signal", "Date"]],
# use_container_width=True)
# st.download_button(
# label="⬇️ Download Articles CSV",
# data=articles_df.to_csv(index=False).encode("utf-8"),
# file_name="articles.csv",
# mime="text/csv"
# )
# else:
# st.info("No articles available.")
# # === Insights Tab ===
# with tab_insights:
# st.subheader("πŸ“Š Top Investment Insights")
# if not insights_df.empty:
# st.dataframe(insights_df, use_container_width=True)
# st.download_button(
# label="⬇️ Download Insights CSV",
# data=insights_df.to_csv(index=False).encode("utf-8"),
# file_name="insights.csv",
# mime="text/csv"
# )
# else:
# st.info("No insights available.")
# # === Debug Tab ===
# with tab_debug:
# st.subheader("πŸ›  Debug Log")
# st.code("\n".join(logs) if logs else "No logs yet.")
# except Exception as e:
# spinner_box.error("❌ Failed.")
# log_box.error(f"❌ Error: {e}")