Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	Create backup9.app.py
Browse files- backup9.app.py +1004 -0
    	
        backup9.app.py
    ADDED
    
    | @@ -0,0 +1,1004 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import streamlit as st
         | 
| 2 | 
            +
            import anthropic
         | 
| 3 | 
            +
            import openai
         | 
| 4 | 
            +
            import base64
         | 
| 5 | 
            +
            from datetime import datetime
         | 
| 6 | 
            +
            import plotly.graph_objects as go
         | 
| 7 | 
            +
            import cv2
         | 
| 8 | 
            +
            import glob
         | 
| 9 | 
            +
            import json
         | 
| 10 | 
            +
            import math
         | 
| 11 | 
            +
            import os
         | 
| 12 | 
            +
            import pytz
         | 
| 13 | 
            +
            import random
         | 
| 14 | 
            +
            import re
         | 
| 15 | 
            +
            import requests
         | 
| 16 | 
            +
            import streamlit.components.v1 as components
         | 
| 17 | 
            +
            import textract
         | 
| 18 | 
            +
            import time
         | 
| 19 | 
            +
            import zipfile
         | 
| 20 | 
            +
            from audio_recorder_streamlit import audio_recorder
         | 
| 21 | 
            +
            from bs4 import BeautifulSoup
         | 
| 22 | 
            +
            from collections import deque
         | 
| 23 | 
            +
            from dotenv import load_dotenv
         | 
| 24 | 
            +
            from gradio_client import Client
         | 
| 25 | 
            +
            from huggingface_hub import InferenceClient
         | 
| 26 | 
            +
            from io import BytesIO
         | 
| 27 | 
            +
            from PIL import Image
         | 
| 28 | 
            +
            from PyPDF2 import PdfReader
         | 
| 29 | 
            +
            from urllib.parse import quote
         | 
| 30 | 
            +
            from xml.etree import ElementTree as ET
         | 
| 31 | 
            +
            from openai import OpenAI
         | 
| 32 | 
            +
            import extra_streamlit_components as stx
         | 
| 33 | 
            +
            from streamlit.runtime.scriptrunner import get_script_run_ctx
         | 
| 34 | 
            +
             | 
| 35 | 
            +
             | 
| 36 | 
            +
            # 1. π²BikeAIπ Configuration and Setup
         | 
| 37 | 
            +
            Site_Name = 'π²BikeAIπ Claude and GPT Multi-Agent Research AI'
         | 
| 38 | 
            +
            title = "π²BikeAIπ Claude and GPT Multi-Agent Research AI"
         | 
| 39 | 
            +
            helpURL = 'https://huggingface.co/awacke1'
         | 
| 40 | 
            +
            bugURL = 'https://huggingface.co/spaces/awacke1'
         | 
| 41 | 
            +
            icons = 'π²π'
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            st.set_page_config(
         | 
| 44 | 
            +
                page_title=title,
         | 
| 45 | 
            +
                page_icon=icons,
         | 
| 46 | 
            +
                layout="wide",
         | 
| 47 | 
            +
                initial_sidebar_state="auto",
         | 
| 48 | 
            +
                menu_items={
         | 
| 49 | 
            +
                    'Get Help': helpURL,
         | 
| 50 | 
            +
                    'Report a bug': bugURL,
         | 
| 51 | 
            +
                    'About': title
         | 
| 52 | 
            +
                }
         | 
| 53 | 
            +
            )
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            # 2. π²BikeAIπ Load environment variables and initialize clients
         | 
| 56 | 
            +
            load_dotenv()
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            # OpenAI setup
         | 
| 59 | 
            +
            openai.api_key = os.getenv('OPENAI_API_KEY')
         | 
| 60 | 
            +
            if openai.api_key == None:
         | 
| 61 | 
            +
                openai.api_key = st.secrets['OPENAI_API_KEY']
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            openai_client = OpenAI(
         | 
| 64 | 
            +
                api_key=os.getenv('OPENAI_API_KEY'),
         | 
| 65 | 
            +
                organization=os.getenv('OPENAI_ORG_ID')
         | 
| 66 | 
            +
            )
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            # 3.π²BikeAIπ Claude setup
         | 
| 69 | 
            +
            anthropic_key = os.getenv("ANTHROPIC_API_KEY_3")
         | 
| 70 | 
            +
            if anthropic_key == None:
         | 
| 71 | 
            +
                anthropic_key = st.secrets["ANTHROPIC_API_KEY"]
         | 
| 72 | 
            +
            claude_client = anthropic.Anthropic(api_key=anthropic_key)
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            # 4.π²BikeAIπ Initialize session states
         | 
| 75 | 
            +
            if 'transcript_history' not in st.session_state:
         | 
| 76 | 
            +
                st.session_state.transcript_history = []
         | 
| 77 | 
            +
            if "chat_history" not in st.session_state:
         | 
| 78 | 
            +
                st.session_state.chat_history = []
         | 
| 79 | 
            +
            if "openai_model" not in st.session_state:
         | 
| 80 | 
            +
                st.session_state["openai_model"] = "gpt-4o-2024-05-13"
         | 
| 81 | 
            +
            if "messages" not in st.session_state:
         | 
| 82 | 
            +
                st.session_state.messages = []
         | 
| 83 | 
            +
            if 'last_voice_input' not in st.session_state:
         | 
| 84 | 
            +
                st.session_state.last_voice_input = ""
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            # 5. π²BikeAIπ HuggingFace AI setup
         | 
| 87 | 
            +
            API_URL = os.getenv('API_URL')
         | 
| 88 | 
            +
            HF_KEY = os.getenv('HF_KEY')
         | 
| 89 | 
            +
            MODEL1 = "meta-llama/Llama-2-7b-chat-hf"
         | 
| 90 | 
            +
            MODEL2 = "openai/whisper-small.en"
         | 
| 91 | 
            +
            headers = {
         | 
| 92 | 
            +
                "Authorization": f"Bearer {HF_KEY}",
         | 
| 93 | 
            +
                "Content-Type": "application/json"
         | 
| 94 | 
            +
            }
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            # 6. π²BikeAIπ Custom CSS
         | 
| 97 | 
            +
            st.markdown("""
         | 
| 98 | 
            +
            <style>
         | 
| 99 | 
            +
                .main {
         | 
| 100 | 
            +
                    background: linear-gradient(to right, #1a1a1a, #2d2d2d);
         | 
| 101 | 
            +
                    color: #ffffff;
         | 
| 102 | 
            +
                }
         | 
| 103 | 
            +
                .stMarkdown {
         | 
| 104 | 
            +
                    font-family: 'Helvetica Neue', sans-serif;
         | 
| 105 | 
            +
                }
         | 
| 106 | 
            +
                .category-header {
         | 
| 107 | 
            +
                    background: linear-gradient(45deg, #2b5876, #4e4376);
         | 
| 108 | 
            +
                    padding: 20px;
         | 
| 109 | 
            +
                    border-radius: 10px;
         | 
| 110 | 
            +
                    margin: 10px 0;
         | 
| 111 | 
            +
                }
         | 
| 112 | 
            +
                .scene-card {
         | 
| 113 | 
            +
                    background: rgba(0,0,0,0.3);
         | 
| 114 | 
            +
                    padding: 15px;
         | 
| 115 | 
            +
                    border-radius: 8px;
         | 
| 116 | 
            +
                    margin: 10px 0;
         | 
| 117 | 
            +
                    border: 1px solid rgba(255,255,255,0.1);
         | 
| 118 | 
            +
                }
         | 
| 119 | 
            +
                .media-gallery {
         | 
| 120 | 
            +
                    display: grid;
         | 
| 121 | 
            +
                    gap: 1rem;
         | 
| 122 | 
            +
                    padding: 1rem;
         | 
| 123 | 
            +
                }
         | 
| 124 | 
            +
                .bike-card {
         | 
| 125 | 
            +
                    background: rgba(255,255,255,0.05);
         | 
| 126 | 
            +
                    border-radius: 10px;
         | 
| 127 | 
            +
                    padding: 15px;
         | 
| 128 | 
            +
                    transition: transform 0.3s;
         | 
| 129 | 
            +
                }
         | 
| 130 | 
            +
                .bike-card:hover {
         | 
| 131 | 
            +
                    transform: scale(1.02);
         | 
| 132 | 
            +
                }
         | 
| 133 | 
            +
            </style>
         | 
| 134 | 
            +
            """, unsafe_allow_html=True)
         | 
