ktejeshnaidu commited on
Commit
e8be885
Β·
verified Β·
1 Parent(s): c20b064

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +160 -44
app.py CHANGED
@@ -1,63 +1,146 @@
 
 
 
 
 
1
  import streamlit as st
2
  import requests
3
  import json
4
  import os
 
 
 
 
 
 
 
 
 
5
 
6
- st.set_page_config(page_title="DocuMind - Enterprise RAG", page_icon="🧠", layout="wide")
 
 
 
 
 
7
 
8
- API_URL = os.environ.get("API_URL", "http://127.0.0.1:8000")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  st.title("🧠 DocuMind")
11
- st.markdown("Enterprise Document Intelligence Chatbot")
 
12
 
13
- # --- Sidebar ---
14
  with st.sidebar:
15
  st.header("🏒 Document Knowledge Base")
16
  st.markdown("Upload PDFs, DOCX, or TXT documents to add them to the system.")
17
 
18
  uploaded_file = st.file_uploader("Upload a new document", type=["txt", "pdf", "docx"])
19
- if uploaded_file and st.button("Ingest Document"):
 
20
  with st.spinner("Ingesting document (creating chunks & embeddings)..."):
21
  files = {"file": (uploaded_file.name, uploaded_file.getvalue())}
22
  try:
23
- res = requests.post(f"{API_URL}/ingest", files=files)
24
  if res.status_code == 200:
25
- st.success(f"{uploaded_file.name} ingested successfully!")
26
  else:
27
- st.error(f"Failed to ingest: {res.text}")
 
 
28
  except Exception as e:
29
- st.error(f"Backend is not running: {e}")
30
-
31
  st.divider()
32
- st.subheader("Indexed Documents")
 
33
  try:
34
- res = requests.get(f"{API_URL}/sources")
35
  if res.status_code == 200:
36
- for doc in res.json().get("documents", []):
37
- st.markdown(f"- πŸ“„ `{doc}`")
38
- except:
39
- st.warning("Could not connect to FastAPI server.")
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- # --- Chat Interface ---
42
  if "messages" not in st.session_state:
43
  st.session_state.messages = []
44
 
45
- # Display history
46
  for msg in st.session_state.messages:
47
  with st.chat_message(msg["role"]):
48
  st.markdown(msg["content"])
49
- if "sources" in msg and msg["sources"]:
50
- with st.expander("Show Sources"):
51
  for idx, src in enumerate(msg["sources"]):
52
- st.caption(f"**Source {idx+1} [Relevance: {src['score']:.2f}]**: {src['source']}")
53
- st.markdown(f"> {src['content']}")
 
 
54
 
55
- if user_input := st.chat_input("Ask a question about your documents..."):
56
- # Add user message
 
 
 
57
  st.session_state.messages.append({"role": "user", "content": user_input})
 
 
58
  with st.chat_message("user"):
59
  st.markdown(user_input)
60
-
61
  # Get assistant response
62
  with st.chat_message("assistant"):
63
  placeholder = st.empty()
@@ -65,32 +148,65 @@ if user_input := st.chat_input("Ask a question about your documents..."):
65
  sources = []
66
 
67
  try:
68
- with requests.post(f"{API_URL}/query", json={"question": user_input}, stream=True) as r:
 
 
 
 
 
69
  r.raise_for_status()
 
70
  for line in r.iter_lines():
71
  if line:
72
- decoded_line = line.decode('utf-8')
73
- data = json.loads(decoded_line)
74
- if data["type"] == "sources":
75
- sources = data["data"]
76
- elif data["type"] == "token":
77
- full_response += data["content"]
78
- placeholder.markdown(full_response + "β–Œ")
79
 
80
- placeholder.markdown(full_response)
81
- if sources:
82
- with st.expander("Show Sources"):
83
- for idx, src in enumerate(sources):
84
- st.caption(f"**Source {idx+1} [Relevance: {src['score']:.2f}]**: {src['source']}")
85
- st.markdown(f"> {src['content']}")
86
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  except Exception as e:
88
- st.error(f"Error querying backend: {e}")
89
- full_response = "Sorry, the backend encountered an error."
90
-
 
