awacke1 commited on
Commit
e0630be
ยท
verified ยท
1 Parent(s): a0abcd6

Update backup13.app.py

Browse files
Files changed (1) hide show
  1. backup13.app.py +110 -80
backup13.app.py CHANGED
@@ -126,7 +126,7 @@ def init_session_state():
126
  'enable_audio': True, 'download_link_cache': {}, 'username': None,
127
  'autosend': True, 'autosearch': True, 'last_message': "", 'last_query': "",
128
  'mp3_files': {}, 'timer_start': time.time(), 'quote_index': 0,
129
- 'quote_source': "famous"
130
  }
131
  for k, v in defaults.items():
132
  if k not in st.session_state:
@@ -213,13 +213,21 @@ async def async_edge_tts_generate(text, voice, username, rate=0, pitch=0, file_f
213
  return st.session_state['audio_cache'][cache_key], 0
214
  start_time = time.time()
215
  text = clean_text_for_tts(text)
216
- if not text:
 
217
  return None, 0
218
  filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(text.encode()).hexdigest()[:8]}.{file_format}"
219
- communicate = edge_tts.Communicate(text, voice, rate=f"{rate:+d}%", pitch=f"{pitch:+d}Hz")
220
- await communicate.save(filename)
221
- st.session_state['audio_cache'][cache_key] = filename
222
- return filename, time.time() - start_time
 
 
 
 
 
 
 
223
 
224
  def play_and_download_audio(file_path):
225
  if file_path and os.path.exists(file_path):
@@ -245,6 +253,8 @@ async def save_chat_entry(username, message, is_markdown=False):
245
  with open(HISTORY_FILE, 'a') as f:
246
  f.write(f"[{timestamp}] {username}: Audio - {audio_file}\n")
247
  st.session_state['mp3_files'][os.path.basename(audio_file)] = audio_file
 
 
248
  await broadcast_message(f"{username}|{message}", "chat")
249
  st.session_state.last_chat_update = time.time()
250
  st.session_state.chat_history.append(entry)
@@ -260,6 +270,44 @@ async def load_chat():
260
  numbered_content = "\n".join(f"{i+1}. {line}" for i, line in enumerate(lines) if line.strip())
261
  return numbered_content
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  # ๐ŸŒ WebSocket Handling
264
  async def websocket_handler(websocket, path):
265
  client_id = str(uuid.uuid4())
@@ -392,28 +440,6 @@ async def create_paper_audio_files(papers, query):
392
  if p['full_audio']:
393
  p['download_base64'] = get_download_link(p['full_audio'])
394
 
395
- async def perform_ai_lookup(q, useArxiv=True, useArxivAudio=False):
396
- client = anthropic.Anthropic(api_key=anthropic_key)
397
- response = client.messages.create(model="claude-3-sonnet-20240229", max_tokens=1000, messages=[{"role": "user", "content": q}])
398
- result = response.content[0].text
399
- st.markdown("### Claude's Reply ๐Ÿง \n" + result)
400
- md_file = create_file(result, "System", "md")
401
- audio_file, _ = await async_edge_tts_generate(result, st.session_state['tts_voice'], "System")
402
- play_and_download_audio(audio_file)
403
-
404
- if useArxiv:
405
- q += result
406
- gradio_client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
407
- refs = gradio_client.predict(q, 10, "Semantic Search", "mistralai/Mixtral-8x7B-Instruct-v0.1", api_name="/update_with_rag_md")[0]
408
- result = f"๐Ÿ”Ž {q}\n\n{refs}"
409
- md_file, audio_file = create_file(result, "System", "md"), (await async_edge_tts_generate(result, st.session_state['tts_voice'], "System"))[0]
410
- play_and_download_audio(audio_file)
411
- papers = parse_arxiv_refs(refs)
412
- if papers and useArxivAudio:
413
- await create_paper_audio_files(papers, q)
414
- return result, papers
415
- return result, []
416
-
417
  def save_vote(file, item, user_hash):
