awacke1 commited on
Commit
58c05f2
โ€ข
1 Parent(s): 68ace7c

Update backup17.app.py

Browse files
Files changed (1) hide show
  1. backup17.app.py +164 -136
backup17.app.py CHANGED
@@ -33,14 +33,20 @@ st.set_page_config(
33
  }
34
  )
35
  load_dotenv()
36
- openai.api_key = os.getenv('OPENAI_API_KEY') or st.secrets['OPENAI_API_KEY']
37
- anthropic_key = os.getenv("ANTHROPIC_API_KEY_3") or st.secrets["ANTHROPIC_API_KEY"]
 
 
 
 
 
 
 
38
  claude_client = anthropic.Anthropic(api_key=anthropic_key)
39
  openai_client = OpenAI(api_key=openai.api_key, organization=os.getenv('OPENAI_ORG_ID'))
40
  HF_KEY = os.getenv('HF_KEY')
41
  API_URL = os.getenv('API_URL')
42
 
43
- # Session states
44
  if 'transcript_history' not in st.session_state:
45
  st.session_state['transcript_history'] = []
46
  if 'chat_history' not in st.session_state:
@@ -57,10 +63,8 @@ if 'edit_new_name' not in st.session_state:
57
  st.session_state['edit_new_name'] = ""
58
  if 'edit_new_content' not in st.session_state:
59
  st.session_state['edit_new_content'] = ""
60
- if 'viewing_file' not in st.session_state:
61
- st.session_state['viewing_file'] = None
62
- if 'viewing_file_type' not in st.session_state:
63
- st.session_state['viewing_file_type'] = None
64
  if 'should_rerun' not in st.session_state:
65
  st.session_state['should_rerun'] = False
66
 
@@ -80,17 +84,34 @@ FILE_EMOJIS = {
80
  "mp3": "๐ŸŽต",
81
  }
82
 
83
- def generate_filename(prompt, file_type="md"):
84
- ctz = pytz.timezone('US/Central')
85
- date_str = datetime.now(ctz).strftime("%m%d_%H%M")
86
- safe = re.sub(r'[<>:"/\\\\|?*\n]', ' ', prompt)
87
- safe = re.sub(r'\s+', ' ', safe).strip()[:90]
88
- return f"{date_str}_{safe}.{file_type}"
89
-
90
- def create_file(filename, prompt, response):
91
- # Creating file does not trigger immediate rerun
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  with open(filename, 'w', encoding='utf-8') as f:
93
  f.write(prompt + "\n\n" + response)
 
94
 
95
  def get_download_link(file):
96
  with open(file, "rb") as f:
@@ -110,7 +131,7 @@ def speech_synthesis_html(result):
110
  components.html(html_code, height=0)
111
 
112
  async def edge_tts_generate_audio(text, voice="en-US-AriaNeural", rate=0, pitch=0):
113
- # Just create mp3 file, no immediate rerun
114
  if not text.strip():
115
  return None
116
  rate_str = f"{rate:+d}%"
@@ -150,7 +171,6 @@ def process_audio(audio_path):
150
  with open(audio_path, "rb") as f:
151
  transcription = openai_client.audio.transcriptions.create(model="whisper-1", file=f)
152
  st.session_state.messages.append({"role": "user", "content": transcription.text})
153
- # No immediate rerun
154
  return transcription.text
155
 
156
  def process_video(video_path, seconds_per_frame=1):
