-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.py
More file actions
194 lines (152 loc) · 6.04 KB
/
Copy pathapp.py
File metadata and controls
194 lines (152 loc) · 6.04 KB
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
190
191
192
193
194
"""
RAG Chatbot Application
=======================
DAY 4: Main Streamlit application entry point.
This is the main file that brings everything together!
Run with: streamlit run app.py
"""
import streamlit as st
# Import configuration and validate settings
from config.settings import settings
# Validate API keys before anything else
try:
settings.validate()
except ValueError as e:
st.error(f"⚠️ Configuration Error:\n\n{str(e)}")
st.stop()
# Import UI components
from ui.components import (
init_session_state,
display_chat_history,
add_message,
display_sidebar_info,
display_file_uploader,
display_processing_status,
)
from ui.chat_interface import ChatInterface
def _display_evidence_tabs(sources: dict):
"""Display a compact evidence panel (no tabs)."""
st.markdown("**Sources & Evidence**")
st.divider()
# Document sources
if sources.get("document_sources"):
st.markdown("**Document Sources:**")
for doc in sources["document_sources"]:
with st.expander(f"📄 {doc['name']}"):
st.markdown(f"**Source:** {doc['name']}")
st.markdown(f"**Preview:** {doc['content_preview']}")
else:
st.markdown("**Document Sources:** None")
st.divider()
# Web sources
if sources.get("web_sources"):
st.markdown("**Web Sources:**")
for web in sources["web_sources"]:
with st.expander(f"🌐 {web.get('title','No title')[:60]}..."):
st.markdown(f"**Title:** {web.get('title','No title')}")
st.markdown(f"**URL:** {web.get('url','')}")
st.markdown(f"**Preview:** {web.get('content_preview','')}")
if web.get('url'):
st.markdown(f"[🔗 Open Link]({web.get('url')})")
else:
st.markdown("**Web Sources:** None")
st.divider()
# Routing & relevance
routing = sources.get("routing", {})
if routing:
if routing.get("category") == "document":
st.markdown("📄 **Document-only search**")
elif routing.get("category") == "web":
st.markdown("🌐 **Web-only search**")
else:
st.markdown("🔀 **Hybrid search** (documents + web)")
st.markdown(f"**Reason:** {routing.get('reason','')}")
# Show relevance evaluation if available
relevance = routing.get("relevance_check")
if relevance:
confidence_color = {
"HIGH": "🟢",
"MEDIUM": "🟡",
"LOW": "🔴"
}.get(relevance.get("confidence"), "⚪")
st.markdown(f"**Local Content Relevance:** {confidence_color} {relevance.get('confidence')}")
st.markdown(f"**Evaluation:** {relevance.get('reason')}")
st.markdown(f"**Confidence Score:** {relevance.get('score',0):.1f}/1.0")
# Page configuration
st.set_page_config(
page_title="RAG Chatbot",
page_icon="🤖",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for better appearance
st.markdown("""
<style>
.stApp {
max-width: 1200px;
margin: 0 auto;
}
</style>
""", unsafe_allow_html=True)
def main():
"""Main application function."""
# Initialize session state
init_session_state()
# Initialize chat interface (cached in session state)
if "chat_interface" not in st.session_state:
st.session_state.chat_interface = ChatInterface()
chat = st.session_state.chat_interface
# Display sidebar
display_sidebar_info()
# Main content area
st.title("RAG Chatbot")
st.markdown("Chat with your documents using AI")
# File upload section
with st.expander("Upload Documents", expanded=not st.session_state.vector_store_initialized):
uploaded_files = display_file_uploader()
if uploaded_files:
# Process button
if st.button("Process Documents", type="primary"):
with st.spinner("Processing documents..."):
try:
num_chunks = chat.process_uploaded_files(uploaded_files)
display_processing_status(
f"Processed {len(uploaded_files)} file(s) into {num_chunks} chunks!",
"success"
)
except Exception as e:
display_processing_status(f"Error: {str(e)}", "error")
# Web search toggle (fixed in sidebar); read value from session state
use_web_search = st.session_state.get("use_web_search", False)
st.divider()
# Display chat history
display_chat_history()
# Chat input
if prompt := st.chat_input("Ask a question about your documents..."):
# Add user message
add_message("user", prompt)
# Display user message
with st.chat_message("user"):
st.markdown(prompt)
# Generate and display assistant response
with st.chat_message("assistant"):
try:
# Stream the response
response_placeholder = st.empty()
full_response = ""
for chunk in chat.get_response(prompt, use_web_search=use_web_search):
full_response += chunk
response_placeholder.markdown(full_response)
# Get detailed sources
sources = chat.get_sources(prompt, use_web_search=use_web_search)
# Display evidence tabs
if sources["document_sources"] or sources["web_sources"]:
_display_evidence_tabs(sources)
# Add assistant message to history
add_message("assistant", full_response, sources)
except Exception as e:
error_msg = f"Error generating response: {str(e)}"
st.error(error_msg)
add_message("assistant", error_msg)
if __name__ == "__main__":
main()