418
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
419
  entry = f"[{timestamp}] {user_hash} voted for {item}"
@@ -474,35 +500,63 @@ def create_zip_of_files(md_files, mp3_files, png_files, mp4_files, query):
474
  return zip_name
475
 
476
  # ๐ŸŽฎ Main Interface
477
- async def async_interface():
478
  init_session_state()
479
  load_mp3_viewer()
480
  saved_username = load_username()
481
  if saved_username and saved_username in FUN_USERNAMES:
482
  st.session_state.username = saved_username
483
  if not st.session_state.username:
484
- available = [n for n in FUN_USERNAMES if not any(f"{n} has joined" in l for l in (await load_chat()).split('\n'))]
485
  st.session_state.username = random.choice(available or list(FUN_USERNAMES.keys()))
486
  st.session_state.tts_voice = FUN_USERNAMES[st.session_state.username]
487
- await save_chat_entry("System ๐ŸŒŸ", f"{st.session_state.username} has joined {START_ROOM}!")
488
  save_username(st.session_state.username)
489
 
490
  st.title(f"{Site_Name} for {st.session_state.username}")
491
  update_marquee_settings_ui()
492
  display_marquee(f"๐Ÿš€ Welcome to {START_ROOM} | ๐Ÿค– {st.session_state.username}", st.session_state['marquee_settings'], "welcome")
493
 
494
- if not st.session_state.server_task:
495
- st.session_state.server_task = asyncio.create_task(run_websocket_server())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
 
497
  tab_main = st.radio("Action:", ["๐ŸŽค Chat & Voice", "๐Ÿ“ธ Media", "๐Ÿ” ArXiv", "๐Ÿ“š PDF to Audio"], horizontal=True)
498
- useArxiv, useArxivAudio = st.checkbox("Search ArXiv", True), st.checkbox("ArXiv Audio", False)
499
- st.session_state.autosend = st.checkbox("Autosend Chat", value=True)
500
- st.session_state.autosearch = st.checkbox("Autosearch ArXiv", value=True)
 
501
 
502
  # ๐ŸŽค Chat & Voice
503
  if tab_main == "๐ŸŽค Chat & Voice":
504
  st.subheader(f"{START_ROOM} Chat ๐Ÿ’ฌ")
505
- chat_content = await load_chat()
506
  chat_container = st.container()
507
  with chat_container:
508
  lines = chat_content.split('\n')
@@ -531,46 +585,21 @@ async def async_interface():
531
  message = st.text_input(f"Message as {st.session_state.username}", key="message_input_paste", value=st.session_state.message_text)
532
  else:
533
  st.image(paste_result.image_data, caption="Pasted Image")
534
- filename = await save_pasted_image(paste_result.image_data, st.session_state.username)
535
  if filename:
536
  st.session_state.pasted_image_data = filename
537
  if (message and message != st.session_state.last_message) or st.session_state.pasted_image_data:
538
  st.session_state.last_message = message
539
- if st.session_state.autosend or st.button("Send ๐Ÿš€"):
540
  if message.strip():
541
- await save_chat_entry(st.session_state.username, message, True)
542
  if st.session_state.pasted_image_data:
543
- await save_chat_entry(st.session_state.username, f"Pasted image: {st.session_state.pasted_image_data}")
544
  st.session_state.pasted_image_data = None
545
  st.session_state.timer_start = time.time()
546
  save_username(st.session_state.username)
547
  st.rerun()