| 135 | 
            +
             | 
| 136 | 
            +
             | 
| 137 | 
            +
            # 7. Helper Functions
         | 
| 138 | 
            +
            def generate_filename(prompt, file_type):
         | 
| 139 | 
            +
                """Generate a safe filename using the prompt and file type."""
         | 
| 140 | 
            +
                central = pytz.timezone('US/Central')
         | 
| 141 | 
            +
                safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
         | 
| 142 | 
            +
                replaced_prompt = re.sub(r'[<>:"/\\|?*\n]', ' ', prompt)
         | 
| 143 | 
            +
                safe_prompt = re.sub(r'\s+', ' ', replaced_prompt).strip()[:230]
         | 
| 144 | 
            +
                return f"{safe_date_time}_{safe_prompt}.{file_type}"
         | 
| 145 | 
            +
             | 
| 146 | 
            +
             | 
| 147 | 
            +
             | 
| 148 | 
            +
             | 
| 149 | 
            +
            # 8. Function to create and save a file (and avoid the black hole of lost data π³)
         | 
| 150 | 
            +
            def create_file(filename, prompt, response, should_save=True):
         | 
| 151 | 
            +
                if not should_save:
         | 
| 152 | 
            +
                    return
         | 
| 153 | 
            +
                with open(filename, 'w', encoding='utf-8') as file:
         | 
| 154 | 
            +
                    file.write(prompt + "\n\n" + response)
         | 
| 155 | 
            +
            def create_and_save_file(content, file_type="md", prompt=None, is_image=False, should_save=True):
         | 
| 156 | 
            +
                """Create and save file with proper handling of different types."""
         | 
| 157 | 
            +
                if not should_save:
         | 
| 158 | 
            +
                    return None
         | 
| 159 | 
            +
                filename = generate_filename(prompt if prompt else content, file_type)
         | 
| 160 | 
            +
                with open(filename, "w", encoding="utf-8") as f:
         | 
| 161 | 
            +
                    if is_image:
         | 
| 162 | 
            +
                        f.write(content)
         | 
| 163 | 
            +
                    else:
         | 
| 164 | 
            +
                        f.write(prompt + "\n\n" + content if prompt else content)
         | 
| 165 | 
            +
                return filename
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                
         | 
| 168 | 
            +
            def get_download_link(file_path):
         | 
| 169 | 
            +
                """Create download link for file."""
         | 
| 170 | 
            +
                with open(file_path, "rb") as file:
         | 
| 171 | 
            +
                    contents = file.read()
         | 
| 172 | 
            +
                b64 = base64.b64encode(contents).decode()
         | 
| 173 | 
            +
                return f'<a href="data:file/txt;base64,{b64}" download="{os.path.basename(file_path)}">Download {os.path.basename(file_path)}π</a>'
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            @st.cache_resource
         | 
| 176 | 
            +
            def SpeechSynthesis(result):
         | 
| 177 | 
            +
                """HTML5 Speech Synthesis."""
         | 
| 178 | 
            +
                documentHTML5 = f'''
         | 
| 179 | 
            +
                <!DOCTYPE html>
         | 
| 180 | 
            +
                <html>
         | 
| 181 | 
            +
                <head>
         | 
| 182 | 
            +
                    <title>Read It Aloud</title>
         | 
| 183 | 
            +
                    <script type="text/javascript">
         | 
| 184 | 
            +
                        function readAloud() {{
         | 
| 185 | 
            +
                            const text = document.getElementById("textArea").value;
         | 
| 186 | 
            +
                            const speech = new SpeechSynthesisUtterance(text);
         | 
| 187 | 
            +
                            window.speechSynthesis.speak(speech);
         | 
| 188 | 
            +
                        }}
         | 
| 189 | 
            +
                    </script>
         | 
| 190 | 
            +
                </head>
         | 
| 191 | 
            +
                <body>
         | 
| 192 | 
            +
                    <h1>π Read It Aloud</h1>
         | 
| 193 | 
            +
                    <textarea id="textArea" rows="10" cols="80">{result}</textarea>
         | 
| 194 | 
            +
                    <br>
         | 
| 195 | 
            +
                    <button onclick="readAloud()">π Read Aloud</button>
         | 
| 196 | 
            +
                </body>
         | 
| 197 | 
            +
                </html>
         | 
| 198 | 
            +
                '''
         | 
| 199 | 
            +
                components.html(documentHTML5, width=1280, height=300)
         | 
| 200 | 
            +
             | 
| 201 | 
            +
            # Media Processing Functions
         | 
| 202 | 
            +
            def process_image(image_input, user_prompt):
         | 
| 203 | 
            +
                """Process image with GPT-4o vision."""
         | 
| 204 | 
            +
                if isinstance(image_input, str):
         | 
| 205 | 
            +
                    with open(image_input, "rb") as image_file:
         | 
| 206 | 
            +
                        image_input = image_file.read()
         | 
| 207 | 
            +
                        
         | 
| 208 | 
            +
                base64_image = base64.b64encode(image_input).decode("utf-8")
         | 
| 209 | 
            +
                
         | 
| 210 | 
            +
                response = openai_client.chat.completions.create(
         | 
| 211 | 
            +
                    model=st.session_state["openai_model"],
         | 
| 212 | 
            +
                    messages=[
         | 
| 213 | 
            +
                        {"role": "system", "content": "You are a helpful assistant that responds in Markdown."},
         | 
| 214 | 
            +
                        {"role": "user", "content": [
         | 
| 215 | 
            +
                            {"type": "text", "text": user_prompt},
         | 
| 216 | 
            +
                            {"type": "image_url", "image_url": {
         | 
| 217 | 
            +
                                "url": f"data:image/png;base64,{base64_image}"
         | 
| 218 | 
            +
                            }}
         | 
| 219 | 
            +
                        ]}
         | 
| 220 | 
            +
                    ],
         | 
| 221 | 
            +
                    temperature=0.0,
         | 
| 222 | 
            +
                )
         | 
| 223 | 
            +
                
         | 
| 224 | 
            +
                return response.choices[0].message.content
         | 
| 225 | 
            +
             | 
| 226 | 
            +
            def process_audio(audio_input, text_input=''):
         | 
| 227 | 
            +
                """Process audio with Whisper and GPT."""
         | 
| 228 | 
            +
                if isinstance(audio_input, str):
         | 
| 229 | 
            +
                    with open(audio_input, "rb") as file:
         | 
| 230 | 
            +
                        audio_input = file.read()
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                transcription = openai_client.audio.transcriptions.create(
         | 
| 233 | 
            +
                    model="whisper-1",
         | 
| 234 | 
            +
                    file=audio_input,
         | 
| 235 | 
            +
                )
         | 
| 236 | 
            +
                
         | 
| 237 | 
            +
                st.session_state.messages.append({"role": "user", "content": transcription.text})
         | 
| 238 | 
            +
                
         | 
| 239 | 
            +
                with st.chat_message("assistant"):
         | 
| 240 | 
            +
                    st.markdown(transcription.text)
         | 
| 241 | 
            +
                    SpeechSynthesis(transcription.text)
         | 
| 242 | 
            +
                    
         | 
| 243 | 
            +
                    filename = generate_filename(transcription.text, "wav")
         | 
| 244 | 
            +
                    create_and_save_file(audio_input, "wav", transcription.text, True)
         | 
| 245 | 
            +
                    
         | 
| 246 | 
            +
            # Modified video processing function without moviepy dependency
         | 
| 247 | 
            +
            def process_video(video_path, seconds_per_frame=1):
         | 
| 248 | 
            +
                """Process video files for frame extraction."""
         | 
| 249 | 
            +
                base64Frames = []
         | 
| 250 | 
            +
                video = cv2.VideoCapture(video_path)
         | 
| 251 | 
            +
                total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
         | 
| 252 | 
            +
                fps = video.get(cv2.CAP_PROP_FPS)
         | 
| 253 | 
            +
                frames_to_skip = int(fps * seconds_per_frame)
         | 
| 254 | 
            +
                
         | 
| 255 | 
            +
                for frame_idx in range(0, total_frames, frames_to_skip):
         | 
| 256 | 
            +
                    video.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
         | 
| 257 | 
            +
                    success, frame = video.read()
         | 
| 258 | 
            +
                    if not success:
         | 
| 259 | 
            +
                        break
         | 
| 260 | 
            +
                    _, buffer = cv2.imencode(".jpg", frame)
         | 
