Spaces:
Running
Running
# import os | |
# import sys | |
# import tempfile | |
# import time | |
# import itertools | |
# import streamlit as st | |
# import pandas as pd | |
# from threading import Thread | |
# from io import StringIO | |
# # Add 'src' to Python path so we can import main.py | |
# 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") | |
# # === Submission logic === | |
# 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: | |
# 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 | |
# # === UI Elements === | |
# spinner_box = st.empty() # For rotating messages | |
# log_box = st.empty() # For logs | |
# 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 language models...", | |
# "π Analyzing investor sentiment...", | |
# "π Summarizing key takeaways...", | |
# "πΉ Building markdown reports..." | |
# ]) | |
# 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 | |
# import openai | |
# openai.OpenAI(api_key=openai_api_key).models.list() | |
# log("β OpenAI API key is valid.") | |
# import requests | |
# tavily_test = requests.post( | |
# "https://api.tavily.com/search", | |
# headers={"Authorization": f"Bearer {tavily_api_key}"}, | |
# json={"query": "test", "days": 1, "max_results": 1} | |
# ) | |
# if tavily_test.status_code == 200: | |
# log("β Tavily API key is valid.") | |
# else: | |
# raise ValueError(f"Tavily error: {tavily_test.status_code} - {tavily_test.text}") | |
# # Run the full pipeline | |
# log("π Running analysis pipeline...") | |
# output_path = run_pipeline(csv_path, tavily_api_key, progress_callback=log) | |
# rotating = False | |
# rotator_thread.join() | |
# spinner_box.success("β Analysis complete!") | |
# if output_path and isinstance(output_path, list): | |
# for path in output_path: | |
# if os.path.exists(path): | |
# with open(path, 'r', encoding='utf-8') as file: | |
# html_content = file.read() | |
# filename = os.path.basename(path) | |
# st.download_button( | |
# label=f"π₯ Download {filename}", | |
# data=html_content, | |
# file_name=filename, | |
# mime="text/html" | |
# ) | |
# st.components.v1.html(html_content, height=600, scrolling=True) | |
# else: | |
# st.error("β No reports were generated.") | |
# 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 itertools | |
import streamlit as st | |
import pandas as pd | |
from threading import Thread | |
from io import StringIO | |
# Add 'src' to Python path so we can import main.py | |
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") | |
# === State control === | |
if "running" not in st.session_state: | |
st.session_state.running = False | |
if "stop_requested" not in st.session_state: | |
st.session_state.stop_requested = False | |
# === Tabs === | |
tabs = st.tabs(["π₯ Input", "π€ Results", "πͺ΅ Logs"]) | |
input_tab, result_tab, log_tab = tabs | |
# === Input Tab === | |
with input_tab: | |
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() | |
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}) | |
run_btn = st.form_submit_button( | |
"Run Analysis" if not st.session_state.running else "Running...", disabled=st.session_state.running | |
) | |
# === Output placeholders === | |
with result_tab: | |
spinner_box = st.empty() | |
download_box = st.empty() | |
with log_tab: | |
log_box = st.empty() | |
stop_btn = st.button("π Stop Analysis", disabled=not st.session_state.running) | |
# === Run if submitted === | |
if run_btn and not st.session_state.running: | |
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: | |
os.environ["OPENAI_API_KEY"] = openai_api_key | |
os.environ["TAVILY_API_KEY"] = tavily_api_key | |
st.session_state.running = True | |
st.session_state.stop_requested = False | |
logs = [] | |
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 | |
def log(msg, level="info"): | |
emoji = {"info": "βΉοΈ", "warning": "β οΈ", "error": "β"}.get(level, "") | |
logs.append(f"{emoji} {msg}") | |
colors = {"info": "blue", "warning": "orange", "error": "red"} | |
styled = [f'<span style="color:{colors.get(level, "black")};">{emoji} {msg}</span>' for msg in logs] | |
log_box.markdown("<br>".join(styled), unsafe_allow_html=True) | |
# Rotating status messages | |
def rotating_messages(): | |
phrases = itertools.cycle([ | |
"π Searching financial news...", | |
"π§ Running language models...", | |
"π Analyzing investor sentiment...", | |
"π Summarizing insights...", | |
"π‘ Generating markdown reports..." | |
]) | |
while st.session_state.running and not st.session_state.stop_requested: | |
spinner_box.markdown(f"β³ {next(phrases)}") | |
time.sleep(1.5) | |
rotator = Thread(target=rotating_messages) | |
rotator.start() | |
try: | |
import openai | |
openai.OpenAI(api_key=openai_api_key).models.list() | |
log("OpenAI API key validated.", "info") | |
import requests | |
test = requests.post( | |
"https://api.tavily.com/search", | |
headers={"Authorization": f"Bearer {tavily_api_key}"}, | |
json={"query": "test", "days": 1, "max_results": 1} | |
) | |
if test.status_code == 200: | |
log("Tavily API key validated.", "info") | |
else: | |
raise ValueError(f"Tavily key rejected: {test.status_code} {test.text}") | |
# Run the pipeline | |
def progress_callback(msg): | |
if st.session_state.stop_requested: | |
raise Exception("β Analysis stopped by user.") | |
log(msg, "info") | |
log("Starting pipeline...", "info") | |
output_path = run_pipeline(csv_path, tavily_api_key, progress_callback=progress_callback) | |
st.session_state.running = False | |
rotator.join() | |
spinner_box.success("β Analysis complete!") | |
if output_path: | |
for path in output_path: | |
if os.path.exists(path): | |
with open(path, "r", encoding="utf-8") as file: | |
html_content = file.read() | |
filename = os.path.basename(path) | |
download_box.download_button( | |
f"π₯ Download {filename}", html_content, filename=filename, mime="text/html" | |
) | |
download_box.components.v1.html(html_content, height=600, scrolling=True) | |
else: | |
log("No reports were generated.", "warning") | |
spinner_box.error("β No reports were generated.") | |
except Exception as e: | |
st.session_state.running = False | |
rotator.join() | |
spinner_box.error(f"β Error: {e}") | |
log(str(e), "error") | |
# === Handle manual stop === | |
if stop_btn and st.session_state.running: | |
st.session_state.stop_requested = True | |
log("π Stop requested by user...", "warning") | |