548
-
549
- st.subheader("๐ŸŽค Speech-to-Chat")
550
- from mycomponent import mycomponent # Correct import
551
- transcript_data = mycomponent(default_value=st.session_state.get('last_transcript', ''), key="speech_input")
552
- if transcript_data and 'value' in transcript_data:
553
- transcript = transcript_data['value'].strip()
554
- if transcript:
555
- st.write(f"๐ŸŽ™๏ธ You said: {transcript}")
556
- if transcript != st.session_state.last_transcript:
557
- st.session_state.last_transcript = transcript
558
- if st.session_state.autosend:
559
- await save_chat_entry(st.session_state.username, transcript, True)
560
- st.session_state.timer_start = time.time()
561
- save_username(st.session_state.username)
562
- # Update chat display without full rerun to reduce flicker
563
- with chat_container:
564
- st.markdown(await load_chat())
565
- else:
566
- if st.button("Send to Chat", key="send_transcript"):
567
- await save_chat_entry(st.session_state.username, transcript, True)
568
- st.session_state.timer_start = time.time()
569
- save_username(st.session_state.username)
570
- st.rerun()
571
- else:
572
- st.write("๐ŸŽ™๏ธ Speak to transcribe your message...")
573
-
574
  # ๐Ÿ“ธ Media
575
  elif tab_main == "๐Ÿ“ธ Media":
576
  st.header("๐Ÿ“ธ Media Gallery")
@@ -602,23 +631,24 @@ async def async_interface():
602
  st.video(mp4)
603
  st.markdown(get_download_link(mp4, "mp4"), unsafe_allow_html=True)
604
 
605
- uploaded_file = st.file_uploader("Upload Media", type=['png', 'mp4', 'mp3'])
606
  if uploaded_file:
607
  filename = f"{format_timestamp_prefix(st.session_state.username)}-{hashlib.md5(uploaded_file.getbuffer()).hexdigest()[:8]}.{uploaded_file.name.split('.')[-1]}"
608
  with open(filename, 'wb') as f:
609
  f.write(uploaded_file.getbuffer())
610
- await save_chat_entry(st.session_state.username, f"Uploaded: {filename}")
611
  st.session_state.timer_start = time.time()
612
  save_username(st.session_state.username)
613
  st.rerun()
614
 
615
  # ๐Ÿ” ArXiv
616
  elif tab_main == "๐Ÿ” ArXiv":
 
617
  q = st.text_input("๐Ÿ” Query:", key="arxiv_query")
618
  if q and q != st.session_state.last_query:
619
  st.session_state.last_query = q
620
- if st.session_state.autosearch or st.button("๐Ÿ” Run"):
621
- result, papers = await perform_ai_lookup(q, useArxiv, useArxivAudio)
622
  for i, p in enumerate(papers, 1):
623
  with st.expander(f"{i}. ๐Ÿ“„ {p['title']}"):
624
  st.markdown(f"**{p['date']} | {p['title']}** โ€” [Link]({p['url']})")
@@ -629,8 +659,8 @@ async def async_interface():
629
  # ๐Ÿ“š PDF to Audio
630
  elif tab_main == "๐Ÿ“š PDF to Audio":
631
  audio_processor = AudioProcessor()
632
- pdf_file = st.file_uploader("Choose PDF", "pdf")
633
- max_pages = st.slider('Pages', 1, 100, 10)
634
  if pdf_file:
635
  with st.spinner('Processing...'):
636
  texts, audios, total = process_pdf(pdf_file, max_pages, st.session_state['tts_voice'], audio_processor)
@@ -642,20 +672,20 @@ async def async_interface():
642
  if audios.get(i):
643
  st.audio(audios[i])
644
  st.markdown(get_download_link(audios[i], "mp3"), unsafe_allow_html=True)
645
- await save_chat_entry(st.session_state.username, f"PDF Page {i+1} converted to audio: {audios[i]}")
646
 
647
  # ๐Ÿ—‚๏ธ Sidebar with Dialog and Audio
648
  st.sidebar.subheader("Voice Settings")
649
- new_username = st.sidebar.selectbox("Change Name/Voice", list(FUN_USERNAMES.keys()), index=list(FUN_USERNAMES.keys()).index(st.session_state.username))
650
  if new_username != st.session_state.username:
651
- await save_chat_entry("System ๐ŸŒŸ", f"{st.session_state.username} changed to {new_username}")
652
  st.session_state.username, st.session_state.tts_voice = new_username, FUN_USERNAMES[new_username]
