Sigrid De los Santos commited on
Commit
8e384aa
Β·
1 Parent(s): 7d2254a

Add matplotlib to requirements

Browse files
Files changed (1) hide show
  1. app.py +210 -138
app.py CHANGED
@@ -1,139 +1,11 @@
1
- import os
2
- import sys
3
- import tempfile
4
- import time
5
- import itertools
6
- import streamlit as st
7
- import pandas as pd
8
- from threading import Thread
9
- from io import StringIO
10
-
11
- # Add 'src' to Python path
12
- sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
13
- from main import run_pipeline
14
-
15
- st.set_page_config(page_title="πŸ“° AI News Analyzer", layout="wide")
16
- st.title("🧠 AI-Powered Investing News Analyzer")
17
-
18
- # === API Key Input ===
19
- st.subheader("πŸ” API Keys")
20
- openai_api_key = st.text_input("OpenAI API Key", type="password").strip()
21
- tavily_api_key = st.text_input("Tavily API Key", type="password").strip()
22
-
23
- # === Topic Input ===
24
- st.subheader("πŸ“ˆ Topics of Interest")
25
- topics_data = []
26
-
27
- with st.form("topics_form"):
28
- topic_count = st.number_input("How many topics?", min_value=1, max_value=10, value=1, step=1)
29
-
30
- for i in range(topic_count):
31
- col1, col2 = st.columns(2)
32
- with col1:
33
- topic = st.text_input(f"Topic {i+1}", key=f"topic_{i}")
34
- with col2:
35
- days = st.number_input(f"Timespan (days)", min_value=1, max_value=30, value=7, key=f"days_{i}")
36
- topics_data.append({"topic": topic, "timespan_days": days})
37
-
38
- submitted = st.form_submit_button("Run Analysis")
39
-
40
- # === Submission logic ===
41
- if submitted:
42
- if not openai_api_key or not tavily_api_key or not all([td['topic'] for td in topics_data]):
43
- st.warning("Please fill in all fields.")
44
- else:
45
- os.environ["OPENAI_API_KEY"] = openai_api_key
46
- os.environ["TAVILY_API_KEY"] = tavily_api_key
47
-
48
- df = pd.DataFrame(topics_data)
49
- with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp_csv:
50
- df.to_csv(tmp_csv.name, index=False)
51
- csv_path = tmp_csv.name
52
-
53
- # Placeholders
54
- spinner_box = st.empty()
55
- log_box = st.empty()
56
-
57
- # Rotating spinner text
58
- rotating = True
59
- logs = []
60
-
61
- def log(msg):
62
- logs.append(msg)
63
- log_box.code("\n".join(logs))
64
-
65
- def rotating_messages():
66
- messages = itertools.cycle([
67
- "πŸ” Searching financial news...",
68
- "🧠 Running language models...",
69
- "πŸ“Š Generating investment reports...",
70
- "πŸ“ Compiling markdown...",
71
- "πŸ”Ž Looking for value signals..."
72
- ])
73
- while rotating:
74
- spinner_box.markdown(f"⏳ {next(messages)}")
75
- time.sleep(1.4)
76
-
77
- rotator_thread = Thread(target=rotating_messages)
78
- rotator_thread.start()
79
-
80
- try:
81
- # Log: API checks
82
- log("πŸ” Checking API keys...")
83
- import openai
84
- openai_client = openai.OpenAI(api_key=openai_api_key)
85
- openai_client.models.list() # triggers check
86
- log("βœ… OpenAI API key is valid.")
87
-
88
- import requests
89
- tavily_check = requests.post(
90
- "https://api.tavily.com/search",
91
- headers={"Authorization": f"Bearer {tavily_api_key}"},
92
- json={"query": "test", "days": 1, "max_results": 1}
93
- )
94
- if tavily_check.status_code == 200:
95
- log("βœ… Tavily API key is valid.")
96
- else:
97
- raise ValueError(f"Tavily key failed: {tavily_check.status_code} - {tavily_check.text}")
98
-
99
- # Run main pipeline
100
- log("πŸš€ Running analysis pipeline...")
101
- output_path = run_pipeline(csv_path, tavily_api_key, progress_callback=log)
102
-
103
- rotating = False
104
- rotator_thread.join()
105
- spinner_box.success("βœ… Analysis complete!")
106
-
107
- if output_path and isinstance(output_path, list):
108
- for path in output_path:
109
- if os.path.exists(path):
110
- with open(path, 'r', encoding='utf-8') as file:
111
- html_content = file.read()
112
- filename = os.path.basename(path)
113
-
114
- st.download_button(
115
- label=f"πŸ“₯ Download {filename}",
116
- data=html_content,
117
- file_name=filename,
118
- mime="text/html"
119
- )
120
- st.components.v1.html(html_content, height=600, scrolling=True)
121
- else:
122
- st.error("❌ No reports were generated.")
123
-
124
- except Exception as e:
125
- rotating = False
126
- rotator_thread.join()
127
- spinner_box.error("❌ Failed.")
128
- log_box.error(f"❌ Error: {e}")
129
-
130
- ##################################################################################################
131
- ##################################################################################################
132
  # import os
