Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	Update app.py
Browse files
    	
        app.py
    CHANGED
    
    | @@ -106,15 +106,9 @@ if 'last_query' not in st.session_state: | |
| 106 | 
             
            if 'marquee_content' not in st.session_state:
         | 
| 107 | 
             
                st.session_state['marquee_content'] = "π Welcome to TalkingAIResearcher | π€ Your Research Assistant"
         | 
| 108 |  | 
| 109 | 
            -
            #  | 
| 110 | 
            -
            if ' | 
| 111 | 
            -
                st.session_state[' | 
| 112 | 
            -
            if 'run_arxiv' not in st.session_state:
         | 
| 113 | 
            -
                st.session_state['run_arxiv'] = False  # disabled by default
         | 
| 114 | 
            -
            if 'autorun_searches' not in st.session_state:
         | 
| 115 | 
            -
                st.session_state['autorun_searches'] = False
         | 
| 116 | 
            -
            if 'autosave_output' not in st.session_state:
         | 
| 117 | 
            -
                st.session_state['autosave_output'] = False
         | 
| 118 |  | 
| 119 | 
             
            # API Keys
         | 
| 120 | 
             
            openai_api_key = os.getenv('OPENAI_API_KEY', "")
         | 
| @@ -134,7 +128,14 @@ API_URL = os.getenv('API_URL') | |
| 134 | 
             
            FILE_EMOJIS = {
         | 
| 135 | 
             
                "md": "π",
         | 
| 136 | 
             
                "mp3": "π΅",
         | 
| 137 | 
            -
                "wav": "π"
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 138 | 
             
            }
         | 
| 139 |  | 
| 140 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| @@ -305,23 +306,18 @@ def play_and_download_audio(file_path, file_type="mp3"): | |
| 305 | 
             
                    st.markdown(dl_link, unsafe_allow_html=True)
         | 
| 306 |  | 
| 307 | 
             
            def save_qa_with_audio(question, answer, voice=None):
         | 
| 308 | 
            -
                """Save Q&A to markdown and also generate audio | 
| 309 | 
             
                if not voice:
         | 
| 310 | 
             
                    voice = st.session_state['tts_voice']
         | 
| 311 |  | 
| 312 | 
             
                combined_text = f"# Question\n{question}\n\n# Answer\n{answer}"
         | 
| 313 | 
            -
                md_file =  | 
| 314 | 
            -
                 | 
| 315 | 
            -
             | 
| 316 | 
            -
             | 
| 317 | 
            -
             | 
| 318 | 
            -
                     | 
| 319 | 
            -
             | 
| 320 | 
            -
                    audio_file = speak_with_edge_tts(
         | 
| 321 | 
            -
                        audio_text,
         | 
| 322 | 
            -
                        voice=voice,
         | 
| 323 | 
            -
                        file_format=st.session_state['audio_format']
         | 
| 324 | 
            -
                    )
         | 
| 325 | 
             
                return md_file, audio_file
         | 
| 326 |  | 
| 327 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| @@ -392,12 +388,9 @@ def create_paper_links_md(papers): | |
| 392 |  | 
| 393 | 
             
            def create_paper_audio_files(papers, input_question):
         | 
| 394 | 
             
                """
         | 
| 395 | 
            -
                For each paper, generate TTS audio summary  | 
| 396 | 
            -
                store  | 
| 397 | 
            -
                and store a base64 link for stable downloading.
         | 
| 398 | 
             
                """
         | 
| 399 | 
            -
                if not st.session_state['autosave_output']:
         | 
| 400 | 
            -
                    return
         | 
| 401 | 
             
                for paper in papers:
         | 
| 402 | 
             
                    try:
         | 
| 403 | 
             
                        audio_text = f"{paper['title']} by {paper['authors']}. {paper['summary']}"
         | 
| @@ -457,35 +450,45 @@ def display_papers_in_sidebar(papers): | |
| 457 | 
             
                            st.markdown(f"**Summary:** {paper['summary'][:300]}...")
         | 
| 458 |  | 
| 459 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 460 | 
            -
            # 4. ZIP  | 
| 461 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 462 |  | 
| 463 | 
            -
            def  | 
| 464 | 
             
                """
         | 
| 465 | 
            -
                Zip up all  | 
| 466 | 
             
                to avoid overly long base64 strings. 
         | 
| 467 | 
             
                """
         | 
| 468 | 
            -
                 | 
| 469 | 
            -
                 | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 470 | 
             
                if not all_files:
         | 
| 471 | 
             
                    return None
         | 
| 472 |  | 
|  | |
| 473 | 
             
                all_content = []
         | 
| 474 | 
             
                for f in all_files:
         | 
| 475 | 
            -
                    if f.endswith( | 
| 476 | 
            -
                        with open(f,  | 
| 477 | 
            -
                            all_content.append( | 
| 478 | 
            -
                     | 
| 479 | 
            -
                         | 
| 480 | 
            -
             | 
| 481 | 
            -
             | 
| 482 | 
            -
                
         | 
| 483 | 
            -
             | 
|  | |
| 484 | 
             
                combined_content = " ".join(all_content)
         | 
| 485 | 
             
                info_terms = get_high_info_terms(combined_content, top_n=10)
         | 
| 486 |  | 
| 487 | 
             
                timestamp = format_timestamp_prefix()
         | 
| 488 | 
            -
                name_text = '-'.join(term for term in info_terms[:5]) | 
| 489 | 
             
                short_zip_name = (timestamp + "_" + name_text)[:20] + ".zip"
         | 
| 490 |  | 
| 491 | 
             
                with zipfile.ZipFile(short_zip_name, 'w') as z:
         | 
| @@ -493,99 +496,102 @@ def create_zip_of_files(md_files, mp3_files, wav_files, input_question): | |
| 493 | 
             
                        z.write(f)
         | 
| 494 | 
             
                return short_zip_name
         | 
| 495 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 496 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 497 | 
             
            # 5. MAIN LOGIC: AI LOOKUP & VOICE INPUT
         | 
| 498 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 499 |  | 
| 500 | 
            -
            def  | 
| 501 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
| 502 | 
             
                client = anthropic.Anthropic(api_key=anthropic_key)
         | 
|  | |
| 503 | 
             
                response = client.messages.create(
         | 
| 504 | 
             
                    model="claude-3-sonnet-20240229",
         | 
| 505 | 
             
                    max_tokens=1000,
         | 
| 506 | 
             
                    messages=[
         | 
| 507 | 
            -
                        {"role": "user", "content":  | 
| 508 | 
             
                    ])
         | 
| 509 | 
            -
                 | 
|  | |
| 510 |  | 
| 511 | 
            -
                 | 
| 512 | 
            -
                 | 
| 513 | 
            -
                 | 
|  | |
|  | |
|  | |
| 514 |  | 
| 515 | 
            -
             | 
| 516 | 
            -
                " | 
| 517 | 
            -
                st.write("### Arxiv's AI: Mixtral 8x7B RAG")
         | 
| 518 | 
             
                client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
         | 
| 519 | 
             
                refs = client.predict(
         | 
| 520 | 
            -
                    q,
         | 
| 521 | 
            -
                     | 
| 522 | 
             
                    "Semantic Search", 
         | 
| 523 | 
             
                    "mistralai/Mixtral-8x7B-Instruct-v0.1",
         | 
| 524 | 
             
                    api_name="/update_with_rag_md"
         | 
| 525 | 
             
                )[0]
         | 
| 526 | 
            -
                
         | 
| 527 | 
             
                r2 = client.predict(
         | 
| 528 | 
             
                    q, 
         | 
| 529 | 
             
                    "mistralai/Mixtral-8x7B-Instruct-v0.1", 
         | 
| 530 | 
             
                    True, 
         | 
| 531 | 
             
                    api_name="/ask_llm"
         | 
| 532 | 
             
                )
         | 
| 533 | 
            -
             | 
| 534 | 
            -
                # Combine the final result
         | 
| 535 | 
             
                result = f"### π {q}\n\n{r2}\n\n{refs}"
         | 
| 536 | 
            -
                 | 
|  | |
|  | |
| 537 |  | 
| 538 | 
            -
                # Parse + handle papers
         | 
| 539 | 
             
                papers = parse_arxiv_refs(refs)
         | 
| 540 | 
             
                if papers:
         | 
| 541 | 
            -
                    # Create minimal links page  | 
| 542 | 
            -
                     | 
| 543 | 
            -
             | 
| 544 | 
            -
             | 
| 545 |  | 
|  | |
| 546 | 
             
                    create_paper_audio_files(papers, input_question=q)
         | 
| 547 | 
             
                    display_papers(papers, get_marquee_settings())
         | 
| 548 | 
             
                    display_papers_in_sidebar(papers)
         | 
| 549 | 
             
                else:
         | 
| 550 | 
             
                    st.warning("No papers found in the response.")
         | 
| 551 | 
            -
                return result
         | 
| 552 |  | 
| 553 | 
            -
             | 
| 554 | 
            -
                "" | 
| 555 | 
            -
                 | 
| 556 | 
            -
                returning a combined response string.
         | 
| 557 | 
            -
                """
         | 
| 558 | 
            -
                combined_response = ""
         | 
| 559 | 
            -
                
         | 
| 560 | 
            -
                if st.session_state['run_claude']:
         | 
| 561 | 
            -
                    claude_response = run_claude_search(q)
         | 
| 562 | 
            -
                    combined_response += "\n\nCLAUDE:\n" + claude_response
         | 
| 563 | 
            -
                
         | 
| 564 | 
            -
                if st.session_state['run_arxiv']:
         | 
| 565 | 
            -
                    arxiv_response = run_arxiv_search(q)
         | 
| 566 | 
            -
                    combined_response += "\n\nARXIV:\n" + arxiv_response
         | 
| 567 | 
            -
                
         | 
| 568 | 
            -
                return combined_response
         | 
| 569 |  | 
| 570 | 
             
            def process_voice_input(text):
         | 
| 571 | 
            -
                """When user sends voice query, we run  | 
| 572 | 
             
                if not text:
         | 
| 573 | 
             
                    return
         | 
| 574 | 
             
                st.subheader("π Search Results")
         | 
| 575 | 
            -
                 | 
| 576 | 
            -
             | 
| 577 | 
            -
             | 
| 578 | 
            -
             | 
|  | |
|  | |
|  | |
| 579 | 
             
                md_file, audio_file = save_qa_with_audio(text, result)
         | 
| 580 | 
            -
             | 
| 581 | 
            -
                 | 
| 582 | 
            -
                 | 
| 583 | 
            -
             | 
| 584 | 
            -
                    play_and_download_audio(audio_file, st.session_state['audio_format'])
         | 
| 585 | 
            -
             | 
| 586 | 
            -
                # 4) Refresh the sidebar file listing if autosave was used
         | 
| 587 | 
            -
                if st.session_state['autosave_output']:
         | 
| 588 | 
            -
                    display_file_history_in_sidebar()
         | 
| 589 |  | 
| 590 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 591 | 
             
            # 6. FILE HISTORY SIDEBAR
         | 
| @@ -593,171 +599,146 @@ def process_voice_input(text): | |
| 593 |  | 
| 594 | 
             
            def display_file_history_in_sidebar():
         | 
| 595 | 
             
                """
         | 
| 596 | 
            -
                Shows a history of each  | 
| 597 | 
             
                order of modification time, with quick icons and optional download links.
         | 
| 598 | 
             
                """
         | 
| 599 | 
             
                st.sidebar.markdown("---")
         | 
| 600 | 
             
                st.sidebar.markdown("### π File History")
         | 
| 601 |  | 
| 602 | 
            -
                #  | 
| 603 | 
            -
                 | 
| 604 | 
            -
             | 
| 605 | 
            -
                     | 
| 606 | 
            -
             | 
| 607 | 
            -
             | 
| 608 | 
            -
             | 
| 609 | 
            -
             | 
| 610 | 
            -
             | 
| 611 | 
            -
                                        os.remove(f)
         | 
| 612 | 
            -
                                    except Exception as e:
         | 
| 613 | 
            -
                                        st.warning(f"Error deleting {f}: {str(e)}")
         | 
| 614 | 
            -
                        st.rerun()
         | 
| 615 | 
            -
                
         | 
| 616 | 
            -
                with col2:
         | 
| 617 | 
            -
                    # Get all files for potential zip
         | 
| 618 | 
            -
                    md_files = [f for f in glob.glob("*.md") if f.lower() != "readme.md"]
         | 
| 619 | 
            -
                    mp3_files = glob.glob("*.mp3")
         | 
| 620 | 
            -
                    wav_files = glob.glob("*.wav")
         | 
| 621 | 
            -
             | 
| 622 | 
            -
                    if md_files or mp3_files or wav_files:
         | 
| 623 | 
            -
                        zip_name = "Download.zip"
         | 
| 624 | 
            -
                        if 'last_query' in st.session_state and st.session_state['last_query']:
         | 
| 625 | 
            -
                            # Use last_query in the zip name
         | 
| 626 | 
            -
                            clean_q = clean_text_for_filename(st.session_state['last_query'])[:30]
         | 
| 627 | 
            -
                            if clean_q:
         | 
| 628 | 
            -
                                zip_name = f"{clean_q}.zip"
         | 
| 629 | 
            -
             | 
| 630 | 
            -
                        if st.button("π¦ Download All"):
         | 
| 631 | 
            -
                            with zipfile.ZipFile(zip_name, 'w') as z:
         | 
| 632 | 
            -
                                for f in md_files + mp3_files + wav_files:
         | 
| 633 | 
            -
                                    z.write(f)
         | 
| 634 | 
            -
                            st.sidebar.markdown(get_download_link(zip_name), unsafe_allow_html=True)
         | 
| 635 | 
            -
             | 
| 636 | 
            -
                # Gather all files
         | 
| 637 | 
            -
                md_files = glob.glob("*.md")
         | 
| 638 | 
            -
                mp3_files = glob.glob("*.mp3")
         | 
| 639 | 
            -
                wav_files = glob.glob("*.wav")
         | 
| 640 | 
            -
                all_files = md_files + mp3_files + wav_files
         | 
| 641 |  | 
| 642 | 
             
                if not all_files:
         | 
| 643 | 
             
                    st.sidebar.write("No files found.")
         | 
| 644 | 
             
                    return
         | 
| 645 |  | 
| 646 | 
            -
                # Sort  | 
| 647 | 
            -
                 | 
| 648 | 
            -
             | 
| 649 | 
            -
                for f in  | 
| 650 | 
            -
                     | 
| 651 | 
            -
                     | 
| 652 | 
            -
                     | 
| 653 | 
            -
                     | 
| 654 | 
            -
             | 
| 655 | 
            -
                    with st.sidebar.expander(f"{emoji} { | 
| 656 | 
            -
                         | 
| 657 | 
            -
                            st.audio(f)
         | 
| 658 | 
             
                        if ext == "md":
         | 
| 659 | 
            -
                            with open(f,  | 
| 660 | 
            -
                                 | 
| 661 | 
            -
                             | 
| 662 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 663 |  | 
| 664 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 665 | 
             
            # 7. MAIN APP
         | 
| 666 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 667 |  | 
| 668 | 
             
            def main():
         | 
| 669 | 
            -
                 | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 670 | 
             
                update_marquee_settings_ui()
         | 
| 671 | 
             
                marquee_settings = get_marquee_settings()
         | 
| 672 |  | 
| 673 | 
            -
                #  | 
| 674 | 
            -
                 | 
| 675 | 
            -
             | 
| 676 | 
            -
             | 
| 677 | 
            -
                with colB:
         | 
| 678 | 
            -
                    st.session_state['run_claude'] = st.checkbox("Claude", value=st.session_state['run_claude'])
         | 
| 679 | 
            -
                with colC:
         | 
| 680 | 
            -
                    st.session_state['run_arxiv'] = st.checkbox("Arxiv", value=st.session_state['run_arxiv'])
         | 
| 681 | 
            -
                with colD:
         | 
| 682 | 
            -
                    st.session_state['autorun_searches'] = st.checkbox("Autorun", value=st.session_state['autorun_searches'])
         | 
| 683 | 
            -
                with colE:
         | 
| 684 | 
            -
                    st.session_state['autosave_output'] = st.checkbox("AutoSave", value=st.session_state['autosave_output'])
         | 
| 685 | 
            -
             | 
| 686 | 
            -
                # 3) Display the marquee welcome
         | 
| 687 | 
             
                display_marquee(st.session_state['marquee_content'], 
         | 
| 688 | 
             
                                {**marquee_settings, "font-size": "28px", "lineHeight": "50px"},
         | 
| 689 | 
             
                                key_suffix="welcome")
         | 
| 690 |  | 
| 691 | 
            -
                #  | 
| 692 | 
            -
                 | 
| 693 | 
            -
             | 
| 694 | 
            -
             | 
| 695 | 
            -
             | 
| 696 | 
            -
             | 
| 697 | 
            -
                    edited_input = st.text_area("βοΈ Edit Input:", value=val_stripped, height=100)
         | 
| 698 | 
            -
                    run_option = st.selectbox("Model:", ["Arxiv"])
         | 
| 699 | 
            -
                    full_audio = st.checkbox("πFullAudio", value=False)
         | 
| 700 | 
            -
                    input_changed = (val != st.session_state.old_val)
         | 
| 701 | 
            -
             | 
| 702 | 
            -
                    # We'll define: if autorun is on, run immediately after input changes
         | 
| 703 | 
            -
                    if st.session_state['autorun_searches'] and input_changed:
         | 
| 704 | 
            -
                        st.session_state.old_val = val
         | 
| 705 | 
            -
                        st.session_state.last_query = edited_input
         | 
| 706 | 
            -
                        process_voice_input(edited_input)
         | 
| 707 | 
            -
                    else:
         | 
| 708 | 
            -
                        if st.button("βΆ Run"):
         | 
| 709 | 
            -
                            st.session_state.old_val = val
         | 
| 710 | 
            -
                            st.session_state.last_query = edited_input
         | 
| 711 | 
            -
                            process_voice_input(edited_input)
         | 
| 712 | 
            -
             | 
| 713 | 
            -
                # ββββββββοΏ½οΏ½οΏ½ββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 714 | 
            -
                # TAB: ArXiv
         | 
| 715 | 
            -
                # (kept for demonstration if user chooses to do Arxiv only)
         | 
| 716 | 
            -
                # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 717 | 
            -
                if tab_main == "π ArXiv":
         | 
| 718 | 
            -
                    st.subheader("π Query ArXiv")
         | 
| 719 | 
            -
                    q = st.text_input("π Query:", key="arxiv_query")
         | 
| 720 | 
            -
                    
         | 
| 721 | 
            -
                    if q and st.button("πRun"):
         | 
| 722 | 
            -
                        st.session_state.last_query = q
         | 
| 723 | 
            -
                        # Even if the tab is "ArXiv," we can just call our standard function 
         | 
| 724 | 
            -
                        # that uses whichever checkboxes are selected (or you can do Arxiv only).
         | 
| 725 | 
            -
                        process_voice_input(q)
         | 
| 726 |  | 
| 727 | 
            -
                #  | 
| 728 | 
            -
                 | 
| 729 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 730 | 
             
                elif tab_main == "π€ Voice":
         | 
| 731 | 
             
                    st.subheader("π€ Voice Input")
         | 
| 732 | 
            -
                    
         | 
| 733 | 
            -
                     | 
| 734 | 
            -
             | 
| 735 | 
            -
                        "Select TTS Voice:",
         | 
| 736 | 
            -
                        options=EDGE_TTS_VOICES,
         | 
| 737 | 
            -
                        index=EDGE_TTS_VOICES.index(st.session_state['tts_voice'])
         | 
| 738 | 
            -
                        if st.session_state['tts_voice'] in EDGE_TTS_VOICES
         | 
| 739 | 
            -
                        else 0
         | 
| 740 | 
            -
                    )
         | 
| 741 | 
            -
                    
         | 
| 742 | 
            -
                    st.markdown("### π Audio Format")
         | 
| 743 | 
            -
                    selected_format = st.radio(
         | 
| 744 | 
            -
                        "Choose Audio Format:",
         | 
| 745 | 
            -
                        options=["MP3", "WAV"],
         | 
| 746 | 
            -
                        index=0 if st.session_state['audio_format'] == "mp3" else 1
         | 
| 747 | 
            -
                    )
         | 
| 748 | 
            -
             | 
| 749 | 
            -
                    # Update session state if voice/format changes
         | 
| 750 | 
            -
                    if selected_voice != st.session_state['tts_voice']:
         | 
| 751 | 
            -
                        st.session_state['tts_voice'] = selected_voice
         | 
| 752 | 
            -
                        st.rerun()
         | 
| 753 | 
            -
                    if selected_format.lower() != st.session_state['audio_format']:
         | 
| 754 | 
            -
                        st.session_state['audio_format'] = selected_format.lower()
         | 
| 755 | 
            -
                        st.rerun()
         | 
| 756 | 
            -
             | 
| 757 | 
            -
                    user_text = st.text_area("π¬ Message:", height=100).strip().replace('\n', ' ')
         | 
| 758 | 
             
                    if st.button("π¨ Send"):
         | 
| 759 | 
            -
                        st.session_state.last_query = user_text
         | 
| 760 | 
            -
                        # If autorun is off, we explicitly run
         | 
| 761 | 
             
                        process_voice_input(user_text)
         | 
| 762 |  | 
| 763 | 
             
                    st.subheader("π Chat History")
         | 
| @@ -765,14 +746,10 @@ def main(): | |
| 765 | 
             
                        st.write("**You:**", c["user"])
         | 
| 766 | 
             
                        st.write("**Response:**", c["claude"])
         | 
| 767 |  | 
| 768 | 
            -
                #  | 
| 769 | 
            -
                # TAB: Media
         | 
| 770 | 
            -
                # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 771 | 
             
                elif tab_main == "πΈ Media":
         | 
| 772 | 
             
                    st.header("πΈ Media Gallery")
         | 
| 773 | 
             
                    tabs = st.tabs(["π΅ Audio", "πΌ Images", "π₯ Video"])
         | 
| 774 | 
            -
                    
         | 
| 775 | 
            -
                    # AUDIO sub-tab
         | 
| 776 | 
             
                    with tabs[0]:
         | 
| 777 | 
             
                        st.subheader("π΅ Audio Files")
         | 
| 778 | 
             
                        audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
         | 
| @@ -785,8 +762,6 @@ def main(): | |
| 785 | 
             
                                    st.markdown(dl_link, unsafe_allow_html=True)
         | 
| 786 | 
             
                        else:
         | 
| 787 | 
             
                            st.write("No audio files found.")
         | 
| 788 | 
            -
                    
         | 
| 789 | 
            -
                    # IMAGES sub-tab
         | 
| 790 | 
             
                    with tabs[1]:
         | 
| 791 | 
             
                        st.subheader("πΌ Image Files")
         | 
| 792 | 
             
                        imgs = glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg")
         | 
| @@ -798,8 +773,6 @@ def main(): | |
| 798 | 
             
                                    st.image(Image.open(f), use_container_width=True)
         | 
| 799 | 
             
                        else:
         | 
| 800 | 
             
                            st.write("No images found.")
         | 
| 801 | 
            -
                    
         | 
| 802 | 
            -
                    # VIDEO sub-tab
         | 
| 803 | 
             
                    with tabs[2]:
         | 
| 804 | 
             
                        st.subheader("π₯ Video Files")
         | 
| 805 | 
             
                        vids = glob.glob("*.mp4") + glob.glob("*.mov") + glob.glob("*.avi")
         | 
| @@ -810,30 +783,45 @@ def main(): | |
| 810 | 
             
                        else:
         | 
| 811 | 
             
                            st.write("No videos found.")
         | 
| 812 |  | 
| 813 | 
            -
                #  | 
| 814 | 
            -
                 | 
| 815 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 816 | 
             
                elif tab_main == "π Editor":
         | 
| 817 | 
             
                    st.write("Select or create a file to edit. (Currently minimal demo)")
         | 
| 818 |  | 
| 819 | 
            -
                # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 820 | 
            -
                # SIDEBAR: FILE HISTORY
         | 
| 821 | 
            -
                # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 822 | 
            -
                display_file_history_in_sidebar()
         | 
| 823 | 
            -
             | 
| 824 | 
            -
                # Some light CSS styling
         | 
| 825 | 
            -
                st.markdown("""
         | 
| 826 | 
            -
                <style>
         | 
| 827 | 
            -
                    .main { background: linear-gradient(to right, #1a1a1a, #2d2d2d); color: #fff; }
         | 
| 828 | 
            -
                    .stMarkdown { font-family: 'Helvetica Neue', sans-serif; }
         | 
| 829 | 
            -
                    .stButton>button { margin-right: 0.5rem; }
         | 
| 830 | 
            -
                </style>
         | 
| 831 | 
            -
                """, unsafe_allow_html=True)
         | 
| 832 | 
            -
             | 
| 833 | 
             
                # Rerun if needed
         | 
| 834 | 
             
                if st.session_state.should_rerun:
         | 
| 835 | 
             
                    st.session_state.should_rerun = False
         | 
| 836 | 
            -
                    st. | 
| 837 |  | 
| 838 | 
             
            if __name__ == "__main__":
         | 
| 839 | 
             
                main()
         | 
|  | |
| 106 | 
             
            if 'marquee_content' not in st.session_state:
         | 
| 107 | 
             
                st.session_state['marquee_content'] = "π Welcome to TalkingAIResearcher | π€ Your Research Assistant"
         | 
| 108 |  | 
| 109 | 
            +
            # New: default AutoRun to False (off)
         | 
| 110 | 
            +
            if 'autorun' not in st.session_state:
         | 
| 111 | 
            +
                st.session_state['autorun'] = False
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 112 |  | 
| 113 | 
             
            # API Keys
         | 
| 114 | 
             
            openai_api_key = os.getenv('OPENAI_API_KEY', "")
         | 
|  | |
| 128 | 
             
            FILE_EMOJIS = {
         | 
| 129 | 
             
                "md": "π",
         | 
| 130 | 
             
                "mp3": "π΅",
         | 
| 131 | 
            +
                "wav": "π",
         | 
| 132 | 
            +
                "pdf": "π",
         | 
| 133 | 
            +
                "mp4": "π₯",
         | 
| 134 | 
            +
                "csv": "π",
         | 
| 135 | 
            +
                "xlsx": "π",
         | 
| 136 | 
            +
                "html": "π",
         | 
| 137 | 
            +
                "py": "π",
         | 
| 138 | 
            +
                "txt": "π"
         | 
| 139 | 
             
            }
         | 
| 140 |  | 
| 141 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
|  | |
| 306 | 
             
                    st.markdown(dl_link, unsafe_allow_html=True)
         | 
| 307 |  | 
| 308 | 
             
            def save_qa_with_audio(question, answer, voice=None):
         | 
| 309 | 
            +
                """Save Q&A to markdown and also generate audio."""
         | 
| 310 | 
             
                if not voice:
         | 
| 311 | 
             
                    voice = st.session_state['tts_voice']
         | 
| 312 |  | 
| 313 | 
             
                combined_text = f"# Question\n{question}\n\n# Answer\n{answer}"
         | 
| 314 | 
            +
                md_file = create_file(question, answer, "md")
         | 
| 315 | 
            +
                audio_text = f"{question}\n\nAnswer: {answer}"
         | 
| 316 | 
            +
                audio_file = speak_with_edge_tts(
         | 
| 317 | 
            +
                    audio_text,
         | 
| 318 | 
            +
                    voice=voice,
         | 
| 319 | 
            +
                    file_format=st.session_state['audio_format']
         | 
| 320 | 
            +
                )
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 321 | 
             
                return md_file, audio_file
         | 
| 322 |  | 
| 323 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
|  | |
| 388 |  | 
| 389 | 
             
            def create_paper_audio_files(papers, input_question):
         | 
| 390 | 
             
                """
         | 
| 391 | 
            +
                For each paper, generate TTS audio summary, store the path in `paper['full_audio']`,
         | 
| 392 | 
            +
                and also store a base64 link for stable downloading.
         | 
|  | |
| 393 | 
             
                """
         | 
|  | |
|  | |
| 394 | 
             
                for paper in papers:
         | 
| 395 | 
             
                    try:
         | 
| 396 | 
             
                        audio_text = f"{paper['title']} by {paper['authors']}. {paper['summary']}"
         | 
|  | |
| 450 | 
             
                            st.markdown(f"**Summary:** {paper['summary'][:300]}...")
         | 
| 451 |  | 
| 452 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 453 | 
            +
            # 4. ZIP & DELETE-ALL UTILS
         | 
| 454 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 455 |  | 
| 456 | 
            +
            def create_zip_of_all_files():
         | 
| 457 | 
             
                """
         | 
| 458 | 
            +
                Zip up all recognized file types, limiting the final zip name to ~20 chars
         | 
| 459 | 
             
                to avoid overly long base64 strings. 
         | 
| 460 | 
             
                """
         | 
| 461 | 
            +
                # Patterns for .md, .pdf, .mp4, .mp3, .wav, .csv, .xlsx, .html, .py, .txt
         | 
| 462 | 
            +
                file_patterns = [
         | 
| 463 | 
            +
                    "*.md", "*.pdf", "*.mp4", "*.mp3", "*.wav",
         | 
| 464 | 
            +
                    "*.csv", "*.xlsx", "*.html", "*.py", "*.txt"
         | 
| 465 | 
            +
                ]
         | 
| 466 | 
            +
                all_files = []
         | 
| 467 | 
            +
                for pat in file_patterns:
         | 
| 468 | 
            +
                    all_files.extend(glob.glob(pat))
         | 
| 469 | 
            +
                all_files = list(set(all_files))  # unique
         | 
| 470 | 
            +
             | 
| 471 | 
             
                if not all_files:
         | 
| 472 | 
             
                    return None
         | 
| 473 |  | 
| 474 | 
            +
                # Combine content for naming
         | 
| 475 | 
             
                all_content = []
         | 
| 476 | 
             
                for f in all_files:
         | 
| 477 | 
            +
                    if f.endswith(".md"):
         | 
| 478 | 
            +
                        with open(f, "r", encoding="utf-8") as fin:
         | 
| 479 | 
            +
                            all_content.append(fin.read())
         | 
| 480 | 
            +
                    else:
         | 
| 481 | 
            +
                        all_content.append(os.path.basename(f))
         | 
| 482 | 
            +
             | 
| 483 | 
            +
                # Add last query if relevant
         | 
| 484 | 
            +
                if st.session_state['last_query']:
         | 
| 485 | 
            +
                    all_content.append(st.session_state['last_query'])
         | 
| 486 | 
            +
             | 
| 487 | 
             
                combined_content = " ".join(all_content)
         | 
| 488 | 
             
                info_terms = get_high_info_terms(combined_content, top_n=10)
         | 
| 489 |  | 
| 490 | 
             
                timestamp = format_timestamp_prefix()
         | 
| 491 | 
            +
                name_text = '-'.join(term for term in info_terms[:5])
         | 
| 492 | 
             
                short_zip_name = (timestamp + "_" + name_text)[:20] + ".zip"
         | 
| 493 |  | 
| 494 | 
             
                with zipfile.ZipFile(short_zip_name, 'w') as z:
         | 
|  | |
| 496 | 
             
                        z.write(f)
         | 
| 497 | 
             
                return short_zip_name
         | 
| 498 |  | 
| 499 | 
            +
            def delete_all_files():
         | 
| 500 | 
            +
                """Removes all recognized file types from the directory."""
         | 
| 501 | 
            +
                file_patterns = [
         | 
| 502 | 
            +
                    "*.md", "*.pdf", "*.mp4", "*.mp3", "*.wav",
         | 
| 503 | 
            +
                    "*.csv", "*.xlsx", "*.html", "*.py", "*.txt"
         | 
| 504 | 
            +
                ]
         | 
| 505 | 
            +
                for pat in file_patterns:
         | 
| 506 | 
            +
                    for f in glob.glob(pat):
         | 
| 507 | 
            +
                        os.remove(f)
         | 
| 508 | 
            +
             | 
| 509 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 510 | 
             
            # 5. MAIN LOGIC: AI LOOKUP & VOICE INPUT
         | 
| 511 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 512 |  | 
| 513 | 
            +
            def perform_ai_lookup(q, vocal_summary=True, extended_refs=False, 
         | 
| 514 | 
            +
                                 titles_summary=True, full_audio=False):
         | 
| 515 | 
            +
                """Main routine that uses Anthropic (Claude) + Gradio ArXiv RAG pipeline."""
         | 
| 516 | 
            +
                start = time.time()
         | 
| 517 | 
            +
             | 
| 518 | 
            +
                # --- 1) Claude API
         | 
| 519 | 
             
                client = anthropic.Anthropic(api_key=anthropic_key)
         | 
| 520 | 
            +
                user_input = q
         | 
| 521 | 
             
                response = client.messages.create(
         | 
| 522 | 
             
                    model="claude-3-sonnet-20240229",
         | 
| 523 | 
             
                    max_tokens=1000,
         | 
| 524 | 
             
                    messages=[
         | 
| 525 | 
            +
                        {"role": "user", "content": user_input}
         | 
| 526 | 
             
                    ])
         | 
| 527 | 
            +
                st.write("Claude's reply π§ :")
         | 
| 528 | 
            +
                st.markdown(response.content[0].text)
         | 
| 529 |  | 
| 530 | 
            +
                # Save & produce audio
         | 
| 531 | 
            +
                result = response.content[0].text
         | 
| 532 | 
            +
                create_file(q, result) 
         | 
| 533 | 
            +
                md_file, audio_file = save_qa_with_audio(q, result)
         | 
| 534 | 
            +
                st.subheader("π Main Response Audio")
         | 
| 535 | 
            +
                play_and_download_audio(audio_file, st.session_state['audio_format'])
         | 
| 536 |  | 
| 537 | 
            +
                # --- 2) Arxiv RAG
         | 
| 538 | 
            +
                st.write("Arxiv's AI this Evening is Mixtral 8x7B...")
         | 
|  | |
| 539 | 
             
                client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
         | 
| 540 | 
             
                refs = client.predict(
         | 
| 541 | 
            +
                    q, 
         | 
| 542 | 
            +
                    20, 
         | 
| 543 | 
             
                    "Semantic Search", 
         | 
| 544 | 
             
                    "mistralai/Mixtral-8x7B-Instruct-v0.1",
         | 
| 545 | 
             
                    api_name="/update_with_rag_md"
         | 
| 546 | 
             
                )[0]
         | 
|  | |
| 547 | 
             
                r2 = client.predict(
         | 
| 548 | 
             
                    q, 
         | 
| 549 | 
             
                    "mistralai/Mixtral-8x7B-Instruct-v0.1", 
         | 
| 550 | 
             
                    True, 
         | 
| 551 | 
             
                    api_name="/ask_llm"
         | 
| 552 | 
             
                )
         | 
| 553 | 
            +
             | 
|  | |
| 554 | 
             
                result = f"### π {q}\n\n{r2}\n\n{refs}"
         | 
| 555 | 
            +
                md_file, audio_file = save_qa_with_audio(q, result)
         | 
| 556 | 
            +
                st.subheader("π Main Response Audio")
         | 
| 557 | 
            +
                play_and_download_audio(audio_file, st.session_state['audio_format'])
         | 
| 558 |  | 
| 559 | 
            +
                # --- 3) Parse + handle papers
         | 
| 560 | 
             
                papers = parse_arxiv_refs(refs)
         | 
| 561 | 
             
                if papers:
         | 
| 562 | 
            +
                    # Create minimal links page first
         | 
| 563 | 
            +
                    paper_links = create_paper_links_md(papers)
         | 
| 564 | 
            +
                    links_file = create_file(q, paper_links, "md")
         | 
| 565 | 
            +
                    st.markdown(paper_links)
         | 
| 566 |  | 
| 567 | 
            +
                    # Then create audio for each paper
         | 
| 568 | 
             
                    create_paper_audio_files(papers, input_question=q)
         | 
| 569 | 
             
                    display_papers(papers, get_marquee_settings())
         | 
| 570 | 
             
                    display_papers_in_sidebar(papers)
         | 
| 571 | 
             
                else:
         | 
| 572 | 
             
                    st.warning("No papers found in the response.")
         | 
|  | |
| 573 |  | 
| 574 | 
            +
                elapsed = time.time() - start
         | 
| 575 | 
            +
                st.write(f"**Total Elapsed:** {elapsed:.2f} s")
         | 
| 576 | 
            +
                return result
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 577 |  | 
| 578 | 
             
            def process_voice_input(text):
         | 
| 579 | 
            +
                """When user sends voice query, we run the AI lookup + Q&A with audio."""
         | 
| 580 | 
             
                if not text:
         | 
| 581 | 
             
                    return
         | 
| 582 | 
             
                st.subheader("π Search Results")
         | 
| 583 | 
            +
                result = perform_ai_lookup(
         | 
| 584 | 
            +
                    text, 
         | 
| 585 | 
            +
                    vocal_summary=True,
         | 
| 586 | 
            +
                    extended_refs=False,
         | 
| 587 | 
            +
                    titles_summary=True,
         | 
| 588 | 
            +
                    full_audio=True
         | 
| 589 | 
            +
                )
         | 
| 590 | 
             
                md_file, audio_file = save_qa_with_audio(text, result)
         | 
| 591 | 
            +
                st.subheader("π Generated Files")
         | 
| 592 | 
            +
                st.write(f"Markdown: {md_file}")
         | 
| 593 | 
            +
                st.write(f"Audio: {audio_file}")
         | 
| 594 | 
            +
                play_and_download_audio(audio_file, st.session_state['audio_format'])
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 595 |  | 
| 596 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 597 | 
             
            # 6. FILE HISTORY SIDEBAR
         | 
|  | |
| 599 |  | 
| 600 | 
             
            def display_file_history_in_sidebar():
         | 
| 601 | 
             
                """
         | 
| 602 | 
            +
                Shows a history of each recognized file in descending
         | 
| 603 | 
             
                order of modification time, with quick icons and optional download links.
         | 
| 604 | 
             
                """
         | 
| 605 | 
             
                st.sidebar.markdown("---")
         | 
| 606 | 
             
                st.sidebar.markdown("### π File History")
         | 
| 607 |  | 
| 608 | 
            +
                # Patterns for .md, .mp3, .wav, .pdf, .mp4, .csv, .xlsx, .html, .py, .txt
         | 
| 609 | 
            +
                patterns = [
         | 
| 610 | 
            +
                    "*.md", "*.pdf", "*.mp4", "*.mp3", "*.wav",
         | 
| 611 | 
            +
                    "*.csv", "*.xlsx", "*.html", "*.py", "*.txt"
         | 
| 612 | 
            +
                ]
         | 
| 613 | 
            +
                all_files = []
         | 
| 614 | 
            +
                for p in patterns:
         | 
| 615 | 
            +
                    all_files.extend(glob.glob(p))
         | 
| 616 | 
            +
                all_files = list(set(all_files))  # unique
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 617 |  | 
| 618 | 
             
                if not all_files:
         | 
| 619 | 
             
                    st.sidebar.write("No files found.")
         | 
| 620 | 
             
                    return
         | 
| 621 |  | 
| 622 | 
            +
                # Sort newest first
         | 
| 623 | 
            +
                all_files = sorted(all_files, key=os.path.getmtime, reverse=True)
         | 
| 624 | 
            +
             | 
| 625 | 
            +
                for f in all_files:
         | 
| 626 | 
            +
                    fname = os.path.basename(f)
         | 
| 627 | 
            +
                    ext = os.path.splitext(fname)[1].lower().strip('.')
         | 
| 628 | 
            +
                    emoji = FILE_EMOJIS.get(ext, 'π¦')
         | 
| 629 | 
            +
                    time_str = datetime.fromtimestamp(os.path.getmtime(f)).strftime("%Y-%m-%d %H:%M:%S")
         | 
| 630 | 
            +
             | 
| 631 | 
            +
                    with st.sidebar.expander(f"{emoji} {fname}"):
         | 
| 632 | 
            +
                        st.write(f"**Modified:** {time_str}")
         | 
|  | |
| 633 | 
             
                        if ext == "md":
         | 
| 634 | 
            +
                            with open(f, "r", encoding="utf-8") as file_in:
         | 
| 635 | 
            +
                                snippet = file_in.read(200).replace("\n", " ")
         | 
| 636 | 
            +
                            if len(snippet) == 200:
         | 
| 637 | 
            +
                                snippet += "..."
         | 
| 638 | 
            +
                            st.write(snippet)
         | 
| 639 | 
            +
                            st.markdown(get_download_link(f, file_type="md"), unsafe_allow_html=True)
         | 
| 640 | 
            +
                        elif ext in ["mp3","wav"]:
         | 
| 641 | 
            +
                            st.audio(f)
         | 
| 642 | 
            +
                            st.markdown(get_download_link(f, file_type=ext), unsafe_allow_html=True)
         | 
| 643 | 
            +
                        else:
         | 
| 644 | 
            +
                            st.markdown(get_download_link(f), unsafe_allow_html=True)
         | 
| 645 |  | 
| 646 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 647 | 
             
            # 7. MAIN APP
         | 
| 648 | 
             
            # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
         | 
| 649 |  | 
| 650 | 
             
            def main():
         | 
| 651 | 
            +
                """
         | 
| 652 | 
            +
                Main Streamlit app. 
         | 
| 653 | 
            +
                Now includes:
         | 
| 654 | 
            +
                  1) Voice & AutoRun at the top of the sidebar,
         | 
| 655 | 
            +
                  2) File Tools (Delete All / Zip All) in the sidebar,
         | 
| 656 | 
            +
                  3) A new 'π€ Upload' tab, 
         | 