653
  st.session_state.timer_start = time.time()
654
  save_username(st.session_state.username)
655
  st.rerun()
656
 
657
  st.sidebar.markdown("### ๐Ÿ’ฌ Chat Dialog & Media")
658
- chat_content = await load_chat()
659
  lines = chat_content.split('\n')
660
  all_files = sorted(glob.glob("*.md") + glob.glob("*.mp3") + glob.glob("*.png") + glob.glob("*.mp4"), key=os.path.getmtime, reverse=True)
661
  for line in lines[-10:]:
@@ -690,13 +720,13 @@ async def async_interface():
690
  st.sidebar.markdown("### ๐Ÿ“‚ File History")
691
  for f in all_files[:10]:
692
  st.sidebar.write(f"{FILE_EMOJIS.get(f.split('.')[-1], '๐Ÿ“„')} {os.path.basename(f)}")
693
- if st.sidebar.button("โฌ‡๏ธ Zip All"):
694
  zip_name = create_zip_of_files(md_files, mp3_files, png_files, mp4_files, "latest_query")
695
  if zip_name:
696
  st.sidebar.markdown(get_download_link(zip_name, "zip"), unsafe_allow_html=True)
697
 
698
- def main():
699
- asyncio.run(async_interface())
700
 
701
  if __name__ == "__main__":
702
  main()
 
126
  'enable_audio': True, 'download_link_cache': {}, 'username': None,
127
  'autosend': True, 'autosearch': True, 'last_message': "", 'last_query': "",
128
  'mp3_files': {}, 'timer_start': time.time(), 'quote_index': 0,
129
+ 'quote_source': "famous", 'last_sent_transcript': "", 'old_val': None
130
  }
131
  for k, v in defaults.items():
132
  if k not in st.session_state:
 
213
  return st.session_state['audio_cache'][cache_key], 0
214
  start_time = time.time()
215
  text = clean_text_for_tts(text)
216
+ if not text or text == "No text":
217
+ print(f"Skipping audio generation for empty/invalid text: '{text}'")
218
  return None, 0
219
  filename = f"{format_timestamp_prefix(username)}-{hashlib.md5(text.encode()).hexdigest()[:8]}.{file_format}"
220
+ try:
221
+ communicate = edge_tts.Communicate(text, voice, rate=f"{rate:+d}%", pitch=f"{pitch:+d}Hz")
222
+ await communicate.save(filename)
223
+ st.session_state['audio_cache'][cache_key] = filename
224
+ return filename, time.time() - start_time
225
+ except edge_tts.exceptions.NoAudioReceived as e:
226
+ print(f"No audio received for text: '{text}' with voice: {voice}. Error: {e}")
227
+ return None, 0
228
+ except Exception as e:
229
+ print(f"Error generating audio for text: '{text}' with voice: {voice}. Error: {e}")
230
+ return None, 0
231
 
232
  def play_and_download_audio(file_path):
233
  if file_path and os.path.exists(file_path):
 
253
  with open(HISTORY_FILE, 'a') as f:
254
  f.write(f"[{timestamp}] {username}: Audio - {audio_file}\n")
255
  st.session_state['mp3_files'][os.path.basename(audio_file)] = audio_file
256
+ else:
257
+ print(f"No audio generated for message: '{message}' by {username}")
258
  await broadcast_message(f"{username}|{message}", "chat")
259
  st.session_state.last_chat_update = time.time()
260
  st.session_state.chat_history.append(entry)
 
270
  numbered_content = "\n".join(f"{i+1}. {line}" for i, line in enumerate(lines) if line.strip())
271
  return numbered_content
272
 
