arubaDev commited on
Commit
4a51780
·
verified ·
1 Parent(s): cc439b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -293
app.py CHANGED
@@ -13,25 +13,20 @@ MODELS = {
13
  "Mistral 7B Instruct": "mistralai/Mistral-7B-Instruct-v0.3",
14
  }
15
 
16
- DATASETS = ["The Stack", "CodeXGLUE"] # Dropdown for dataset selection
17
- HF_TOKEN = os.getenv("HF_TOKEN") # Set in your Space's Secrets
18
  DB_PATH = "history.db"
19
 
20
  SYSTEM_DEFAULT = (
21
- "Specializes in databases, APIs, auth, CRUD."
22
- "Provides complete backend code scaffolds."
23
- "Provide full backend code scaffolds with files, paths, and commands. "
24
  "Declines frontend-heavy requests."
25
  )
26
 
27
  # ---------------------------
28
  # DB Setup
29
  # ---------------------------
30
- def db():
31
- conn = sqlite3.connect(DB_PATH)
32
- conn.execute("PRAGMA journal_mode=WAL;")
33
- return conn
34
-
35
  def init_db():
36
  conn = db()
37
  cur = conn.cursor()
@@ -62,10 +57,10 @@ def create_session(title: str = "New chat") -> int:
62
  "INSERT INTO sessions (title, created_at) VALUES (?, ?)",
63
  (title, datetime.utcnow().isoformat())
64
  )
65
- session_id = cur.lastrowid
66
  conn.commit()
67
  conn.close()
68
- return session_id
69
 
70
  def delete_session(session_id: int):
71
  conn = db()
@@ -93,9 +88,8 @@ def get_messages(session_id: int):
93
  WHERE session_id = ?
94
  ORDER BY id ASC