@@ -203,14 +223,17 @@ def perform_ai_lookup(q, vocal_summary=True, extended_refs=False, titles_summary
203
 
204
  st.markdown(result)
205
 
 
206
  if vocal_summary:
207
- audio_file_main = speak_with_edge_tts(r2, voice="en-US-AriaNeural", rate=0, pitch=0)
 
208
  st.write("### ๐ŸŽ™๏ธ Vocal Summary (Short Answer)")
209
  play_and_download_audio(audio_file_main)
210
 
211
  if extended_refs:
212
  summaries_text = "Here are the summaries from the references: " + refs.replace('"','')
213
- audio_file_refs = speak_with_edge_tts(summaries_text, voice="en-US-AriaNeural", rate=0, pitch=0)
 
214
  st.write("### ๐Ÿ“œ Extended References & Summaries")
215
  play_and_download_audio(audio_file_refs)
216
 
@@ -222,14 +245,15 @@ def perform_ai_lookup(q, vocal_summary=True, extended_refs=False, titles_summary
222
  titles.append(m.group(1))
223
  if titles:
224
  titles_text = "Here are the titles of the papers: " + ", ".join(titles)
225
- audio_file_titles = speak_with_edge_tts(titles_text, voice="en-US-AriaNeural", rate=0, pitch=0)
 
226
  st.write("### ๐Ÿ”– Paper Titles")
227
  play_and_download_audio(audio_file_titles)
228
 
229
  elapsed = time.time()-start
230
  st.write(f"**Total Elapsed:** {elapsed:.2f} s")
231
- fn = generate_filename(q,"md")
232
- create_file(fn,q,result)
233
  return result
234
 
235
  def process_with_gpt(text):
@@ -245,7 +269,7 @@ def process_with_gpt(text):
245
  )
246
  ans = c.choices[0].message.content
247
  st.write("GPT-4o: " + ans)
248
- create_file(generate_filename(text,"md"),text,ans)
249
  st.session_state.messages.append({"role":"assistant","content":ans})
250
  return ans
251
 
@@ -261,22 +285,19 @@ def process_with_claude(text):
261
  )
262
  ans = r.content[0].text
263
  st.write("Claude: " + ans)
264
- create_file(generate_filename(text,"md"),text,ans)
265
  st.session_state.chat_history.append({"user":text,"claude":ans})
266
  return ans
267
 
268
  def create_zip_of_files(md_files, mp3_files):
269
- # Exclude README.md if present
270
  md_files = [f for f in md_files if os.path.basename(f).lower() != 'readme.md']
271
-
272
  all_files = md_files + mp3_files
273
  if not all_files:
274
  return None
275
- # Build a descriptive name from file stems
276
  stems = [os.path.splitext(os.path.basename(f))[0] for f in all_files]
277
- # Join them
278
  joined = "_".join(stems)
279
- # Truncate if too long
280
  if len(joined) > 50:
281
  joined = joined[:50] + "_etc"
282
  zip_name = f"{joined}.zip"
@@ -285,106 +306,109 @@ def create_zip_of_files(md_files, mp3_files):
285
  z.write(f)
286
  return zip_name
287
 
288
- def get_media_html(p,typ="video",w="100%"):
289
- d = base64.b64encode(open(p,'rb').read()).decode()
290
- if typ=="video":
291
- return f'<video width="{w}" controls autoplay muted loop><source src="data:video/mp4;base64,{d}" type="video/mp4"></video>'
292
- else:
293
- return f'<audio controls style="width:{w};"><source src="data:audio/mpeg;base64,{d}" type="audio/mpeg"></audio>'
294
-
295
  def load_files_for_sidebar():
296
- # Gather all md and mp3 files
297
  md_files = glob.glob("*.md")
298
  mp3_files = glob.glob("*.mp3")
299
 
300
- # Exclude README.md from listings
301
  md_files = [f for f in md_files if os.path.basename(f).lower() != 'readme.md']
302
 
303
- files_by_ext = defaultdict(list)
304
- if md_files: files_by_ext['md'].extend(md_files)
305
- if mp3_files: files_by_ext['mp3'].extend(mp3_files)
306
-
307
- # Sort each extension group by modification time descending
308
- for ext in files_by_ext:
309
- files_by_ext[ext].sort(key=lambda x: os.path.getmtime(x), reverse=True)
310
- return files_by_ext
311
 
312
- def display_file_manager_sidebar(files_by_ext):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  st.sidebar.title("๐ŸŽต Audio & Document Manager")
314
 
315
- md_files = files_by_ext.get('md', [])
316
- mp3_files = files_by_ext.get('mp3', [])
317
-
318
- # Buttons to delete all except README.md (already excluded)
319
- col_del = st.sidebar.columns(3)
320
- with col_del[0]:
 
 
 
 
 
 
321
  if st.button("๐Ÿ—‘ Del All MD"):
322
- for f in md_files:
323
  os.remove(f)
324
  st.session_state.should_rerun = True
325
- with col_del[1]:
326
  if st.button("๐Ÿ—‘ Del All MP3"):