273
+ async def perform_ai_lookup(q, vocal_summary=True, extended_refs=False, titles_summary=True, full_audio=False, useArxiv=True, useArxivAudio=False):
274
+ start = time.time()
275
+ client = anthropic.Anthropic(api_key=anthropic_key)
276
+ response = client.messages.create(
277
+ model="claude-3-sonnet-20240229",
278
+ max_tokens=1000,
279
+ messages=[{"role": "user", "content": q}]
280
+ )
281
+ st.write("Claude's reply ๐Ÿง :")
282
+ st.markdown(response.content[0].text)
283
+
284
+ result = response.content[0].text
285
+ md_file = create_file(q, result, "System")
286
+ audio_file, _ = await async_edge_tts_generate(result, st.session_state['tts_voice'], "System")
287
+ st.subheader("๐Ÿ“ Main Response Audio")
288
+ play_and_download_audio(audio_file)
289
+
290
+ if useArxiv:
291
+ q = q + result
292
+ st.write('Running Arxiv RAG with Claude inputs.')
293
+ gradio_client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
294
+ refs = gradio_client.predict(
295
+ q, 10, "Semantic Search", "mistralai/Mixtral-8x7B-Instruct-v0.1", api_name="/update_with_rag_md"
296
+ )[0]
297
+ result = f"๐Ÿ”Ž {q}\n\n{refs}"
298
+ md_file = create_file(q, result, "System")
299
+ audio_file, _ = await async_edge_tts_generate(result, st.session_state['tts_voice'], "System")
300
+ st.subheader("๐Ÿ“ ArXiv Response Audio")
301
+ play_and_download_audio(audio_file)
302
+
303
+ papers = parse_arxiv_refs(refs)
304
+ if papers and useArxivAudio:
305
+ await create_paper_audio_files(papers, q)
306
+ return result, papers
307
+ elapsed = time.time() - start
308
+ st.write(f"**Total Elapsed:** {elapsed:.2f} s")
309
+ return result, []
310
+
311
  # ๐ŸŒ WebSocket Handling
312
  async def websocket_handler(websocket, path):
313
  client_id = str(uuid.uuid4())
 
440
  if p['full_audio']:
441
  p['download_base64'] = get_download_link(p['full_audio'])
442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  def save_vote(file, item, user_hash):
444
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
445
  entry = f"[{timestamp}] {user_hash} voted for {item}"
 
500
  return zip_name
501
 
502
  # ๐ŸŽฎ Main Interface
503
+ def main():
504
  init_session_state()
505
  load_mp3_viewer()
506
  saved_username = load_username()
507
  if saved_username and saved_username in FUN_USERNAMES:
508
  st.session_state.username = saved_username
509
  if not st.session_state.username:
510
+ available = [n for n in FUN_USERNAMES if not any(f"{n} has joined" in l for l in asyncio.run(load_chat()).split('\n'))]
511
  st.session_state.username = random.choice(available or list(FUN_USERNAMES.keys()))
512
  st.session_state.tts_voice = FUN_USERNAMES[st.session_state.username]
513
+ asyncio.run(save_chat_entry("System ๐ŸŒŸ", f"{st.session_state.username} has joined {START_ROOM}!"))
514
  save_username(st.session_state.username)
515
 
516
  st.title(f"{Site_Name} for {st.session_state.username}")
517
  update_marquee_settings_ui()
518
  display_marquee(f"๐Ÿš€ Welcome to {START_ROOM} | ๐Ÿค– {st.session_state.username}", st.session_state['marquee_settings'], "welcome")
519
 
