Ani14 commited on
Commit
1a96a2f
Β·
verified Β·
1 Parent(s): 249c688

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -34
app.py CHANGED
@@ -10,8 +10,8 @@ from tavily import TavilyClient
10
  import feedparser
11
  from fuzzywuzzy import fuzz
12
  from fpdf import FPDF
13
- from io import BytesIO
14
  from duckduckgo_search import DDGS
 
15
 
16
  # --- Load API Keys ---
17
  load_dotenv()
@@ -65,7 +65,7 @@ def call_llm(messages, model="deepseek/deepseek-chat-v3-0324:free", max_tokens=4
65
  except json.JSONDecodeError:
66
  pass
67
 
68
- def get_image_urls(query, max_images=3):
69
  with DDGS() as ddgs:
70
  return [img["image"] for img in ddgs.images(query, max_results=max_images)]
71
 
@@ -163,7 +163,6 @@ def download_threads_as_pdf(chat_threads):
163
  for msg in chats:
164
  role = "You" if msg["role"] == "user" else "Assistant"
165
  text = f"{role}: {msg['content']}"
166
- # Safely encode for Latin-1 by replacing unknown characters
167
  try:
168
  text = text.encode('latin-1').decode('latin-1')
169
  except UnicodeEncodeError:
@@ -176,11 +175,9 @@ def download_threads_as_pdf(chat_threads):
176
  pdf_output.seek(0)
177
  return pdf_output
178
 
 
 
179
 
180
- # --- Streamlit UI ---
181
- st.set_page_config(page_title="🧠 Deep Research Assistant 3.0", layout="centered")
182
-
183
- # --- Load Memory ---
184
  if "memory_bank" not in st.session_state:
185
  st.session_state.memory_bank = []
186
  if "chat_threads" not in st.session_state:
@@ -192,20 +189,43 @@ load_session_data()
192
 
193
  # --- Sidebar ---
194
  with st.sidebar:
195
- st.title("Deep Research Assistant 3.0 πŸš€")
196
- topic = st.text_input("πŸ” Enter research topic")
 
197
  report_type = st.selectbox("πŸ“„ Report Type", ["Summary", "Detailed Report", "Thorough Academic Research"])
198
  tone = st.selectbox("🎯 Tone", ["Objective", "Persuasive", "Narrative"])
199
  source_type = st.selectbox("πŸ“š Sources", ["Web Only", "Academic Only", "Hybrid"])
200
- custom_domains = st.text_input("🌐 Optional Domains", placeholder="example.com, nature.com")
201
- research_button = st.button("πŸš€ Start Research")
 
 
 
 
 
 
 
202
 
203
- # --- Main Area ---
204
- st.title("πŸ“˜ Research Output")
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  if research_button and topic:
207
  try:
208
- with st.status("πŸ” Gathering sources..."):
209
  all_sources = []
210
  if source_type in ["Web Only", "Hybrid"]:
211
  all_sources += get_sources(topic, custom_domains) if custom_domains.strip() else get_sources(topic)
@@ -234,13 +254,13 @@ if research_button and topic:
234
  "Thorough Academic Research": "Craft a full academic paper >1000 words."
235
  }[report_type]
236
 
 
237
  thread_id = str(uuid.uuid4())
238
  st.session_state.current_thread_id = thread_id
239
  st.session_state.chat_threads[thread_id] = []
240
 
241
  prompt = f"""
242
  Use past learnings:
243
-
244
  {previous_learnings}
245
 
246
  New Topic:
@@ -259,6 +279,7 @@ Citations:
259
  {chr(10).join(citations)}
260
  """
261
 
 
262
  st.subheader(f"πŸ“ {report_type} on '{topic}'")
263
  output_placeholder = st.empty()
264
  final_output = ""
@@ -274,31 +295,49 @@ Citations:
274
  except Exception as e:
275
  st.error(f"❌ Error: {e}")
276
 
277
- # --- Chat Threads and Follow-ups ---
278
  st.divider()
279
  st.subheader("πŸ“‚ Your Research Threads")
280
 
 
 
 
281
  for tid, chats in st.session_state.chat_threads.items():