95
  """, (session_id,))
96
- rows = cur.fetchall()
97
  conn.close()
98
- msgs = [{"role": role, "content": content} for (role, content) in rows]
99
  return msgs
100
 
101
  def add_message(session_id: int, role: str, content: str):
@@ -112,24 +106,17 @@ def update_session_title_if_needed(session_id: int, first_user_text: str):
112
  conn = db()
113
  cur = conn.cursor()
114
  cur.execute("SELECT COUNT(*) FROM messages WHERE session_id=? AND role='user'", (session_id,))
115
- count_users = cur.fetchone()[0]
116
- if count_users == 1:
117
  title = first_user_text.strip().split("\n")[0]
118
  title = (title[:50] + "…") if len(title) > 50 else title
119
  cur.execute("UPDATE sessions SET title=? WHERE id=?", (title or "New chat", session_id))
120
  conn.commit()
121
  conn.close()
122
 
123
- # ---------------------------
124
- # Helpers
125
- # ---------------------------
126
  def label_to_id(label: str | None) -> int | None:
127
- if not label:
128
- return None
129
- try:
130
- return int(label.split("•", 1)[0].strip())
131
- except Exception:
132
- return None
133
 
134
  def build_api_messages(session_id: int, system_message: str):
135
  msgs = [{"role": "system", "content": system_message.strip()}]
@@ -137,23 +124,24 @@ def build_api_messages(session_id: int, system_message: str):
137
  return msgs
138
 
139
  def get_client(model_choice: str):
140
- model_id = MODELS.get(model_choice, list(MODELS.values())[0])
141
- return InferenceClient(model_id, token=HF_TOKEN)
142
 
143
  def load_dataset_by_name(name: str):
144
- if name == "The Stack":
145
- return load_dataset("bigcode/the-stack", split="train")
146
- elif name == "CodeXGLUE":
147
- return load_dataset("google/code_x_glue_cc_code_to_code_trans", split="train")
148
  return None
149
 
 
 
 
 
150
  # ---------------------------
151
- # Gradio Callbacks
152
  # ---------------------------
153
  def refresh_sessions_cb():
154
  labels, _ = list_sessions()
155
  selected = labels[0] if labels else None
156
- visible = True if selected else False
157
  return (
158
  gr.update(choices=labels, value=selected),
159
  gr.update(visible=visible),
@@ -166,350 +154,159 @@ def new_chat_cb():
166
  sid = create_session("New chat")
167
  labels, _ = list_sessions()
168
  selected = next((lbl for lbl in labels if lbl.startswith(f"{sid} ")), None)
169
- # Return: session_list, chatbot (empty), user_box cleared, then make edit/save/delete/refresh visible
170
  return (
171
  gr.update(choices=labels, value=selected),
172
- [], # chatbot messages
173
- "", # user_box cleared
174
- gr.update(visible=True), # edit_title_box visible
175
- gr.update(visible=True), # save_title_btn visible
176
- gr.update(visible=True), # del_btn visible
177
- gr.update(visible=True), # refresh_btn visible
178
  )
179
 
180
  def load_session_cb(selected_label):
181
  sid = label_to_id(selected_label)
182
- if not sid:
183
- # no valid selection -> hide controls
184
- return [], gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
185
- msgs = get_messages(sid)
186
- return (
187
- msgs,
188
- gr.update(visible=True),
189
- gr.update(visible=True),
190
- gr.update(visible=True),
191
- gr.update(visible=True),
192
- )
193
 
194
  def delete_chat_cb(selected_label):
195
  sid = label_to_id(selected_label)
196
- if sid:
197
- delete_session(sid)
198
  labels, _ = list_sessions()
199
  selected = labels[0] if labels else None
200
- visible = True if selected else False
201
- return (
202
- gr.update(choices=labels, value=selected),
203
- [], # chatbot cleared
204
- gr.update(visible=visible),
205
- gr.update(visible=visible),
206
- gr.update(visible=visible),
207
- gr.update(visible=visible),
208
- )
209
-
210
- FRONTEND_KEYWORDS = [
211
- "react", "vue", "angular", "html", "css", "javascript", "tailwind", "recharts", "typescript"
212
- ]
213
-
214
- def is_frontend_request(user_text: str) -> bool:
215
- text_lower = user_text.lower()
216
- return any(kw in text_lower for kw in FRONTEND_KEYWORDS)
217
 
218
- # --- Fixed send_cb to show user message ---
219
  def send_cb(user_text, selected_label, chatbot_msgs, system_message, max_tokens, temperature, top_p, model_choice, dataset_choice, *args):
220
- sid = label_to_id(selected_label)
221
- if sid is None:
222
- sid = create_session("New chat")
223
- labels, _ = list_sessions()
224
- selected_label = next((lbl for lbl in labels if lbl.startswith(f"{sid} ")), None)
225
-
226
- # Save user message
227
  add_message(sid, "user", user_text)
228
  update_session_title_if_needed(sid, user_text)
229
 
230
- display_msgs = chatbot_msgs[:]
231
- display_msgs.append({"role": "user", "content": user_text})
232
-
233
- # Check for frontend-heavy request
234
  if is_frontend_request(user_text):
235
  apology = "⚠️ I'm a backend-focused assistant and cannot provide frontend code."
236
  display_msgs.append({"role": "assistant", "content": apology})
237
  add_message(sid, "assistant", apology)
238
- yield (display_msgs, "", selected_label)
239
  return
240
 
241
- # Normal backend response
242
  display_msgs.append({"role": "assistant", "content": "…"})
243
- yield (display_msgs, "", selected_label)
244
 
245
  client = get_client(model_choice)
246
  api_messages = build_api_messages(sid, system_message)
247
  partial = ""
248
 
249
  try:
250
- for chunk in client.chat_completion(
251
- messages=api_messages,
252
- max_tokens=int(max_tokens),
253
- temperature=float(temperature),
254
- top_p=float(top_p),
255
- stream=True,
256
- ):
257
- # --- FIX: handle models that send empty chunks or use message instead of delta ---
258
- if not hasattr(chunk, "choices") or not chunk.choices:
259
- continue
260
  choice = chunk.choices[0]
261
- delta = ""
262
- if hasattr(choice, "delta") and choice.delta and getattr(choice.delta, "content", None) is not None:
263
- delta = choice.delta.content
264
- elif hasattr(choice, "message") and getattr(choice.message, "content", None) is not None:
265
- delta = choice.message.content
266
-
267
  if delta:
268
  partial += delta
269
  display_msgs[-1]["content"] = partial
270
- yield (display_msgs, "", selected_label)
271
-
272
  add_message(sid, "assistant", partial)
273
-
274
  except Exception as e:
275
- display_msgs[-1]["content"] = f"⚠️ Error: {str(e)}"
276
- yield (display_msgs, "", selected_label)
277
 
 
278
  def regenerate_cb(selected_label, system_message, max_tokens, temperature, top_p, model_choice, dataset_choice):
279
  sid = label_to_id(selected_label)
280
- if sid is None:
281
- return [], ""
282
-
283
  msgs = get_messages(sid)
284
- if not msgs:
285
- return [], ""
286
-
287
- # Remove the last assistant message if it exists (to regenerate it)
288
  if msgs and msgs[-1]["role"] == "assistant":
289
  conn = db()
290
  cur = conn.cursor()
291
- cur.execute("""
292
- DELETE FROM messages
293
- WHERE id = (
294
- SELECT id FROM messages
295
- WHERE session_id=?
296
- ORDER BY id DESC LIMIT 1
297
- )
298
- """, (sid,))
299
  conn.commit()
300
  conn.close()
301
  msgs = get_messages(sid)
302
-
303
- dataset = load_dataset_by_name(dataset_choice)
304
- api_messages = [{"role": "system", "content": system_message.strip()}] + msgs
305
  display_msgs = msgs + [{"role": "assistant", "content": ""}]
306
-
307
  client = get_client(model_choice)
308
  partial = ""
309
-
310
  try:
311
- for chunk in client.chat_completion(
312
- messages=api_messages,
313
- max_tokens=int(max_tokens),
314
- temperature=float(temperature),
315
- top_p=float(top_p),
316
- stream=True,
317
- ):
318
- # --- FIX: handle models that send empty chunks or use message instead of delta ---
319
- if not hasattr(chunk, "choices") or not chunk.choices:
320
- continue
321
- choice = chunk.choices[0]
322
- delta = ""
323
- if hasattr(choice, "delta") and choice.delta and getattr(choice.delta, "content", None) is not None:
324
- delta = choice.delta.content
325
- elif hasattr(choice, "message") and getattr(choice.message, "content", None) is not None:
326
- delta = choice.message.content
327
-
328
  if delta:
329
  partial += delta
330
  display_msgs[-1]["content"] = partial
331
  yield display_msgs
332
-
333
  add_message(sid, "assistant", partial)
334
-
335
  except Exception as e:
336
- display_msgs[-1]["content"] = f"⚠️ Error: {str(e)}"
337
- yield (display_msgs, "", selected_label)
338
 
339
  # ---------------------------
340
  # App UI
341
  # ---------------------------
342
  init_db()
343
  labels, _ = list_sessions()
344
- if not labels:
345
- first_sid = create_session("New chat")
346
- labels, _ = list_sessions()
347
-
348
  default_selected = labels[0] if labels else None
349
 
350
  with gr.Blocks(title="Backend-Focused LLaMA/Mistral CRUD Assistant", theme=gr.themes.Soft()) as demo:
351
- # Minimal CSS for compact, professional look
352
  gr.HTML("""