133
  # import sys
134
  # import tempfile
 
 
135
  # import streamlit as st
136
  # import pandas as pd
 
137
  # from io import StringIO
138
 
139
  # # Add 'src' to Python path so we can import main.py
@@ -178,14 +50,56 @@ if submitted:
178
  # df.to_csv(tmp_csv.name, index=False)
179
  # csv_path = tmp_csv.name
180
 
181
- # progress_box = st.empty()
182
-
183
- # def show_progress(msg):
184
- # progress_box.markdown(f"⏳ {msg}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
  # try:
187
- # output_path = run_pipeline(csv_path, tavily_api_key, progress_callback=show_progress)
188
- # progress_box.success("βœ… Analysis complete!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  # if output_path and isinstance(output_path, list):
191
  # for path in output_path:
@@ -203,7 +117,165 @@ if submitted:
203
  # st.components.v1.html(html_content, height=600, scrolling=True)
204
  # else:
205
  # st.error("❌ No reports were generated.")
 
206
  # except Exception as e:
207
- # progress_box.error(f"❌ Error: {e}")
 
 
 
208
 
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # import os
2
  # import sys
3
  # import tempfile
4
+ # import time
5
+ # import itertools
6
  # import streamlit as st
7
  # import pandas as pd
8
+ # from threading import Thread
9
  # from io import StringIO
10
 
11
  # # Add 'src' to Python path so we can import main.py
 
50
  # df.to_csv(tmp_csv.name, index=False)
51
  # csv_path = tmp_csv.name
52
 
53
+ # # === UI Elements ===
54
+ # spinner_box = st.empty() # For rotating messages
55
+ # log_box = st.empty() # For logs
56
+ # logs = []
57
+ # rotating = True
58
+
59
+ # def log(msg):
60
+ # logs.append(msg)
61
+ # log_box.code("\n".join(logs))
62
+
63
+ # # === Rotating UI Messages ===
64
+ # def rotating_messages():
65
+ # messages = itertools.cycle([
66
+ # "πŸ” Searching financial news...",
67
+ # "🧠 Running language models...",
68
+ # "πŸ“Š Analyzing investor sentiment...",
69
+ # "πŸ“ Summarizing key takeaways...",
70
+ # "πŸ’Ή Building markdown reports..."
71
+ # ])
72
+ # while rotating:
73
+ # spinner_box.markdown(f"⏳ {next(messages)}")
74
+ # time.sleep(1.5)
75
+
76
+ # rotator_thread = Thread(target=rotating_messages)
77
+ # rotator_thread.start()
78
 
79
  # try:
