Update src/streamlit_app.py
Browse files- src/streamlit_app.py +14 -27
src/streamlit_app.py
CHANGED
|
@@ -74,20 +74,16 @@ def generate_dynamic_suggestions_from_toc(toc, chunks, doc_name="Document"):
|
|
| 74 |
# ==========================================================
|
| 75 |
st.markdown("""
|
| 76 |
<style>
|
| 77 |
-
div.block-container {
|
| 78 |
-
padding-top: 1rem;
|
| 79 |
-
max-width: 1100px;
|
| 80 |
-
}
|
| 81 |
h2, h3, h4 { color: #f3f4f6; font-weight: 600; }
|
| 82 |
h3 { font-size: 1.1rem; margin-bottom: 0.4rem; }
|
| 83 |
-
h4 { font-size: 1rem; margin-bottom: 0.2rem; color: #9ca3af; }
|
| 84 |
.status-line {
|
| 85 |
background: #0f172a;
|
| 86 |
border-left: 4px solid #10b981;
|
| 87 |
border-radius: 6px;
|
| 88 |
padding: 8px 14px;
|
| 89 |
color: #d1fae5;
|
| 90 |
-
margin-bottom: 0.
|
| 91 |
}
|
| 92 |
.suggest-chip {
|
| 93 |
background-color: #111827;
|
|
@@ -115,17 +111,13 @@ h4 { font-size: 1rem; margin-bottom: 0.2rem; color: #9ca3af; }
|
|
| 115 |
padding: 8px 12px;
|
| 116 |
font-size: 14px;
|
| 117 |
}
|
| 118 |
-
.stTextInput > div > div > input:focus {
|
| 119 |
-
border-color: #3b82f6;
|
| 120 |
-
box-shadow: 0 0 6px rgba(59,130,246,0.3);
|
| 121 |
-
}
|
| 122 |
.answer-box {
|
| 123 |
background: linear-gradient(135deg, #0f172a, #1e293b);
|
| 124 |
border-left: 4px solid #3b82f6;
|
| 125 |
border-radius: 8px;
|
| 126 |
padding: 16px 18px;
|
| 127 |
color: #f1f5f9;
|
| 128 |
-
margin-top: 0.
|
| 129 |
}
|
| 130 |
section.ask-block { margin-top: 0.5rem; margin-bottom: 0.2rem; }
|
| 131 |
section.answer-block { margin-top: 0.2rem; }
|
|
@@ -133,18 +125,19 @@ section.answer-block { margin-top: 0.2rem; }
|
|
| 133 |
""", unsafe_allow_html=True)
|
| 134 |
|
| 135 |
# ==========================================================
|
| 136 |
-
# π§ Sidebar
|
| 137 |
# ==========================================================
|
| 138 |
with st.sidebar:
|
| 139 |
st.markdown("### π§ Response Mode")
|
| 140 |
mode = st.radio("", ["Strict (Document-only)", "Extended (Document + general)"], index=0)
|
| 141 |
reasoning_mode = mode.startswith("Extended")
|
|
|
|
| 142 |
|
| 143 |
-
st.
|
| 144 |
-
|
| 145 |
-
chunk_size = st.slider("Chunk Size (characters)", 200, 1500, 1000, step=50)
|
| 146 |
overlap = st.slider("Chunk Overlap", 50, 200, 120, step=10)
|
| 147 |
top_k = st.slider("Top K Results", 1, 10, 5)
|
|
|
|
| 148 |
st.markdown("---")
|
| 149 |
st.caption("β¨ Built by Shubham Sharma")
|
| 150 |
|
|
@@ -179,14 +172,14 @@ if doc_choice == "-- Select --":
|
|
| 179 |
else:
|
| 180 |
if doc_choice == "Sample PDF":
|
| 181 |
temp_path = os.path.join(os.path.dirname(__file__), "sample.pdf")
|
| 182 |
-
st.
|
| 183 |
else:
|
| 184 |
uploaded_file = st.file_uploader("π Upload your PDF", type="pdf")
|
| 185 |
if uploaded_file:
|
| 186 |
temp_path = os.path.join("/tmp", uploaded_file.name)
|
| 187 |
with open(temp_path, "wb") as f:
|
| 188 |
f.write(uploaded_file.getbuffer())
|
| 189 |
-
st.
|
| 190 |
else:
|
| 191 |
temp_path = None
|
| 192 |
|
|
@@ -207,7 +200,6 @@ else:
|
|
| 207 |
with st.spinner("βοΈ Building FAISS index..."):
|
| 208 |
embeddings = cache_embeddings(os.path.basename(temp_path), chunks, embed_chunks)
|
| 209 |
index = build_faiss_index(embeddings)
|
| 210 |
-
st.markdown("<div class='status-line'>β
Document ready β you can now ask questions below.</div>", unsafe_allow_html=True)
|
| 211 |
|
| 212 |
# ----------------------------------------------------------
|
| 213 |
# π¬ Ask a Question
|
|
@@ -222,15 +214,11 @@ else:
|
|
| 222 |
if cols[i % 3].button(f"π {q}", key=f"sugg_{i}", on_click=select_suggestion, args=(q,)):
|
| 223 |
pass
|
| 224 |
|
| 225 |
-
toggle_text = "Show
|
| 226 |
if st.button(toggle_text, key="toggle_sugg"):
|
| 227 |
st.session_state.show_more = not st.session_state.show_more
|
| 228 |
st.experimental_rerun()
|
| 229 |
|
| 230 |
-
# π§ Clean version (no yellow warning)
|
| 231 |
-
if "user_query_input" not in st.session_state:
|
| 232 |
-
st.session_state.user_query_input = ""
|
| 233 |
-
|
| 234 |
user_query = st.text_input("Type your question or click one above:", key="user_query_input")
|
| 235 |
st.markdown("</section>", unsafe_allow_html=True)
|
| 236 |
|
|
@@ -238,24 +226,23 @@ else:
|
|
| 238 |
# π€ Assistant
|
| 239 |
# ----------------------------------------------------------
|
| 240 |
if user_query.strip():
|
| 241 |
-
with st.spinner("π
|
| 242 |
retrieved = retrieve_chunks(user_query, index, chunks, top_k=top_k, embeddings=embeddings)
|
| 243 |
answer = generate_answer(user_query, retrieved, reasoning_mode=reasoning_mode)
|
| 244 |
|
| 245 |
st.markdown("<section class='answer-block'>", unsafe_allow_html=True)
|
| 246 |
st.subheader("Assistant")
|
| 247 |
st.markdown(f"<div class='answer-box'>π‘ {answer}</div>", unsafe_allow_html=True)
|
| 248 |
-
st.caption("Strict mode = document-only; Extended = may include general context.")
|
| 249 |
st.markdown("</section>", unsafe_allow_html=True)
|
| 250 |
|
| 251 |
-
with st.expander("
|
| 252 |
for i, r in enumerate(retrieved, start=1):
|
| 253 |
st.markdown(f"**Chunk {i}:** {r}")
|
| 254 |
|
| 255 |
# ----------------------------------------------------------
|
| 256 |
# π Explore Document
|
| 257 |
# ----------------------------------------------------------
|
| 258 |
-
with st.expander("
|
| 259 |
if toc:
|
| 260 |
st.markdown("**Table of Contents**")
|
| 261 |
toc_text = "\n".join([f"{sec}. {title}" for sec, title in toc])
|
|
|
|
| 74 |
# ==========================================================
|
| 75 |
st.markdown("""
|
| 76 |
<style>
|
| 77 |
+
div.block-container { padding-top: 1rem; max-width: 1100px; }
|
|
|
|
|
|
|
|
|
|
| 78 |
h2, h3, h4 { color: #f3f4f6; font-weight: 600; }
|
| 79 |
h3 { font-size: 1.1rem; margin-bottom: 0.4rem; }
|
|
|
|
| 80 |
.status-line {
|
| 81 |
background: #0f172a;
|
| 82 |
border-left: 4px solid #10b981;
|
| 83 |
border-radius: 6px;
|
| 84 |
padding: 8px 14px;
|
| 85 |
color: #d1fae5;
|
| 86 |
+
margin-bottom: 0.6rem;
|
| 87 |
}
|
| 88 |
.suggest-chip {
|
| 89 |
background-color: #111827;
|
|
|
|
| 111 |
padding: 8px 12px;
|
| 112 |
font-size: 14px;
|
| 113 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
.answer-box {
|
| 115 |
background: linear-gradient(135deg, #0f172a, #1e293b);
|
| 116 |
border-left: 4px solid #3b82f6;
|
| 117 |
border-radius: 8px;
|
| 118 |
padding: 16px 18px;
|
| 119 |
color: #f1f5f9;
|
| 120 |
+
margin-top: 0.5rem;
|
| 121 |
}
|
| 122 |
section.ask-block { margin-top: 0.5rem; margin-bottom: 0.2rem; }
|
| 123 |
section.answer-block { margin-top: 0.2rem; }
|
|
|
|
| 125 |
""", unsafe_allow_html=True)
|
| 126 |
|
| 127 |
# ==========================================================
|
| 128 |
+
# π§ Sidebar (simplified)
|
| 129 |
# ==========================================================
|
| 130 |
with st.sidebar:
|
| 131 |
st.markdown("### π§ Response Mode")
|
| 132 |
mode = st.radio("", ["Strict (Document-only)", "Extended (Document + general)"], index=0)
|
| 133 |
reasoning_mode = mode.startswith("Extended")
|
| 134 |
+
st.caption("Strict = answers only from the document. Extended = may include helpful general info.")
|
| 135 |
|
| 136 |
+
with st.expander("βοΈ Advanced Settings (for developers)", expanded=False):
|
| 137 |
+
chunk_size = st.slider("Chunk Size", 200, 1500, 1000, step=50)
|
|
|
|
| 138 |
overlap = st.slider("Chunk Overlap", 50, 200, 120, step=10)
|
| 139 |
top_k = st.slider("Top K Results", 1, 10, 5)
|
| 140 |
+
|
| 141 |
st.markdown("---")
|
| 142 |
st.caption("β¨ Built by Shubham Sharma")
|
| 143 |
|
|
|
|
| 172 |
else:
|
| 173 |
if doc_choice == "Sample PDF":
|
| 174 |
temp_path = os.path.join(os.path.dirname(__file__), "sample.pdf")
|
| 175 |
+
st.markdown("<div class='status-line'>π Using built-in Sample PDF β ready to query below.</div>", unsafe_allow_html=True)
|
| 176 |
else:
|
| 177 |
uploaded_file = st.file_uploader("π Upload your PDF", type="pdf")
|
| 178 |
if uploaded_file:
|
| 179 |
temp_path = os.path.join("/tmp", uploaded_file.name)
|
| 180 |
with open(temp_path, "wb") as f:
|
| 181 |
f.write(uploaded_file.getbuffer())
|
| 182 |
+
st.markdown(f"<div class='status-line'>β
'{uploaded_file.name}' uploaded successfully β ready to query below.</div>", unsafe_allow_html=True)
|
| 183 |
else:
|
| 184 |
temp_path = None
|
| 185 |
|
|
|
|
| 200 |
with st.spinner("βοΈ Building FAISS index..."):
|
| 201 |
embeddings = cache_embeddings(os.path.basename(temp_path), chunks, embed_chunks)
|
| 202 |
index = build_faiss_index(embeddings)
|
|
|
|
| 203 |
|
| 204 |
# ----------------------------------------------------------
|
| 205 |
# π¬ Ask a Question
|
|
|
|
| 214 |
if cols[i % 3].button(f"π {q}", key=f"sugg_{i}", on_click=select_suggestion, args=(q,)):
|
| 215 |
pass
|
| 216 |
|
| 217 |
+
toggle_text = "Show all sample questions β²" if st.session_state.show_more else "Show all sample questions βΌ"
|
| 218 |
if st.button(toggle_text, key="toggle_sugg"):
|
| 219 |
st.session_state.show_more = not st.session_state.show_more
|
| 220 |
st.experimental_rerun()
|
| 221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
user_query = st.text_input("Type your question or click one above:", key="user_query_input")
|
| 223 |
st.markdown("</section>", unsafe_allow_html=True)
|
| 224 |
|
|
|
|
| 226 |
# π€ Assistant
|
| 227 |
# ----------------------------------------------------------
|
| 228 |
if user_query.strip():
|
| 229 |
+
with st.spinner("π Generating response..."):
|
| 230 |
retrieved = retrieve_chunks(user_query, index, chunks, top_k=top_k, embeddings=embeddings)
|
| 231 |
answer = generate_answer(user_query, retrieved, reasoning_mode=reasoning_mode)
|
| 232 |
|
| 233 |
st.markdown("<section class='answer-block'>", unsafe_allow_html=True)
|
| 234 |
st.subheader("Assistant")
|
| 235 |
st.markdown(f"<div class='answer-box'>π‘ {answer}</div>", unsafe_allow_html=True)
|
|
|
|
| 236 |
st.markdown("</section>", unsafe_allow_html=True)
|
| 237 |
|
| 238 |
+
with st.expander("π§© See Source Passages"):
|
| 239 |
for i, r in enumerate(retrieved, start=1):
|
| 240 |
st.markdown(f"**Chunk {i}:** {r}")
|
| 241 |
|
| 242 |
# ----------------------------------------------------------
|
| 243 |
# π Explore Document
|
| 244 |
# ----------------------------------------------------------
|
| 245 |
+
with st.expander("π View Original Document Content"):
|
| 246 |
if toc:
|
| 247 |
st.markdown("**Table of Contents**")
|
| 248 |
toc_text = "\n".join([f"{sec}. {title}" for sec, title in toc])
|