353
  <style>
354
- /* compact action row below chat list */
355
- #session-actions-row .gr-button {
356
- margin-right: 6px;
357
- }
358
- /* keep settings compact */
359
- .compact-sliders .gr-slider,
360
- .compact-sliders .gr-number { margin-bottom: 0.5rem !important; }
361
- .system-message-compact .gr-textarea {
362
- min-height: 80px !important;
363
- max-height: 120px !important;
364
- }
365
  </style>
366
  """)
367
 
368
- gr.Markdown("## 🗄️ LLaMA & Mistral Backend-Focused CRUD Automation — with Persistent History")
369
 
370
  with gr.Row(equal_height=True):
371
  with gr.Column(scale=1, min_width=260):
372
  gr.Markdown("### 📁 Sessions")
373
-
374
- # Main session list
375
- session_list = gr.Radio(
376
- choices=labels,
377
- value=default_selected,
378
- label="Your Chats",
379
- interactive=True
380
- )
381
-
382
- # Row for actions (visible/hidden controlled via callbacks)
383
  with gr.Row(elem_id="session-actions-row"):
384
- new_btn = gr.Button("New Chat", elem_id="new-chat-btn")
385
- rename_btn = gr.Button("Rename", elem_id="rename-chat-btn", visible=False)
386
- save_title_btn = gr.Button("Save", elem_id="save-title-btn", visible=False)
387
- del_btn = gr.Button("Delete", elem_id="delete-chat-btn", visible=False)
388
- refresh_btn = gr.Button("Refresh", elem_id="refresh-btn", visible=False)
389
-
390
- # Rename textbox (hidden until Rename is clicked)
391
- edit_title_box = gr.Textbox(
392
- label="Edit Chat Name",
393
- placeholder="Type new chat name here…",
394
- visible=False
395
- )
396
-
397
- # Callback to open the rename box (show edit box + save button)
398
- def show_rename_ui():
399
- return gr.update(visible=True), gr.update(visible=True)
400
-
401
- rename_btn.click(fn=show_rename_ui, outputs=[edit_title_box, save_title_btn])
402
-
403
- # Callback for renaming -> updates DB and refreshes list, clears edit box
404
- def rename_session_cb(new_title, selected_label):
405
- sid = label_to_id(selected_label)
406
- if sid and new_title.strip():
407
- conn = db()
408
- cur = conn.cursor()
409
- cur.execute("UPDATE sessions SET title=? WHERE id=?", (new_title.strip(), sid))
410
- conn.commit()
411
- conn.close()
412
- labels, _ = list_sessions()
413
- new_selected = next((lbl for lbl in labels if lbl.startswith(f"{sid} ")), None)
414
- # return updated session list selection and clear the edit box value
415
- return gr.update(choices=labels, value=new_selected), gr.update(value="")
416
-
417
- save_title_btn.click(
418
- rename_session_cb,
419
- inputs=[edit_title_box, session_list],
420
- outputs=[session_list, edit_title_box]
421
- )
422
-
423
- # -------- Model selection --------
424
  gr.Markdown("### 🤖 Model Selection")
425
- model_choice = gr.Dropdown(
426
- choices=list(MODELS.keys()),
427
- value=list(MODELS.keys())[0],
428
- label="Choose a model",
429
- interactive=True
430
- )
431
-
432
- # -------- Dataset selection --------
433
  gr.Markdown("### 📚 Dataset Selection")
434
- dataset_choice = gr.Dropdown(
435
- choices=DATASETS,
436
- value=DATASETS[0],
437
- label="Select a dataset",
438
- interactive=True
439
- )
440
-
441
- # -------- Generation settings --------
442
  gr.Markdown("### ⚙️ Generation Settings")
443
  with gr.Group(elem_classes="system-message-compact"):
444
- system_box = gr.Textbox(
445
- value=SYSTEM_DEFAULT,
446
- label="System message",
447
- lines=3
448
- )
449
-
450
  with gr.Group(elem_classes="compact-sliders"):
451
  max_tokens = gr.Slider(256, 4096, value=1200, step=16, label="Max tokens")
452
  temperature = gr.Slider(0.0, 2.0, value=0.25, step=0.05, label="Temperature")
453
  top_p = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-p")
454
 
455
- # with gr.Column(scale=3):
456
- # chatbot = gr.Chatbot(label="Assistant", height=500, type="messages")
457
- # with gr.Row():
458
- # user_box = gr.Textbox(placeholder="Describe your CRUD/backend task…", lines=3, scale=5)
459
- # with gr.Row():
460
- # send_btn = gr.Button("Send ▶️", variant="primary")
461
- # regen_btn = gr.Button("Regenerate 🔁", variant="secondary")
462
  with gr.Column(scale=3):
463
- chatbot = gr.Chatbot(label="Assistant", height=500, type="messages")
464
-
465
- # --- Single row for textbox + buttons ---
466
- with gr.Row():
467
- user_box = gr.Textbox(
468
- placeholder="Describe your CRUD/backend task…",
469
- lines=3,
470
- scale=5
471
- )
472
- send_btn = gr.Button("Send ▶️", variant="primary", scale=1)
473
- regen_btn = gr.Button("Regenerate 🔁", variant="secondary", scale=1)
474
-
475
-
476
- # Wire callbacks updated outputs so visibility changes flow correctly
477
- refresh_btn.click(
478
- refresh_sessions_cb,
479
- outputs=[session_list, edit_title_box, save_title_btn, del_btn, refresh_btn],
480
- )
481
- new_btn.click(
482
- new_chat_cb,
483
- outputs=[session_list, chatbot, user_box, edit_title_box, save_title_btn, del_btn, refresh_btn],
484
- )
485
- del_btn.click(
486
- delete_chat_cb,
487
- inputs=session_list,
488
- outputs=[session_list, chatbot, edit_title_box, save_title_btn, del_btn, refresh_btn],
489
- )
490
- session_list.change(
491
- load_session_cb,
492
- inputs=session_list,
493
- outputs=[chatbot, edit_title_box, save_title_btn, del_btn, refresh_btn],
494
- )
495
-
496
- send_btn.click(
497
- send_cb,
498
- inputs=[user_box, session_list, chatbot, system_box, max_tokens, temperature, top_p, model_choice, dataset_choice],
499
- outputs=[chatbot, user_box, session_list]
500
- )
501
-
502
- user_box.submit(
503
- send_cb,
504
- inputs=[user_box, session_list, chatbot, system_box, max_tokens, temperature, top_p, model_choice, dataset_choice],
505
- outputs=[chatbot, user_box, session_list]
506
- )
507
-
508
- regen_btn.click(
509
- regenerate_cb,
510
- inputs=[session_list, system_box, max_tokens, temperature, top_p, model_choice, dataset_choice],
511
- outputs=chatbot
512
- )
513
 
514
  if __name__ == "__main__":
515
  demo.launch()
 
13
  "Mistral 7B Instruct": "mistralai/Mistral-7B-Instruct-v0.3",
14
  }
15
 
16
+ DATASETS = ["The Stack", "CodeXGLUE"]
17
+ HF_TOKEN = os.getenv("HF_TOKEN")
18
  DB_PATH = "history.db"
19
 
20
  SYSTEM_DEFAULT = (
21
+ "Specializes in databases, APIs, auth, CRUD. "
22
+ "Provides complete backend code scaffolds. "
 
23
  "Declines frontend-heavy requests."
24
  )
25
 
26
  # ---------------------------
27
  # DB Setup
28
  # ---------------------------
29
+ def db(): return sqlite3.connect(DB_PATH)
 
 
 
 
30
  def init_db():
31
  conn = db()
32
  cur = conn.cursor()
 
57
  "INSERT INTO sessions (title, created_at) VALUES (?, ?)",
58
  (title, datetime.utcnow().isoformat())
59
  )
60
+ sid = cur.lastrowid
61
  conn.commit()
62
  conn.close()
63
+ return sid
64
 
65
  def delete_session(session_id: int):
66
  conn = db()
 
88
  WHERE session_id = ?
89
  ORDER BY id ASC
90
  """, (session_id,))