80
+ # # Check API Keys
81
+ # import openai
82
+ # openai.OpenAI(api_key=openai_api_key).models.list()
83
+ # log("βœ… OpenAI API key is valid.")
84
+
85
+ # import requests
86
+ # tavily_test = requests.post(
87
+ # "https://api.tavily.com/search",
88
+ # headers={"Authorization": f"Bearer {tavily_api_key}"},
89
+ # json={"query": "test", "days": 1, "max_results": 1}
90
+ # )
91
+ # if tavily_test.status_code == 200:
92
+ # log("βœ… Tavily API key is valid.")
93
+ # else:
94
+ # raise ValueError(f"Tavily error: {tavily_test.status_code} - {tavily_test.text}")
95
+
96
+ # # Run the full pipeline
97
+ # log("πŸš€ Running analysis pipeline...")
98
+ # output_path = run_pipeline(csv_path, tavily_api_key, progress_callback=log)
99
+
100
+ # rotating = False
101
+ # rotator_thread.join()
102
+ # spinner_box.success("βœ… Analysis complete!")
103
 
104
  # if output_path and isinstance(output_path, list):
105
  # for path in output_path:
 
117
  # st.components.v1.html(html_content, height=600, scrolling=True)
118
  # else:
119
  # st.error("❌ No reports were generated.")
120
+
121
  # except Exception as e:
122
+ # rotating = False
123
+ # rotator_thread.join()
124
+ # spinner_box.error("❌ Failed.")
125
+ # log_box.error(f"❌ Error: {e}")
126
 
127
 
