import streamlit as st import streamlit.components.v1 as components import asyncio import edge_tts import os import base64 import json from datetime import datetime from typing import Optional, Dict, List import glob # Configure page st.set_page_config( page_title="Research Assistant", page_icon="🔬", layout="wide", initial_sidebar_state="expanded" ) # Initialize session state if 'current_query' not in st.session_state: st.session_state.current_query = '' if 'last_response' not in st.session_state: st.session_state.last_response = '' if 'audio_queue' not in st.session_state: st.session_state.audio_queue = [] if 'mermaid_history' not in st.session_state: st.session_state.mermaid_history = [] # Custom CSS st.markdown(""" """, unsafe_allow_html=True) def generate_mermaid_html(mermaid_code: str, height: int = 400) -> str: """Generate responsive Mermaid diagram HTML with click handling.""" return f"""
{mermaid_code}
""" async def generate_speech(text: str, voice: str = "en-US-AriaNeural") -> Optional[str]: """Generate speech using Edge TTS.""" if not text.strip(): return None timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") output_file = f"speech_{timestamp}.mp3" communicate = edge_tts.Communicate(text, voice) await communicate.save(output_file) return output_file def process_arxiv_search(query: str) -> Dict: """Process Arxiv search with your existing research code.""" # Integrate your Arxiv search code here # This is a placeholder that simulates a response return { "title": "Sample Research Paper", "abstract": "This is a sample abstract...", "authors": ["Author 1", "Author 2"], "url": "https://arxiv.org/abs/..." } def create_audio_player(file_path: str) -> str: """Create an HTML audio player with download button.""" with open(file_path, "rb") as audio_file: audio_bytes = audio_file.read() audio_b64 = base64.b64encode(audio_bytes).decode() return f"""
Download Audio
""" def handle_node_click(node_id: str): """Handle Mermaid diagram node clicks.""" # Convert node ID to search query query = node_id.replace('_', ' ') # Perform search results = process_arxiv_search(query) # Generate speech from results asyncio.run(generate_speech(results['abstract'])) # Update session state st.session_state.current_query = query st.session_state.last_response = results # Main Mermaid diagram definition RESEARCH_DIAGRAM = """ graph TD A[Literature Review] --> B[Data Analysis] B --> C[Results] C --> D[Conclusions] click A callback "Research Methodology" click B callback "Statistical Analysis" click C callback "Research Findings" click D callback "Research Impact" style A fill:#f9f,stroke:#333,stroke-width:4px style B fill:#bbf,stroke:#333,stroke-width:4px style C fill:#bfb,stroke:#333,stroke-width:4px style D fill:#fbb,stroke:#333,stroke-width:4px """ def main(): st.title("📚 Research Assistant") # Sidebar configuration st.sidebar.header("Configuration") voice_option = st.sidebar.selectbox( "Select Voice", ["en-US-AriaNeural", "en-US-GuyNeural", "en-GB-SoniaNeural"] ) # Main layout col1, col2 = st.columns([2, 3]) with col1: st.subheader("Research Map") components.html( generate_mermaid_html(RESEARCH_DIAGRAM), height=500, scrolling=True ) st.markdown("### Recent Searches") for query in st.session_state.mermaid_history[-5:]: st.info(query) with col2: st.subheader("Research Results") # Manual search option search_query = st.text_input("Enter search query:") if st.button("Search"): handle_node_click(search_query) # Display current results if st.session_state.last_response: with st.container(): st.markdown("#### Latest Results") st.json(st.session_state.last_response) # Audio playback audio_files = glob.glob("speech_*.mp3") if audio_files: latest_audio = max(audio_files, key=os.path.getctime) st.markdown(create_audio_player(latest_audio), unsafe_allow_html=True) # Cleanup old audio files for file in glob.glob("speech_*.mp3")[:-5]: # Keep only last 5 files try: os.remove(file) except: pass if __name__ == "__main__": main()