91
+ msgs = [{"role": role, "content": content} for (role, content) in cur.fetchall()]
92
  conn.close()
 
93
  return msgs
94
 
95
  def add_message(session_id: int, role: str, content: str):
 
106
  conn = db()
107
  cur = conn.cursor()
108
  cur.execute("SELECT COUNT(*) FROM messages WHERE session_id=? AND role='user'", (session_id,))
109
+ if cur.fetchone()[0] == 1:
 
110
  title = first_user_text.strip().split("\n")[0]
111
  title = (title[:50] + "…") if len(title) > 50 else title
112
  cur.execute("UPDATE sessions SET title=? WHERE id=?", (title or "New chat", session_id))
113
  conn.commit()
114
  conn.close()
115
 
 
 
 
116
  def label_to_id(label: str | None) -> int | None:
117
+ if not label: return None
118
+ try: return int(label.split("•", 1)[0].strip())
119
+ except: return None
 
 
 
120
 
121
  def build_api_messages(session_id: int, system_message: str):
122
  msgs = [{"role": "system", "content": system_message.strip()}]
 
124
  return msgs
125
 
126
  def get_client(model_choice: str):
127
+ return InferenceClient(MODELS.get(model_choice, list(MODELS.values())[0]), token=HF_TOKEN)
 