128
+ ##################################################################################################
129
+ ##################################################################################################
130
+ import os
131
+ import sys
132
+ import tempfile
133
+ import time
134
+ import itertools
135
+ import streamlit as st
136
+ import pandas as pd
137
+ from threading import Thread
138
+ from io import StringIO
139
+
140
+ # Add 'src' to Python path so we can import main.py
141
+ sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
142
+ from main import run_pipeline
143
+
144
+ st.set_page_config(page_title="πŸ“° AI News Analyzer", layout="wide")
145
+ st.title("🧠 AI-Powered Investing News Analyzer")
146
+
147
+ # === State control ===
148
+ if "running" not in st.session_state:
149
+ st.session_state.running = False
150
+ if "stop_requested" not in st.session_state:
151
+ st.session_state.stop_requested = False
152
+
153
+ # === Tabs ===
154
+ tabs = st.tabs(["πŸ“₯ Input", "πŸ“€ Results", "πŸͺ΅ Logs"])
155
+ input_tab, result_tab, log_tab = tabs
156
+
157
+ # === Input Tab ===
158
+ with input_tab:
159
+ st.subheader("πŸ” API Keys")
160
+ openai_api_key = st.text_input("OpenAI API Key", type="password").strip()
161
+ tavily_api_key = st.text_input("Tavily API Key", type="password").strip()
162
+
163
+ st.subheader("πŸ“ˆ Topics of Interest")
164
+ topics_data = []
165
+
166
+ with st.form("topics_form"):
167
+ topic_count = st.number_input("How many topics?", min_value=1, max_value=10, value=1, step=1)
168
+
169
+ for i in range(topic_count):
170
+ col1, col2 = st.columns(2)
171
+ with col1:
172
+ topic = st.text_input(f"Topic {i+1}", key=f"topic_{i}")
173
+ with col2:
174
+ days = st.number_input(f"Timespan (days)", min_value=1, max_value=30, value=7, key=f"days_{i}")
175
+ topics_data.append({"topic": topic, "timespan_days": days})
176
+
177
+ run_btn = st.form_submit_button(
178
+ "Run Analysis" if not st.session_state.running else "Running...", disabled=st.session_state.running
179
+ )
180
+
181
+ # === Output placeholders ===
182
+ with result_tab:
183
+ spinner_box = st.empty()
184
+ download_box = st.empty()
185
+
186
+ with log_tab:
187
+ log_box = st.empty()
188
+ stop_btn = st.button("πŸ›‘ Stop Analysis", disabled=not st.session_state.running)
189
+
190
+ # === Run if submitted ===
191
+ if run_btn and not st.session_state.running:
192
+ if not openai_api_key or not tavily_api_key or not all([td['topic'] for td in topics_data]):
193
+ st.warning("Please fill in all fields.")
194
+ else:
195
+ os.environ["OPENAI_API_KEY"] = openai_api_key
196
+ os.environ["TAVILY_API_KEY"] = tavily_api_key
197
+ st.session_state.running = True
198
+ st.session_state.stop_requested = False
199
+ logs = []
200
+
201
+ df = pd.DataFrame(topics_data)
202
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp_csv:
203
+ df.to_csv(tmp_csv.name, index=False)
204
+ csv_path = tmp_csv.name
205
+
206
+ def log(msg, level="info"):
207
+ emoji = {"info": "ℹ️", "warning": "⚠️", "error": "❌"}.get(level, "")
208
+ logs.append(f"{emoji} {msg}")
209
+ colors = {"info": "blue", "warning": "orange", "error": "red"}
210
+ styled = [f'<span style="color:{colors.get(level, "black")};">{emoji} {msg}</span>' for msg in logs]
211
+ log_box.markdown("<br>".join(styled), unsafe_allow_html=True)
212
+
213
+ # Rotating status messages
214
+ def rotating_messages():
215
+ phrases = itertools.cycle([
216
+ "πŸ” Searching financial news...",
217
+ "🧠 Running language models...",
218
+ "πŸ“Š Analyzing investor sentiment...",
219
+ "πŸ“ Summarizing insights...",
220
+ "πŸ’‘ Generating markdown reports..."
221
+ ])
222
+ while st.session_state.running and not st.session_state.stop_requested:
223
+ spinner_box.markdown(f"⏳ {next(phrases)}")
224
+ time.sleep(1.5)
225
+
226
+ rotator = Thread(target=rotating_messages)
227
+ rotator.start()
228
+
229
+ try:
230
+ import openai
231
+ openai.OpenAI(api_key=openai_api_key).models.list()
232
+ log("OpenAI API key validated.", "info")
233
+
234
+ import requests
235
+ test = requests.post(
236
+ "https://api.tavily.com/search",
237
+ headers={"Authorization": f"Bearer {tavily_api_key}"},
238
+ json={"query": "test", "days": 1, "max_results": 1}
239
+ )
240
+ if test.status_code == 200:
241
+ log("Tavily API key validated.", "info")
242
+ else:
243
+ raise ValueError(f"Tavily key rejected: {test.status_code} {test.text}")
244
+
245
+ # Run the pipeline
246
+ def progress_callback(msg):
247
+ if st.session_state.stop_requested:
248
+ raise Exception("β›” Analysis stopped by user.")
249
+ log(msg, "info")
250
+
251
+ log("Starting pipeline...", "info")
252
+ output_path = run_pipeline(csv_path, tavily_api_key, progress_callback=progress_callback)
253
+
254
+ st.session_state.running = False
255
+ rotator.join()
256
+ spinner_box.success("βœ… Analysis complete!")
257
+
258
+ if output_path:
259
+ for path in output_path:
260
+ if os.path.exists(path):
261
+ with open(path, "r", encoding="utf-8") as file:
262
+ html_content = file.read()
263
+ filename = os.path.basename(path)
264
+ download_box.download_button(
265
+ f"πŸ“₯ Download {filename}", html_content, filename=filename, mime="text/html"
266
+ )
267
+ download_box.components.v1.html(html_content, height=600, scrolling=True)
268
+ else:
269
+ log("No reports were generated.", "warning")
270
+ spinner_box.error("❌ No reports were generated.")
271
+
272
+ except Exception as e:
273
+ st.session_state.running = False
274
+ rotator.join()
275
+ spinner_box.error(f"❌ Error: {e}")
276
+ log(str(e), "error")
277
+
278
+ # === Handle manual stop ===
279
+ if stop_btn and st.session_state.running:
280
+ st.session_state.stop_requested = True
281
+ log("πŸ›‘ Stop requested by user...", "warning")