Darayut commited on
Commit
5d9de5b
Β·
verified Β·
1 Parent(s): 3298436

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +182 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,184 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import os
3
+ import shutil
4
+ import fitz # PyMuPDF
5
+ from simple_rag import generate_data_store, ask_question, DATA_PATH, CHROMA_PATH # <- Added CHROMA_PATH
6
 
7
+ # --- Page Configuration ---
8
+ st.set_page_config(page_title="DocChat", layout="wide")
9
+
10
+ # --- DARK MODE STYLING ---
11
+ st.markdown("""
12
+ <style>
13
+ body { background-color: var(--background-color); }
14
+ .stChatBubble {
15
+ padding: 0.8rem 1rem;
16
+ border-radius: 0.6rem;
17
+ margin-bottom: 1rem;
18
+ }
19
+ .user {
20
+ background-color: var(--primary-color-bg);
21
+ border-left: 4px solid #4285F4;
22
+ }
23
+ .bot {
24
+ background-color: var(--secondary-color-bg);
25
+ border-left: 4px solid #34A853;
26
+ }
27
+ .context {
28
+ font-size: 0.9rem;
29
+ color: var(--text-color);
30
+ }
31
+ </style>
32
+ """, unsafe_allow_html=True)
33
+
34
+ # --- Set up state ---
35
+ if "chat_history" not in st.session_state:
36
+ st.session_state.chat_history = []
37
+ if "dark_mode" not in st.session_state:
38
+ st.session_state.dark_mode = False
39
+
40
+ # --- Sidebar: Settings + Clear Vector Store ---
41
+ with st.sidebar:
42
+ st.title("βš™οΈ Settings")
43
+ st.session_state.dark_mode = st.toggle("πŸŒ‘ Dark Mode", value=st.session_state.dark_mode)
44
+
45
+ # Set CSS vars
46
+ if st.session_state.dark_mode:
47
+ st.markdown("""
48
+ <style>
49
+ :root {
50
+ --background-color: #111827;
51
+ --text-color: #f3f4f6;
52
+ --primary-color-bg: #1e293b;
53
+ --secondary-color-bg: #334155;
54
+ }
55
+ </style>
56
+ """, unsafe_allow_html=True)
57
+ else:
58
+ st.markdown("""
59
+ <style>
60
+ :root {
61
+ --background-color: #ffffff;
62
+ --text-color: #1f2937;
63
+ --primary-color-bg: #e0f2fe;
64
+ --secondary-color-bg: #f3f4f6;
65
+ }
66
+ </style>
67
+ """, unsafe_allow_html=True)
68
+
69
+ # --- Clear Chroma Vector Store Option ---
70
+ if st.button("πŸ—‘οΈ Clear Vector Store"):
71
+ try:
72
+ if os.path.exists(CHROMA_PATH):
73
+ shutil.rmtree(CHROMA_PATH)
74
+ st.success("βœ… Vector store cleared.")
75
+ else:
76
+ st.info("ℹ️ No vector store found.")
77
+ except Exception as e:
78
+ st.error(f"❌ Failed to clear vector store: {e}")
79
+
80
+ # --- Title ---
81
+ st.title("πŸ’¬ DocChat – Ask Anything From Your PDFs")
82
+
83
+ # --- File Upload Sidebar ---
84
+ with st.sidebar:
85
+ st.subheader("πŸ“‚ Uploaded PDFs")
86
+ uploaded_files = st.file_uploader(
87
+ "Upload PDF files", type=["pdf"], accept_multiple_files=True
88
+ )
89
+
90
+ def render_pdf_preview(pdf_path, highlights=None, max_pages=3):
91
+ doc = fitz.open(pdf_path)
92
+ images = []
93
+
94
+ for page_num in range(min(len(doc), max_pages)):
95
+ page = doc.load_page(page_num)
96
+
97
+ if highlights:
98
+ for h in highlights:
99
+ if h["filename"] == os.path.basename(pdf_path) and h["page"] == page_num + 1:
100
+ areas = page.search_for(h["text"], hit_max=5)
101
+ for rect in areas:
102
+ page.draw_rect(rect, color=(1, 1, 0), fill=(1, 1, 0), overlay=True)
103
+
104
+ pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
105
+ img_bytes = pix.tobytes("png")
106
+ images.append(img_bytes)
107
+
108
+ doc.close()
109
+ return images
110
+
111
+ if uploaded_files:
112
+ if os.path.exists(DATA_PATH):
113
+ shutil.rmtree(DATA_PATH)
114
+ os.makedirs(DATA_PATH, exist_ok=True)
115
+
116
+ file_names = []
117
+ for uploaded_file in uploaded_files:
118
+ file_path = os.path.join(DATA_PATH, uploaded_file.name)
119
+ file_names.append(uploaded_file.name)
120
+ with open(file_path, "wb") as f:
121
+ f.write(uploaded_file.read())
122
+
123
+ st.success(f"Uploaded {len(uploaded_files)} file(s).")
124
+
125
+ if st.button("⚑ Generate Vector Store"):
126
+ with st.spinner("Processing and indexing..."):
127
+ generate_data_store()
128
+ st.success("βœ… Knowledge base ready!")
129
+
130
+ st.markdown("### 🧾 File Manager")
131
+ for name in file_names:
132
+ st.markdown(f"- πŸ“„ `{name}`")
133
+ with st.expander("πŸ–Ό Preview Pages"):
134
+ file_path = os.path.join(DATA_PATH, name)
135
+
136
+ file_highlights = []
137
+ for chat in st.session_state.chat_history:
138
+ for chunk in chat["context"]:
139
+ if chunk["filename"] == name:
140
+ file_highlights.append(chunk)
141
+
142
+ images = render_pdf_preview(file_path, highlights=file_highlights)
143
+
144
+ for img in images:
145
+ st.image(img, use_container_width=True)
146
+
147
+ # --- Main Chat Section ---
148
+ st.markdown("### 🧠 Ask Your Question")
149
+ query = st.text_input("Type your question here...", placeholder="e.g. What is the conclusion of the document?")
150
+
151
+ col1, col2 = st.columns([1, 1])
152
+
153
+ with col1:
154
+ if st.button("πŸš€ Get Answer"):
155
+ if not query.strip():
156
+ st.warning("Please enter a question.")
157
+ else:
158
+ with st.spinner("Thinking..."):
159
+ answer, context_chunks = ask_question(query)
160
+
161
+ st.session_state.chat_history.append({
162
+ "question": query,
163
+ "answer": answer,
164
+ "context": context_chunks
165
+ })
166
+
167
+ with col2:
168
+ if st.button("πŸ—‘οΈ Clear Chat"):
169
+ st.session_state.chat_history = []
170
+
171
+ # --- Display Chat History ---
172
+ if st.session_state.chat_history:
173
+ st.markdown("### πŸ—‚οΈ Chat History")
174
+ for chat in reversed(st.session_state.chat_history):
175
+ st.markdown(f'<div class="stChatBubble user"><b>Q:</b> {chat["question"]}</div>', unsafe_allow_html=True)
176
+ st.markdown(f'<div class="stChatBubble bot"><b>A:</b> {chat["answer"]}</div>', unsafe_allow_html=True)
177
+ with st.expander("🧾 View Context Used"):
178
+ for chunk in chat["context"]:
179
+ st.markdown(f"""
180
+ <div style="background-color: #fef9c3; padding: 10px; border-radius: 6px; margin-bottom: 10px;">
181
+ <b>πŸ“„ {chunk['filename']} – Page {chunk['page']}</b>
182
+ <pre style="white-space: pre-wrap;">{chunk['text']}</pre>
183
+ </div>
184
+ """, unsafe_allow_html=True)