128
 
129
  def load_dataset_by_name(name: str):
130
+ if name == "The Stack": return load_dataset("bigcode/the-stack", split="train")
131
+ if name == "CodeXGLUE": return load_dataset("google/code_x_glue_cc_code_to_code_trans", split="train")
 
 
132
  return None
133
 
134
+ FRONTEND_KEYWORDS = ["react", "vue", "angular", "html", "css", "javascript", "tailwind", "recharts", "typescript"]
135
+ def is_frontend_request(user_text: str) -> bool:
136
+ return any(kw in user_text.lower() for kw in FRONTEND_KEYWORDS)
137
+
138
  # ---------------------------
139
+ # Callbacks
140
  # ---------------------------
141
  def refresh_sessions_cb():
142
  labels, _ = list_sessions()
143
  selected = labels[0] if labels else None
144
+ visible = bool(selected)
145
  return (
146
  gr.update(choices=labels, value=selected),
147
  gr.update(visible=visible),
 
154
  sid = create_session("New chat")
155
  labels, _ = list_sessions()
156
  selected = next((lbl for lbl in labels if lbl.startswith(f"{sid} ")), None)
 
157
  return (
158
  gr.update(choices=labels, value=selected),
159
+ [], "", # chatbot cleared, user box cleared
160
+ gr.update(visible=True), gr.update(visible=True),
161
+ gr.update(visible=True), gr.update(visible=True),
 
 
 
162
  )
163
 
164
  def load_session_cb(selected_label):
165
  sid = label_to_id(selected_label)
166
+ if not sid: return [], gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
167
+ return get_messages(sid), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)
 
 
 
 
 
 
 
 
 
