qwendashcoder commited on
Commit
7971ff5
Β·
verified Β·
1 Parent(s): 1b464e7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -4
app.py CHANGED
@@ -61,7 +61,7 @@ def load_model(selected_model):
61
  return None, f"**❌ Unavailable: {error_msg}**"
62
 
63
  # ================== MULTI-CHAT HELPERS ==================
64
- def create_new_chat(user_chats, logged_in_username):
65
  if not logged_in_username:
66
  return user_chats, None, [], gr.update(choices=[], value=None), "⚠️ Please login first!", ""
67
  new_num = len(user_chats) + 1
@@ -72,7 +72,7 @@ def create_new_chat(user_chats, logged_in_username):
72
  save_chats(logged_in_username, new_user_chats, auth_globals) # Persist changes
73
  return new_user_chats, new_title, [], gr.update(choices=choices, value=new_title), f"βœ… New chat created: {new_title}", ""
74
 
75
- def switch_chat(selected_title, user_chats):
76
  if not selected_title or not user_chats:
77
  return [], None, ""
78
  for chat in user_chats:
@@ -80,7 +80,7 @@ def switch_chat(selected_title, user_chats):
80
  return chat["history"], selected_title, chat.get("context", "")
81
  return [], None, ""
82
 
83
- def delete_current_chat(current_title, user_chats, logged_in_username):
84
  if not logged_in_username or not current_title:
85
  return user_chats, current_title, [], gr.update(), "⚠️ Nothing to delete!", ""
86
  new_user_chats = [chat for chat in user_chats if chat["title"] != current_title]
