import streamlit as st import time import datetime import os from models import load_llm from chains import build_chat_chain, build_rag_chain, build_quiz_chain from vectorstore import get_retriever, add_document from utils import load_bible, cloze_text, translate_text from storage import init_db, add_memory_card, get_cards # App Title st.title("AbideVerse ✝️🌿") st.markdown("*Your Daily AI-Powered Bible Verse Companion*") st.set_page_config(page_title="AbideVerse – Your Daily AI-Powered Bible Verse Companion") # -------- Helper: Initialize the storage -------- init_db() if "first_load" not in st.session_state: st.session_state.first_load = True # Initialize session state if "last_provider" not in st.session_state: st.session_state.last_provider = None if "last_model" not in st.session_state: st.session_state.last_model = None # Track active tab in session state (default = first tab) if "active_tab" not in st.session_state: st.session_state.active_tab = "πŸ’¬ Chat" # default if st.session_state.first_load: st.markdown("#### ✝️🌿 Welcome to AbideVerse") st.markdown("> ✝️ *β€œAbide in me, and I in you. As the branch cannot bear fruit by itself, unless it abides in the vine, neither can you, unless you abide in me.” (John 15:4, ESV)*") st.session_state.first_load = False # -------- Helper: Translation wrapper -------- def maybe_translate(text): lang_map = { "English": "en", "Traditional Chinese": "zh-TW", "Simplified Chinese": "zh-CN" } return translate_text(text, lang_map.get(language)) if language != "English" else text # ---------------- Sidebar Settings ---------------- st.sidebar.header("βš™οΈ Settings") # Step 1: Provider selection #provider = st.sidebar.selectbox("LLM Provider", ["ollama", "huggingface", "openai", "gemini", "anthropic"],) provider = st.sidebar.selectbox("🧠 LLM Provider", ["ollama"]) # Step 2: Dynamically show model options based on provider if provider == "ollama": model_name = st.sidebar.selectbox("πŸͺΆ Ollama Model", ["tinyllama", "llama3"]) elif provider == "huggingface": model_name = st.sidebar.selectbox("🧬 Hugging Face Model", [ "TinyLlama/TinyLlama-1.1B-Chat-v1.0", "Qwen/Qwen1.5-1.8B-Chat", "mistralai/Mistral-7B-Instruct", "microsoft/Phi-3-medium-4k-instruct", "google/gemma-2-9b-it", "tiiuae/falcon-rw-1b", "google/flan-t5-small" ]) elif provider == "openai": model_name = st.sidebar.selectbox("🌐 OpenAI Model", ["gpt-3.5-turbo", "gpt-4"]) elif provider == "gemini": model_name = st.sidebar.selectbox("🌐 OpenAI Model", ["gemini-1.5-pro"]) elif provider == "anthropic": model_name = st.sidebar.selectbox("🌐 OpenAI Model", ["claude-3-opus"]) else: model_name = None # fallback language = st.sidebar.selectbox("Language", ["English", "Traditional Chinese", "Simplified Chinese"]) # --- Detect change and clear cache --- if provider != st.session_state.last_provider or model_name != st.session_state.last_model: st.cache_resource.clear() st.session_state.last_provider = provider st.session_state.last_model = model_name # ====================================================== # ---------------- Main LLMs start here ---------------- # ====================================================== # Display the selections #st.markdown(f"**Provider:** {provider} | **Model:** {model_name} | **Language:** {language}") llm = load_llm(provider, model_name) # ---------------------------------------------- # ---------------- Tab Handlers ---------------- # ---------------------------------------------- # ---------------- Chat starts here ---------------- def chat_tab(): st.subheader("Conversational Bible Chat") user_msg = st.text_input("Ask AbideVerse anything:") if st.button("Send") and user_msg: chat_chain = build_chat_chain(llm) response = chat_chain.invoke({"message": user_msg}) st.write(maybe_translate(response)) # ---------------- RAG Bible Q&A starts here ---------------- def rag_tab(): st.subheader("RAG Bible Q&A") doc = st.text_area("Paste Bible notes or devotional text to index:") if st.button("Add to RAG Store"): add_document(doc) st.success("Added to vectorstore!") question = st.text_input("Ask a question from your documents:") if st.button("RAG Search"): retriever = get_retriever(provider) rag_chain = build_rag_chain(llm, retriever) answer = rag_chain.invoke(question) st.write(maybe_translate(answer)) # ---------------- Bible Memorization starts here ---------------- def memorize_tab(): st.subheader("Bible Memorization") bible = load_bible() verse = st.selectbox("Choose a verse:", list(bible.values())) if st.button("Generate Cloze Quiz"): cloze = cloze_text(verse) add_memory_card(verse, cloze) st.cache_data.clear() # Clear cache so new card shows up st.code(cloze) st.write("πŸ“˜ Saved Memory Cards:") for card in get_cards(): st.write(f"- {card[2]}") # ---------------- Daily Devotion (AI Generated) starts here ---------------- def devotion_tab(): st.subheader("Daily Devotion (AI Generated)") verse = st.text_input("Enter a verse to reflect on:") if st.button("Generate Devotion"): chain = build_chat_chain(llm) prompt = f"Create a short devotion based on this verse: {verse}" text = chain.invoke({"message": prompt}) st.write(maybe_translate(text)) # ---------------- joyolord starts here ---------------- def joyolord_tab(): st.subheader("δΈ»ηš„ε–œζ¨‚ | 笑裑藏道") st.markdown("[ε•Ÿε‹•γ€ŒδΈ»ηš„ε–œζ¨‚ | 笑裑藏道」App (Launch Joyolord App)](https://joyolordapp.web.app/)") # ---------------- ✝️πŸͺ”πŸŒΏ Spiritual Prep starts here ---------------- def spiritual_prep_tab(): st.subheader("Spiritual Prep ✝️🌿") st.markdown("🌿 *Prepare AbideVerse for a spiritually and technically ready experience.*") st.markdown("✝️ **β€œAbide in me, and I in you…” (John 15:4, ESV)**") st.markdown("---") if st.button("πŸ”₯ Warm Cache"): _ = load_llm(provider, model_name) _ = build_chat_chain(load_llm(provider, model_name)) _ = load_bible() st.success("Cache warmed!") if st.button("πŸ§ͺ Test Response"): try: start = time.time() llm_instance = load_llm(provider, model_name) test_chain = build_chat_chain(llm_instance) test_prompt = "Summarize John 1:1 in one sentence." test_output = test_chain.invoke({"message": test_prompt}) duration = time.time() - start st.markdown("**Test Output:**") st.write(maybe_translate(test_output)) st.markdown(f"**⏱️ Response Time:** {duration:.2f} seconds") st.markdown(f"**πŸ” Model Used:** `{provider}` – `{model_name}`") except Exception as e: st.error(f"Test failed: {e}") if st.button("πŸ“– Preload Verse"): try: bible = load_bible() preload_key = "John 1:1" preload_verse = bible.get(preload_key, "In the beginning was the Word...") cloze = cloze_text(preload_verse) add_memory_card(preload_verse, cloze) st.cache_data.clear() st.success(f"Preloaded verse: {preload_key}") st.code(cloze) except Exception as e: st.error(f"Preload failed: {e}") if st.button("🧹 Clear Cache"): st.cache_data.clear() st.cache_resource.clear() st.session_state["last_cache_clear"] = f"πŸ•’ Cleared at {time.strftime('%H:%M:%S')}" st.session_state["first_load"] = True st.success("Cache cleared!") if "last_cache_clear" in st.session_state: st.markdown(st.session_state["last_cache_clear"]) # ---------------- Settings starts here ---------------- def settings_tab(): st.subheader("App Settings") st.markdown("Global app configuration is managed in the sidebar.") st.markdown(f""" - 🧠 **LLM Provider:** {provider} - πŸͺΆ **Model:** {model_name} - 🌐 **Language / translation:** {language} - βš™οΈ **Theme & layout**: (future) """) # ---------------- Tab Registry ---------------- tabs_config = [ ("πŸ’¬ Chat", chat_tab), ("πŸ“š RAG", rag_tab), ("🧠 Memorize", memorize_tab), ("πŸŒ… Devotions", devotion_tab), ("😊 δΈ»ηš„ε–œζ¨‚", joyolord_tab), ("πŸ•ŠοΈ Spiritual Prep", spiritual_prep_tab), # NEW ("πŸ”§ App Setting", settings_tab), ] # ---------------- Tab Rendering ---------------- tab_labels = [label for label, _ in tabs_config] tab_objects = st.tabs(tab_labels) for tab_obj, (label, handler) in zip(tab_objects, tabs_config): with tab_obj: handler() # render each tab