168
 
169
  def delete_chat_cb(selected_label):
170
  sid = label_to_id(selected_label)
171
+ if sid: delete_session(sid)
 
172
  labels, _ = list_sessions()
173
  selected = labels[0] if labels else None
174
+ visible = bool(selected)
175
+ return gr.update(choices=labels, value=selected), [], gr.update(visible=visible), gr.update(visible=visible), gr.update(visible=visible), gr.update(visible=visible)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ # --- Send ---
178
  def send_cb(user_text, selected_label, chatbot_msgs, system_message, max_tokens, temperature, top_p, model_choice, dataset_choice, *args):
179
+ sid = label_to_id(selected_label) or create_session("New chat")
 
 
 
 
 
 
180
  add_message(sid, "user", user_text)
181
  update_session_title_if_needed(sid, user_text)
182
 
183
+ display_msgs = chatbot_msgs[:] + [{"role": "user", "content": user_text}]
 
 
 
184
  if is_frontend_request(user_text):
185
  apology = "⚠️ I'm a backend-focused assistant and cannot provide frontend code."
186
  display_msgs.append({"role": "assistant", "content": apology})
187
  add_message(sid, "assistant", apology)
188
+ yield display_msgs, "", selected_label
189
  return
190
 
 
191
  display_msgs.append({"role": "assistant", "content": "…"})
192
+ yield display_msgs, "", selected_label
193
 