327
- for f in mp3_files:
328
  os.remove(f)
329
  st.session_state.should_rerun = True
330
- with col_del[2]:
331
  if st.button("โฌ‡๏ธ Zip All"):
332
- # create a zip of all md and mp3 except README.md
333
- z = create_zip_of_files(md_files, mp3_files)
334
  if z:
335
  st.sidebar.markdown(get_download_link(z),unsafe_allow_html=True)
336
 
337
- ext_counts = {ext: len(files) for ext, files in files_by_ext.items()}
338
- sorted_ext = sorted(files_by_ext.keys(), key=lambda x: ext_counts[x], reverse=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
- # Display files with actions
341
- for ext in sorted_ext:
342
- emoji = FILE_EMOJIS.get(ext, "๐Ÿ“ฆ")
343
- count = len(files_by_ext[ext])
344
- with st.sidebar.expander(f"{emoji} {ext.upper()} Files ({count})", expanded=True):
345
- for f in files_by_ext[ext]:
346
  fname = os.path.basename(f)
347
  ctime = datetime.fromtimestamp(os.path.getmtime(f)).strftime("%Y-%m-%d %H:%M:%S")
348
- # Show filename and buttons in a row
349
  st.write(f"**{fname}** - {ctime}")
350
- file_buttons_col = st.columns([1,1,1])
351
- with file_buttons_col[0]:
352
- if st.button("๐Ÿ‘€View", key="view_"+f):
353
- st.session_state.viewing_file = f
354
- st.session_state.viewing_file_type = ext
355
- # No rerun needed, just set state
356
- with file_buttons_col[1]:
357
- if ext == "md":
358
- if st.button("โœ๏ธEdit", key="edit_"+f):
359
- st.session_state.editing_file = f
360
- st.session_state.edit_new_name = fname.replace(".md","")
361
- st.session_state.edit_new_content = open(f,'r',encoding='utf-8').read()
362
- st.session_state.should_rerun = True
363
- with file_buttons_col[2]:
364
- if st.button("๐Ÿ—‘Del", key="del_"+f):
365
- os.remove(f)
366
- st.session_state.should_rerun = True
367
-
368
- # If editing an md file
369
- if st.session_state.editing_file and os.path.exists(st.session_state.editing_file):
370
- st.sidebar.subheader(f"Editing: {os.path.basename(st.session_state.editing_file)}")
371
- st.session_state.edit_new_name = st.sidebar.text_input("New name (no extension):", value=st.session_state.edit_new_name)
372
- st.session_state.edit_new_content = st.sidebar.text_area("Content:", st.session_state.edit_new_content, height=200)
373
- c1,c2 = st.sidebar.columns(2)
374
- with c1:
375
- if st.button("Save"):
376
- old_path = st.session_state.editing_file
377
- new_path = st.session_state.edit_new_name + ".md"
378
- if new_path != os.path.basename(old_path):
379
- os.rename(old_path, new_path)
380
- with open(new_path,'w',encoding='utf-8') as f:
381
- f.write(st.session_state.edit_new_content)
382
- st.session_state.editing_file = None
383
- st.session_state.should_rerun = True
384
- with c2:
385
- if st.button("Cancel"):
386
- st.session_state.editing_file = None
387
- st.session_state.should_rerun = True
388
 
389
  def main():
390
  st.sidebar.markdown("### ๐ŸšฒBikeAI๏ฟฝ๏ฟฝ๏ฟฝ Multi-Agent Research AI")
@@ -392,7 +416,6 @@ def main():
392
 
393
  model_choice = st.sidebar.radio("AI Model:", ["Arxiv","GPT-4o","Claude-3","GPT+Claude+Arxiv"], index=0)
394
 
395
- # Main Input Component
396
  mycomponent = components.declare_component("mycomponent", path="mycomponent")
397
  val = mycomponent(my_input_value="Hello")
398
  if val:
@@ -409,12 +432,16 @@ def main():
409
  col1,col2,col3=st.columns(3)
410
  with col1:
411
  st.subheader("GPT-4o Omni:")
412
- try: process_with_gpt(user_input)
413
- except: st.write('GPT 4o error')
 
 
414
  with col2:
415
  st.subheader("Claude-3 Sonnet:")
416
- try: process_with_claude(user_input)
417
- except: st.write('Claude error')
 
 
418
  with col3:
419
  st.subheader("Arxiv + Mistral:")
420
  try:
@@ -426,16 +453,13 @@ def main():
426
  st.subheader("๐Ÿ” Search ArXiv")
427
  q=st.text_input("Research query:")
428
 
429
- # ๐ŸŽ›๏ธ Audio Generation Options
430
  st.markdown("### ๐ŸŽ›๏ธ Audio Generation Options")
431
  vocal_summary = st.checkbox("๐ŸŽ™๏ธ Vocal Summary (Short Answer)", value=True)
432
  extended_refs = st.checkbox("๐Ÿ“œ Extended References & Summaries (Long)", value=False)
433
  titles_summary = st.checkbox("๐Ÿ”– Paper Titles Only", value=True)
434
 
435
- if q:
436
- q = q.strip()
437
- if q and st.button("Run ArXiv Query"):
438
- perform_ai_lookup(q, vocal_summary=vocal_summary, extended_refs=extended_refs, titles_summary=titles_summary)
439
 
440
  elif tab_main == "๐ŸŽค Voice Input":
441
  st.subheader("๐ŸŽค Voice Recognition")
@@ -513,27 +537,31 @@ def main():
513
  else:
514
  st.write("Select a file from the sidebar to edit.")
515
 
516
- # After main content, load files and display in sidebar
517
- files_by_ext = load_files_for_sidebar()
518
- display_file_manager_sidebar(files_by_ext)
519
 
520
- # If viewing a file, show its content below (in the main area)
521
- if st.session_state.viewing_file and os.path.exists(st.session_state.viewing_file):
522
  st.write("---")
523
- st.write(f"**Viewing File:** {os.path.basename(st.session_state.viewing_file)}")
524
- if st.session_state.viewing_file_type == "md":
525
- # show markdown
526
- content = open(st.session_state.viewing_file,'r',encoding='utf-8').read()
527
- st.markdown(content)
528
- elif st.session_state.viewing_file_type == "mp3":
529
- # show audio
530
- st.audio(st.session_state.viewing_file)
531
- # Optionally add a "Close View" button
532
- if st.button("Close View"):
533
- st.session_state.viewing_file = None
534
- st.session_state.viewing_file_type = None
535
-
536
- # If user-triggered changes happened, rerun once at the end
 
 
 
 
537
  if st.session_state.should_rerun:
538
  st.session_state.should_rerun = False
539
  st.rerun()
 
33
  }
