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()