| 261 | 
            +
                    base64Frames.append(base64.b64encode(buffer).decode("utf-8"))
         | 
| 262 | 
            +
                
         | 
| 263 | 
            +
                video.release()
         | 
| 264 | 
            +
                return base64Frames, None
         | 
| 265 | 
            +
             | 
| 266 | 
            +
            def process_video_with_gpt(video_input, user_prompt):
         | 
| 267 | 
            +
                """Process video with GPT-4 vision."""
         | 
| 268 | 
            +
                base64Frames, _ = process_video(video_input)
         | 
| 269 | 
            +
                
         | 
| 270 | 
            +
                response = openai_client.chat.completions.create(
         | 
| 271 | 
            +
                    model=st.session_state["openai_model"],
         | 
| 272 | 
            +
                    messages=[
         | 
| 273 | 
            +
                        {"role": "system", "content": "Analyze the video frames and provide a detailed description."},
         | 
| 274 | 
            +
                        {"role": "user", "content": [
         | 
| 275 | 
            +
                            {"type": "text", "text": user_prompt},
         | 
| 276 | 
            +
                            *[{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{frame}"}}
         | 
| 277 | 
            +
                              for frame in base64Frames]
         | 
| 278 | 
            +
                        ]}
         | 
| 279 | 
            +
                    ]
         | 
| 280 | 
            +
                )
         | 
| 281 | 
            +
                return response.choices[0].message.content
         | 
| 282 | 
            +
             | 
| 283 | 
            +
                
         | 
| 284 | 
            +
            def extract_urls(text):
         | 
| 285 | 
            +
                try:
         | 
| 286 | 
            +
                    date_pattern = re.compile(r'### (\d{2} \w{3} \d{4})')
         | 
| 287 | 
            +
                    abs_link_pattern = re.compile(r'\[(.*?)\]\((https://arxiv\.org/abs/\d+\.\d+)\)')
         | 
| 288 | 
            +
                    pdf_link_pattern = re.compile(r'\[β¬οΈ\]\((https://arxiv\.org/pdf/\d+\.\d+)\)')
         | 
| 289 | 
            +
                    title_pattern = re.compile(r'### \d{2} \w{3} \d{4} \| \[(.*?)\]')
         | 
| 290 | 
            +
                    date_matches = date_pattern.findall(text)
         | 
| 291 | 
            +
                    abs_link_matches = abs_link_pattern.findall(text)
         | 
| 292 | 
            +
                    pdf_link_matches = pdf_link_pattern.findall(text)
         | 
| 293 | 
            +
                    title_matches = title_pattern.findall(text)
         | 
| 294 | 
            +
             | 
| 295 | 
            +
                    # markdown with the extracted fields
         | 
| 296 | 
            +
                    markdown_text = ""
         | 
| 297 | 
            +
                    for i in range(len(date_matches)):
         | 
| 298 | 
            +
                        date = date_matches[i]
         | 
| 299 | 
            +
                        title = title_matches[i]
         | 
| 300 | 
            +
                        abs_link = abs_link_matches[i][1]
         | 
| 301 | 
            +
                        pdf_link = pdf_link_matches[i]
         | 
| 302 | 
            +
                        markdown_text += f"**Date:** {date}\n\n"
         | 
| 303 | 
            +
                        markdown_text += f"**Title:** {title}\n\n"
         | 
| 304 | 
            +
                        markdown_text += f"**Abstract Link:** [{abs_link}]({abs_link})\n\n"
         | 
| 305 | 
            +
                        markdown_text += f"**PDF Link:** [{pdf_link}]({pdf_link})\n\n"
         | 
| 306 | 
            +
                        markdown_text += "---\n\n"
         | 
| 307 | 
            +
                    return markdown_text
         | 
| 308 | 
            +
                
         | 
| 309 | 
            +
                except:
         | 
| 310 | 
            +
                    st.write('.')
         | 
| 311 | 
            +
                    return ''
         | 
| 312 | 
            +
             | 
| 313 | 
            +
             | 
| 314 | 
            +
            def search_arxiv(query):
         | 
| 315 | 
            +
                
         | 
| 316 | 
            +
                st.write("Performing AI Lookup...")
         | 
| 317 | 
            +
                client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
         | 
| 318 | 
            +
                
         | 
| 319 | 
            +
                result1 = client.predict(
         | 
| 320 | 
            +
                    prompt=query,
         | 
| 321 | 
            +
                    llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
         | 
| 322 | 
            +
                    stream_outputs=True,
         | 
| 323 | 
            +
                    api_name="/ask_llm"
         | 
| 324 | 
            +
                )
         | 
| 325 | 
            +
                st.markdown("### Mixtral-8x7B-Instruct-v0.1 Result")
         | 
| 326 | 
            +
                st.markdown(result1)
         | 
| 327 | 
            +
             | 
| 328 | 
            +
                result2 = client.predict(
         | 
| 329 | 
            +
                    prompt=query,
         | 
| 330 | 
            +
                    llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
         | 
| 331 | 
            +
                    stream_outputs=True,
         | 
| 332 | 
            +
                    api_name="/ask_llm"
         | 
| 333 | 
            +
                )
         | 
| 334 | 
            +
                st.markdown("### Mistral-7B-Instruct-v0.2 Result")
         | 
| 335 | 
            +
                st.markdown(result2)
         | 
| 336 | 
            +
                combined_result = f"{result1}\n\n{result2}"
         | 
| 337 | 
            +
                return combined_result
         | 
| 338 | 
            +
             | 
| 339 | 
            +
                #return responseall
         | 
| 340 | 
            +
             | 
| 341 | 
            +
             | 
| 342 | 
            +
            # Function to generate a filename based on prompt and time (because names matter π)
         | 
| 343 | 
            +
            def generate_filename(prompt, file_type):
         | 
| 344 | 
            +
                central = pytz.timezone('US/Central')
         | 
| 345 | 
            +
                safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
         | 
| 346 | 
            +
                safe_prompt = re.sub(r'\W+', '_', prompt)[:90]
         | 
| 347 | 
            +
                return f"{safe_date_time}_{safe_prompt}.{file_type}"
         | 
| 348 | 
            +
             | 
| 349 | 
            +
            # Function to create and save a file (and avoid the black hole of lost data π³)
         | 
| 350 | 
            +
            def create_file(filename, prompt, response):
         | 
| 351 | 
            +
                with open(filename, 'w', encoding='utf-8') as file:
         | 
| 352 | 
            +
                    file.write(prompt + "\n\n" + response)
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                
         | 
| 355 | 
            +
            def perform_ai_lookup(query):
         | 
| 356 | 
            +
                start_time = time.strftime("%Y-%m-%d %H:%M:%S")
         | 
| 357 | 
            +
                client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
         | 
| 358 | 
            +
                response1 = client.predict(
         | 
| 359 | 
            +
                    query,
         | 
| 360 | 
            +
                    20,
         | 
| 361 | 
            +
                    "Semantic Search",
         | 
| 362 | 
            +
                    "mistralai/Mixtral-8x7B-Instruct-v0.1",
         | 
| 363 | 
            +
                    api_name="/update_with_rag_md"
         | 
| 364 | 
            +
                )
         | 
| 365 | 
            +
                Question = '### π ' + query + '\r\n'  # Format for markdown display with links
         | 
| 366 | 
            +
                References =  response1[0]  
         | 
| 367 | 
            +
                ReferenceLinks = extract_urls(References)
         | 
| 368 | 
            +
             | 
| 369 | 
            +
                RunSecondQuery = True
         | 
| 370 | 
            +
                results=''
         | 
| 371 | 
            +
                if RunSecondQuery:
         | 
| 372 | 
            +
                    # Search 2 - Retrieve the Summary with Papers Context and Original Query
         | 
| 373 | 
            +
                    response2 = client.predict(
         | 
| 374 | 
            +
                        query,
         | 
| 375 | 
            +
                        "mistralai/Mixtral-8x7B-Instruct-v0.1",
         | 
| 376 | 
            +
                        True,
         | 
| 377 | 
            +
                        api_name="/ask_llm"
         | 
| 378 | 
            +
                    )
         | 
| 379 | 
            +
                    if len(response2) > 10:
         | 
| 380 | 
            +
                        Answer = response2
         | 
| 381 | 
            +
                        SpeechSynthesis(Answer)
         | 
| 382 | 
            +
                        # Restructure results to follow format of Question, Answer, References, ReferenceLinks
         | 
| 383 | 
            +
                        results = Question + '\r\n' + Answer + '\r\n' + References + '\r\n' + ReferenceLinks
         | 
| 384 | 
            +
                        st.markdown(results)
         | 
| 385 | 
            +
             | 
| 386 | 
            +
                st.write('πRun of Multi-Agent System Paper Summary Spec is Complete')
         | 
| 387 | 
            +
                end_time = time.strftime("%Y-%m-%d %H:%M:%S")
         | 
| 388 | 
            +
                start_timestamp = time.mktime(time.strptime(start_time, "%Y-%m-%d %H:%M:%S"))
         | 
| 389 | 
            +
                end_timestamp = time.mktime(time.strptime(end_time, "%Y-%m-%d %H:%M:%S"))
         | 
| 390 | 
            +
                elapsed_seconds = end_timestamp - start_timestamp
         | 
| 391 | 
            +
                st.write(f"Start time: {start_time}")
         | 
| 392 | 
            +
                st.write(f"Finish time: {end_time}")
         | 
| 393 | 
            +
                st.write(f"Elapsed time: {elapsed_seconds:.2f} seconds")
         | 
| 394 | 
            +
             | 
| 395 | 
            +
                
         | 
| 396 | 
            +
                filename = generate_filename(query, "md")
         | 
| 397 | 
            +
                create_file(filename, query, results)
         | 
| 398 | 
            +
                return results
         | 
| 399 | 
            +
             | 
| 400 | 
            +
            # Chat Processing Functions
         | 
| 401 | 
            +
            def process_with_gpt(text_input):
         | 
| 402 | 
            +
                """Process text with GPT-4o."""
         | 
| 403 | 
            +
                if text_input:
         | 
| 404 | 
            +
                    st.session_state.messages.append({"role": "user", "content": text_input})
         | 
| 405 | 
            +
                    
         | 
| 406 | 
            +
                    with st.chat_message("user"):
         | 
| 407 | 
            +
                        st.markdown(text_input)
         | 
| 408 | 
            +
                    
         | 
| 409 | 
            +
                    with st.chat_message("assistant"):
         | 
| 410 | 
            +
                        completion = openai_client.chat.completions.create(
         | 
| 411 | 
            +
                            model=st.session_state["openai_model"],
         | 
| 412 | 
            +
                            messages=[
         | 
| 413 | 
            +
                                {"role": m["role"], "content": m["content"]}
         | 
| 414 | 
            +
                                for m in st.session_state.messages
         | 
| 415 | 
            +
                            ],
         | 
| 416 | 
            +
                            stream=False
         | 
| 417 | 
            +
                        )
         | 
| 418 | 
            +
                        return_text = completion.choices[0].message.content
         | 
| 419 | 
            +
                        st.write("GPT-4o: " + return_text)
         | 
| 420 | 
            +
                        
         | 
| 421 | 
            +
                        #filename = generate_filename(text_input, "md")
         | 
| 422 | 
            +
                        filename = generate_filename("GPT-4o: " + return_text, "md")
         | 
| 423 | 
            +
                        create_file(filename, text_input, return_text)
         | 
| 424 | 
            +
                        st.session_state.messages.append({"role": "assistant", "content": return_text})
         | 
| 425 | 
            +
                        return return_text
         | 
| 426 | 
            +
             | 
| 427 | 
            +
            def process_with_claude(text_input):
         | 
| 428 | 
            +
                """Process text with Claude."""
         | 
| 429 | 
            +
                if text_input:
         | 
| 430 | 
            +
             | 
| 431 | 
            +
                    with st.chat_message("user"):
         | 
| 432 | 
            +
                        st.markdown(text_input)
         | 
| 433 | 
            +
             | 
| 434 | 
            +
                    with st.chat_message("assistant"):
         | 
| 435 | 
            +
                        response = claude_client.messages.create(
         | 
| 436 | 
            +
                            model="claude-3-sonnet-20240229",
         | 
| 437 | 
            +
                            max_tokens=1000,
         | 
| 438 | 
            +
                            messages=[
         | 
| 439 | 
            +
                                {"role": "user", "content": text_input}
         | 
| 440 | 
            +
                            ]
         | 
| 441 | 
            +
                        )
         | 
| 442 | 
            +
                        response_text = response.content[0].text
         | 
| 443 | 
            +
                        st.write("Claude: " + response_text)
         | 
| 444 | 
            +
                        
         | 
| 445 | 
            +
                        #filename = generate_filename(text_input, "md")
         | 
| 446 | 
            +
                        filename = generate_filename("Claude: " + response_text, "md")
         | 
| 447 | 
            +
                        create_file(filename, text_input, response_text)
         | 
| 448 | 
            +
                        
         | 
| 449 | 
            +
                        st.session_state.chat_history.append({
         | 
| 450 | 
            +
                            "user": text_input,
         | 
| 451 | 
            +
                            "claude": response_text
         | 
| 452 | 
            +
                        })
         | 
| 453 | 
            +
                        return response_text
         | 
| 454 | 
            +
             | 
| 455 | 
            +
            # File Management Functions
         | 
| 456 | 
            +
            def load_file(file_name):
         | 
| 457 | 
            +
                """Load file content."""
         | 
| 458 | 
            +
                with open(file_name, "r", encoding='utf-8') as file:
         | 
| 459 | 
            +
                    content = file.read()
         | 
| 460 | 
            +
                return content
         | 
| 461 | 
            +
             | 
| 462 | 
            +
            def create_zip_of_files(files):
         | 
| 463 | 
            +
                """Create zip archive of files."""
         | 
| 464 | 
            +
                zip_name = "all_files.zip"
         | 
| 465 | 
            +
                with zipfile.ZipFile(zip_name, 'w') as zipf:
         | 
| 466 | 
            +
                    for file in files:
         | 
| 467 | 
            +
                        zipf.write(file)
         | 
| 468 | 
            +
                return zip_name
         | 
| 469 | 
            +
             | 
| 470 | 
            +
             | 
| 471 | 
            +
             | 
| 472 | 
            +
            def get_media_html(media_path, media_type="video", width="100%"):
         | 
| 473 | 
            +
                """Generate HTML for media player."""
         | 
| 474 | 
            +
                media_data = base64.b64encode(open(media_path, 'rb').read()).decode()
         | 
| 475 | 
            +
                if media_type == "video":
         | 
| 476 | 
            +
                    return f'''
         | 
| 477 | 
            +
                    <video width="{width}" controls autoplay muted loop>
         | 
| 478 | 
            +
                        <source src="data:video/mp4;base64,{media_data}" type="video/mp4">
         | 
| 479 | 
            +
                        Your browser does not support the video tag.
         | 
| 480 | 
            +
                    </video>
         | 
| 481 | 
            +
                    '''
         | 
| 482 | 
            +
                else:  # audio
         | 
| 483 | 
            +
                    return f'''
         | 
| 484 | 
            +
                    <audio controls style="width: {width};">
         | 
| 485 | 
            +
                        <source src="data:audio/mpeg;base64,{media_data}" type="audio/mpeg">
         | 
| 486 | 
            +
                        Your browser does not support the audio element.
         | 
| 487 | 
            +
                    </audio>
         | 
| 488 | 
            +
                    '''
         | 
| 489 | 
            +
             | 
| 490 | 
            +
            def create_media_gallery():
         | 
| 491 | 
            +
                """Create the media gallery interface."""
         | 
| 492 | 
            +
                st.header("π¬ Media Gallery")
         | 
| 493 | 
            +
                
         | 
| 494 | 
            +
                tabs = st.tabs(["πΌοΈ Images", "π΅ Audio", "π₯ Video"])
         | 
| 495 | 
            +
                
         | 
| 496 | 
            +
                with tabs[0]:
         | 
| 497 | 
            +
                    image_files = glob.glob("*.png") + glob.glob("*.jpg")
         | 
| 498 | 
            +
                    if image_files:
         | 
| 499 | 
            +
                        num_cols = st.slider("Number of columns", 1, 5, 3)
         | 
| 500 | 
            +
                        cols = st.columns(num_cols)
         | 
| 501 | 
            +
                        for idx, image_file in enumerate(image_files):
         | 
| 502 | 
            +
                            with cols[idx % num_cols]:
         | 
| 503 | 
            +
                                img = Image.open(image_file)
         | 
| 504 | 
            +
                                st.image(img, use_container_width=True)
         | 
| 505 | 
            +
                                
         | 
| 506 | 
            +
                                # Add GPT vision analysis option
         | 
| 507 | 
            +
                                if st.button(f"Analyze {os.path.basename(image_file)}"):
         | 
| 508 | 
            +
                                    analysis = process_image(image_file, 
         | 
| 509 | 
            +
                                                          "Describe this image in detail and identify key elements.")
         | 
| 510 | 
            +
                                    st.markdown(analysis)
         | 
| 511 | 
            +
                
         | 
| 512 | 
            +
                with tabs[1]:
         | 
| 513 | 
            +
                    audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
         | 
| 514 | 
            +
                    for audio_file in audio_files:
         | 
| 515 | 
            +
                        with st.expander(f"π΅ {os.path.basename(audio_file)}"):
         | 
| 516 | 
            +
                            st.markdown(get_media_html(audio_file, "audio"), unsafe_allow_html=True)
         | 
| 517 | 
            +
                            if st.button(f"Transcribe {os.path.basename(audio_file)}"):
         | 
| 518 | 
            +
                                with open(audio_file, "rb") as f:
         | 
| 519 | 
            +
                                    transcription = process_audio(f)
         | 
| 520 | 
            +
                                    st.write(transcription)
         | 
| 521 | 
            +
                
         | 
| 522 | 
            +
                with tabs[2]:
         | 
| 523 | 
            +
                    video_files = glob.glob("*.mp4")
         | 
| 524 | 
            +
                    for video_file in video_files:
         | 
| 525 | 
            +
                        with st.expander(f"π₯ {os.path.basename(video_file)}"):
         | 
| 526 | 
            +
                            st.markdown(get_media_html(video_file, "video"), unsafe_allow_html=True)
         | 
| 527 | 
            +
                            if st.button(f"Analyze {os.path.basename(video_file)}"):
         | 
| 528 | 
            +
                                analysis = process_video_with_gpt(video_file, 
         | 
| 529 | 
            +
                                                                "Describe what's happening in this video.")
         | 
| 530 | 
            +
                                st.markdown(analysis)
         | 
| 531 | 
            +
                
         | 
| 532 | 
            +
             | 
| 533 | 
            +
             | 
| 534 | 
            +
            def display_file_manager():
         | 
| 535 | 
            +
                """Display file management sidebar with guaranteed unique button keys."""
         | 
| 536 | 
            +
                st.sidebar.title("π File Management")
         | 
| 537 | 
            +
                
         | 
| 538 | 
            +
                all_files = glob.glob("*.md")
         | 
| 539 | 
            +
                all_files.sort(reverse=True)
         | 
| 540 | 
            +
             | 
| 541 | 
            +
                if st.sidebar.button("π Delete All", key="delete_all_files_button"):
         | 
| 542 | 
            +
                    for file in all_files:
         | 
| 543 | 
            +
                        os.remove(file)
         | 
| 544 | 
            +
                    st.rerun()
         | 
| 545 | 
            +
             | 
| 546 | 
            +
                if st.sidebar.button("β¬οΈ Download All", key="download_all_files_button"):
         | 
| 547 | 
            +
                    zip_file = create_zip_of_files(all_files)
         | 
| 548 | 
            +
                    st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
         | 
| 549 | 
            +
             | 
| 550 | 
            +
                # Create unique keys using file attributes
         | 
| 551 | 
            +
                for idx, file in enumerate(all_files):
         | 
| 552 | 
            +
                    # Get file stats for unique identification
         | 
| 553 | 
            +
                    file_stat = os.stat(file)
         | 
| 554 | 
            +
                    unique_id = f"{idx}_{file_stat.st_size}_{file_stat.st_mtime}"
         | 
| 555 | 
            +
                    
         | 
| 556 | 
            +
                    col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
         | 
| 557 | 
            +
                    with col1:
         | 
| 558 | 
            +
                        if st.button("π", key=f"view_{unique_id}"):
         | 
| 559 | 
            +
                            st.session_state.current_file = file
         | 
| 560 | 
            +
                            st.session_state.file_content = load_file(file)
         | 
| 561 | 
            +
                    with col2:
         | 
| 562 | 
            +
                        st.markdown(get_download_link(file), unsafe_allow_html=True)
         | 
| 563 | 
            +
                    with col3:
         | 
| 564 | 
            +
                        if st.button("π", key=f"edit_{unique_id}"):
         | 
| 565 | 
            +
                            st.session_state.current_file = file
         | 
| 566 | 
            +
                            st.session_state.file_content = load_file(file)
         | 
| 567 | 
            +
                    with col4:
         | 
| 568 | 
            +
                        if st.button("π", key=f"delete_{unique_id}"):
         | 
| 569 | 
            +
                            os.remove(file)
         | 
| 570 | 
            +
                            st.rerun()
         | 
| 571 | 
            +
             | 
| 572 | 
            +
             | 
| 573 | 
            +
             | 
| 574 | 
            +
             | 
| 575 | 
            +
            # Speech Recognition HTML Component
         | 
| 576 | 
            +
            speech_recognition_html = """
         | 
| 577 | 
            +
            <!DOCTYPE html>
         | 
| 578 | 
            +
            <html>
         | 
| 579 | 
            +
            <head>
         | 
| 580 | 
            +
                <title>Continuous Speech Demo</title>
         | 
| 581 | 
            +
                <style>
         | 
| 582 | 
            +
                    body { 
         | 
| 583 | 
            +
                        font-family: sans-serif; 
         | 
| 584 | 
            +
                        padding: 20px; 
         | 
| 585 | 
            +
                        max-width: 800px;
         | 
| 586 | 
            +
                        margin: 0 auto;
         | 
| 587 | 
            +
                    }
         | 
| 588 | 
            +
                    button { 
         | 
| 589 | 
            +
                        padding: 10px 20px; 
         | 
| 590 | 
            +
                        margin: 10px 5px;
         | 
| 591 | 
            +
                        font-size: 16px;
         | 
| 592 | 
            +
                    }
         | 
| 593 | 
            +
                    #status { 
         | 
| 594 | 
            +
                        margin: 10px 0;
         | 
| 595 | 
            +
                        padding: 10px;
         | 
| 596 | 
            +
                        background: #e8f5e9;
         | 
| 597 | 
            +
                        border-radius: 4px;
         | 
| 598 | 
            +
                    }
         | 
| 599 | 
            +
                    #output {
         | 
| 600 | 
            +
                        white-space: pre-wrap;
         | 
| 601 | 
            +
                        padding: 15px;
         | 
| 602 | 
            +
                        background: #f5f5f5;
         | 
| 603 | 
            +
                        border-radius: 4px;
         | 
| 604 | 
            +
                        margin: 10px 0;
         | 
| 605 | 
            +
                        min-height: 100px;
         | 
| 606 | 
            +
                        max-height: 400px;
         | 
| 607 | 
            +
                        overflow-y: auto;
         | 
| 608 | 
            +
                    }
         | 
| 609 | 
            +
                    .controls {
         | 
| 610 | 
            +
                        margin: 10px 0;
         | 
| 611 | 
            +
                    }
         | 
| 612 | 
            +
                </style>
         | 
| 613 | 
            +
            </head>
         | 
| 614 | 
            +
            <body>
         | 
| 615 | 
            +
                <div class="controls">
         | 
| 616 | 
            +
                    <button id="start">Start Listening</button>
         | 
| 617 | 
            +
                    <button id="stop" disabled>Stop Listening</button>
         | 
| 618 | 
            +
                    <button id="clear">Clear Text</button>
         | 
| 619 | 
            +
                </div>
         | 
| 620 | 
            +
                <div id="status">Ready</div>
         | 
| 621 | 
            +
                <div id="output"></div>
         | 
| 622 | 
            +
                
         | 
| 623 | 
            +
                <!-- Add the hidden input here -->
         | 
| 624 | 
            +
                <input type="hidden" id="streamlit-data" value="">
         | 
| 625 | 
            +
                
         | 
| 626 | 
            +
                <script>
         | 
| 627 | 
            +
                    if (!('webkitSpeechRecognition' in window)) {
         | 
| 628 | 
            +
                        alert('Speech recognition not supported');
         | 
| 629 | 
            +
                    } else {
         | 
| 630 | 
            +
                        const recognition = new webkitSpeechRecognition();
         | 
| 631 | 
            +
                        const startButton = document.getElementById('start');
         | 
| 632 | 
            +
                        const stopButton = document.getElementById('stop');
         | 
| 633 | 
            +
                        const clearButton = document.getElementById('clear');
         | 
| 634 | 
            +
                        const status = document.getElementById('status');
         | 
| 635 | 
            +
                        const output = document.getElementById('output');
         | 
| 636 | 
            +
                        let fullTranscript = '';
         | 
| 637 | 
            +
                        let lastUpdateTime = Date.now();
         | 
| 638 | 
            +
             | 
| 639 | 
            +
                        // Configure recognition
         | 
| 640 | 
            +
                        recognition.continuous = true;
         | 
| 641 | 
            +
                        recognition.interimResults = true;
         | 
| 642 | 
            +
             | 
| 643 | 
            +
                        // Function to start recognition
         | 
| 644 | 
            +
                        const startRecognition = () => {
         | 
| 645 | 
            +
                            try {
         | 
| 646 | 
            +
                                recognition.start();
         | 
| 647 | 
            +
                                status.textContent = 'Listening...';
         | 
| 648 | 
            +
                                startButton.disabled = true;
         | 
| 649 | 
            +
                                stopButton.disabled = false;
         | 
| 650 | 
            +
                            } catch (e) {
         | 
| 651 | 
            +
                                console.error(e);
         | 
| 652 | 
            +
                                status.textContent = 'Error: ' + e.message;
         | 
| 653 | 
            +
                            }
         | 
| 654 | 
            +
                        };
         | 
| 655 | 
            +
             | 
| 656 | 
            +
                        // Auto-start on load
         | 
| 657 | 
            +
                        window.addEventListener('load', () => {
         | 
| 658 | 
            +
                            setTimeout(startRecognition, 1000);
         | 
| 659 | 
            +
                        });
         | 
| 660 | 
            +
             | 
| 661 | 
            +
                        startButton.onclick = startRecognition;
         | 
| 662 | 
            +
             | 
| 663 | 
            +
                        stopButton.onclick = () => {
         | 
| 664 | 
            +
                            recognition.stop();
         | 
| 665 | 
            +
                            status.textContent = 'Stopped';
         | 
| 666 | 
            +
                            startButton.disabled = false;
         | 
| 667 | 
            +
                            stopButton.disabled = true;
         | 
| 668 | 
            +
                        };
         | 
| 669 | 
            +
             | 
| 670 | 
            +
                        clearButton.onclick = () => {
         | 
| 671 | 
            +
                            fullTranscript = '';
         | 
| 672 | 
            +
                            output.textContent = '';
         | 
| 673 | 
            +
                            window.parent.postMessage({
         | 
| 674 | 
            +
                                type: 'clear_transcript',
         | 
| 675 | 
            +
                            }, '*');
         | 
| 676 | 
            +
                        };
         | 
| 677 | 
            +
             | 
| 678 | 
            +
                        recognition.onresult = (event) => {
         | 
| 679 | 
            +
                            let interimTranscript = '';
         | 
| 680 | 
            +
                            let finalTranscript = '';
         | 
| 681 | 
            +
             | 
| 682 | 
            +
                            for (let i = event.resultIndex; i < event.results.length; i++) {
         | 
| 683 | 
            +
                                const transcript = event.results[i][0].transcript;
         | 
| 684 | 
            +
                                if (event.results[i].isFinal) {
         | 
| 685 | 
            +
                                    finalTranscript += transcript + '\\n';
         | 
| 686 | 
            +
                                } else {
         | 
| 687 | 
            +
                                    interimTranscript += transcript;
         | 
| 688 | 
            +
                                }
         | 
| 689 | 
            +
                            }
         | 
| 690 | 
            +
             | 
| 691 | 
            +
                            if (finalTranscript || (Date.now() - lastUpdateTime > 5000)) {
         | 
| 692 | 
            +
                                if (finalTranscript) {
         | 
| 693 | 
            +
                                    fullTranscript += finalTranscript;
         | 
| 694 | 
            +
                                    
         | 
| 695 | 
            +
                                    // Update the hidden input value
         | 
| 696 | 
            +
                                    document.getElementById('streamlit-data').value = fullTranscript;
         | 
| 697 | 
            +
                                }
         | 
| 698 | 
            +
                                lastUpdateTime = Date.now();
         | 
| 699 | 
            +
                            }            
         | 
| 700 | 
            +
             | 
| 701 | 
            +
                            output.textContent = fullTranscript + (interimTranscript ? '... ' + interimTranscript : '');
         | 
| 702 | 
            +
                            output.scrollTop = output.scrollHeight;
         | 
| 703 | 
            +
             | 
| 704 | 
            +
                            document.getElementById('streamlit-data').value = fullTranscript;
         | 
| 705 | 
            +
             | 
| 706 | 
            +
                        };
         | 
| 707 | 
            +
             | 
| 708 | 
            +
                        recognition.onend = () => {
         | 
| 709 | 
            +
                            if (!stopButton.disabled) {
         | 
| 710 | 
            +
                                try {
         | 
| 711 | 
            +
                                    recognition.start();
         | 
| 712 | 
            +
                                    console.log('Restarted recognition');
         | 
| 713 | 
            +
                                } catch (e) {
         | 
| 714 | 
            +
                                    console.error('Failed to restart recognition:', e);
         | 
| 715 | 
            +
                                    status.textContent = 'Error restarting: ' + e.message;
         | 
| 716 | 
            +
                                    startButton.disabled = false;
         | 
| 717 | 
            +
                                    stopButton.disabled = true;
         | 
| 718 | 
            +
                                }
         | 
| 719 | 
            +
                            }
         | 
| 720 | 
            +
                        };
         | 
| 721 | 
            +
             | 
| 722 | 
            +
                        recognition.onerror = (event) => {
         | 
| 723 | 
            +
                            console.error('Recognition error:', event.error);
         | 
| 724 | 
            +
                            status.textContent = 'Error: ' + event.error;
         | 
| 725 | 
            +
                            
         | 
| 726 | 
            +
                            if (event.error === 'not-allowed' || event.error === 'service-not-allowed') {
         | 
| 727 | 
            +
                                startButton.disabled = false;
         | 
| 728 | 
            +
                                stopButton.disabled = true;
         | 
| 729 | 
            +
                            }
         | 
| 730 | 
            +
                        };
         | 
| 731 | 
            +
                    }
         | 
| 732 | 
            +
                </script>
         | 
| 733 | 
            +
            </body>
         | 
| 734 | 
            +
            </html>
         | 
| 735 | 
            +
            """
         | 
| 736 | 
            +
             | 
| 737 | 
            +
            # Helper Functions
         | 
| 738 | 
            +
            def generate_filename(prompt, file_type):
         | 
| 739 | 
            +
                central = pytz.timezone('US/Central')
         | 
| 740 | 
            +
                safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
         | 
| 741 | 
            +
                replaced_prompt = re.sub(r'[<>:"/\\|?*\n]', ' ', prompt)
         | 
| 742 | 
            +
                safe_prompt = re.sub(r'\s+', ' ', replaced_prompt).strip()[:230]
         | 
| 743 | 
            +
                return f"{safe_date_time}_{safe_prompt}.{file_type}"
         | 
| 744 | 
            +
             | 
| 745 | 
            +
            # File Management Functions
         | 
| 746 | 
            +
            def load_file(file_name):
         | 
| 747 | 
            +
                """Load file content."""
         | 
| 748 | 
            +
                with open(file_name, "r", encoding='utf-8') as file:
         | 
| 749 | 
            +
                    content = file.read()
         | 
| 750 | 
            +
                return content
         | 
| 751 | 
            +
             | 
| 752 | 
            +
            def create_zip_of_files(files):
         | 
| 753 | 
            +
                """Create zip archive of files."""
         | 
| 754 | 
            +
                zip_name = "all_files.zip"
         | 
| 755 | 
            +
                with zipfile.ZipFile(zip_name, 'w') as zipf:
         | 
| 756 | 
            +
                    for file in files:
         | 
| 757 | 
            +
                        zipf.write(file)
         | 
| 758 | 
            +
                return zip_name
         | 
| 759 | 
            +
             | 
| 760 | 
            +
            def get_download_link(file):
         | 
| 761 | 
            +
                """Create download link for file."""
         | 
| 762 | 
            +
                with open(file, "rb") as f:
         | 
| 763 | 
            +
                    contents = f.read()
         | 
| 764 | 
            +
                b64 = base64.b64encode(contents).decode()
         | 
| 765 | 
            +
                return f'<a href="data:file/txt;base64,{b64}" download="{os.path.basename(file)}">Download {os.path.basename(file)}π</a>'
         | 
| 766 | 
            +
             | 
| 767 | 
            +
            def display_file_manager():
         | 
| 768 | 
            +
                """Display file management sidebar."""
         | 
| 769 | 
            +
                st.sidebar.title("π File Management")
         | 
| 770 | 
            +
                
         | 
| 771 | 
            +
                all_files = glob.glob("*.md")
         | 
| 772 | 
            +
                all_files.sort(reverse=True)
         | 
| 773 | 
            +
             | 
| 774 | 
            +
                if st.sidebar.button("π Delete All"):
         | 
| 775 | 
            +
                    for file in all_files:
         | 
| 776 | 
            +
                        os.remove(file)
         | 
| 777 | 
            +
                    st.rerun()
         | 
| 778 | 
            +
             | 
| 779 | 
            +
                if st.sidebar.button("β¬οΈ Download All"):
         | 
| 780 | 
            +
                    zip_file = create_zip_of_files(all_files)
         | 
| 781 | 
            +
                    st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
         | 
| 782 | 
            +
             | 
| 783 | 
            +
                for file in all_files:
         | 
| 784 | 
            +
                    col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
         | 
| 785 | 
            +
                    with col1:
         | 
| 786 | 
            +
                        if st.button("π", key="view_"+file):
         | 
| 787 | 
            +
                            st.session_state.current_file = file
         | 
| 788 | 
            +
                            st.session_state.file_content = load_file(file)
         | 
| 789 | 
            +
                    with col2:
         | 
| 790 | 
            +
                        st.markdown(get_download_link(file), unsafe_allow_html=True)
         | 
| 791 | 
            +
                    with col3:
         | 
| 792 | 
            +
                        if st.button("π", key="edit_"+file):
         | 
| 793 | 
            +
                            st.session_state.current_file = file
         | 
| 794 | 
            +
                            st.session_state.file_content = load_file(file)
         | 
| 795 | 
            +
                    with col4:
         | 
| 796 | 
            +
                        if st.button("π", key="delete_"+file):
         | 
| 797 | 
            +
                            os.remove(file)
         | 
| 798 | 
            +
                            st.rerun()
         | 
| 799 | 
            +
             | 
| 800 | 
            +
            def create_media_gallery():
         | 
| 801 | 
            +
                """Create the media gallery interface."""
         | 
| 802 | 
            +
                st.header("π¬ Media Gallery")
         | 
| 803 | 
            +
                
         | 
| 804 | 
            +
                tabs = st.tabs(["πΌοΈ Images", "π΅ Audio", "π₯ Video"])
         | 
| 805 | 
            +
                
         | 
| 806 | 
            +
                with tabs[0]:
         | 
| 807 | 
            +
                    image_files = glob.glob("*.png") + glob.glob("*.jpg")
         | 
| 808 | 
            +
                    if image_files:
         | 
| 809 | 
            +
                        num_cols = st.slider("Number of columns", 1, 5, 3)
         | 
| 810 | 
            +
                        cols = st.columns(num_cols)
         | 
| 811 | 
            +
                        for idx, image_file in enumerate(image_files):
         | 
| 812 | 
            +
                            with cols[idx % num_cols]:
         | 
| 813 | 
            +
                                img = Image.open(image_file)
         | 
| 814 | 
            +
                                st.image(img, use_container_width=True)
         | 
| 815 | 
            +
                                
         | 
| 816 | 
            +
                                # Add GPT vision analysis option
         | 
| 817 | 
            +
                                if st.button(f"Analyze {os.path.basename(image_file)}"):
         | 
| 818 | 
            +
                                    analysis = process_image(image_file, 
         | 
| 819 | 
            +
                                                          "Describe this image in detail and identify key elements.")
         | 
| 820 | 
            +
                                    st.markdown(analysis)
         | 
| 821 | 
            +
                
         | 
| 822 | 
            +
                with tabs[1]:
         | 
| 823 | 
            +
                    audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
         | 
| 824 | 
            +
                    for audio_file in audio_files:
         | 
| 825 | 
            +
                        with st.expander(f"π΅ {os.path.basename(audio_file)}"):
         | 
| 826 | 
            +
                            st.markdown(get_media_html(audio_file, "audio"), unsafe_allow_html=True)
         | 
| 827 | 
            +
                            if st.button(f"Transcribe {os.path.basename(audio_file)}"):
         | 
| 828 | 
            +
                                with open(audio_file, "rb") as f:
         | 
| 829 | 
            +
                                    transcription = process_audio(f)
         | 
| 830 | 
            +
                                    st.write(transcription)
         | 
| 831 | 
            +
                
         | 
| 832 | 
            +
                with tabs[2]:
         | 
| 833 | 
            +
                    video_files = glob.glob("*.mp4")
         | 
| 834 | 
            +
                    for video_file in video_files:
         | 
| 835 | 
            +
                        with st.expander(f"π₯ {os.path.basename(video_file)}"):
         | 
| 836 | 
            +
                            st.markdown(get_media_html(video_file, "video"), unsafe_allow_html=True)
         | 
| 837 | 
            +
                            if st.button(f"Analyze {os.path.basename(video_file)}"):
         | 
| 838 | 
            +
                                analysis = process_video_with_gpt(video_file, 
         | 
| 839 | 
            +
                                                                "Describe what's happening in this video.")
         | 
| 840 | 
            +
                                st.markdown(analysis)
         | 
| 841 | 
            +
                
         | 
| 842 | 
            +
             | 
| 843 | 
            +
             | 
| 844 | 
            +
            def get_media_html(media_path, media_type="video", width="100%"):
         | 
| 845 | 
            +
                """Generate HTML for media player."""
         | 
| 846 | 
            +
                media_data = base64.b64encode(open(media_path, 'rb').read()).decode()
         | 
| 847 | 
            +
                if media_type == "video":
         | 
| 848 | 
            +
                    return f'''
         | 
| 849 | 
            +
                    <video width="{width}" controls autoplay muted loop>
         | 
| 850 | 
            +
                        <source src="data:video/mp4;base64,{media_data}" type="video/mp4">
         | 
| 851 | 
            +
                        Your browser does not support the video tag.
         | 
| 852 | 
            +
                    </video>
         | 
| 853 | 
            +
                    '''
         | 
| 854 | 
            +
                else:  # audio
         | 
| 855 | 
            +
                    return f'''
         | 
| 856 | 
            +
                    <audio controls style="width: {width};">
         | 
| 857 | 
            +
                        <source src="data:audio/mpeg;base64,{media_data}" type="audio/mpeg">
         | 
| 858 | 
            +
                        Your browser does not support the audio element.
         | 
| 859 | 
            +
                    </audio>
         | 
| 860 | 
            +
                    '''
         | 
| 861 | 
            +
             | 
| 862 | 
            +
            @st.cache_resource
         | 
| 863 | 
            +
            def set_transcript(text):
         | 
| 864 | 
            +
                """Set transcript in session state."""
         | 
| 865 | 
            +
                st.session_state.voice_transcript = text
         | 
| 866 | 
            +
             | 
| 867 | 
            +
            def main():
         | 
| 868 | 
            +
                st.sidebar.markdown("### π²BikeAIπ Claude and GPT Multi-Agent Research AI")
         | 
| 869 | 
            +
                
         | 
| 870 | 
            +
                # Main navigation
         | 
| 871 | 
            +
                tab_main = st.radio("Choose Action:", 
         | 
| 872 | 
            +
                                    ["π€ Voice Input", "π¬ Chat", "πΈ Media Gallery", "π Search ArXiv", "π File Editor"],
         | 
| 873 | 
            +
                                    horizontal=True)
         | 
| 874 | 
            +
                
         | 
| 875 | 
            +
                if tab_main == "π€ Voice Input":
         | 
| 876 | 
            +
                    st.subheader("Voice Recognition")
         | 
| 877 | 
            +
                    
         | 
| 878 | 
            +
                    # Initialize session state for the transcript
         | 
| 879 | 
            +
                    if 'voice_transcript' not in st.session_state:
         | 
| 880 | 
            +
                        st.session_state.voice_transcript = ""
         | 
| 881 | 
            +
                    
         | 
| 882 | 
            +
                    # Display speech recognition component and capture returned value
         | 
| 883 | 
            +
                    transcript = st.components.v1.html(speech_recognition_html, height=400)
         | 
| 884 | 
            +
                    
         | 
| 885 | 
            +
                    # Update session state if there's new data
         | 
| 886 | 
            +
                    if transcript is not None and transcript != "":
         | 
| 887 | 
            +
                        st.session_state.voice_transcript = transcript
         | 
| 888 | 
            +
                    
         | 
| 889 | 
            +
                    # Display the transcript in a Streamlit text area
         | 
| 890 | 
            +
                    st.markdown("### Processed Voice Input:")
         | 
| 891 | 
            +
                    st.text_area("Voice Transcript", st.session_state.voice_transcript, height=100)
         | 
| 892 | 
            +
                    
         | 
| 893 | 
            +
                    # Add functionality to process the transcript
         | 
| 894 | 
            +
                    if st.button("Process Transcript"):
         | 
| 895 | 
            +
                        st.subheader("AI Response to Transcript")
         | 
| 896 | 
            +
                        gpt_response = process_with_gpt(st.session_state.voice_transcript)
         | 
| 897 | 
            +
                        st.markdown(gpt_response)
         | 
| 898 | 
            +
                    
         | 
| 899 | 
            +
                    # Option to clear the transcript
         | 
| 900 | 
            +
                    if st.button("Clear Transcript"):
         | 
| 901 | 
            +
                        st.session_state.voice_transcript = ""
         | 
| 902 | 
            +
                        st.rerun()
         | 
| 903 | 
            +
                        
         | 
| 904 | 
            +
             | 
| 905 | 
            +
                    # Buttons to process the transcript
         | 
| 906 | 
            +
                    if st.button("Search with GPT"):
         | 
| 907 | 
            +
                        st.subheader("GPT-4o Response")
         | 
| 908 | 
            +
                        gpt_response = process_with_gpt(st.session_state.voice_transcript)
         | 
| 909 | 
            +
                        st.markdown(gpt_response)
         | 
| 910 | 
            +
             | 
| 911 | 
            +
                    if st.button("Search with Claude"):
         | 
| 912 | 
            +
                        st.subheader("Claude Response")
         | 
| 913 | 
            +
                        claude_response = process_with_claude(st.session_state.voice_transcript)
         | 
| 914 | 
            +
                        st.markdown(claude_response)
         | 
| 915 | 
            +
             | 
| 916 | 
            +
                    if st.button("Search ArXiv"):
         | 
| 917 | 
            +
                        st.subheader("ArXiv Search Results")
         | 
| 918 | 
            +
                        arxiv_results = perform_ai_lookup(st.session_state.voice_transcript)
         | 
| 919 | 
            +
                        st.markdown(arxiv_results)
         | 
| 920 | 
            +
                        
         | 
| 921 | 
            +
                    
         | 
| 922 | 
            +
                    # Display last voice input
         | 
| 923 | 
            +
                    if st.session_state.last_voice_input:
         | 
| 924 | 
            +
                        st.text_area("Last Voice Input:", st.session_state.last_voice_input, height=100)
         | 
| 925 | 
            +
                
         | 
| 926 | 
            +
                
         | 
| 927 | 
            +
                if tab_main == "π¬ Chat":
         | 
| 928 | 
            +
                    # Model Selection
         | 
| 929 | 
            +
                    model_choice = st.sidebar.radio(
         | 
| 930 | 
            +
                        "Choose AI Model:",
         | 
| 931 | 
            +
                        ["GPT-4o", "Claude-3", "GPT+Claude+Arxiv"]
         | 
| 932 | 
            +
                    )
         | 
| 933 | 
            +
                    
         | 
| 934 | 
            +
                    # Chat Interface
         | 
| 935 | 
            +
                    user_input = st.text_area("Message:", height=100)
         | 
| 936 | 
            +
                    
         | 
| 937 | 
            +
                    if st.button("Send π¨"):
         | 
| 938 | 
            +
                        if user_input:
         | 
| 939 | 
            +
                            if model_choice == "GPT-4o":
         | 
| 940 | 
            +
                                gpt_response = process_with_gpt(user_input)
         | 
| 941 | 
            +
                            elif model_choice == "Claude-3":
         | 
| 942 | 
            +
                                claude_response = process_with_claude(user_input)
         | 
| 943 | 
            +
                            else:  # Both
         | 
| 944 | 
            +
                                col1, col2, col3 = st.columns(3)
         | 
| 945 | 
            +
                                with col2:
         | 
| 946 | 
            +
                                    st.subheader("Claude-3.5 Sonnet:")
         | 
| 947 | 
            +
                                    try:
         | 
| 948 | 
            +
                                        claude_response = process_with_claude(user_input)
         | 
| 949 | 
            +
                                    except:
         | 
| 950 | 
            +
                                        st.write('Claude 3.5 Sonnet out of tokens.')
         | 
| 951 | 
            +
                                with col1:
         | 
| 952 | 
            +
                                    st.subheader("GPT-4o Omni:")
         | 
| 953 | 
            +
                                    try:
         | 
| 954 | 
            +
                                        gpt_response = process_with_gpt(user_input)  
         | 
| 955 | 
            +
                                    except:
         | 
| 956 | 
            +
                                        st.write('GPT 4o out of tokens')
         | 
| 957 | 
            +
                                with col3:
         | 
| 958 | 
            +
                                    st.subheader("Arxiv and Mistral Research:")
         | 
| 959 | 
            +
                                    with st.spinner("Searching ArXiv..."):
         | 
| 960 | 
            +
                                        #results = search_arxiv(user_input)
         | 
| 961 | 
            +
                                        results = perform_ai_lookup(user_input)
         | 
| 962 | 
            +
                                        
         | 
| 963 | 
            +
                                        st.markdown(results)
         | 
| 964 | 
            +
                                        
         | 
| 965 | 
            +
                    # Display Chat History
         | 
| 966 | 
            +
                    st.subheader("Chat History π")
         | 
| 967 | 
            +
                    tab1, tab2 = st.tabs(["Claude History", "GPT-4o History"])
         | 
| 968 | 
            +
                    
         | 
| 969 | 
            +
                    with tab1:
         | 
| 970 | 
            +
                        for chat in st.session_state.chat_history:
         | 
| 971 | 
            +
                            st.text_area("You:", chat["user"], height=100)
         | 
| 972 | 
            +
                            st.text_area("Claude:", chat["claude"], height=200)
         | 
| 973 | 
            +
                            st.markdown(chat["claude"])
         | 
| 974 | 
            +
                    
         | 
| 975 | 
            +
                    with tab2:
         | 
| 976 | 
            +
                        for message in st.session_state.messages:
         | 
| 977 | 
            +
                            with st.chat_message(message["role"]):
         | 
| 978 | 
            +
                                st.markdown(message["content"])
         | 
| 979 | 
            +
                
         | 
| 980 | 
            +
                elif tab_main == "πΈ Media Gallery":
         | 
| 981 | 
            +
                    create_media_gallery()
         | 
| 982 | 
            +
                
         | 
| 983 | 
            +
                elif tab_main == "π Search ArXiv":
         | 
| 984 | 
            +
                    query = st.text_input("Enter your research query:")
         | 
| 985 | 
            +
                    if query:
         | 
| 986 | 
            +
                        with st.spinner("Searching ArXiv..."):
         | 
| 987 | 
            +
                            results = search_arxiv(query)
         | 
| 988 | 
            +
                            st.markdown(results)
         | 
| 989 | 
            +
                
         | 
| 990 | 
            +
                elif tab_main == "π File Editor":
         | 
| 991 | 
            +
                    if hasattr(st.session_state, 'current_file'):
         | 
| 992 | 
            +
                        st.subheader(f"Editing: {st.session_state.current_file}")
         | 
| 993 | 
            +
                        new_content = st.text_area("Content:", st.session_state.file_content, height=300)
         | 
| 994 | 
            +
                        if st.button("Save Changes"):
         | 
| 995 | 
            +
                            with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
         | 
| 996 | 
            +
                                file.write(new_content)
         | 
| 997 | 
            +
                            st.success("File updated successfully!")
         | 
| 998 | 
            +
                
         | 
| 999 | 
            +
             | 
| 1000 | 
            +
                # Always show file manager in sidebar
         | 
| 1001 | 
            +
                display_file_manager()
         | 
| 1002 | 
            +
             | 
| 1003 | 
            +
            if __name__ == "__main__":
         | 
| 1004 | 
            +
                main()
         | 