@@ -113,6 +113,64 @@ def save_chat_context(new_context, user_chats, current_chat_title, logged_in_use
113
  def format_history_for_chatbot(history):
114
  """Return history as-is (already dict format)"""
115
  return history or []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  # ================== CHAT HANDLER WRAPPER (with file limit) ==================
118
  def handle_chat(msg, chatbot, current_model, logged_in_username, user_chats_state, current_chat_title, mode_radio, auth_globals_state, file_upload, current_chat_context):
@@ -140,6 +198,8 @@ def handle_chat(msg, chatbot, current_model, logged_in_username, user_chats_stat
140
  except Exception as e:
141
  gr.Warning(f"⚠️ An error occurred in the chat processing: {str(e)}")
142
  return chatbot # Gracefully return the existing chatbot state
 
 
143
  # ================== GUI ==================
144
  with gr.Blocks(title="NVIDIA AI Chat") as demo:
145
  gr.Markdown("# 🟒 NVIDIA AI Chat\n**School Project β€’ Pre-approved usernames only β€’ Max 20 Accounts globally**")
@@ -154,8 +214,12 @@ with gr.Blocks(title="NVIDIA AI Chat") as demo:
154
  current_chat_title = gr.State(None)
155
  current_chat_context = gr.State("") # Added: State for current chat's context
156
  auth_globals_state = gr.State(auth_globals)
 
 
157
  status_label = gr.Markdown("⚠️ No model loaded. Login + create/select a chat to begin.", elem_id="status-bold") # Made more prominent
158
 
 
 
159
  with gr.Row():
160
  with gr.Column(scale=1, min_width=200):
161
  gr.Markdown("### πŸ“‹ Your Chats")
@@ -182,6 +246,39 @@ with gr.Blocks(title="NVIDIA AI Chat") as demo:
182
  interactive=True, visible=False)
183
  save_context_btn = gr.Button("πŸ’Ύ Save Context", variant="secondary", visible=False)
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  with gr.Row():
186
  msg = gr.Textbox(placeholder="Ask anything...", show_label=False, scale=9)
187
  file_upload = gr.File(
@@ -211,7 +308,7 @@ with gr.Blocks(title="NVIDIA AI Chat") as demo:
211
  # ================== EVENTS ==================
212
  load_btn.click(load_model, model_dropdown, [current_model, status_label])
213
 
214
- new_chat_btn.click(create_new_chat, [user_chats_state, logged_in_username], [user_chats_state, current_chat_title, chatbot, chat_dropdown, status_label, current_chat_context])
215
 
216
  delete_chat_btn.click(delete_current_chat, [current_chat_title, user_chats_state, logged_in_username], [user_chats_state, current_chat_title, chatbot, chat_dropdown, status_label, current_chat_context])
217
 
@@ -249,4 +346,46 @@ with gr.Blocks(title="NVIDIA AI Chat") as demo:
249
  chatbot
250
  ).then(lambda: "", None, msg)
251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  demo.launch(auth=(username, password), theme=gr.themes.Soft(), server_name="0.0.0.0", debug=True, show_error=True)
 
61
  return None, f"**❌ Unavailable: {error_msg}**"
62
 
63
  # ================== MULTI-CHAT HELPERS ==================
64
+ def create_new_chat(user_chats, logged_in_username, coding_files):
65
  if not logged_in_username:
66
  return user_chats, None, [], gr.update(choices=[], value=None), "⚠️ Please login first!", ""
67
  new_num = len(user_chats) + 1
 
72
  save_chats(logged_in_username, new_user_chats, auth_globals) # Persist changes
73
  return new_user_chats, new_title, [], gr.update(choices=choices, value=new_title), f"βœ… New chat created: {new_title}", ""
74
 
75
+ def switch_chat(selected_title, user_chats, coding_files):
76
  if not selected_title or not user_chats:
77
  return [], None, ""
78
  for chat in user_chats:
 
80
  return chat["history"], selected_title, chat.get("context", "")
81
  return [], None, ""
82
 
83
+ def delete_current_chat(current_title, user_chats, logged_in_username, coding_files):
84
  if not logged_in_username or not current_title:
85
  return user_chats, current_title, [], gr.update(), "⚠️ Nothing to delete!", ""
86
  new_user_chats = [chat for chat in user_chats if chat["title"] != current_title]
 
113
  def format_history_for_chatbot(history):
114
  """Return history as-is (already dict format)"""
115
  return history or []
116
+
117
+
118
+ def refresh_file_list(user_chats, current_title):
119
+ if not current_title or not user_chats:
120
+ return gr.update(choices=[], value=None)
121
+ for chat in user_chats:
122
+ if chat["title"] == current_title:
123
+ files = list(chat.get("coding_files", {}).keys())
124
+ return gr.update(choices=files, value=files[0] if files else None)
125
+ return gr.update(choices=[], value=None)
126
+
127
+ def load_file_to_editor(selected_file, user_chats, current_title):
128
+ if not selected_file or not current_title:
129
+ return "", "python"
130
+ for chat in user_chats:
131
+ if chat["title"] == current_title:
132
+ f = chat.get("coding_files", {}).get(selected_file, {})
133
+ return f.get("content", ""), f.get("language", "python")
134
+ return "", "python"
135
+
136
+ def save_file_content(selected_file, new_content, new_language, user_chats, current_title, logged_in_username, auth_globals):
137
+ if not selected_file or not current_title or not logged_in_username:
138
+ return user_chats, "❌ No file selected"
139
+ for chat in user_chats:
140
+ if chat["title"] == current_title:
141
+ if "coding_files" not in chat:
142
+ chat["coding_files"] = {}
143
+ chat["coding_files"][selected_file] = {"content": new_content, "language": new_language}
144
+ break
145
+ save_chats(logged_in_username, user_chats, auth_globals)
146
+ return user_chats, f"βœ… Saved {selected_file}"
147
+
148
+ def add_uploaded_files(uploaded_files, user_chats, current_title, logged_in_username, auth_globals):
149
+ if not uploaded_files or not current_title:
150
+ return user_chats, gr.update(), "❌ No chat selected"
151
+ for chat in user_chats:
152
+ if chat["title"] == current_title:
153
+ if "coding_files" not in chat:
154
+ chat["coding_files"] = {}
155
+ for path in uploaded_files if isinstance(uploaded_files, list) else [uploaded_files]:
156
+ name = os.path.basename(path)
157
+ with open(path, "r", encoding="utf-8") as f:
158
+ content = f.read()
159
+ lang = "python" if name.endswith(".py") else "javascript" if name.endswith(".js") else "html" if name.endswith(".html") else "text"
160
+ chat["coding_files"][name] = {"content": content, "language": lang}
161
+ break
162
+ save_chats(logged_in_username, user_chats, auth_globals)
163
+ return user_chats, refresh_file_list(user_chats, current_title), "βœ… Files added to persistent storage"
164
+
165
+ def delete_selected_file(selected_file, user_chats, current_title, logged_in_username, auth_globals):
166
+ if not selected_file or not current_title:
167
+ return user_chats, gr.update(), "❌ Nothing to delete"
168
+ for chat in user_chats:
169
+ if chat["title"] == current_title and "coding_files" in chat:
170
+ chat["coding_files"].pop(selected_file, None)
171
+ break
172
+ save_chats(logged_in_username, user_chats, auth_globals)
173
+ return user_chats, refresh_file_list(user_chats, current_title), f"πŸ—‘οΈ Deleted {selected_file}"
174
 
175
  # ================== CHAT HANDLER WRAPPER (with file limit) ==================
176
  def handle_chat(msg, chatbot, current_model, logged_in_username, user_chats_state, current_chat_title, mode_radio, auth_globals_state, file_upload, current_chat_context):
 
198
  except Exception as e:
199
  gr.Warning(f"⚠️ An error occurred in the chat processing: {str(e)}")
200
  return chatbot # Gracefully return the existing chatbot state
201
+
202
+
203
  # ================== GUI ==================
204
  with gr.Blocks(title="NVIDIA AI Chat") as demo:
205
  gr.Markdown("# 🟒 NVIDIA AI Chat\n**School Project β€’ Pre-approved usernames only β€’ Max 20 Accounts globally**")
 
214
  current_chat_title = gr.State(None)
215
  current_chat_context = gr.State("") # Added: State for current chat's context
216
  auth_globals_state = gr.State(auth_globals)
217
+ coding_files_state = gr.State({}) # { "filename.py": {"content": "...", "language": "python"} }
218
+ current_file_name = gr.State(None)
219
  status_label = gr.Markdown("⚠️ No model loaded. Login + create/select a chat to begin.", elem_id="status-bold") # Made more prominent
220
 
221
+
222
+
223
  with gr.Row():
224
  with gr.Column(scale=1, min_width=200):
225
  gr.Markdown("### πŸ“‹ Your Chats")
 
246
  interactive=True, visible=False)