| 657 | 
            +
                  4) Everything else from your original code snippet.
         | 
| 658 | 
            +
                """
         | 
| 659 | 
            +
             | 
| 660 | 
            +
                # -- 1) Voice & AutoRun at top of sidebar --
         | 
| 661 | 
            +
                st.sidebar.title("Global Settings")
         | 
| 662 | 
            +
                selected_voice = st.sidebar.selectbox(
         | 
| 663 | 
            +
                    "TTS Voice",
         | 
| 664 | 
            +
                    options=EDGE_TTS_VOICES,
         | 
| 665 | 
            +
                    index=EDGE_TTS_VOICES.index(st.session_state['tts_voice'])
         | 
| 666 | 
            +
                )
         | 
| 667 | 
            +
                # Autorun defaults to off (False)
         | 
| 668 | 
            +
                st.session_state.autorun = st.sidebar.checkbox("AutoRun", value=st.session_state.autorun)
         | 
| 669 | 
            +
             | 
| 670 | 
            +
                # Audio format
         | 
| 671 | 
            +
                audio_format = st.sidebar.radio("Audio Format", ["MP3","WAV"], index=0)
         | 
| 672 | 
            +
                if selected_voice != st.session_state['tts_voice']:
         | 
| 673 | 
            +
                    st.session_state['tts_voice'] = selected_voice
         | 
| 674 | 
            +
                    st.experimental_rerun()
         | 
| 675 | 
            +
                if audio_format.lower() != st.session_state['audio_format']:
         | 
| 676 | 
            +
                    st.session_state['audio_format'] = audio_format.lower()
         | 
| 677 | 
            +
                    st.experimental_rerun()
         | 
| 678 | 
            +
             | 
| 679 | 
            +
                # -- 2) File Tools: Delete All / Zip All
         | 
| 680 | 
            +
                st.sidebar.markdown("---")
         | 
| 681 | 
            +
                st.sidebar.markdown("### π File Tools")
         | 
| 682 | 
            +
                col_del, col_zip = st.sidebar.columns(2)
         | 
| 683 | 
            +
                with col_del:
         | 
| 684 | 
            +
                    if st.button("π Delete All"):
         | 
| 685 | 
            +
                        delete_all_files()
         | 
| 686 | 
            +
                        st.sidebar.success("All recognized files removed!")
         | 
| 687 | 
            +
                        st.experimental_rerun()
         | 
| 688 | 
            +
                with col_zip:
         | 
| 689 | 
            +
                    if st.button("π¦ Zip All"):
         | 
| 690 | 
            +
                        zip_name = create_zip_of_all_files()
         | 
| 691 | 
            +
                        if zip_name:
         | 
| 692 | 
            +
                            st.sidebar.markdown(get_download_link(zip_name, "zip"), unsafe_allow_html=True)
         | 
| 693 | 
            +
             | 
| 694 | 
            +
                # -- 3) Marquee Settings
         | 
| 695 | 
             
                update_marquee_settings_ui()
         | 
| 696 | 
             
                marquee_settings = get_marquee_settings()
         | 
| 697 |  | 
| 698 | 
            +
                # -- 4) File History in sidebar
         | 
| 699 | 
            +
                display_file_history_in_sidebar()
         | 
| 700 | 
            +
             | 
| 701 | 
            +
                # -- 5) Display marquee
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 702 | 
             
                display_marquee(st.session_state['marquee_content'], 
         | 
| 703 | 
             
                                {**marquee_settings, "font-size": "28px", "lineHeight": "50px"},
         | 
| 704 | 
             
                                key_suffix="welcome")
         | 
| 705 |  | 
| 706 | 
            +
                # -- 6) Main action tabs
         | 
| 707 | 
            +
                tab_main = st.radio(
         | 
| 708 | 
            +
                    "Action:", 
         | 
| 709 | 
            +
                    ["π€ Upload", "π€ Voice", "πΈ Media", "π ArXiv", "π Editor"], 
         | 
| 710 | 
            +
                    horizontal=True
         | 
| 711 | 
            +
                )
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 712 |  | 
| 713 | 
            +
                # 6a) Upload Tab
         | 
| 714 | 
            +
                if tab_main == "π€ Upload":
         | 
| 715 | 
            +
                    st.header("π€ Upload Files")
         | 
| 716 | 
            +
                    accepted_types = [
         | 
| 717 | 
            +
                        # We'll accept basically everything (None in file_uploader),
         | 
| 718 | 
            +
                        # but let's specify for clarity:
         | 
| 719 | 
            +
                        "text/plain", "text/markdown", "audio/mpeg", "audio/wav",
         | 
| 720 | 
            +
                        "image/png", "image/jpeg", "video/mp4", "application/pdf",
         | 
| 721 | 
            +
                        "application/vnd.ms-excel",
         | 
| 722 | 
            +
                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
         | 
| 723 | 
            +
                        "text/html", "application/octet-stream",
         | 
| 724 | 
            +
                    ]
         | 
| 725 | 
            +
                    uploaded = st.file_uploader("Select files to upload:", 
         | 
| 726 | 
            +
                                                accept_multiple_files=True, 
         | 
| 727 | 
            +
                                                type=None)
         | 
| 728 | 
            +
                    if uploaded:
         | 
| 729 | 
            +
                        for uf in uploaded:
         | 
| 730 | 
            +
                            with open(uf.name, "wb") as outfile:
         | 
| 731 | 
            +
                                outfile.write(uf.read())
         | 
| 732 | 
            +
                        st.success("Uploaded!")
         | 
| 733 | 
            +
                        st.session_state.should_rerun = True
         | 
| 734 | 
            +
             | 
| 735 | 
            +
                # 6b) Voice Tab
         | 
| 736 | 
             
                elif tab_main == "π€ Voice":
         | 
| 737 | 
             
                    st.subheader("π€ Voice Input")
         | 
| 738 | 
            +
                    user_text = st.text_area("π¬ Message:", height=100)
         | 
| 739 | 
            +
                    user_text = user_text.strip().replace('\n', ' ')
         | 
| 740 | 
            +
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 741 | 
             
                    if st.button("π¨ Send"):
         | 
|  | |
|  | |
| 742 | 
             
                        process_voice_input(user_text)
         | 
| 743 |  | 
| 744 | 
             
                    st.subheader("π Chat History")
         | 
|  | |
| 746 | 
             
                        st.write("**You:**", c["user"])
         | 
| 747 | 
             
                        st.write("**Response:**", c["claude"])
         | 
| 748 |  | 
| 749 | 
            +
                # 6c) Media Tab
         | 
|  | |
|  | |
| 750 | 
             
                elif tab_main == "πΈ Media":
         | 
| 751 | 
             
                    st.header("πΈ Media Gallery")
         | 
| 752 | 
             
                    tabs = st.tabs(["π΅ Audio", "πΌ Images", "π₯ Video"])
         | 
|  | |
|  | |
| 753 | 
             
                    with tabs[0]:
         | 
| 754 | 
             
                        st.subheader("π΅ Audio Files")
         | 
| 755 | 
             
                        audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
         | 
|  | |
| 762 | 
             
                                    st.markdown(dl_link, unsafe_allow_html=True)
         | 
| 763 | 
             
                        else:
         | 
| 764 | 
             
                            st.write("No audio files found.")
         | 
|  | |
|  | |
| 765 | 
             
                    with tabs[1]:
         | 
| 766 | 
             
                        st.subheader("πΌ Image Files")
         | 
| 767 | 
             
                        imgs = glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg")
         | 
|  | |
| 773 | 
             
                                    st.image(Image.open(f), use_container_width=True)
         | 
| 774 | 
             
                        else:
         | 
| 775 | 
             
                            st.write("No images found.")
         | 
|  | |
|  | |
| 776 | 
             
                    with tabs[2]:
         | 
| 777 | 
             
                        st.subheader("π₯ Video Files")
         | 
| 778 | 
             
                        vids = glob.glob("*.mp4") + glob.glob("*.mov") + glob.glob("*.avi")
         | 
|  | |
| 783 | 
             
                        else:
         | 
| 784 | 
             
                            st.write("No videos found.")
         | 
| 785 |  | 
| 786 | 
            +
                # 6d) ArXiv Tab
         | 
| 787 | 
            +
                elif tab_main == "π ArXiv":
         | 
| 788 | 
            +
                    st.subheader("π Query ArXiv")
         | 
| 789 | 
            +
                    q = st.text_input("π Query:", key="arxiv_query")
         | 
| 790 | 
            +
                    
         | 
| 791 | 
            +
                    st.markdown("### π Options")
         | 
| 792 | 
            +
                    st.write("(AutoRun is in the sidebar.)")
         | 
| 793 | 
            +
                    extended_refs = st.checkbox("πLongRefs", value=False, key="option_extended_refs")
         | 
| 794 | 
            +
                    titles_summary = st.checkbox("πTitlesOnly", value=True, key="option_titles_summary")
         | 
| 795 | 
            +
                    full_audio = st.checkbox("πFullAudio", value=False, key="option_full_audio")
         | 
| 796 | 
            +
                    full_transcript = st.checkbox("π§ΎFullTranscript", value=False, key="option_full_transcript")
         | 
| 797 | 
            +
                    
         | 
| 798 | 
            +
                    if q and st.button("πRun"):
         | 
| 799 | 
            +
                        st.session_state.last_query = q
         | 
| 800 | 
            +
                        result = perform_ai_lookup(q, 
         | 
| 801 | 
            +
                                                   extended_refs=extended_refs, 
         | 
| 802 | 
            +
                                                   titles_summary=titles_summary, 
         | 
| 803 | 
            +
                                                   full_audio=full_audio)
         | 
| 804 | 
            +
                        if full_transcript:
         | 
| 805 | 
            +
                            create_file(q, result, "md")
         | 
| 806 | 
            +
             | 
| 807 | 
            +
                    # If AutoRun is ON and user typed something
         | 
| 808 | 
            +
                    if st.session_state.autorun and q:
         | 
| 809 | 
            +
                        st.session_state.last_query = q
         | 
| 810 | 
            +
                        result = perform_ai_lookup(q, 
         | 
| 811 | 
            +
                                                   extended_refs=extended_refs, 
         | 
| 812 | 
            +
                                                   titles_summary=titles_summary, 
         | 
| 813 | 
            +
                                                   full_audio=full_audio)
         | 
| 814 | 
            +
                        if full_transcript:
         | 
| 815 | 
            +
                            create_file(q, result, "md")
         | 
| 816 | 
            +
             | 
| 817 | 
            +
                # 6e) Editor Tab
         | 
| 818 | 
             
                elif tab_main == "π Editor":
         | 
| 819 | 
             
                    st.write("Select or create a file to edit. (Currently minimal demo)")
         | 
| 820 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 821 | 
             
                # Rerun if needed
         | 
| 822 | 
             
                if st.session_state.should_rerun:
         | 
| 823 | 
             
                    st.session_state.should_rerun = False
         | 
| 824 | 
            +
                    st.experimental_rerun()
         | 
| 825 |  | 
| 826 | 
             
            if __name__ == "__main__":
         | 
| 827 | 
             
                main()
         | 
