Spaces:
Sleeping
Sleeping
File size: 6,969 Bytes
f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f 43aa251 01e771f f9c215a 01e771f f9c215a 01e771f 43aa251 01e771f 43aa251 01e771f 43aa251 01e771f 43aa251 01e771f c4a40a4 f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f f9c215a 01e771f 35c31e7 01e771f 43aa251 01e771f 43aa251 01e771f f9c215a 01e771f f9c215a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | """
Streamlit App for RAG Chatbot - Agentic AI eBook
Modern ChatGPT-style UI with chat_input at root level
"""
import os
import sys
import streamlit as st
from dotenv import load_dotenv
# Add parent directory to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Load environment variables
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.env')
load_dotenv(env_path)
# Import RAG pipeline
from app.rag_pipeline import RAGPipeline
# Page config
st.set_page_config(
page_title="Agentic AI eBook Chatbot",
page_icon="π€",
layout="centered"
)
# CSS styling
st.markdown("""
<style>
.main-title {
text-align: center;
font-size: 2.2rem;
font-weight: 700;
color: #667eea;
margin-bottom: 0.5rem;
}
.subtitle {
text-align: center;
color: #888;
margin-bottom: 1.5rem;
}
.conf-high { background: #d4edda; color: #155724; padding: 0.2rem 0.6rem; border-radius: 10px; font-size: 0.8rem; }
.conf-medium { background: #fff3cd; color: #856404; padding: 0.2rem 0.6rem; border-radius: 10px; font-size: 0.8rem; }
.conf-low { background: #f8d7da; color: #721c24; padding: 0.2rem 0.6rem; border-radius: 10px; font-size: 0.8rem; }
.source-chip { background: #e9ecef; color: #495057; padding: 0.15rem 0.5rem; border-radius: 10px; font-size: 0.75rem; margin: 0.1rem; display: inline-block; }
</style>
""", unsafe_allow_html=True)
# Session state
if "messages" not in st.session_state:
st.session_state.messages = []
if "pipeline" not in st.session_state:
st.session_state.pipeline = None
# Sidebar
with st.sidebar:
st.header("βοΈ Settings")
pinecone_key = st.text_input("Pinecone API Key", type="password", value=os.getenv("PINECONE_API_KEY", ""))
index_name = st.text_input("Pinecone Index", value=os.getenv("PINECONE_INDEX", "agentic-ai-ebook"))
groq_key = st.text_input("Groq API Key (FREE)", type="password", value=os.getenv("GROQ_API_KEY", ""))
openai_key = st.text_input("OpenAI Key (optional)", type="password", value=os.getenv("OPENAI_API_KEY", ""))
st.markdown("---")
top_k = st.slider("Chunks to retrieve", 1, 10, 6)
use_llm = st.checkbox("Use LLM", value=True)
st.markdown("---")
if st.button("π Initialize Pipeline", type="primary", use_container_width=True):
with st.spinner("Initializing..."):
try:
st.session_state.pipeline = RAGPipeline(
pinecone_api_key=pinecone_key,
index_name=index_name,
namespace="agentic-ai",
openai_api_key=openai_key if openai_key else None,
groq_api_key=groq_key if groq_key else None,
local_only=False
)
st.success("β
Ready!")
except Exception as e:
st.error(f"β {str(e)}")
if st.session_state.pipeline:
st.success("β Pipeline Ready")
else:
st.warning("β Not Initialized")
# Auto-initialize if env vars exist
if st.session_state.pipeline is None:
pk = os.getenv("PINECONE_API_KEY", "")
gk = os.getenv("GROQ_API_KEY", "")
if pk and gk:
try:
st.session_state.pipeline = RAGPipeline(
pinecone_api_key=pk,
index_name=os.getenv("PINECONE_INDEX", "agentic-ai-ebook"),
namespace="agentic-ai",
openai_api_key=os.getenv("OPENAI_API_KEY", ""),
groq_api_key=gk,
local_only=False
)
except:
pass
# Header
st.markdown('<h1 class="main-title">π€ Agentic AI Chatbot</h1>', unsafe_allow_html=True)
st.markdown('<p class="subtitle">Ask questions about the Agentic AI eBook β’ Grounded answers only</p>', unsafe_allow_html=True)
# Display chat messages
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.write(msg["content"])
if msg["role"] == "assistant" and "confidence" in msg:
conf = msg["confidence"]
conf_class = "conf-high" if conf >= 0.7 else ("conf-medium" if conf >= 0.4 else "conf-low")
st.markdown(f'<span class="{conf_class}">Confidence: {conf:.0%}</span>', unsafe_allow_html=True)
if msg.get("sources"):
sources_html = " ".join([f'<span class="source-chip">π P.{s}</span>' for s in msg["sources"][:5]])
st.markdown(f"Sources: {sources_html}", unsafe_allow_html=True)
# Sample questions if empty
if not st.session_state.messages:
st.markdown("### π‘ Try asking:")
samples = [
"What is the definition of agentic AI?",
"What are the key characteristics of agentic systems?",
"What risks does the eBook mention?",
"What safeguards are recommended?"
]
cols = st.columns(2)
for i, q in enumerate(samples):
with cols[i % 2]:
if st.button(q, key=f"s{i}", use_container_width=True):
if st.session_state.pipeline:
st.session_state.messages.append({"role": "user", "content": q})
st.rerun()
else:
st.warning("Initialize pipeline first!")
# Clear button
if st.session_state.messages:
if st.button("ποΈ Clear Chat"):
st.session_state.messages = []
st.rerun()
# Chat input - MUST be at root level (not inside any container/column)
user_input = st.chat_input("Ask a question about the Agentic AI eBook...")
if user_input:
if st.session_state.pipeline is None:
st.warning("β οΈ Please initialize the pipeline first (sidebar β Initialize)")
else:
# Add user message
st.session_state.messages.append({"role": "user", "content": user_input})
# Get response
try:
response = st.session_state.pipeline.query(user_input, top_k=top_k, use_llm=use_llm)
answer = response.get("final_answer", "No answer found.")
confidence = response.get("confidence", 0.0)
chunks = response.get("retrieved_chunks", [])
sources = sorted(set([c.get("page", "?") for c in chunks]))
st.session_state.messages.append({
"role": "assistant",
"content": answer,
"confidence": confidence,
"sources": sources
})
except Exception as e:
st.session_state.messages.append({
"role": "assistant",
"content": f"Error: {str(e)}",
"confidence": 0,
"sources": []
})
st.rerun()
# Footer
st.markdown("---")
st.markdown("""
<div style="text-align: center; color: #888; font-size: 0.8rem;">
Built with LangGraph β’ Pinecone β’ Groq β’ Streamlit
</div>
""", unsafe_allow_html=True)
|