247
  save_context_btn = gr.Button("πŸ’Ύ Save Context", variant="secondary", visible=False)
248
 
249
+ # ================== CODING MODE FILE MANAGER (visible only in Coding Mode) ==================
250
+ with gr.Row(visible=False) as coding_manager_row:
251
+ with gr.Column(scale=1, min_width=280):
252
+ gr.Markdown("### πŸ“ Persistent Project Files\n(saved per chat β€’ only in Coding Mode)")
253
+ file_upload_coding = gr.File(
254
+ label="Upload files",
255
+ file_types=[".py",".js",".html",".css",".txt",".md",".json",".ts"],
256
+ file_count="multiple",
257
+ type="filepath"
258
+ )
259
+ add_files_btn = gr.Button("βž• Add / Replace files", variant="primary")
260
+
261
+ file_list_dropdown = gr.Dropdown(choices=[], label="Select file to edit", interactive=True)
262
+ delete_file_btn = gr.Button("πŸ—‘οΈ Delete selected file", variant="stop", size="sm")
263
+
264
+ with gr.Column(scale=4):
265
+ file_editor = gr.Code(
266
+ label="Editor",
267
+ value="",
268
+ language="python",
269
+ lines=24,
270
+ interactive=True,
271
+ show_label=True
272
+ )
273
+ with gr.Row():
274
+ language_selector = gr.Dropdown(
275
+ choices=["python", "javascript", "typescript", "html", "css", "markdown", "json", "text"],
276
+ value="python",
277
+ label="Language",
278
+ scale=1
279
+ )
280
+ save_file_btn = gr.Button("πŸ’Ύ Save file", variant="primary", scale=2)
281
+
282
  with gr.Row():
283
  msg = gr.Textbox(placeholder="Ask anything...", show_label=False, scale=9)
284
  file_upload = gr.File(
 
308
  # ================== EVENTS ==================
309
  load_btn.click(load_model, model_dropdown, [current_model, status_label])
310
 
311
+ new_chat_btn.click(create_new_chat[], [user_chats_state, logged_in_username], [user_chats_state, current_chat_title, chatbot, chat_dropdown, status_label, current_chat_context])
312
 
313
  delete_chat_btn.click(delete_current_chat, [current_chat_title, user_chats_state, logged_in_username], [user_chats_state, current_chat_title, chatbot, chat_dropdown, status_label, current_chat_context])
314
 
 
346
  chatbot
347
  ).then(lambda: "", None, msg)
348
 
349
+ # File manager events
350
+ add_files_btn.click(
351
+ add_uploaded_files,
352
+ [file_upload_coding, user_chats_state, current_chat_title, logged_in_username, auth_globals_state],
353
+ [user_chats_state, file_list_dropdown, status_label]
354
+ )
355
+
356
+ file_list_dropdown.change(
357
+ load_file_to_editor,
358
+ [file_list_dropdown, user_chats_state, current_chat_title],
359
+ [file_editor, language_selector]
360
+ )
361
+
362
+ save_file_btn.click(
363
+ save_file_content,
364
+ [file_list_dropdown, file_editor, language_selector, user_chats_state, current_chat_title, logged_in_username, auth_globals_state],
365
+ [user_chats_state, status_label]
366
+ ).then(refresh_file_list, [user_chats_state, current_chat_title], file_list_dropdown)
367
+
368
+ delete_file_btn.click(
369
+ delete_selected_file,
370
+ [file_list_dropdown, user_chats_state, current_chat_title, logged_in_username, auth_globals_state],
371
+ [user_chats_state, file_list_dropdown, status_label]
372
+ )
373
+
374
+ language_selector.change(
375
+ lambda lang: gr.update(language=lang),
376
+ language_selector,
377
+ file_editor
378
+ )
379
+
380
+ # Show/hide file manager when mode changes
381
+ mode_radio.change(
382
+ lambda m: gr.update(visible=(m == "πŸ’» Coding Mode")),
383
+ mode_radio,
384
+ coding_manager_row
385
+ ).then(
386
+ refresh_file_list,
387
+ [user_chats_state, current_chat_title],
388
+ file_list_dropdown
389
+ )
390
+
391
  demo.launch(auth=(username, password), theme=gr.themes.Soft(), server_name="0.0.0.0", debug=True, show_error=True)