ringdoorbell_chatbot / src /streamlit_app.py
foreversheikh's picture
Upload 8 files
ebc1af9 verified
# rag_streamlit_app.py
import streamlit as st
import os
import warnings
import re
from dotenv import load_dotenv
from chat_logic import setup_default_rag, OPENAI_KEY # Import core logic
# Suppress LangChain and other warnings for a clean Streamlit app
warnings.filterwarnings("ignore")
load_dotenv()
# --- Configuration ---
st.set_page_config(page_title="Ring App RAG Chatbot", layout="wide")
# --- Initialize Session State ---
if 'chain' not in st.session_state:
st.session_state.chain = None
if 'chat_history' not in st.session_state:
st.session_state.chat_history = []
if 'memory' not in st.session_state:
st.session_state.memory = None
if 'openai_api_key' not in st.session_state:
st.session_state.openai_api_key = OPENAI_KEY
# --- Functions for UI Actions ---
def clear_chat_history():
"""Resets the chat history and the memory buffer."""
if st.session_state.memory:
st.session_state.memory.clear()
st.session_state.chat_history = []
st.toast("Chat history cleared!", icon="🧹")
def initialize_rag_system():
"""Initializes the RAG chain using the hardcoded default file."""
if st.session_state.openai_api_key:
with st.spinner("Setting up the Ring App knowledge base..."):
try:
model = "gpt-4-turbo"
# CALL THE NEW DEFAULT SETUP FUNCTION
chain, memory = setup_default_rag(st.session_state.openai_api_key, model)
st.session_state.chain = chain
st.session_state.memory = memory
st.session_state.chat_history = []
st.toast("Ring App knowledge base loaded and chatbot ready!", icon="✅")
except FileNotFoundError as e:
st.error(f"FATAL ERROR: {e}. Please ensure 'default_rag_file.pdf' is in the script directory.")
st.session_state.chain = None
except Exception as e:
st.error(f"Error setting up RAG system: {e}")
st.session_state.chain = None
st.session_state.memory = None
elif not st.session_state.openai_api_key:
st.error("Please enter your OpenAI API Key in the sidebar.")
def generate_response(prompt):
"""Invokes the RAG chain with the user's prompt."""
if st.session_state.chain:
try:
# Invoke the chain
response = st.session_state.chain.invoke({"question": prompt})
answer = response.get("answer", "Sorry, I couldn't find an answer based only on the Ring App document.")
# Clean response logic
answer = re.sub(r'\\n|\r|\n', ' ', answer)
answer = re.sub(r'(Sources?:\s*.+$)', '', answer, flags=re.IGNORECASE)
answer = re.sub(r'\[[^\]]*\]|\([^\)]*\)', '', answer)
answer = re.sub(r'[*_#>`~\-]{1,}', ' ', answer)
answer = re.sub(r'\s{2,}', ' ', answer).strip()
# Update chat history state
st.session_state.chat_history.append({"role": "user", "content": prompt})
st.session_state.chat_history.append({"role": "assistant", "content": answer})
return answer
except Exception as e:
st.error(f"An error occurred during the conversation: {e}")
return "Sorry, there was an error processing your request."
else:
return "Please initialize the chatbot using the button in the sidebar."
# --- Streamlit UI Layout ---
st.title("Ring App Support Chatbot")
st.markdown("This RAG system is pre-loaded with knowledge about the **Ring Doorbell App**")
# Sidebar for configuration
with st.sidebar:
st.header("Configuration")
# API Key Input
st.session_state.openai_api_key = st.text_input(
"OpenAI API Key",
value=st.session_state.openai_api_key,
type="password",
help="Required to use OpenAI embeddings and models."
)
st.markdown("---")
# Initialization Button
if st.button("Initialize Chatbot", type="primary"):
initialize_rag_system()
st.caption("The chatbot will only answer from the pre-loaded Ring App documentation.")
st.markdown("---")
# Reset Button
if st.button("Clear History", help="Clears conversation memory and chat display."):
clear_chat_history()
# Check if the system is initialized and ready
if st.session_state.chain:
st.success("System Ready! Ask a question below.")
# --- Main Chat Interface ---
# Display chat messages from history
for message in st.session_state.chat_history:
with st.chat_message(message["role"]):
st.write(message["content"])
# Initial state prompt
if not st.session_state.chain and not st.session_state.chat_history:
st.info("Click **Initialize Chatbot** in the sidebar to load the default Ring App knowledge base.")
st.stop()
# Chat input box
if prompt := st.chat_input("Ask a question about Ring App setup, dashboard, or history..."):
# Immediately display user message
with st.chat_message("user"):
st.write(prompt)
# Generate and display assistant response
with st.chat_message("assistant"):
with st.spinner("Thinking..."):
response_text = generate_response(prompt)
st.write(response_text)