shukdevdattaEX commited on
Commit
49e1d15
·
verified ·
1 Parent(s): c5cc57a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -46
app.py CHANGED
@@ -7,10 +7,16 @@ import pdfplumber
7
  from docx import Document as DocxDocument
8
  import json
9
  from datetime import datetime
 
10
 
11
  # Global variables
12
  chat_engine = None
13
  conversation_history = []
 
 
 
 
 
14
 
15
  # Function to read PDF files
16
  def read_pdf(file_path):
@@ -30,7 +36,7 @@ def read_docx(file_path):
30
 
31
  # Function to load and index documents
32
  def load_data(files, api_key):
33
- global chat_engine
34
 
35
  if not files or not api_key:
36
  return "Please provide both API key and files to proceed."
@@ -48,6 +54,9 @@ def load_data(files, api_key):
48
  # Set OpenAI API key
49
  os.environ["OPENAI_API_KEY"] = api_key
50
 
 
 
 
51
  Settings.llm = OpenAI(
52
  model="gpt-3.5-turbo",
53
  temperature=0.5,
@@ -64,11 +73,15 @@ def load_data(files, api_key):
64
 
65
  # Function to handle chat
66
  def chat_with_docs(message, history, api_key):
67
- global chat_engine, conversation_history
68
 
69
  if not api_key:
70
  return history + [{"role": "assistant", "content": "Please enter your OpenAI API key first."}]
71
 
 
 
 
 
72
  if chat_engine is None:
73
  return history + [
74
  {"role": "user", "content": message},
@@ -91,41 +104,54 @@ def chat_with_docs(message, history, api_key):
91
  ]
92
 
93
  # Function to save conversation
94
- def save_conversation():
95
- global conversation_history
 
 
 
96
 
97
  if not conversation_history:
98
  return "No conversation to save.", gr.update()
99
 
100
  try:
 
 
 
 
101
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
102
  with open("conversations.json", "a") as f:
103
  conv_data = {
104
  "timestamp": timestamp,
 
105
  "messages": conversation_history
106
  }
107
  json.dump(conv_data, f)
108
  f.write("\n")
109
 
110
  # Update the dropdown choices
111
- choices = get_conversation_choices()
112
  return "Conversation saved successfully!", gr.update(choices=choices)
113
  except Exception as e:
114
  return f"Error saving conversation: {str(e)}", gr.update()
115
 
116
  # Function to get conversation choices for dropdown
117
- def get_conversation_choices():
 
 
 
118
  if os.path.exists("conversations.json"):
119
  try:
 
120
  with open("conversations.json", "r") as f:
121
  conversations = [json.loads(line) for line in f]
122
 
123
  choices = []
124
  for i, conv in enumerate(conversations):
125
- timestamp = conv.get("timestamp", "Unknown time")
126
- # Format: "1. 2024-01-13 14:30:45"
127
- formatted_time = datetime.strptime(timestamp, "%Y%m%d_%H%M%S").strftime("%Y-%m-%d %H:%M:%S")
128
- choices.append(f"{i + 1}. {formatted_time}")
 
129
 
130
  return choices
131
  except Exception as e:
@@ -133,36 +159,51 @@ def get_conversation_choices():
133
  return []
134
 
135
  # Function to load previous conversations
136
- def load_conversations():
 
 
 
137
  if os.path.exists("conversations.json"):
138
  try:
 
139
  with open("conversations.json", "r") as f:
140
  conversations = [json.loads(line) for line in f]
141
 
142
  conv_text = ""
 
143
  for i, conv in enumerate(conversations):
144
- conv_text += f"\n{'='*50}\nConversation {i + 1}\n{'='*50}\n"
145
- timestamp = conv.get("timestamp", "Unknown time")
146
- formatted_time = datetime.strptime(timestamp, "%Y%m%d_%H%M%S").strftime("%Y-%m-%d %H:%M:%S")
147
- conv_text += f"Timestamp: {formatted_time}\n\n"
148
-
149
- messages = conv.get("messages", conv)
150
- for message in messages:
151
- role = message.get('role', 'unknown')
152
- content = message.get('content', '')
153
- conv_text += f"{role.upper()}: {content}\n\n"
 
 
 
 
 
 
154
 
155
- return conv_text if conv_text else "No previous conversations found."
156
  except Exception as e:
157
  return f"Error loading conversations: {str(e)}"
158
  return "No previous conversations found."
159
 
160
  # Function to view selected conversation
161
- def view_selected_conversation(selection):
 
 
 
162
  if not selection or selection == "Select a conversation":
163
  return "Please select a conversation to view."
164
 
165
  try:
 
166
  # Extract conversation number from selection
167
  conv_number = int(selection.split(".")[0]) - 1
168
 
@@ -172,6 +213,11 @@ def view_selected_conversation(selection):
172
 
173
  if conv_number < len(conversations):
174
  conv = conversations[conv_number]
 
 
 
 
 
175
  conv_text = f"{'='*50}\n"
176
  timestamp = conv.get("timestamp", "Unknown time")
177
  formatted_time = datetime.strptime(timestamp, "%Y%m%d_%H%M%S").strftime("%Y-%m-%d %H:%M:%S")
@@ -191,11 +237,15 @@ def view_selected_conversation(selection):
191
  return f"Error viewing conversation: {str(e)}"
192
 
193
  # Function to delete selected conversation
194
- def delete_selected_conversation(selection):
 
 
 
195
  if not selection or selection == "Select a conversation":
196
- return "Please select a conversation to delete.", gr.update(), ""
197
 
198
  try:
 
199
  # Extract conversation number from selection
200
  conv_number = int(selection.split(".")[0]) - 1
201
 
@@ -204,6 +254,12 @@ def delete_selected_conversation(selection):
204
  conversations = [json.loads(line) for line in f]
205
 
206
  if conv_number < len(conversations):
 
 
 
 
 
 
207
  # Remove the selected conversation
208
  del conversations[conv_number]
209
 
@@ -214,18 +270,18 @@ def delete_selected_conversation(selection):
214
  f.write("\n")
215
 
216
  # Update dropdown choices
217
- choices = get_conversation_choices()
218
 
219
  # Get updated all conversations display
220
- all_convs = load_conversations()
221
 
222
- return f"Conversation {conv_number + 1} deleted successfully!", gr.update(choices=choices, value="Select a conversation"), all_convs
223
  else:
224
- return "Conversation not found.", gr.update(), ""
225
 
226
- return "No conversations file found.", gr.update(), ""
227
  except Exception as e:
228
- return f"Error deleting conversation: {str(e)}", gr.update(), ""
229
 
230
  # Function to clear current conversation
231
  def clear_conversation():
@@ -233,25 +289,54 @@ def clear_conversation():
233
  conversation_history = []
234
  return []
235
 
236
- # Function to delete all conversations
237
- def delete_all_conversations():
 
 
 
238
  try:
 
 
239
  if os.path.exists("conversations.json"):
240
- os.remove("conversations.json")
241
- return "All conversations deleted successfully!", gr.update(choices=[], value="Select a conversation"), "No previous conversations found."
242
- return "No conversations to delete.", gr.update(), "No previous conversations found."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  except Exception as e:
244
- return f"Error deleting conversations: {str(e)}", gr.update(), ""
245
 
246
  # Function to refresh dropdown
247
- def refresh_dropdown():
248
- choices = get_conversation_choices()
 
 
249
  return gr.update(choices=choices)
250
 
251
  # Create Gradio interface
252
- with gr.Blocks(title="Chat with Documents 💬 📚") as demo:
253
  gr.Markdown("# Chat with Documents 💬 📚")
254
  gr.Markdown("Upload PDF or DOCX files and chat with them using AI!")
 
255
 
256
  with gr.Row():
257
  with gr.Column(scale=2):
@@ -297,6 +382,7 @@ with gr.Blocks(title="Chat with Documents 💬 📚") as demo:
297
 
298
  with gr.Column(scale=1):
299
  gr.Markdown("### Conversation Management")
 
300
 
301
  with gr.Row():
302
  load_convs_btn = gr.Button("Load All Conversations")
@@ -312,7 +398,7 @@ with gr.Blocks(title="Chat with Documents 💬 📚") as demo:
312
 
313
  conversation_dropdown = gr.Dropdown(
314
  label="Select Conversation",
315
- choices=get_conversation_choices(),
316
  value="Select a conversation",
317
  interactive=True
318
  )
@@ -326,7 +412,7 @@ with gr.Blocks(title="Chat with Documents 💬 📚") as demo:
326
 
327
  with gr.Row():
328
  delete_selected_btn = gr.Button("Delete Selected", variant="stop")
329
- delete_all_btn = gr.Button("Delete All", variant="stop")
330
 
331
  delete_status = gr.Textbox(label="Delete Status", interactive=False)
332
 
@@ -356,34 +442,38 @@ with gr.Blocks(title="Chat with Documents 💬 📚") as demo:
356
 
357
  save_btn.click(
358
  fn=save_conversation,
 
359
  outputs=[save_status, conversation_dropdown]
360
  )
361
 
362
  load_convs_btn.click(
363
  fn=load_conversations,
 
364
  outputs=convs_display
365
  )
366
 
367
  refresh_btn.click(
368
  fn=refresh_dropdown,
 
369
  outputs=conversation_dropdown
370
  )
371
 
372
  view_btn.click(
373
  fn=view_selected_conversation,
374
- inputs=conversation_dropdown,
375
  outputs=selected_conv_display
376
  )
377
 
378
  delete_selected_btn.click(
379
  fn=delete_selected_conversation,
380
- inputs=conversation_dropdown,
381
- outputs=[delete_status, conversation_dropdown, convs_display]
382
  )
383
 
384
  delete_all_btn.click(
385
  fn=delete_all_conversations,
386
- outputs=[delete_status, conversation_dropdown, convs_display]
 
387
  )
388
 
389
  if __name__ == "__main__":
 
7
  from docx import Document as DocxDocument
8
  import json
9
  from datetime import datetime
10
+ import hashlib
11
 
12
  # Global variables
13
  chat_engine = None
14
  conversation_history = []
15
+ current_api_key_hash = None
16
+
17
+ # Function to hash API key for identification
18
+ def hash_api_key(api_key):
19
+ return hashlib.sha256(api_key.encode()).hexdigest()
20
 
21
  # Function to read PDF files
22
  def read_pdf(file_path):
 
36
 
37
  # Function to load and index documents
38
  def load_data(files, api_key):
39
+ global chat_engine, current_api_key_hash
40
 
41
  if not files or not api_key:
42
  return "Please provide both API key and files to proceed."
 
54
  # Set OpenAI API key
55
  os.environ["OPENAI_API_KEY"] = api_key
56
 
57
+ # Store hashed API key
58
+ current_api_key_hash = hash_api_key(api_key)
59
+
60
  Settings.llm = OpenAI(
61
  model="gpt-3.5-turbo",
62
  temperature=0.5,
 
73
 
74
  # Function to handle chat
75
  def chat_with_docs(message, history, api_key):
76
+ global chat_engine, conversation_history, current_api_key_hash
77
 
78
  if not api_key:
79
  return history + [{"role": "assistant", "content": "Please enter your OpenAI API key first."}]
80
 
81
+ # Set current API key hash if not set
82
+ if current_api_key_hash is None:
83
+ current_api_key_hash = hash_api_key(api_key)
84
+
85
  if chat_engine is None:
86
  return history + [
87
  {"role": "user", "content": message},
 
104
  ]
105
 
106
  # Function to save conversation
107
+ def save_conversation(api_key):
108
+ global conversation_history, current_api_key_hash
109
+
110
+ if not api_key:
111
+ return "Please enter your OpenAI API key first.", gr.update()
112
 
113
  if not conversation_history:
114
  return "No conversation to save.", gr.update()
115
 
116
  try:
117
+ # Set current API key hash if not set
118
+ if current_api_key_hash is None:
119
+ current_api_key_hash = hash_api_key(api_key)
120
+
121
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
122
  with open("conversations.json", "a") as f:
123
  conv_data = {
124
  "timestamp": timestamp,
125
+ "api_key_hash": current_api_key_hash,
126
  "messages": conversation_history
127
  }
128
  json.dump(conv_data, f)
129
  f.write("\n")
130
 
131
  # Update the dropdown choices
132
+ choices = get_conversation_choices(api_key)
133
  return "Conversation saved successfully!", gr.update(choices=choices)
134
  except Exception as e:
135
  return f"Error saving conversation: {str(e)}", gr.update()
136
 
137
  # Function to get conversation choices for dropdown
138
+ def get_conversation_choices(api_key):
139
+ if not api_key:
140
+ return []
141
+
142
  if os.path.exists("conversations.json"):
143
  try:
144
+ api_key_hash = hash_api_key(api_key)
145
  with open("conversations.json", "r") as f:
146
  conversations = [json.loads(line) for line in f]
147
 
148
  choices = []
149
  for i, conv in enumerate(conversations):
150
+ # Only show conversations for this API key
151
+ if conv.get("api_key_hash") == api_key_hash:
152
+ timestamp = conv.get("timestamp", "Unknown time")
153
+ formatted_time = datetime.strptime(timestamp, "%Y%m%d_%H%M%S").strftime("%Y-%m-%d %H:%M:%S")
154
+ choices.append(f"{i + 1}. {formatted_time}")
155
 
156
  return choices
157
  except Exception as e:
 
159
  return []
160
 
161
  # Function to load previous conversations
162
+ def load_conversations(api_key):
163
+ if not api_key:
164
+ return "Please enter your OpenAI API key to view conversations."
165
+
166
  if os.path.exists("conversations.json"):
167
  try:
168
+ api_key_hash = hash_api_key(api_key)
169
  with open("conversations.json", "r") as f:
170
  conversations = [json.loads(line) for line in f]
171
 
172
  conv_text = ""
173
+ conv_count = 0
174
  for i, conv in enumerate(conversations):
175
+ # Only show conversations for this API key
176
+ if conv.get("api_key_hash") == api_key_hash:
177
+ conv_count += 1
178
+ conv_text += f"\n{'='*50}\nConversation {i + 1}\n{'='*50}\n"
179
+ timestamp = conv.get("timestamp", "Unknown time")
180
+ formatted_time = datetime.strptime(timestamp, "%Y%m%d_%H%M%S").strftime("%Y-%m-%d %H:%M:%S")
181
+ conv_text += f"Timestamp: {formatted_time}\n\n"
182
+
183
+ messages = conv.get("messages", conv)
184
+ for message in messages:
185
+ role = message.get('role', 'unknown')
186
+ content = message.get('content', '')
187
+ conv_text += f"{role.upper()}: {content}\n\n"
188
+
189
+ if conv_count == 0:
190
+ return "No conversations found for your API key."
191
 
192
+ return conv_text
193
  except Exception as e:
194
  return f"Error loading conversations: {str(e)}"
195
  return "No previous conversations found."
196
 
197
  # Function to view selected conversation
198
+ def view_selected_conversation(selection, api_key):
199
+ if not api_key:
200
+ return "Please enter your OpenAI API key first."
201
+
202
  if not selection or selection == "Select a conversation":
203
  return "Please select a conversation to view."
204
 
205
  try:
206
+ api_key_hash = hash_api_key(api_key)
207
  # Extract conversation number from selection
208
  conv_number = int(selection.split(".")[0]) - 1
209
 
 
213
 
214
  if conv_number < len(conversations):
215
  conv = conversations[conv_number]
216
+
217
+ # Check if this conversation belongs to the current API key
218
+ if conv.get("api_key_hash") != api_key_hash:
219
+ return "This conversation does not belong to your API key."
220
+
221
  conv_text = f"{'='*50}\n"
222
  timestamp = conv.get("timestamp", "Unknown time")
223
  formatted_time = datetime.strptime(timestamp, "%Y%m%d_%H%M%S").strftime("%Y-%m-%d %H:%M:%S")
 
237
  return f"Error viewing conversation: {str(e)}"
238
 
239
  # Function to delete selected conversation
240
+ def delete_selected_conversation(selection, api_key):
241
+ if not api_key:
242
+ return "Please enter your OpenAI API key first.", gr.update(), "", ""
243
+
244
  if not selection or selection == "Select a conversation":
245
+ return "Please select a conversation to delete.", gr.update(), "", ""
246
 
247
  try:
248
+ api_key_hash = hash_api_key(api_key)
249
  # Extract conversation number from selection
250
  conv_number = int(selection.split(".")[0]) - 1
251
 
 
254
  conversations = [json.loads(line) for line in f]
255
 
256
  if conv_number < len(conversations):
257
+ conv = conversations[conv_number]
258
+
259
+ # Check if this conversation belongs to the current API key
260
+ if conv.get("api_key_hash") != api_key_hash:
261
+ return "You can only delete your own conversations.", gr.update(), "", ""
262
+
263
  # Remove the selected conversation
264
  del conversations[conv_number]
265
 
 
270
  f.write("\n")
271
 
272
  # Update dropdown choices
273
+ choices = get_conversation_choices(api_key)
274
 
275
  # Get updated all conversations display
276
+ all_convs = load_conversations(api_key)
277
 
278
+ return f"Conversation {conv_number + 1} deleted successfully!", gr.update(choices=choices, value="Select a conversation"), all_convs, ""
279
  else:
280
+ return "Conversation not found.", gr.update(), "", ""
281
 
282
+ return "No conversations file found.", gr.update(), "", ""
283
  except Exception as e:
284
+ return f"Error deleting conversation: {str(e)}", gr.update(), "", ""
285
 
286
  # Function to clear current conversation
287
  def clear_conversation():
 
289
  conversation_history = []
290
  return []
291
 
292
+ # Function to delete all conversations for current API key
293
+ def delete_all_conversations(api_key):
294
+ if not api_key:
295
+ return "Please enter your OpenAI API key first.", gr.update(), "", ""
296
+
297
  try:
298
+ api_key_hash = hash_api_key(api_key)
299
+
300
  if os.path.exists("conversations.json"):
301
+ with open("conversations.json", "r") as f:
302
+ conversations = [json.loads(line) for line in f]
303
+
304
+ # Keep only conversations that don't belong to this API key
305
+ remaining_conversations = [conv for conv in conversations if conv.get("api_key_hash") != api_key_hash]
306
+
307
+ deleted_count = len(conversations) - len(remaining_conversations)
308
+
309
+ if deleted_count == 0:
310
+ return "No conversations to delete for your API key.", gr.update(), "No previous conversations found.", ""
311
+
312
+ # Write back remaining conversations
313
+ with open("conversations.json", "w") as f:
314
+ for conv in remaining_conversations:
315
+ json.dump(conv, f)
316
+ f.write("\n")
317
+
318
+ # If no conversations left, remove the file
319
+ if len(remaining_conversations) == 0:
320
+ os.remove("conversations.json")
321
+
322
+ return f"All {deleted_count} conversation(s) deleted successfully!", gr.update(choices=[], value="Select a conversation"), "No previous conversations found.", ""
323
+
324
+ return "No conversations to delete.", gr.update(), "No previous conversations found.", ""
325
  except Exception as e:
326
+ return f"Error deleting conversations: {str(e)}", gr.update(), "", ""
327
 
328
  # Function to refresh dropdown
329
+ def refresh_dropdown(api_key):
330
+ if not api_key:
331
+ return gr.update(choices=[])
332
+ choices = get_conversation_choices(api_key)
333
  return gr.update(choices=choices)
334
 
335
  # Create Gradio interface
336
+ with gr.Blocks(title="Chat with Documents 💬 📚", theme=gr.themes.Ocean()) as demo:
337
  gr.Markdown("# Chat with Documents 💬 📚")
338
  gr.Markdown("Upload PDF or DOCX files and chat with them using AI!")
339
+ gr.Markdown("**Note:** Your conversations are private and tied to your API key. Only you can view and manage your conversations.")
340
 
341
  with gr.Row():
342
  with gr.Column(scale=2):
 
382
 
383
  with gr.Column(scale=1):
384
  gr.Markdown("### Conversation Management")
385
+ gr.Markdown("_Only your conversations are shown below_")
386
 
387
  with gr.Row():
388
  load_convs_btn = gr.Button("Load All Conversations")
 
398
 
399
  conversation_dropdown = gr.Dropdown(
400
  label="Select Conversation",
401
+ choices=[],
402
  value="Select a conversation",
403
  interactive=True
404
  )
 
412
 
413
  with gr.Row():
414
  delete_selected_btn = gr.Button("Delete Selected", variant="stop")
415
+ delete_all_btn = gr.Button("Delete All Mine", variant="stop")
416
 
417
  delete_status = gr.Textbox(label="Delete Status", interactive=False)
418
 
 
442
 
443
  save_btn.click(
444
  fn=save_conversation,
445
+ inputs=api_key_input,
446
  outputs=[save_status, conversation_dropdown]
447
  )
448
 
449
  load_convs_btn.click(
450
  fn=load_conversations,
451
+ inputs=api_key_input,
452
  outputs=convs_display
453
  )
454
 
455
  refresh_btn.click(
456
  fn=refresh_dropdown,
457
+ inputs=api_key_input,
458
  outputs=conversation_dropdown
459
  )
460
 
461
  view_btn.click(
462
  fn=view_selected_conversation,
463
+ inputs=[conversation_dropdown, api_key_input],
464
  outputs=selected_conv_display
465
  )
466
 
467
  delete_selected_btn.click(
468
  fn=delete_selected_conversation,
469
+ inputs=[conversation_dropdown, api_key_input],
470
+ outputs=[delete_status, conversation_dropdown, convs_display, selected_conv_display]
471
  )
472
 
473
  delete_all_btn.click(
474
  fn=delete_all_conversations,
475
+ inputs=api_key_input,
476
+ outputs=[delete_status, conversation_dropdown, convs_display, selected_conv_display]
477
  )
478
 
479
  if __name__ == "__main__":