194
  client = get_client(model_choice)
195
  api_messages = build_api_messages(sid, system_message)
196
  partial = ""
197
 
198
  try:
199
+ for chunk in client.chat_completion(messages=api_messages, max_tokens=int(max_tokens), temperature=float(temperature), top_p=float(top_p), stream=True):
200
+ if not hasattr(chunk, "choices") or not chunk.choices: continue
 
 
 
 
 
 
 
 
201
  choice = chunk.choices[0]
202
+ delta = getattr(getattr(choice, "delta", None), "content", None) or getattr(getattr(choice, "message", None), "content", None) or ""
 
 
 
 
 
203
  if delta:
204
  partial += delta
205
  display_msgs[-1]["content"] = partial
206
+ yield display_msgs, "", selected_label
 
207
  add_message(sid, "assistant", partial)
 
208
  except Exception as e:
209
+ display_msgs[-1]["content"] = f"⚠️ Error: {e}"
210
+ yield display_msgs, "", selected_label
211
 
212
+ # --- Regenerate ---
213
  def regenerate_cb(selected_label, system_message, max_tokens, temperature, top_p, model_choice, dataset_choice):
214
  sid = label_to_id(selected_label)
215
+ if not sid: return [], ""
 
 
216
  msgs = get_messages(sid)
 
 
 
 
217
  if msgs and msgs[-1]["role"] == "assistant":
218
  conn = db()
219
  cur = conn.cursor()
220
+ cur.execute("DELETE FROM messages WHERE id=(SELECT id FROM messages WHERE session_id=? ORDER BY id DESC LIMIT 1)", (sid,))
 
 
 
 
 
 
 
221
  conn.commit()
222
  conn.close()
223
  msgs = get_messages(sid)
 
 
 
224
  display_msgs = msgs + [{"role": "assistant", "content": ""}]
 
225
  client = get_client(model_choice)
226
  partial = ""
 
227
  try:
228
+ for chunk in client.chat_completion(messages=[{"role": "system", "content": system_message.strip()}]+msgs, max_tokens=int(max_tokens), temperature=float(temperature), top_p=float(top_p), stream=True):
229
+ if not hasattr(chunk, "choices") or not chunk.choices: continue
230
+ delta = getattr(getattr(chunk.choices[0], "delta", None), "content", None) or getattr(getattr(chunk.choices[0], "message", None), "content", None) or ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  if delta:
232
  partial += delta
233
  display_msgs[-1]["content"] = partial
234
  yield display_msgs
 
235
  add_message(sid, "assistant", partial)
 
236
  except Exception as e:
237
+ display_msgs[-1]["content"] = f"⚠️ Error: {e}"
238
+ yield display_msgs, "", selected_label
239
 
240
  # ---------------------------
241
  # App UI
242
  # ---------------------------
243
  init_db()
244
  labels, _ = list_sessions()
245
+ if not labels: create_session("New chat"); labels, _ = list_sessions()
 
 
 
246
  default_selected = labels[0] if labels else None
247
 
248
  with gr.Blocks(title="Backend-Focused LLaMA/Mistral CRUD Assistant", theme=gr.themes.Soft()) as demo:
249
+ # --- Custom CSS ---
250
  gr.HTML("""
251
  <style>
252
+ /* Chat scroll */
253
+ .gr-chatbot { max-height: 500px !important; overflow-y: auto !important; }
254
+ /* Compact left panel */
255
+ .compact-sliders .gr-slider, .compact-sliders .gr-number { margin-bottom:0.5rem !important; font-size:0.9rem;}
256
+ .system-message-compact .gr-textarea { min-height:80px !important; max-height:120px !important; font-size:0.9rem; }
257
+ /* Action buttons compact */
258
+ #session-actions-row .gr-button { margin-right: 6px; margin-bottom:3px; font-size:0.9rem;}
259
+ /* Input + buttons row */
260
+ .user-input-row .gr-textbox, .user-input-row .gr-button { margin:0 !important; padding:0.4rem 0.6rem !important; }
 
 
261
  </style>
262
  """)
