Sahana31 commited on
Commit
61607a6
Β·
verified Β·
1 Parent(s): 9e415dc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -164
app.py CHANGED
@@ -1,51 +1,44 @@
1
- """
2
- Dwani.ai Gradio UI - FIXED File Upload + Backend Health Check
3
- """
4
-
5
  import gradio as gr
6
  import requests
7
  from typing import List, Dict
8
- from datetime import datetime
9
  import time
10
- import json
11
 
12
- # BACKEND MUST BE LIVE - Test this first!
13
- API_BASE = "https://sahana31-rag-backend.hf.space."
14
 
15
  class DwaniClient:
16
  def __init__(self, base_url=API_BASE):
17
  self.base_url = base_url.rstrip('/')
18
 
19
  def test_backend(self):
20
- """Test if backend is alive"""
21
  try:
22
- resp = requests.get(f"{self.base_url}/", timeout=5)
23
- return resp.status_code == 200, resp.json().get('status', 'Unknown')
24
- except:
25
- return False, "Backend not responding"
 
26
 
27
- def upload_file(self, file_obj) -> dict:
28
- """Upload single file object (Gradio format)"""
29
- files = {'file': (file_obj.name, file_obj, 'application/pdf')}
30
- resp = requests.post(f"{self.base_url}/files/upload",
31
- files=files, timeout=30)
32
- resp.raise_for_status()
33
- return resp.json()
34
 
35
- def get_file_status(self, file_id: str) -> dict:
36
  resp = requests.get(f"{self.base_url}/files/{file_id}", timeout=10)
37
  resp.raise_for_status()
38
  return resp.json()
39
 
40
- def list_files(self) -> List[dict]:
41
  resp = requests.get(f"{self.base_url}/files/", timeout=10)
42
  resp.raise_for_status()
43
  return resp.json()
44
 
45
- def chat(self, file_ids: List[str], messages: List[Dict]) -> dict:
46
  payload = {"file_ids": file_ids, "messages": messages}
47
- resp = requests.post(f"{self.base_url}/chat-with-document",
48
- json=payload, timeout=60)
49
  resp.raise_for_status()
50
  return resp.json()
51
 
@@ -55,69 +48,56 @@ chat_history = []
55
  selected_files = []
56
 
57
  def test_connection():
58
- """Test backend connection"""
59
  is_alive, status = client.test_backend()
60
  if is_alive:
61
  return f"βœ… Backend LIVE: {status}", gr.update(visible=True)
62
- else:
63
- return f"❌ Backend DOWN: {status}\n\nFIX: Check https://huggingface.co/spaces/Sahana31/RAG_backend", gr.update(visible=False)
64
 
