import streamlit as st import os from typing import Optional, List from dotenv import load_dotenv import gdown import llm_providers import tantivy_search import json import zipfile import agent INDEX_PATH = "./index" # Load environment variables load_dotenv() class SearchAgentUI: index_path = INDEX_PATH gdrive_index_id = os.getenv("GDRIVE_INDEX_ID", "1lpbBCPimwcNfC0VZOlQueA4SHNGIp5_t") @st.cache_resource def get_agent(_self,api_keys): index_path = INDEX_PATH return agent.Agent(index_path,api_keys) def download_index_from_gdrive(self) -> bool: try: zip_path = "index.zip" url = f"https://drive.google.com/uc?id={self.gdrive_index_id}" gdown.download(url, zip_path, quiet=False) with zipfile.ZipFile(zip_path, 'r') as zip_ref: zip_ref.extractall(".") os.remove(zip_path) return True except Exception as e: st.error(f"Failed to download index: {str(e)}") return False @st.cache_resource def initialize_system(_self,api_keys:dict[str,str]) -> tuple[bool, str, List[str]]: try: # download index if not os.path.exists(_self.index_path): st.warning("Index folder not found. Attempting to download from Google Drive...") if not _self.download_index_from_gdrive(): return False, "שגיאה: לא ניתן להוריד את האינדקס", [] st.success("Index downloaded successfully!") _self.llm_providers = llm_providers.LLMProvider(api_keys) available_providers = _self.llm_providers.get_available_providers() if not available_providers: return False, "שגיאה: לא נמצאו ספקי AI זמינים. אנא הזן מפתח API אחד לפחות.", [] return True, "המערכת מוכנה לחי শবפש", available_providers except Exception as ex: return False, f"שגיאה באתחול המערכת: {str(ex)}", [] def update_messages(self, messages): st.session_state.messages = messages def main(self): st.set_page_config( page_title="איתוריא", layout="wide", initial_sidebar_state="expanded" ) # Enhanced styling with better visual hierarchy and modern design st.markdown(""" """, unsafe_allow_html=True) # Initialize session state for message deduplication if "messages" not in st.session_state: st.session_state.messages = [] st.session_state.api_keys = { 'Gemimi': "", 'Claude': "", 'ChatGPT': "" } # Sidebar settings with st.sidebar: st.title("הגדרות") st.subheader("הגדרת מפתחות API") # API Key inputs with improved styling for provider, label in [ ('Gemimi', 'Google API Key'), ('ChatGPT', 'OpenAI API Key'), ('Claude', 'Anthropic API Key') ]: key = st.text_input( label, value=st.session_state.api_keys[provider], type="password", key=f"{provider}_key", help=f"הזן את מפתח ה-API של {label}" ) st.session_state.api_keys[provider] = key # Provider-specific links links = { 'Gemimi': 'https://aistudio.google.com/app/apikey', 'ChatGPT': 'https://platform.openai.com/account/api-keys', 'Claude': 'https://console.anthropic.com/' } st.html(f' ניתן להשיג מפתח כאן ') st.markdown("---") # Initialize system success, status_msg, available_providers = self.initialize_system(st.session_state.api_keys) if not success: st.error(status_msg) return import agent agent = self.get_agent(st.session_state.api_keys) # Provider selection in sidebar with st.sidebar: if st.button("צ'אט חדש"): st.session_state.messages = [] agent.clear_chat() if 'provider' not in st.session_state or st.session_state.provider not in available_providers: st.session_state.provider = available_providers[0] provider = st.selectbox( "ספק בינה מלאכותית", options=available_providers, key='provider', help="בחר את מודל הAI לשימוש (רק מודלים עם מפתח API זמין יוצגו)" ) if agent: agent.set_llm(provider) # Main chat interface query = st.chat_input("הזן שאלה", key="chat_input") if query: stream = agent.chat(query) for chunk in stream: st.session_state.messages = chunk["messages"] for message in st.session_state.messages: if message.type == "tool": if message.name == "search": results =json.loads(message.content) if message.content else [] with st.expander(f"🔍 תוצאות חיפוש: {len(results)}"): for result in results: st.write(result['reference']) st.info(result['text']) elif message.name == "read_text": st.expander(f"📝 טקסט: {message.content}") elif message.type == "ai": if message.content: with st.chat_message(message.type): if isinstance(message.content, list): for item in message.content: st.write(item) else: st.write(message.content) for tool_call in message.tool_calls: with st.expander(f"🛠️ שימוש בכלי: {tool_call['name']}"): st.json(tool_call["args"]) else: # user message with st.chat_message(message.type): st.write(message.content) if __name__ == "__main__": app = SearchAgentUI() app.main()