520
+ # Speech Component at Top Level
521
+ mycomponent = components.declare_component("mycomponent", path="mycomponent")
522
+ val = mycomponent(my_input_value="Hello from MyComponent")
523
+ if val:
524
+ val_stripped = val.replace('\\n', ' ')
525
+ edited_input = st.text_area("โœ๏ธ Edit Input:", value=val_stripped, height=100, key="speech_input")
526
+ run_option = st.selectbox("Model:", ["Chat", "Arxiv"], key="model_select")
527
+ col1, col2 = st.columns(2)
528
+ with col1:
529
+ autorun = st.checkbox("โš™ AutoRun", value=True, key="autorun")
530
+ with col2:
531
+ full_audio = st.checkbox("๐Ÿ“š FullAudio", value=False, key="full_audio")
532
+
533
+ input_changed = (val != st.session_state.old_val)
534
+
535
+ if autorun and input_changed:
536
+ st.session_state.old_val = val
537
+ st.session_state.last_query = edited_input
538
+ if run_option == "Chat":
539
+ asyncio.run(save_chat_entry(st.session_state.username, edited_input, True))
540
+ elif run_option == "Arxiv":
541
+ asyncio.run(perform_ai_lookup(edited_input, useArxiv=True, useArxivAudio=full_audio))
542
+ elif st.button("โ–ถ Run", key="run_button"):
543
+ st.session_state.old_val = val
544
+ st.session_state.last_query = edited_input
545
+ if run_option == "Chat":
546
+ asyncio.run(save_chat_entry(st.session_state.username, edited_input, True))
547
+ elif run_option == "Arxiv":
548
+ asyncio.run(perform_ai_lookup(edited_input, useArxiv=True, useArxivAudio=full_audio))
549
 
550
  tab_main = st.radio("Action:", ["๐ŸŽค Chat & Voice", "๐Ÿ“ธ Media", "๐Ÿ” ArXiv", "๐Ÿ“š PDF to Audio"], horizontal=True)
551
+ useArxiv = st.checkbox("Search ArXiv", True, key="use_arxiv")
552
+ useArxivAudio = st.checkbox("ArXiv Audio", False, key="use_arxiv_audio")
553
+ st.session_state.autosend = st.checkbox("Autosend Chat", value=True, key="autosend")
554
+ st.session_state.autosearch = st.checkbox("Autosearch ArXiv", value=True, key="autosearch")
555
 
556
  # ๐ŸŽค Chat & Voice
557
  if tab_main == "๐ŸŽค Chat & Voice":
558
  st.subheader(f"{START_ROOM} Chat ๐Ÿ’ฌ")
559
+ chat_content = asyncio.run(load_chat())
560
  chat_container = st.container()
561
  with chat_container:
562
  lines = chat_content.split('\n')
 
585
  message = st.text_input(f"Message as {st.session_state.username}", key="message_input_paste", value=st.session_state.message_text)
586
  else:
587
  st.image(paste_result.image_data, caption="Pasted Image")
588
+ filename = asyncio.run(save_pasted_image(paste_result.image_data, st.session_state.username))
589
  if filename:
590
  st.session_state.pasted_image_data = filename
591
  if (message and message != st.session_state.last_message) or st.session_state.pasted_image_data:
592
  st.session_state.last_message = message
593
+ if st.session_state.autosend or st.button("Send ๐Ÿš€", key="send_button"):
594
  if message.strip():
595
+ asyncio.run(save_chat_entry(st.session_state.username, message, True))
596
  if st.session_state.pasted_image_data:
597
+ asyncio.run(save_chat_entry(st.session_state.username, f"Pasted image: {st.session_state.pasted_image_data}"))
598
  st.session_state.pasted_image_data = None
599
  st.session_state.timer_start = time.time()
600
  save_username(st.session_state.username)
601
  st.rerun()
602
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603
  # ๐Ÿ“ธ Media
604
  elif tab_main == "๐Ÿ“ธ Media":
605
  st.header("๐Ÿ“ธ Media Gallery")
 
631
  st.video(mp4)
632
  st.markdown(get_download_link(mp4, "mp4"), unsafe_allow_html=True)
633
 
634
+ uploaded_file = st.file_uploader("Upload Media", type=['png', 'mp4', 'mp3'], key="media_upload")
635
  if uploaded_file:
636
  filename = f"{format_timestamp_prefix(st.session_state.username)}-{hashlib.md5(uploaded_file.getbuffer()).hexdigest()[:8]}.{uploaded_file.name.split('.')[-1]}"
637
  with open(filename, 'wb') as f:
638
  f.write(uploaded_file.getbuffer())
