awacke1 commited on
Commit
22ec79b
β€’
1 Parent(s): 43252e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -90
app.py CHANGED
@@ -5,7 +5,7 @@ import streamlit.components.v1 as components
5
  from datetime import datetime
6
  from audio_recorder_streamlit import audio_recorder
7
  from bs4 import BeautifulSoup
8
- from collections import deque
9
  from dotenv import load_dotenv
10
  from gradio_client import Client
11
  from huggingface_hub import InferenceClient
@@ -51,6 +51,9 @@ st.markdown("""
51
  <style>
52
  .main { background: linear-gradient(to right, #1a1a1a, #2d2d2d); color: #fff; }
53
  .stMarkdown { font-family: 'Helvetica Neue', sans-serif; }
 
 
 
54
  </style>
55
  """, unsafe_allow_html=True)
56
 
@@ -65,6 +68,7 @@ def generate_filename(prompt, file_type="md"):
65
  def create_file(filename, prompt, response):
66
  with open(filename, 'w', encoding='utf-8') as f:
67
  f.write(prompt + "\n\n" + response)
 
68
 
69
  def get_download_link(file):
70
  with open(file, "rb") as f:
@@ -93,6 +97,7 @@ async def edge_tts_generate_audio(text, voice="en-US-AriaNeural", rate=0, pitch=
93
  communicate = edge_tts.Communicate(text, voice, rate=rate_str, pitch=pitch_str)
94
  out_fn = generate_filename(text,"mp3")
95
  await communicate.save(out_fn)
 
96
  return out_fn
97
 
98
  def speak_with_edge_tts(text, voice="en-US-AriaNeural", rate=0, pitch=0):
@@ -102,7 +107,6 @@ def play_and_download_audio(file_path):
102
  if file_path and os.path.exists(file_path):
103
  st.audio(file_path)
104
  st.markdown(get_download_link(file_path), unsafe_allow_html=True)
105
- #---------------------------
106
 
107
  def process_image(image_path, user_prompt):
108
  with open(image_path, "rb") as imgf:
@@ -125,6 +129,7 @@ def process_audio(audio_path):
125
  with open(audio_path, "rb") as f:
126
  transcription = openai_client.audio.transcriptions.create(model="whisper-1", file=f)
127
  st.session_state.messages.append({"role": "user", "content": transcription.text})
 
128
  return transcription.text
129
 
130
  def process_video(video_path, seconds_per_frame=1):
@@ -230,6 +235,7 @@ def process_with_gpt(text):
230
  st.write("GPT-4o: " + ans)
231
  create_file(generate_filename(text,"md"),text,ans)
232
  st.session_state.messages.append({"role":"assistant","content":ans})
 
233
  return ans
234
 
235
  def process_with_claude(text):
@@ -246,16 +252,18 @@ def process_with_claude(text):
246
  st.write("Claude: " + ans)
247
  create_file(generate_filename(text,"md"),text,ans)
248
  st.session_state.chat_history.append({"user":text,"claude":ans})
 
249
  return ans
250
 
251
  def create_zip_of_files():
252
- md_files = glob.glob("*.md")
253
- mp3_files = glob.glob("*.mp3")
254
  all_files = md_files + mp3_files
255
  zip_name = "all_files.zip"
256
  with zipfile.ZipFile(zip_name,'w') as z:
257
  for f in all_files:
258
  z.write(f)
 
259
  return zip_name
260
 
261
  def get_media_html(p,typ="video",w="100%"):
@@ -265,81 +273,109 @@ def get_media_html(p,typ="video",w="100%"):
265
  else:
266
  return f'<audio controls style="width:{w};"><source src="data:audio/mpeg;base64,{d}" type="audio/mpeg"></audio>'
267
 
268
- # CHANGES START HERE:
269
- # Define file emojis and the directory to scan
270
- FILE_EMOJIS = {
271
- "cards": "πŸ—ƒοΈ",
272
- "csv": "πŸ“Š",
273
- "heic": "πŸ–ΌοΈ",
274
- "ico": "πŸͺ§",
275
- "jpeg": "πŸ–ΌοΈ",
276
- "json": "πŸ”§",
277
- "md": "πŸ“",
278
- "mid": "🎼",
279
- "mov": "πŸŽ₯",
280
- "mp3": "🎡",
281
- "mp4": "🎞️",
282
- "png": "πŸ–ΌοΈ",
283
- "svg": "πŸ–ŒοΈ",
284
- "txt": "πŸ“„",
285
- "wav": "🎢",
286
- "webm": "πŸ“½οΈ",
287
- "webp": "🏞️",
288
- "zip": "πŸ“¦",
289
- }
290
  MEDIA_DIR = "Media"
291
 
292
- def get_file_ext(filename):
293
- return os.path.splitext(filename)[1].lower().strip('.')
294
-
295
- def load_files():
296
- all_files = []
297
- for root, dirs, files in os.walk(MEDIA_DIR):
298
- for f in files:
299
- fp = os.path.join(root, f)
300
- if os.path.isfile(fp):
301
- ext = get_file_ext(fp)
302
- mod_time = os.path.getmtime(fp)
303
- all_files.append((fp, ext, mod_time))
304
- return all_files
305
 
306
  def display_files_sidebar():
307
- st.sidebar.title("πŸ“‚ Media Files")
308
-
309
- all_files = load_files()
310
- from collections import defaultdict
311
- ext_map = defaultdict(list)
312
- for fp, ext, mod_time in all_files:
313
- ext_map[ext].append((fp, mod_time))
314
-
315
- # Sort files in each extension group by modification time descending
316
- for ext in ext_map:
317
- ext_map[ext].sort(key=lambda x: x[1], reverse=True)
318
-
319
- # Sort extensions by number of files descending
320
- sorted_ext = sorted(ext_map.keys(), key=lambda x: len(ext_map[x]), reverse=True)
321
-
322
- for ext in sorted_ext:
323
- emoji = FILE_EMOJIS.get(ext, "πŸ“")
324
- count = len(ext_map[ext])
325
- with st.sidebar.expander(f"{emoji} {ext.upper()} ({count})"):
326
- for fp, mod_time in ext_map[ext]:
327
- basename = os.path.basename(fp)
328
- last_mod = datetime.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M:%S")
329
- col1, col2 = st.columns([3,1])
330
- with col1:
331
- st.write(f"**{basename}** - Modified: {last_mod}")
332
- with col2:
333
- if ext == "mp3":
334
- # For MP3, load download link only after user clicks an expander
335
- mp3_exp = st.expander("Load MP3 Download Link")
336
- with mp3_exp:
337
- st.markdown(get_download_link(fp), unsafe_allow_html=True)
338
- # If desired, add an on-demand audio player here.
339
- else:
340
- # Direct download link for other files
341
- st.markdown(get_download_link(fp), unsafe_allow_html=True)
342
- # CHANGES END HERE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
 
344
  def main():
345
  st.sidebar.markdown("### 🚲BikeAIπŸ† Multi-Agent Research AI")
@@ -433,42 +469,35 @@ def main():
433
  st.header("🎬 Media Gallery - Images and Videos")
434
  tabs = st.tabs(["πŸ–ΌοΈ Images", "πŸŽ₯ Video"])
435
  with tabs[0]:
436
- imgs = glob.glob("*.png")+glob.glob("*.jpg")
437
  if imgs:
438
  c = st.slider("Cols",1,5,3)
439
  cols = st.columns(c)
440
  for i,f in enumerate(imgs):
441
  with cols[i%c]:
442
  st.image(Image.open(f),use_container_width=True)
443
- if st.button(f"πŸ‘€ Analyze {os.path.basename(f)}"):
444
  a = process_image(f,"Describe this image.")
445
  st.markdown(a)
446
  else:
447
  st.write("No images found.")
448
  with tabs[1]:
449
- vids = glob.glob("*.mp4")
450
  if vids:
451
  for v in vids:
452
  with st.expander(f"πŸŽ₯ {os.path.basename(v)}"):
453
  st.markdown(get_media_html(v,"video"),unsafe_allow_html=True)
454
- if st.button(f"Analyze {os.path.basename(v)}"):
455
  a = process_video_with_gpt(v,"Describe video.")
456
  st.markdown(a)
457
  else:
458
  st.write("No videos found.")
459
 
460
  elif tab_main == "πŸ“ File Editor":
461
- if getattr(st.session_state,'current_file',None):
462
- st.subheader(f"Editing: {st.session_state.current_file}")
463
- new_text = st.text_area("Content:", st.session_state.file_content, height=300)
464
- if st.button("Save"):
465
- with open(st.session_state.current_file,'w',encoding='utf-8') as f:
466
- f.write(new_text)
467
- st.success("Updated!")
468
- else:
469
- st.write("Select a file from the sidebar to edit.")
470
-
471
- # Use the new sidebar display function
472
  display_files_sidebar()
473
 
474
  if __name__=="__main__":
 
5
  from datetime import datetime
6
  from audio_recorder_streamlit import audio_recorder
7
  from bs4 import BeautifulSoup
8
+ from collections import defaultdict, deque
9
  from dotenv import load_dotenv
10
  from gradio_client import Client
11
  from huggingface_hub import InferenceClient
 
51
  <style>
52
  .main { background: linear-gradient(to right, #1a1a1a, #2d2d2d); color: #fff; }
53
  .stMarkdown { font-family: 'Helvetica Neue', sans-serif; }
54
+ .stButton>button {
55
+ margin-right: 0.5rem;
56
+ }
57
  </style>
58
  """, unsafe_allow_html=True)
59
 
 
68
  def create_file(filename, prompt, response):
69
  with open(filename, 'w', encoding='utf-8') as f:
70
  f.write(prompt + "\n\n" + response)
71
+ st.experimental_rerun()
72
 
73
  def get_download_link(file):
74
  with open(file, "rb") as f:
 
97
  communicate = edge_tts.Communicate(text, voice, rate=rate_str, pitch=pitch_str)
98
  out_fn = generate_filename(text,"mp3")
99
  await communicate.save(out_fn)
100
+ st.experimental_rerun()
101
  return out_fn
102
 
103
  def speak_with_edge_tts(text, voice="en-US-AriaNeural", rate=0, pitch=0):
 
107
  if file_path and os.path.exists(file_path):
108
  st.audio(file_path)
109
  st.markdown(get_download_link(file_path), unsafe_allow_html=True)
 
110
 
111
  def process_image(image_path, user_prompt):
112
  with open(image_path, "rb") as imgf:
 
129
  with open(audio_path, "rb") as f:
130
  transcription = openai_client.audio.transcriptions.create(model="whisper-1", file=f)
131
  st.session_state.messages.append({"role": "user", "content": transcription.text})
132
+ st.experimental_rerun()
133
  return transcription.text
134
 
135
  def process_video(video_path, seconds_per_frame=1):
 
235
  st.write("GPT-4o: " + ans)
236
  create_file(generate_filename(text,"md"),text,ans)
237
  st.session_state.messages.append({"role":"assistant","content":ans})
238
+ st.experimental_rerun()
239
  return ans
240
 
241
  def process_with_claude(text):
 
252
  st.write("Claude: " + ans)
253
  create_file(generate_filename(text,"md"),text,ans)
254
  st.session_state.chat_history.append({"user":text,"claude":ans})
255
+ st.experimental_rerun()
256
  return ans
257
 
258
  def create_zip_of_files():
259
+ md_files = glob.glob("Media/*.md")
260
+ mp3_files = glob.glob("Media/*.mp3")
261
  all_files = md_files + mp3_files
262
  zip_name = "all_files.zip"
263
  with zipfile.ZipFile(zip_name,'w') as z:
264
  for f in all_files:
265
  z.write(f)
266
+ st.experimental_rerun()
267
  return zip_name
268
 
269
  def get_media_html(p,typ="video",w="100%"):
 
273
  else:
274
  return f'<audio controls style="width:{w};"><source src="data:audio/mpeg;base64,{d}" type="audio/mpeg"></audio>'
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  MEDIA_DIR = "Media"
277
 
278
+ def load_md_mp3_pairs():
279
+ # This function groups .md and .mp3 files by their filename stem
280
+ files = glob.glob(os.path.join(MEDIA_DIR,"*.md")) + glob.glob(os.path.join(MEDIA_DIR,"*.mp3"))
281
+ grouped = defaultdict(dict)
282
+ for f in files:
283
+ base = os.path.basename(f)
284
+ stem, ext = os.path.splitext(base)
285
+ ext = ext.lower()
286
+ if ext == '.md':
287
+ grouped[stem]['md'] = f
288
+ elif ext == '.mp3':
289
+ grouped[stem]['mp3'] = f
290
+ return grouped
291
 
292
  def display_files_sidebar():
293
+ st.sidebar.title("πŸ“‚ Files")
294
+ pairs = load_md_mp3_pairs()
295
+
296
+ # Sort by modification time of the MD if exists, else mp3. Descending by latest mod time.
297
+ def mod_time(pair):
298
+ # Return the newest mod time of available files in the pair
299
+ times = []
300
+ for f in pair.values():
301
+ times.append(os.path.getmtime(f))
302
+ return max(times)
303
+ sorted_pairs = sorted(pairs.items(), key=lambda x: mod_time(x[1]), reverse=True)
304
+
305
+ for stem, files_dict in sorted_pairs:
306
+ with st.sidebar.expander(f"**{stem}**"):
307
+ # Display action buttons per file type
308
+ # If MD file exists:
309
+ if 'md' in files_dict:
310
+ md_file = files_dict['md']
311
+ c1, c2, c3, c4 = st.columns([2,1,1,1])
312
+ with c1:
313
+ st.write("**Markdown File**")
314
+ with c2:
315
+ if st.button("πŸ‘€ View", key="view_md_"+stem):
316
+ content = open(md_file,'r',encoding='utf-8').read()
317
+ st.markdown("**MD File Content:**")
318
+ st.markdown(content)
319
+ with c3:
320
+ # Edit name/content
321
+ if st.button("✏️ Edit", key="edit_md_"+stem):
322
+ st.session_state.editing_md = stem
323
+ st.experimental_rerun()
324
+ with c4:
325
+ if st.button("πŸ—‘ Delete", key="del_md_"+stem):
326
+ os.remove(md_file)
327
+ st.experimental_rerun()
328
+ else:
329
+ st.write("No .md file for this stem.")
330
+
331
+ # If MP3 file exists:
332
+ if 'mp3' in files_dict:
333
+ mp3_file = files_dict['mp3']
334
+ c1, c2, c3 = st.columns([2,1,1])
335
+ with c1:
336
+ st.write("**Audio File**")
337
+ with c2:
338
+ if st.button("πŸ‘€ View", key="view_mp3_"+stem):
339
+ st.audio(mp3_file)
340
+ with c3:
341
+ if st.button("πŸ—‘ Delete", key="del_mp3_"+stem):
342
+ os.remove(mp3_file)
343
+ st.experimental_rerun()
344
+ else:
345
+ st.write("No .mp3 file for this stem.")
346
+
347
+ # Button to create a zip of all files
348
+ if len(pairs) > 0:
349
+ if st.sidebar.button("⬇️ Download All (.md and .mp3)"):
350
+ z = create_zip_of_files()
351
+ st.sidebar.markdown(get_download_link(z),unsafe_allow_html=True)
352
+
353
+ # If editing an MD file:
354
+ if 'editing_md' in st.session_state:
355
+ stem = st.session_state.editing_md
356
+ pairs = load_md_mp3_pairs()
357
+ files_dict = pairs.get(stem, {})
358
+ if 'md' in files_dict:
359
+ md_file = files_dict['md']
360
+ content = open(md_file,'r',encoding='utf-8').read()
361
+ st.sidebar.subheader(f"Editing: {stem}.md")
362
+ new_stem = st.sidebar.text_input("New stem (filename without extension):", value=stem)
363
+ new_content = st.sidebar.text_area("Content:", content, height=200)
364
+ if st.sidebar.button("Save Changes"):
365
+ # If name changed, rename the file
366
+ if new_stem != stem:
367
+ new_path = os.path.join(MEDIA_DIR, new_stem+".md")
368
+ os.rename(md_file, new_path)
369
+ md_file = new_path
370
+ # Update content
371
+ with open(md_file,'w',encoding='utf-8') as f:
372
+ f.write(new_content)
373
+ del st.session_state.editing_md
374
+ st.experimental_rerun()
375
+ if st.sidebar.button("Cancel"):
376
+ del st.session_state.editing_md
377
+ st.experimental_rerun()
378
+
379
 
380
  def main():
381
  st.sidebar.markdown("### 🚲BikeAIπŸ† Multi-Agent Research AI")
 
469
  st.header("🎬 Media Gallery - Images and Videos")
470
  tabs = st.tabs(["πŸ–ΌοΈ Images", "πŸŽ₯ Video"])
471
  with tabs[0]:
472
+ imgs = glob.glob("Media/*.png")+glob.glob("Media/*.jpg")
473
  if imgs:
474
  c = st.slider("Cols",1,5,3)
475
  cols = st.columns(c)
476
  for i,f in enumerate(imgs):
477
  with cols[i%c]:
478
  st.image(Image.open(f),use_container_width=True)
479
+ if st.button(f"πŸ‘€ Analyze {os.path.basename(f)}", key=f"analyze_{f}"):
480
  a = process_image(f,"Describe this image.")
481
  st.markdown(a)
482
  else:
483
  st.write("No images found.")
484
  with tabs[1]:
485
+ vids = glob.glob("Media/*.mp4")
486
  if vids:
487
  for v in vids:
488
  with st.expander(f"πŸŽ₯ {os.path.basename(v)}"):
489
  st.markdown(get_media_html(v,"video"),unsafe_allow_html=True)
490
+ if st.button(f"Analyze {os.path.basename(v)}", key=f"analyze_{v}"):
491
  a = process_video_with_gpt(v,"Describe video.")
492
  st.markdown(a)
493
  else:
494
  st.write("No videos found.")
495
 
496
  elif tab_main == "πŸ“ File Editor":
497
+ st.write("Use the sidebar to edit .md files by clicking the ✏️ button on the desired file.")
498
+
499
+
500
+ # Display file list last to ensure updates
 
 
 
 
 
 
 
501
  display_files_sidebar()
502
 
503
  if __name__=="__main__":