282
- with st.expander(f"Thread {tid[:8]}"):
283
- for msg in chats:
284
- role = "πŸ§‘ You" if msg['role'] == 'user' else "πŸ€– Assistant"
285
- st.markdown(f"**{role}:** {msg['content']}")
286
-
287
- followup = st.text_input(f"πŸ’¬ Ask more in Thread {tid[:8]}:", key=f"followup_{tid}")
288
- if st.button(f"Ask Follow-up {tid}", key=f"button_{tid}"):
289
- if followup:
290
- response = ""
291
- for chunk in call_llm(st.session_state.chat_threads[tid] + [{"role": "user", "content": followup}], max_tokens=2000):
292
- response += chunk
293
- st.session_state.chat_threads[tid].append({"role": "user", "content": followup})
294
- st.session_state.chat_threads[tid].append({"role": "assistant", "content": response})
295
- save_session_data()
296
- st.rerun()
297
-
298
- # --- Download Button ---
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  if st.session_state.chat_threads:
 
 
300
  pdf_file = download_threads_as_pdf(st.session_state.chat_threads)
301
- st.download_button("πŸ“₯ Download All Threads as PDF", data=pdf_file, file_name="Research_Threads.pdf", mime="application/pdf")
302
 
303
 
304
 
 
10
  import feedparser
11
  from fuzzywuzzy import fuzz
12
  from fpdf import FPDF
 
13
  from duckduckgo_search import DDGS
14
+ from io import BytesIO
15
 
16
  # --- Load API Keys ---
17
  load_dotenv()
 
65
  except json.JSONDecodeError:
66
  pass
67
 
68
+ def get_image_urls(query, max_images=5):
69
  with DDGS() as ddgs:
70
  return [img["image"] for img in ddgs.images(query, max_results=max_images)]
71
 
 
163
  for msg in chats:
164
  role = "You" if msg["role"] == "user" else "Assistant"
165
  text = f"{role}: {msg['content']}"
 
166
  try:
167
  text = text.encode('latin-1').decode('latin-1')
168
  except UnicodeEncodeError:
 
175
  pdf_output.seek(0)
176
  return pdf_output
177
 
178
+ # --- Streamlit UI Setup ---
179
+ st.set_page_config(page_title="🧠 Deep Research Assistant 4.0", layout="centered")
180
 
 
 
 
 
181
  if "memory_bank" not in st.session_state:
182
  st.session_state.memory_bank = []
183
  if "chat_threads" not in st.session_state:
 
189
 
190
  # --- Sidebar ---
191
  with st.sidebar:
192
+ st.image("https://raw.githubusercontent.com/mk-gurucharan/streamlit-deep-research/main/deep_research_logo.png", use_column_width=True)
193
+ st.markdown("## πŸ” Start New Research")
194
+ topic = st.text_input("🧠 Topic")
195
  report_type = st.selectbox("πŸ“„ Report Type", ["Summary", "Detailed Report", "Thorough Academic Research"])
196
  tone = st.selectbox("🎯 Tone", ["Objective", "Persuasive", "Narrative"])
197
  source_type = st.selectbox("πŸ“š Sources", ["Web Only", "Academic Only", "Hybrid"])
198
+ custom_domains = st.text_input("🌐 Optional Domains", placeholder="forbes.com, mit.edu")
199
+ research_button = st.button("πŸš€ Run Deep Research", use_container_width=True)
200
+ st.markdown("---")
201
+ st.markdown("Made with ❀️ by Cutie AI ✨")
202
+
203
+ # --- Main Title ---
204
+ st.title("πŸŒ™ Deep Research Assistant 4.0")
205
+ st.markdown("Where serious research meets serious style. πŸ§ πŸ’–")
206
+ st.divider()
207
 
208
+ # Continue from here for Main Research Section...
 
209
 