34
  )
35
  load_dotenv()
36
+
37
+ openai_api_key = os.getenv('OPENAI_API_KEY', "")
38
+ anthropic_key = os.getenv('ANTHROPIC_API_KEY_3', "")
39
+ if 'OPENAI_API_KEY' in st.secrets:
40
+ openai_api_key = st.secrets['OPENAI_API_KEY']
41
+ if 'ANTHROPIC_API_KEY' in st.secrets:
42
+ anthropic_key = st.secrets["ANTHROPIC_API_KEY"]
43
+
44
+ openai.api_key = openai_api_key
45
  claude_client = anthropic.Anthropic(api_key=anthropic_key)
46
  openai_client = OpenAI(api_key=openai.api_key, organization=os.getenv('OPENAI_ORG_ID'))
47
  HF_KEY = os.getenv('HF_KEY')
48
  API_URL = os.getenv('API_URL')
49
 
 
50
  if 'transcript_history' not in st.session_state:
51
  st.session_state['transcript_history'] = []
52
  if 'chat_history' not in st.session_state:
 
63
  st.session_state['edit_new_name'] = ""
64
  if 'edit_new_content' not in st.session_state:
65
  st.session_state['edit_new_content'] = ""
66
+ if 'viewing_prefix' not in st.session_state:
67
+ st.session_state['viewing_prefix'] = None
 
 
68
  if 'should_rerun' not in st.session_state:
69
  st.session_state['should_rerun'] = False
70
 
 
84
  "mp3": "๐ŸŽต",
85
  }
86
 