65
- def poll_file_status(file_id: str, max_wait=120):
66
- """Poll until file ready"""
67
- for i in range(max_wait//2):
68
  try:
69
  status = client.get_file_status(file_id)
70
- if status['status'] == 'completed':
71
- return status, True
72
- if status['status'] == 'failed':
73
- return status, False
74
  time.sleep(2)
75
- except Exception as e:
76
  time.sleep(2)
77
  return {'status': 'timeout'}, False
78
 
79
  def upload_multiple(files):
80
- """Handle Gradio file list"""
81
  global uploaded_files
82
-
83
  if not files:
84
- return "No files selected", gr.update(choices=[]), create_file_list(), gr.update()
85
 
86
  status_msgs = ["**πŸ“€ UPLOADING...**"]
87
-
88
  for file_obj in files:
89
  try:
90
- # Upload file
91
  result = client.upload_file(file_obj)
92
  file_id = result['file_id']
93
  filename = result['filename']
94
 
95
- uploaded_files[file_id] = {
96
- 'filename': filename,
97
- 'status': 'pending',
98
- 'file_id': file_id
99
- }
100
 
101
- # Poll status
102
  final_status, success = poll_file_status(file_id)
103
-
104
  if success:
105
  uploaded_files[file_id]['status'] = 'completed'
106
  status_msgs.append(f"βœ… {filename}")
107
  else:
108
- uploaded_files[file_id]['status'] = final_status['status']
109
  status_msgs.append(f"❌ {filename} - {final_status['status']}")
110
-
111
- except requests.exceptions.HTTPError as e:
112
- status_msgs.append(f"❌ {file_obj.name} - HTTP {e.response.status_code}")
113
  except Exception as e:
114
  status_msgs.append(f"❌ {file_obj.name} - {str(e)}")
115
 
116
- # Only completed files for chat
117
- choices = [(info['filename'], info['file_id']) for info in uploaded_files.values()
118
- if info['status'] == 'completed']
119
-
120
- return "\n".join(status_msgs), gr.update(choices=choices), create_file_list(), gr.update()
 
 
 
 
 
 
121
 
122
  def refresh_files():
123
  try:
@@ -125,140 +105,68 @@ def refresh_files():
125
  global uploaded_files
126
  uploaded_files.clear()
127
  for f in files:
128
- uploaded_files[f['file_id']] = {
129
- 'filename': f['filename'],
130
- 'status': f['status'],
131
- 'file_id': f['file_id']
132
- }
133
  choices = [(f['filename'], f['file_id']) for f in files if f['status'] == 'completed']
134
  return create_file_list(), gr.update(choices=choices)
135
- except Exception as e:
136
- return f"❌ Refresh failed: {str(e)}", gr.update()
137
-
138
- def create_file_list():
139
- if not uploaded_files:
140
- return "**No files uploaded**"
141
-
142
- lines = ["**πŸ“ Your Files:**"]
143
- for info in uploaded_files.values():
144
- emoji = {'completed': 'βœ…', 'processing': 'πŸ”„', 'pending': '⏳', 'failed': '❌'}.get(info['status'], '❓')
145
- lines.append(f"{emoji} {info['filename']} ({info['status']})")
146
- return "\n".join(lines)
147
 
148
- def update_selected_files(files):
149
  global selected_files
150
  selected_files = files or []
151
  return len(selected_files)
152
 
153
  def send_message(message, history):
154
  global chat_history, selected_files
 
 
155
 
156
- if not message.strip():
157
- return history, ""
158
-
159
- if not selected_files:
160
- return history, "⚠️ Select files first!"
161
-
162
- # Add user message
163
- user_msg = {"role": "user", "content": message}
164
- thinking_msg = {"role": "assistant", "content": "πŸ”„ Thinking..."}
165
-
166
- new_history = history + [user_msg, thinking_msg]
167
 
168
  try:
169
- # Send to backend
170
- api_messages = chat_history + [user_msg]
171
- result = client.chat(selected_files, api_messages)
172
-
173
- # Update history
174
- chat_history.extend([user_msg, {"role": "assistant", "content": result['answer']}])
175
-
176
- # Format response
177
- response = format_chat_response(result)
178
- final_history = history + [user_msg, {"role": "assistant", "content": response}]
179
-
180
- return final_history, ""
181
-
182
  except Exception as e:
183
- error_msg = f"❌ Error: {str(e)}"
184
- return new_history[:-1] + [{"role": "assistant", "content": error_msg}], error_msg
185
-
186
- def format_chat_response(result):
187
- answer = result['answer']
188
- if result.get('sources'):
189
- sources = "\n\n**πŸ“š Sources:**\n"
190
- for i, src in enumerate(result['sources'][:3], 1):
191
- sources += f"{i}. **{src['filename']}** (Page {src.get('page', '?')})\n"
192
- excerpt = src.get('excerpt', '')[:100] + "..."
193
- sources += f" > {excerpt}\n"
194
- return answer + sources
195
- return answer
196
 
197
  def clear_chat():
198
  global chat_history
199
  chat_history = []
200
  return []
201
 
202
- # === GRADIO UI ===
203
- with gr.Blocks(title="Dwani.ai RAG") as demo:
204
- gr.Markdown("# πŸ“š Dwani.ai - Document Chatbot")
205
- gr.Markdown("**Upload PDFs β†’ Chat with page-accurate citations**")
206
-
207
- # Backend status
208
- with gr.Row():
209
- status_display = gr.Markdown("🟑 Testing backend...")
210
- test_btn = gr.Button("πŸ” Test Backend", variant="secondary")
211
 
212
  with gr.Row():
213
  with gr.Column(scale=1):
214
- gr.Markdown("## πŸ“€ Upload PDFs")
215
- file_input = gr.File(
216
- label="Select multiple PDFs",
217
- file_types=[".pdf"],
218
- file_count="multiple"
219
- )
220
- upload_btn = gr.Button("πŸš€ Upload & Process", variant="primary")
221
-
222
- status_output = gr.Markdown("Ready...")
223
- refresh_btn = gr.Button("πŸ”„ Refresh")
224
  files_display = gr.Markdown("No files")
225
 
226
- with gr.Column(scale=2):
227
- gr.Markdown("## πŸ“‹ Document Manager")
228
- file_checkboxes = gr.CheckboxGroup(
229
- label="Chat with these files:",
230
- choices=[],
231
- value=[],
232
- )
233
- file_count = gr.Number(label="Selected", interactive=False)
234
-
235
- with gr.Row():
236
- gr.Markdown("## πŸ’¬ Chat")
237
- chatbot = gr.Chatbot(height=500)
238
 
 
239
  with gr.Row():
240
- msg_input = gr.Textbox(placeholder="Ask about your documents...", scale=4)
241
- send_btn = gr.Button("Send", variant="primary", scale=1)
242
-
243
- clear_btn = gr.Button("πŸ—‘οΈ New Chat", variant="secondary")
244
 
245
- # Events
246
- test_btn.click(test_connection, outputs=[status_display, upload_btn])
247
 
248
  upload_btn.click(
249
- upload_multiple,
250
- inputs=file_input,
251
- outputs=[status_output, file_checkboxes, files_display, file_count]
252
  )
253
-
254
- refresh_btn.click(refresh_files, outputs=[files_display, file_checkboxes])
255
-
256
- file_checkboxes.change(update_selected_files, inputs=file_checkboxes, outputs=file_count)
257
-
258
- send_btn.click(send_message, inputs=[msg_input, chatbot], outputs=[chatbot, msg_input])
259
- msg_input.submit(send_message, inputs=[msg_input, chatbot], outputs=[chatbot, msg_input])
260
-
261
- clear_btn.click(clear_chat, outputs=chatbot)
262
-
263
- if __name__ == "__main__":
264
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
1
  import gradio as gr
2
  import requests
3
  from typing import List, Dict
 
4
  import time
 
5
 
6
+ # βœ… FIXED API URL
7
+ API_BASE = "https://huggingface.co/spaces/Sahana31/RAG_backend"
8
 
9
  class DwaniClient:
10
  def __init__(self, base_url=API_BASE):
11
  self.base_url = base_url.rstrip('/')
12
 
13
  def test_backend(self):
 
14
  try:
15
+ resp = requests.get(f"{self.base_url}/", timeout=10)
16
+ resp.raise_for_status()
17
+ return True, resp.json().get('status', 'OK')
18
+ except Exception as e:
19
+ return False, str(e)[:100]
20
 
21
+ def upload_file(self, file_obj):
22
+ # βœ… FIXED file handling
23
+ with open(file_obj.name, 'rb') as f:
24
+ files = {'file': (file_obj.name, f, 'application/pdf')}
25
+ resp = requests.post(f"{self.base_url}/files/upload", files=files, timeout=30)
26
+ resp.raise_for_status()
27
+ return resp.json()
28
 
29
+ def get_file_status(self, file_id):
30
  resp = requests.get(f"{self.base_url}/files/{file_id}", timeout=10)
31
  resp.raise_for_status()
32
  return resp.json()
33
 
34
+ def list_files(self):
35
  resp = requests.get(f"{self.base_url}/files/", timeout=10)
36
  resp.raise_for_status()
37
  return resp.json()
38
 
39
+ def chat(self, file_ids: List[str], messages: List[Dict]):
40
  payload = {"file_ids": file_ids, "messages": messages}
41
+ resp = requests.post(f"{self.base_url}/chat-with-document", json=payload, timeout=60)
 
42
  resp.raise_for_status()
43
  return resp.json()
44
 
 
48
  selected_files = []
49
 
50
  def test_connection():
 
51
  is_alive, status = client.test_backend()
52
  if is_alive:
53
  return f"βœ… Backend LIVE: {status}", gr.update(visible=True)
54
+ return f"❌ Backend DOWN: {status}", gr.update(visible=False)
 
55
 
56
+ def poll_file_status(file_id, max_wait=60):
57
+ for _ in range(max_wait):
 
58
  try:
59
  status = client.get_file_status(file_id)
60
+ if status['status'] == 'completed': return status, True
61
+ if status['status'] == 'failed': return status, False
 
 
62
  time.sleep(2)
63
+ except:
64
  time.sleep(2)
65
  return {'status': 'timeout'}, False
66
 
67
  def upload_multiple(files):
 
68
  global uploaded_files
 
69
  if not files:
70
+ return "No files", gr.update(choices=[]), "No files", 0
71
 
72
  status_msgs = ["**πŸ“€ UPLOADING...**"]
 
73
  for file_obj in files:
74
  try:
 
75
  result = client.upload_file(file_obj)
76
  file_id = result['file_id']
77
  filename = result['filename']
78
 
79
+ uploaded_files[file_id] = {'filename': filename, 'status': 'pending'}
 
 
 
 
80
 
 
81
  final_status, success = poll_file_status(file_id)
 
82
  if success:
83
  uploaded_files[file_id]['status'] = 'completed'
84
  status_msgs.append(f"βœ… {filename}")
85
  else:
 
86
  status_msgs.append(f"❌ {filename} - {final_status['status']}")
 
 
 
87
  except Exception as e:
88
  status_msgs.append(f"❌ {file_obj.name} - {str(e)}")
89
 
90
+ choices = [(info['filename'], info['file_id']) for info in uploaded_files.values() if info['status'] == 'completed']
91
+ return "\n".join(status_msgs), gr.update(choices=choices), create_file_list(), len(choices)
92
+
93
+ def create_file_list():
94
+ if not uploaded_files:
95
+ return "**No files**"
96
+ lines = ["**πŸ“ Files:**"]
97
+ for info in uploaded_files.values():
98
+ emoji = {'completed': 'βœ…', 'pending': '⏳', 'failed': '❌'}.get(info['status'], '❓')
99
+ lines.append(f"{emoji} {info['filename']}")
100
+ return "\n".join(lines)
101
 
102
  def refresh_files():
103
  try:
 
105
  global uploaded_files
106
  uploaded_files.clear()
107
  for f in files:
108
+ uploaded_files[f['file_id']] = {'filename': f['filename'], 'status': f['status'], 'file_id': f['file_id']}
 
 
 
 
109
  choices = [(f['filename'], f['file_id']) for f in files if f['status'] == 'completed']
110
  return create_file_list(), gr.update(choices=choices)
111
+ except:
112
+ return "❌ Refresh failed", gr.update()
 
 
 
 
 
 
 
 
 
 
113
 
114
+ def file_selector(files):
115
  global selected_files
116
  selected_files = files or []
117
  return len(selected_files)
118
 
119
  def send_message(message, history):
120
  global chat_history, selected_files
121
+ if not message or not selected_files:
122
+ return history, "⚠️ Select files & enter message"
123
 
124
+ new_history = history + [(message, "Thinking...")]
 
 
 
 
 
 
 
 
 
 
125
 
126
  try:
127
+ result = client.chat(selected_files, chat_history + [{"role": "user", "content": message}])
128
+ response = result['answer']
129
+ if result.get('sources'):
130
+ response += "\n\n**Sources:**\n" + "\n".join([f"β€’ {s['filename']} (p{s['page']})" for s in result['sources'][:3]])
131
+ return new_history[:-1] + [(message, response)], ""
 
 
 
 
 
 
 
 
132
  except Exception as e:
133
+ return new_history[:-1] + [(message, f"❌ {str(e)}")], ""
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  def clear_chat():
136
  global chat_history
137
  chat_history = []
138
  return []
139
 
140
+ # βœ… HF SPACES UI - NO LAUNCH BLOCK
141
+ with gr.Blocks(title="Dwani.ai") as demo:
142
+ gr.Markdown("# πŸ“š Dwani.ai - Document Chat")
143
+ gr.Markdown("**Upload PDFs β†’ Chat with citations**")
144
+
145
+ status_display = gr.Markdown("🟑 Testing backend...")
146
+ gr.Button("πŸ” Test Backend", variant="secondary").click(
147
+ test_connection, outputs=[status_display]
148
+ )
149
 
150
  with gr.Row():
151
  with gr.Column(scale=1):
152
+ file_input = gr.File(file_types=[".pdf"], file_count="multiple", label="πŸ“€ PDFs")
153
+ upload_btn = gr.Button("πŸš€ Upload", variant="primary")
154
+ status_output = gr.Markdown("Ready")
 
 
 
 
 
 
 
155
  files_display = gr.Markdown("No files")
156
 
157
+ with gr.Column(scale=1):
158
+ file_checkboxes = gr.CheckboxGroup(choices=[], label="Chat with:")
159
+ gr.Number(label="Selected", interactive=False)
 
 
 
 
 
 
 
 
 
160
 
161
+ chatbot = gr.Chatbot(height=400)
162
  with gr.Row():
163
+ msg = gr.Textbox(placeholder="Ask about documents...", scale=4)
164
+ gr.Button("Send", scale=1).click(send_message, inputs=[msg, chatbot], outputs=[chatbot, msg])
 
 
165
 
166
+ gr.Button("Clear").click(clear_chat, outputs=chatbot)
 
167
 
168
  upload_btn.click(
169
+ upload_multiple,
170
+ inputs=file_input,
171
+ outputs=[status_output, file_checkboxes, files_display, gr.Number()]
172
  )