639
+ asyncio.run(save_chat_entry(st.session_state.username, f"Uploaded: {filename}"))
640
  st.session_state.timer_start = time.time()
641
  save_username(st.session_state.username)
642
  st.rerun()
643
 
644
  # ๐Ÿ” ArXiv
645
  elif tab_main == "๐Ÿ” ArXiv":
646
+ st.subheader("๐Ÿ” Query ArXiv")
647
  q = st.text_input("๐Ÿ” Query:", key="arxiv_query")
648
  if q and q != st.session_state.last_query:
649
  st.session_state.last_query = q
650
+ if st.session_state.autosearch or st.button("๐Ÿ” Run", key="arxiv_run"):
651
+ result, papers = asyncio.run(perform_ai_lookup(q, useArxiv=useArxiv, useArxivAudio=useArxivAudio))
652
  for i, p in enumerate(papers, 1):
653
  with st.expander(f"{i}. ๐Ÿ“„ {p['title']}"):
654
  st.markdown(f"**{p['date']} | {p['title']}** โ€” [Link]({p['url']})")
 
659
  # ๐Ÿ“š PDF to Audio
660
  elif tab_main == "๐Ÿ“š PDF to Audio":
661
  audio_processor = AudioProcessor()
662
+ pdf_file = st.file_uploader("Choose PDF", "pdf", key="pdf_upload")
663
+ max_pages = st.slider('Pages', 1, 100, 10, key="pdf_pages")
664
  if pdf_file:
665
  with st.spinner('Processing...'):
666
  texts, audios, total = process_pdf(pdf_file, max_pages, st.session_state['tts_voice'], audio_processor)
 
672
  if audios.get(i):
673
  st.audio(audios[i])
674
  st.markdown(get_download_link(audios[i], "mp3"), unsafe_allow_html=True)
675
+ asyncio.run(save_chat_entry(st.session_state.username, f"PDF Page {i+1} converted to audio: {audios[i]}"))
676
 
677
  # ๐Ÿ—‚๏ธ Sidebar with Dialog and Audio
678
  st.sidebar.subheader("Voice Settings")
679
+ new_username = st.sidebar.selectbox("Change Name/Voice", list(FUN_USERNAMES.keys()), index=list(FUN_USERNAMES.keys()).index(st.session_state.username), key="username_select")
680
  if new_username != st.session_state.username:
681
+ asyncio.run(save_chat_entry("System ๐ŸŒŸ", f"{st.session_state.username} changed to {new_username}"))
682
  st.session_state.username, st.session_state.tts_voice = new_username, FUN_USERNAMES[new_username]
683
  st.session_state.timer_start = time.time()
684
  save_username(st.session_state.username)
685
  st.rerun()
686
 
687
  st.sidebar.markdown("### ๐Ÿ’ฌ Chat Dialog & Media")
688
+ chat_content = asyncio.run(load_chat())
689
  lines = chat_content.split('\n')
690
  all_files = sorted(glob.glob("*.md") + glob.glob("*.mp3") + glob.glob("*.png") + glob.glob("*.mp4"), key=os.path.getmtime, reverse=True)
691
  for line in lines[-10:]:
 
720
  st.sidebar.markdown("### ๐Ÿ“‚ File History")
721
  for f in all_files[:10]:
722
  st.sidebar.write(f"{FILE_EMOJIS.get(f.split('.')[-1], '๐Ÿ“„')} {os.path.basename(f)}")
723
+ if st.sidebar.button("โฌ‡๏ธ Zip All", key="zip_all"):
724
  zip_name = create_zip_of_files(md_files, mp3_files, png_files, mp4_files, "latest_query")
725
  if zip_name:
726
  st.sidebar.markdown(get_download_link(zip_name, "zip"), unsafe_allow_html=True)
727
 
728
+ if not st.session_state.server_task:
729
+ st.session_state.server_task = asyncio.create_task(run_websocket_server())
730
 
731
  if __name__ == "__main__":
732
  main()