87
+ def clean_for_speech(text: str) -> str:
88
+ text = text.replace("\n", " ")
89
+ text = text.replace("</s>", " ")
90
+ text = text.replace("#", "")
91
+ # Remove links like (https://...)
92
+ text = re.sub(r"\(https?:\/\/[^\)]+\)", "", text)
93
+ text = re.sub(r"\s+", " ", text).strip()
94
+ return text
95
+
96
+ def generate_filename(content, file_type="md"):
97
+ # Prefix: YYMM_HHmm_ -> total 10 chars including underscore
98
+ # Actually: %y%m_%H%M gives 9 chars, add trailing underscore for total 10 chars.
99
+ # Example: 23 09 _12 45 _ => '2309_1245_'
100
+ prefix = datetime.now().strftime("%y%m_%H%M") + "_"
101
+ # Extract some words from content
102
+ words = re.findall(r"\w+", content)
103
+ # Take first 3 words for filename segment
104
+ name_text = '_'.join(words[:3]) if words else 'file'
105
+ filename = f"{prefix}{name_text}.{file_type}"
106
+ return filename
107
+
108
+ def create_file(prompt, response, file_type="md"):
109
+ # Decide which content to base the filename on (prefer response)
110
+ base_content = response.strip() if response.strip() else prompt.strip()
111
+ filename = generate_filename(base_content, file_type)
112
  with open(filename, 'w', encoding='utf-8') as f:
113
  f.write(prompt + "\n\n" + response)
114
+ return filename
115
 
116
  def get_download_link(file):
117
  with open(file, "rb") as f:
 
131
  components.html(html_code, height=0)
132
 
133
  async def edge_tts_generate_audio(text, voice="en-US-AriaNeural", rate=0, pitch=0):
134
+ text = clean_for_speech(text)
135
  if not text.strip():
136
  return None
137
  rate_str = f"{rate:+d}%"
 
171
  with open(audio_path, "rb") as f:
172
  transcription = openai_client.audio.transcriptions.create(model="whisper-1", file=f)
173
  st.session_state.messages.append({"role": "user", "content": transcription.text})
 
174
  return transcription.text
175
 
176
  def process_video(video_path, seconds_per_frame=1):
 
223
 
224
  st.markdown(result)
225
 
226
+ # Clean for speech before TTS
227
  if vocal_summary:
228
+ main_text = clean_for_speech(r2)
229
+ audio_file_main = speak_with_edge_tts(main_text)
230
  st.write("### ๐ŸŽ™๏ธ Vocal Summary (Short Answer)")
231
  play_and_download_audio(audio_file_main)
232
 
233
  if extended_refs:
234
  summaries_text = "Here are the summaries from the references: " + refs.replace('"','')
235
+ summaries_text = clean_for_speech(summaries_text)
236
+ audio_file_refs = speak_with_edge_tts(summaries_text)
237
  st.write("### ๐Ÿ“œ Extended References & Summaries")
238
  play_and_download_audio(audio_file_refs)
239
 
 
245
  titles.append(m.group(1))
246
  if titles:
247
  titles_text = "Here are the titles of the papers: " + ", ".join(titles)
248
+ titles_text = clean_for_speech(titles_text)
249
+ audio_file_titles = speak_with_edge_tts(titles_text)
250
  st.write("### ๐Ÿ”– Paper Titles")
251
  play_and_download_audio(audio_file_titles)
252
 
253
  elapsed = time.time()-start
254
  st.write(f"**Total Elapsed:** {elapsed:.2f} s")
255
+ # Create MD file from q and result
256
+ create_file(q, result, "md")
257
  return result
258
 
259
  def process_with_gpt(text):
 
269
  )
270
  ans = c.choices[0].message.content
271
  st.write("GPT-4o: " + ans)
272
+ create_file(text, ans, "md")
273
  st.session_state.messages.append({"role":"assistant","content":ans})
274
  return ans
275
 
 
285
  )
286
  ans = r.content[0].text
287
  st.write("Claude: " + ans)
288
+ create_file(text, ans, "md")
289
  st.session_state.chat_history.append({"user":text,"claude":ans})
290
  return ans
291
 
292
  def create_zip_of_files(md_files, mp3_files):
293
+ # Exclude README.md
294
  md_files = [f for f in md_files if os.path.basename(f).lower() != 'readme.md']
 
295
  all_files = md_files + mp3_files
296
  if not all_files:
297
  return None