263
 
264
+ gr.Markdown("## 🗄️ LLaMA & Mistral Backend-Focused CRUD Automation — Persistent History")
265
 
266
  with gr.Row(equal_height=True):
267
  with gr.Column(scale=1, min_width=260):
268
  gr.Markdown("### 📁 Sessions")
269
+ session_list = gr.Radio(choices=labels, value=default_selected, label="Your Chats", interactive=True)
 
 
 
 
 
 
 
 
 
270
  with gr.Row(elem_id="session-actions-row"):
271
+ new_btn = gr.Button("New Chat")
272
+ rename_btn = gr.Button("Rename", visible=False)
273
+ save_title_btn = gr.Button("Save", visible=False)
274
+ del_btn = gr.Button("Delete", visible=False)
275
+ refresh_btn = gr.Button("Refresh", visible=False)
276
+ edit_title_box = gr.Textbox(label="Edit Chat Name", placeholder="Type new chat name…", visible=False)
277
+
278
+ # Model selection
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  gr.Markdown("### 🤖 Model Selection")
280
+ model_choice = gr.Dropdown(choices=list(MODELS.keys()), value=list(MODELS.keys())[0], label="Choose a model", interactive=True)
281
+
282
+ # Dataset selection
 
 
 
 
 
283
  gr.Markdown("### 📚 Dataset Selection")
284
+ dataset_choice = gr.Dropdown(choices=DATASETS, value=DATASETS[0], label="Select a dataset", interactive=True)
285
+
286
+ # Generation settings
 
 
 
 
 
287
  gr.Markdown("### ⚙️ Generation Settings")
288
  with gr.Group(elem_classes="system-message-compact"):
289
+ system_box = gr.Textbox(value=SYSTEM_DEFAULT, label="System message", lines=3)
 
 
 
 
 
290
  with gr.Group(elem_classes="compact-sliders"):
291
  max_tokens = gr.Slider(256, 4096, value=1200, step=16, label="Max tokens")
292
  temperature = gr.Slider(0.0, 2.0, value=0.25, step=0.05, label="Temperature")
293
  top_p = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-p")
294
 
 
 
 
 
 
 
 
295
  with gr.Column(scale=3):
296
+ chatbot = gr.Chatbot(label="Assistant", type="messages")
297
+ with gr.Row(elem_classes="user-input-row"):
298
+ user_box = gr.Textbox(placeholder="Describe your CRUD/backend task…", lines=3, scale=5)
299
+ send_btn = gr.Button("▶️", variant="primary", scale=1)
300
+ regen_btn = gr.Button("🔁", variant="secondary", scale=1)
301
+
302
+ # --- Wire callbacks ---
303
+ refresh_btn.click(refresh_sessions_cb, outputs=[session_list, edit_title_box, save_title_btn, del_btn, refresh_btn])
304
+ new_btn.click(new_chat_cb, outputs=[session_list, chatbot, user_box, edit_title_box, save_title_btn, del_btn, refresh_btn])
305
+ del_btn.click(delete_chat_cb, inputs=session_list, outputs=[session_list, chatbot, edit_title_box, save_title_btn, del_btn, refresh_btn])
306
+ session_list.change(load_session_cb, inputs=session_list, outputs=[chatbot, edit_title_box, save_title_btn, del_btn, refresh_btn])
307
+ send_btn.click(send_cb, inputs=[user_box, session_list, chatbot, system_box, max_tokens, temperature, top_p, model_choice, dataset_choice], outputs=[chatbot, user_box, session_list])
308
+ user_box.submit(send_cb, inputs=[user_box, session_list, chatbot, system_box, max_tokens, temperature, top_p, model_choice, dataset_choice], outputs=[chatbot, user_box, session_list])
309
+ regen_btn.click(regenerate_cb, inputs=[session_list, system_box, max_tokens, temperature, top_p, model_choice, dataset_choice], outputs=chatbot)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
 
311
  if __name__ == "__main__":
312
  demo.launch()