210
+ # --- Show Web Images from Topic ---
211
+ if topic and research_button:
212
+ st.subheader("πŸ–Ό Related Images from the Web")
213
+ try:
214
+ topic_images = get_image_urls(topic, max_images=6)
215
+ if topic_images:
216
+ img_cols = st.columns(3)
217
+ for idx, img_url in enumerate(topic_images):
218
+ with img_cols[idx % 3]:
219
+ st.image(img_url, use_column_width=True)
220
+ else:
221
+ st.info("No images found for this topic.")
222
+ except Exception as e:
223
+ st.warning(f"Couldn't load topic images. ({e})")
224
+
225
+ # --- Main Research Section ---
226
  if research_button and topic:
227
  try:
228
+ with st.status("πŸ”Ž Gathering sources..."):
229
  all_sources = []
230
  if source_type in ["Web Only", "Hybrid"]:
231
  all_sources += get_sources(topic, custom_domains) if custom_domains.strip() else get_sources(topic)
 
254
  "Thorough Academic Research": "Craft a full academic paper >1000 words."
255
  }[report_type]
256
 
257
+ # Create New Thread
258
  thread_id = str(uuid.uuid4())
259
  st.session_state.current_thread_id = thread_id
260
  st.session_state.chat_threads[thread_id] = []
261
 
262
  prompt = f"""
263
  Use past learnings:
 
264
  {previous_learnings}
265
 
266
  New Topic:
 
279
  {chr(10).join(citations)}
280
  """
281
 
282
+ # --- Generate Report ---
283
  st.subheader(f"πŸ“ {report_type} on '{topic}'")
284
  output_placeholder = st.empty()
285
  final_output = ""
 
295
  except Exception as e:
296
  st.error(f"❌ Error: {e}")
297
 
298
+ # --- Chat Threads Section ---
299
  st.divider()
300
  st.subheader("πŸ“‚ Your Research Threads")
301
 
302
+ user_avatar = "https://cdn-icons-png.flaticon.com/512/9131/9131529.png"
303
+ assistant_avatar = "https://cdn-icons-png.flaticon.com/512/4712/4712107.png"
304
+
305
  for tid, chats in st.session_state.chat_threads.items():
306
+ with st.container():
307
+ with st.expander(f"🧡 Thread {tid[:8]}", expanded=False):
308
+ for msg in chats:
309
+ avatar = user_avatar if msg['role'] == 'user' else assistant_avatar
310
+ bubble_color = "#DCF8C6" if msg['role'] == 'user' else "#F0F0F0"
311
+ align = "flex-end" if msg['role'] == 'user' else "flex-start"
312
+
313
+ st.markdown(f"""
314
+ <div style="display: flex; justify-content: {align}; margin-bottom: 10px;">
315
+ <img src="{avatar}" width="30" style="margin-right: 10px; border-radius: 50%;">
316
+ <div style="background-color: {bubble_color}; padding: 10px 15px; border-radius: 10px; max-width: 70%;">
317
+ {msg['content']}
318
+ </div>
319
+ </div>
320
+ """, unsafe_allow_html=True)
321
+
322
+ followup = st.text_input(f"πŸ’¬ Continue Thread {tid[:8]}:", key=f"followup_{tid}")
323
+ if st.button(f"Ask Follow-up {tid}", key=f"button_{tid}"):
324
+ if followup:
325
+ with st.spinner("πŸ€– Assistant is typing..."):
326
+ response = ""
327
+ for chunk in call_llm(st.session_state.chat_threads[tid] + [{"role": "user", "content": followup}], max_tokens=2000):
328
+ response += chunk
329
+ st.markdown(response)
330
+ st.session_state.chat_threads[tid].append({"role": "user", "content": followup})
331
+ st.session_state.chat_threads[tid].append({"role": "assistant", "content": response})
332
+ save_session_data()
333
+ st.experimental_rerun()
334
+
335
+ # --- Download All Threads Section ---
336
  if st.session_state.chat_threads:
337
+ st.divider()
338
+ st.subheader("πŸ“₯ Export Your Work")
339
  pdf_file = download_threads_as_pdf(st.session_state.chat_threads)
340
+ st.download_button("πŸ“₯ Download All Threads as PDF", data=pdf_file, file_name="Research_Threads.pdf", mime="application/pdf", use_container_width=True)
341
 
342
 
343