298
+ # Build a descriptive name
299
  stems = [os.path.splitext(os.path.basename(f))[0] for f in all_files]
 
300
  joined = "_".join(stems)
 
301
  if len(joined) > 50:
302
  joined = joined[:50] + "_etc"
303
  zip_name = f"{joined}.zip"
 
306
  z.write(f)
307
  return zip_name
308
 
 
 
 
 
 
 
 
309
  def load_files_for_sidebar():
310
+ # Gather files
311
  md_files = glob.glob("*.md")
312
  mp3_files = glob.glob("*.mp3")
313
 
314
+ # Exclude README.md
315
  md_files = [f for f in md_files if os.path.basename(f).lower() != 'readme.md']
316
 
317
+ all_files = md_files + mp3_files
 
 
 
 
 
 
 
318
 
319
+ # Group by first 10 chars of filename
320
+ groups = defaultdict(list)
321
+ for f in all_files:
322
+ fname = os.path.basename(f)
323
+ prefix = fname[:10] # first 10 chars as group prefix
324
+ groups[prefix].append(f)
325
+
326
+ # Sort files in each group by mod time descending
327
+ for prefix in groups:
328
+ groups[prefix].sort(key=lambda x: os.path.getmtime(x), reverse=True)
329
+
330
+ # Sort prefixes by newest file time
331
+ sorted_prefixes = sorted(groups.keys(), key=lambda pre: max(os.path.getmtime(x) for x in groups[pre]), reverse=True)
332
+
333
+ return groups, sorted_prefixes
334
+
335
+ def extract_keywords_from_md(files):
336
+ # Combine all MD content
337
+ text = ""
338
+ for f in files:
339
+ if f.endswith(".md"):
340
+ c = open(f,'r',encoding='utf-8').read()
341
+ text += " " + c
342
+ # Extract first 5 unique words
343
+ words = re.findall(r"\w+", text.lower())
344
+ unique_words = []
345
+ for w in words:
346
+ if w not in unique_words:
347
+ unique_words.append(w)
348
+ if len(unique_words) == 5:
349
+ break
350
+ return unique_words
351
+
352
+ def display_file_manager_sidebar(groups, sorted_prefixes):
353
  st.sidebar.title("๐ŸŽต Audio & Document Manager")
354
 
355
+ # Collect all md and mp3 files for zip operations
356
+ all_md = []
357
+ all_mp3 = []
358
+ for prefix in groups:
359
+ for f in groups[prefix]:
360
+ if f.endswith(".md"):
361
+ all_md.append(f)
362
+ elif f.endswith(".mp3"):
363
+ all_mp3.append(f)
364
+
365
+ top_bar = st.sidebar.columns(3)
366
+ with top_bar[0]:
367
  if st.button("๐Ÿ—‘ Del All MD"):
368
+ for f in all_md:
369
  os.remove(f)
370
  st.session_state.should_rerun = True
371
+ with top_bar[1]:
372
  if st.button("๐Ÿ—‘ Del All MP3"):
373
+ for f in all_mp3:
374
  os.remove(f)
375
  st.session_state.should_rerun = True
376
+ with top_bar[2]:
377
  if st.button("โฌ‡๏ธ Zip All"):
378
+ z = create_zip_of_files(all_md, all_mp3)
 
379
  if z:
380
  st.sidebar.markdown(get_download_link(z),unsafe_allow_html=True)
381
 
382
+ for prefix in sorted_prefixes:
383
+ files = groups[prefix]
384
+ # Extract 5-word keywords from MD in this group
385
+ kw = extract_keywords_from_md(files)
386
+ keywords_str = " ".join(kw) if kw else "No Keywords"
387
+ with st.sidebar.expander(f"{prefix} Files ({len(files)}) - Keywords: {keywords_str}", expanded=True):
388
+ # Delete group / View group
389
+ c1,c2 = st.columns(2)
390
+ with c1:
391
+ if st.button("๐Ÿ‘€View Group", key="view_group_"+prefix):
392
+ st.session_state.viewing_prefix = prefix
393
+ # No rerun needed, just state update
394
+ with c2:
395
+ if st.button("๐Ÿ—‘Del Group", key="del_group_"+prefix):
396
+ for f in files:
397
+ os.remove(f)
398
+ st.session_state.should_rerun = True
399
 