91
  # Save assistant message
92
  st.session_state.messages.append({
93
- "role": "assistant",
94
  "content": full_response,
95
  "sources": sources
96
  })
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ DocuMind - Unified FastAPI + Streamlit App for HuggingFace Spaces
3
+ Combines backend API and frontend UI in a single process
4
+ """
5
+
6
  import streamlit as st
7
  import requests
8
  import json
9
  import os
10
+ import subprocess
11
+ import time
12
+ import sys
13
+ from threading import Thread
14
+ from pathlib import Path
15
+
16
+ # ============================================================================
17
+ # STREAMLIT CONFIG (Must be first)
18
+ # ============================================================================
19
 
20
+ st.set_page_config(
21
+ page_title="DocuMind - Enterprise RAG",
22
+ page_icon="🧠",
23
+ layout="wide",
24
+ initial_sidebar_state="expanded"
25
+ )
26
 
27
+ # ============================================================================
28
+ # BACKEND STARTUP
29
+ # ============================================================================
30
+
31
+ @st.cache_resource
32
+ def start_backend_server():
33
+ """Start FastAPI backend in a separate thread"""
34
+
35
+ def run_server():
36
+ # Import FastAPI backend components
37
+ from main import app as fastapi_app
38
+ import uvicorn
39
+
40
+ # Run uvicorn server
41
+ uvicorn.run(
42
+ fastapi_app,
43
+ host="127.0.0.1",
44
+ port=8000,
45
+ log_level="warning",
46
+ access_log=False
47
+ )
48
+
49
+ # Start backend in daemon thread
50
+ backend_thread = Thread(target=run_server, daemon=True)
51
+ backend_thread.start()
52
+
53
+ # Give backend time to start
54
+ time.sleep(2)
55
+
56
+ return "Backend started"
57
+
58
+ # Start backend
59
+ try:
60
+ start_backend_server()
61
+ API_URL = "http://127.0.0.1:8000"
62
+ except Exception as e:
63
+ st.error(f"Failed to start backend: {e}")
64
+ st.stop()
65
+
66
+ # ============================================================================
67
+ # STREAMLIT FRONTEND UI
68
+ # ============================================================================
69
 
70
  st.title("🧠 DocuMind")
71
+ st.markdown("**Enterprise Document Intelligence Chatbot**")
72
+ st.markdown("---")
73
 
74
+ # --- Sidebar for Document Upload ---
75
  with st.sidebar:
76
  st.header("🏒 Document Knowledge Base")
77
  st.markdown("Upload PDFs, DOCX, or TXT documents to add them to the system.")
78
 
79
  uploaded_file = st.file_uploader("Upload a new document", type=["txt", "pdf", "docx"])
80
+
81
+ if uploaded_file and st.button("Ingest Document", key="ingest_btn"):
82
  with st.spinner("Ingesting document (creating chunks & embeddings)..."):
83
  files = {"file": (uploaded_file.name, uploaded_file.getvalue())}
84
  try:
85
+ res = requests.post(f"{API_URL}/ingest", files=files, timeout=30)
86
  if res.status_code == 200:
87
+ st.success(f"βœ… {uploaded_file.name} ingested successfully!")
88
  else:
89
+ st.error(f"❌ Failed to ingest: {res.text}")
90
+ except requests.exceptions.ConnectionError:
91
+ st.error("⚠️ Backend is not running. Please refresh the page.")
92
  except Exception as e:
93
+ st.error(f"⚠️ Error: {str(e)}")
94
+
95
  st.divider()
96
+
97
+ st.subheader("πŸ“„ Indexed Documents")
98
  try:
99
+ res = requests.get(f"{API_URL}/sources", timeout=10)
100
  if res.status_code == 200:
101
+ documents = res.json().get("documents", [])
102
+ if documents:
103
+ for doc in documents:
104
+ st.markdown(f"- `{doc}`")
105
+ else:
106
+ st.info("No documents indexed yet.")
107
+ else:
108
+ st.warning("Could not fetch documents list")
109
+ except requests.exceptions.ConnectionError:
110
+ st.warning("⚠️ Could not connect to backend")
111
+ except Exception as e:
112
+ st.warning(f"⚠️ Error: {str(e)}")
113
+
114
+ # --- Main Chat Interface ---
115
+ st.subheader("πŸ’¬ Chat with Your Documents")
116
 
117
+ # Initialize session state
118
  if "messages" not in st.session_state:
119
  st.session_state.messages = []
120
 
121
+ # Display chat history
122
  for msg in st.session_state.messages:
123
  with st.chat_message(msg["role"]):
124
  st.markdown(msg["content"])
125
+ if "sources" in msg and msg.get("sources"):
126
+ with st.expander("πŸ“š Show Sources"):
127
  for idx, src in enumerate(msg["sources"]):
128
+ score = src.get('score', 0)
129
+ st.caption(f"**Source {idx+1}** [Relevance: {score:.2%}]")
130
+ st.markdown(f"**From:** `{src.get('source', 'Unknown')}`")
131
+ st.markdown(f"> {src.get('content', '')[:500]}...")
132
 
133
+ # Chat input
134
+ user_input = st.chat_input("Ask a question about your documents...")
135
+
136
+ if user_input:
137
+ # Add user message to history
138
  st.session_state.messages.append({"role": "user", "content": user_input})
139
+
140
+ # Display user message
141
  with st.chat_message("user"):
142
  st.markdown(user_input)
143
+
144
  # Get assistant response
145
  with st.chat_message("assistant"):
146
  placeholder = st.empty()
 
148
  sources = []
149
 
150
  try:
151
+ with requests.post(
152
+ f"{API_URL}/query",
153
+ json={"question": user_input},
154
+ stream=True,
155
+ timeout=60
156
+ ) as r:
157
  r.raise_for_status()
158
+
159
  for line in r.iter_lines():
160
  if line:
161
+ try:
162
+ decoded_line = line.decode('utf-8')
163
+ data = json.loads(decoded_line)
 
 
 
 
164
 
165
+ if data.get("type") == "sources":
166
+ sources = data.get("data", [])
167
+ elif data.get("type") == "token":
168
+ full_response += data.get("content", "")
169
+ placeholder.markdown(full_response + "β–Œ")
170
+ except json.JSONDecodeError:
171
+ continue
172
+
173
+ placeholder.markdown(full_response)
174
+
175
+ # Display sources if available
176
+ if sources:
177
+ with st.expander("πŸ“š Show Sources"):
178
+ for idx, src in enumerate(sources):
179
+ score = src.get('score', 0)
180
+ st.caption(f"**Source {idx+1}** [Relevance: {score:.2%}]")
181
+ st.markdown(f"**From:** `{src.get('source', 'Unknown')}`")
182
+ st.markdown(f"> {src.get('content', '')[:500]}...")
183
+
184
+ except requests.exceptions.Timeout:
185
+ error_msg = "⏱️ Request timed out. Please try a shorter question."
186
+ st.error(error_msg)
187
+ full_response = error_msg
188
+ except requests.exceptions.ConnectionError:
189
+ error_msg = "⚠️ Backend connection failed. Please refresh the page."
190
+ st.error(error_msg)
191
+ full_response = error_msg
192
  except Exception as e:
193
+ error_msg = f"❌ Error: {str(e)}"
194
+ st.error(error_msg)
195
+ full_response = error_msg
196
+
197
  # Save assistant message
198
  st.session_state.messages.append({
199
+ "role": "assistant",
200
  "content": full_response,
201
  "sources": sources
202
  })
203
+
204
+ # Footer
205
+ st.divider()
206
+ st.markdown(
207
+ "<div style='text-align: center; color: gray; font-size: 0.8em;'>"
208
+ "DocuMind - Enterprise RAG Chatbot | "
209
+ "<a href='https://github.com/TejeshNaiduKona/DocuMind' target='_blank'>GitHub</a>"
210
+ "</div>",
211
+ unsafe_allow_html=True
212
+ )