400
+ for f in files:
 
 
 
 
 
401
  fname = os.path.basename(f)
402
  ctime = datetime.fromtimestamp(os.path.getmtime(f)).strftime("%Y-%m-%d %H:%M:%S")
403
+ ext = os.path.splitext(fname)[1].lower().strip('.')
404
  st.write(f"**{fname}** - {ctime}")
405
+ # Individual file actions are less necessary if we have group actions
406
+ # But we can still provide them if desired.
407
+ # The user requested grouping primarily, but we can keep minimal file actions if needed.
408
+ # In instructions now, main focus is group view/delete.
409
+ # We'll omit individual file view/edit here since we have group view.
410
+ # If needed, re-add them similarly as before.
411
+ # For now, rely on "View Group" to see all files.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
 
413
  def main():
414
  st.sidebar.markdown("### ๐ŸšฒBikeAI๏ฟฝ๏ฟฝ๏ฟฝ Multi-Agent Research AI")
 
416
 
417
  model_choice = st.sidebar.radio("AI Model:", ["Arxiv","GPT-4o","Claude-3","GPT+Claude+Arxiv"], index=0)
418
 
 
419
  mycomponent = components.declare_component("mycomponent", path="mycomponent")
420
  val = mycomponent(my_input_value="Hello")
421
  if val:
 
432
  col1,col2,col3=st.columns(3)
433
  with col1:
434
  st.subheader("GPT-4o Omni:")
435
+ try:
436
+ process_with_gpt(user_input)
437
+ except:
438
+ st.write('GPT 4o error')
439
  with col2:
440
  st.subheader("Claude-3 Sonnet:")
441
+ try:
442
+ process_with_claude(user_input)
443
+ except:
444
+ st.write('Claude error')
445
  with col3:
446
  st.subheader("Arxiv + Mistral:")
447
  try:
 
453
  st.subheader("๐Ÿ” Search ArXiv")
454
  q=st.text_input("Research query:")
455
 
 
456
  st.markdown("### ๐ŸŽ›๏ธ Audio Generation Options")
457
  vocal_summary = st.checkbox("๐ŸŽ™๏ธ Vocal Summary (Short Answer)", value=True)
458
  extended_refs = st.checkbox("๐Ÿ“œ Extended References & Summaries (Long)", value=False)
459
  titles_summary = st.checkbox("๐Ÿ”– Paper Titles Only", value=True)
460
 
461
+ if q and st.button("Run ArXiv Query"):
462
+ perform_ai_lookup(q, vocal_summary=vocal_summary, extended_refs=extended_refs, titles_summary=titles_summary)
 
 
463
 
464
  elif tab_main == "๐ŸŽค Voice Input":
465
  st.subheader("๐ŸŽค Voice Recognition")
 
537
  else:
538
  st.write("Select a file from the sidebar to edit.")
539
 
540
+ # After main content, load and show file groups in sidebar
541
+ groups, sorted_prefixes = load_files_for_sidebar()
542
+ display_file_manager_sidebar(groups, sorted_prefixes)
543
 
544
+ # If viewing a prefix group, show all files in main area
545
+ if st.session_state.viewing_prefix and st.session_state.viewing_prefix in groups:
546
  st.write("---")
547
+ st.write(f"**Viewing Group:** {st.session_state.viewing_prefix}")
548
+ # Show all files in this prefix group in order (mp3 and md)
549
+ # Sort by mod time descending (already sorted)
550
+ for f in groups[st.session_state.viewing_prefix]:
551
+ fname = os.path.basename(f)
552
+ ext = os.path.splitext(fname)[1].lower().strip('.')
553
+ st.write(f"### {fname}")
554
+ if ext == "md":
555
+ content = open(f,'r',encoding='utf-8').read()
556
+ st.markdown(content)
557
+ elif ext == "mp3":
558
+ st.audio(f)
559
+ else:
560
+ # just show a download link
561
+ st.markdown(get_download_link(f), unsafe_allow_html=True)
562
+ if st.button("Close Group View"):
563
+ st.session_state.viewing_prefix = None
564
+
565
  if st.session_state.should_rerun:
566
  st.session_state.should_rerun = False
567
  st.rerun()