vedaco commited on
Commit
4873762
Β·
verified Β·
1 Parent(s): 79bbbdb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +182 -131
app.py CHANGED
@@ -1,4 +1,4 @@
1
- """Gradio App for Veda Programming Assistant - Gradio 6.2.0"""
2
 
3
  import gradio as gr
4
  import tensorflow as tf
@@ -12,45 +12,107 @@ from train import VedaTrainer
12
  from config import MODEL_DIR
13
 
14
 
 
15
  model = None
16
  tokenizer = None
17
- conversation_history = []
18
  current_conv_id = -1
19
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  def initialize():
22
- """Initialize the assistant"""
23
  global model, tokenizer
24
-
25
  print("Initializing Veda Programming Assistant...")
26
-
27
  config_path = os.path.join(MODEL_DIR, "config.json")
28
-
29
  if os.path.exists(config_path):
30
  print("Loading existing model...")
31
-
32
- with open(config_path, 'r') as f:
33
  config = json.load(f)
34
-
35
  tokenizer = VedaTokenizer()
36
  tokenizer.load(os.path.join(MODEL_DIR, "tokenizer.json"))
37
-
38
  model = VedaProgrammingLLM(
39
- vocab_size=config['vocab_size'],
40
- max_length=config['max_length'],
41
- d_model=config['d_model'],
42
- num_heads=config['num_heads'],
43
- num_layers=config['num_layers'],
44
- ff_dim=config['ff_dim']
45
  )
46
-
47
- dummy = tf.zeros((1, config['max_length']), dtype=tf.int32)
48
  model(dummy)
49
  model.load_weights(os.path.join(MODEL_DIR, "weights.h5"))
50
-
51
  print("Model loaded!")
52
  else:
53
- print("Training new model...")
54
  trainer = VedaTrainer()
55
  trainer.train(epochs=15)
56
  model = trainer.model
@@ -59,108 +121,112 @@ def initialize():
59
 
60
 
61
  def clean_response(text: str) -> str:
62
- """Clean the response"""
63
  text = text.replace("<CODE>", "\n```python\n")
64
  text = text.replace("<ENDCODE>", "\n```\n")
65
-
66
  for token in ["<PAD>", "<UNK>", "<START>", "<END>", "<USER>", "<ASSISTANT>"]:
67
  text = text.replace(token, "")
68
-
69
- lines = text.split('\n')
70
  cleaned = []
71
  empty_count = 0
72
-
73
  for line in lines:
74
- if line.strip() == '':
75
  empty_count += 1
76
  if empty_count <= 2:
77
  cleaned.append(line)
78
  else:
79
  empty_count = 0
80
  cleaned.append(line)
81
-
82
- return '\n'.join(cleaned).strip()
83
 
84
 
85
  def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int = 200) -> str:
86
- """Generate a response"""
87
- global current_conv_id
88
-
89
  if model is None:
90
  return "Model is loading, please wait..."
91
-
92
- if not user_input.strip():
 
93
  return "Please type a message!"
94
-
95
  try:
 
96
  context = ""
97
  for msg in conversation_history[-3:]:
98
  context += f"<USER> {msg['user']}\n<ASSISTANT> {msg['assistant']}\n"
99
-
100
  prompt = context + f"<USER> {user_input}\n<ASSISTANT>"
101
-
102
  tokens = tokenizer.encode(prompt)
103
-
 
104
  if len(tokens) > model.max_length - max_tokens:
105
  tokens = tokens[-(model.max_length - max_tokens):]
106
-
107
  generated = model.generate(
108
  tokens,
109
  max_new_tokens=max_tokens,
110
  temperature=temperature,
111
  top_k=50,
112
  top_p=0.9,
113
- repetition_penalty=1.2
114
  )
115
-
116
  response = tokenizer.decode(generated)
117
-
 
118
  if "<ASSISTANT>" in response:
119
- parts = response.split("<ASSISTANT>")
120
- response = parts[-1].strip()
121
-
122
  if "<USER>" in response:
123
  response = response.split("<USER>")[0].strip()
124
-
125
  response = clean_response(response)
126
-
127
  if not response:
128
  response = "I'm not sure how to respond to that. Could you try rephrasing?"
129
-
130
- conversation_history.append({
131
- 'user': user_input,
132
- 'assistant': response
133
- })
134
-
135
  current_conv_id = db.save_conversation(user_input, response)
136
-
137
  return response
138
-
139
  except Exception as e:
140
  import traceback
141
  traceback.print_exc()
142
  return f"Error: {str(e)}"
143
 
144
 
 
145
  def respond(message, history, temperature, max_tokens):
146
- """Chat function using messages format for Gradio 6.x"""
147
- if not message or not message.strip():
148
- return "", history if history else []
149
-
150
- bot_message = generate_response(message, temperature, max_tokens)
151
-
152
- if history is None:
153
- history = []
154
-
155
- # Gradio 6.x requires messages format
156
- new_history = list(history)
157
- new_history.append({"role": "user", "content": message})
158
- new_history.append({"role": "assistant", "content": bot_message})
159
-
160
- return "", new_history
 
161
 
162
 
163
  def feedback_good():
 
164
  if current_conv_id > 0:
165
  db.update_feedback(current_conv_id, 1)
166
  return "πŸ‘ Thanks for the positive feedback!"
@@ -168,6 +234,7 @@ def feedback_good():
168
 
169
 
170
  def feedback_bad():
 
171
  if current_conv_id > 0:
172
  db.update_feedback(current_conv_id, -1)
173
  return "πŸ‘Ž Thanks! I'll try to improve."
@@ -181,26 +248,26 @@ def clear_chat():
181
 
182
 
183
  def retrain(epochs):
184
- """Retrain with good conversations"""
185
  global model, tokenizer
186
-
187
  good_convs = db.get_good_conversations()
188
-
189
  if not good_convs:
190
  return "No approved conversations yet. Rate some responses as 'Good' first!"
191
-
192
  extra_data = ""
193
  for conv in good_convs:
194
  extra_data += f"<USER> {conv['user_input']}\n"
195
  extra_data += f"<ASSISTANT> {conv['assistant_response']}\n\n"
196
-
197
  trainer = VedaTrainer()
198
  history = trainer.train(epochs=int(epochs), extra_data=extra_data)
199
-
200
  model = trainer.model
201
  tokenizer = trainer.tokenizer
202
-
203
- loss = history.history['loss'][-1]
204
  return f"βœ… Training complete! Loss: {loss:.4f}, Used {len(good_convs)} conversations"
205
 
206
 
@@ -216,81 +283,69 @@ def get_stats():
216
  """
217
 
218
 
219
- # Initialize model at startup
220
  print("Starting initialization...")
221
  initialize()
222
  print("Initialization complete!")
223
 
224
 
225
- # Create Gradio interface
226
  with gr.Blocks(title="Veda Programming Assistant") as demo:
227
-
228
- gr.Markdown("""
229
- # πŸ•‰οΈ Veda Programming Assistant
230
-
231
- I can **chat**, **write code**, **explain concepts**, and **answer questions**!
232
- """)
233
-
 
234
  with gr.Tabs():
235
-
236
  with gr.TabItem("πŸ’¬ Chat"):
237
  chatbot = gr.Chatbot(
238
  label="Conversation",
239
  height=400,
240
- value=[]
241
  )
242
-
243
  with gr.Row():
244
  msg = gr.Textbox(
245
  label="Your message",
246
  placeholder="Ask me anything about programming...",
247
  lines=2,
248
- scale=4
249
  )
250
  send_btn = gr.Button("Send", variant="primary", scale=1)
251
-
252
  with gr.Row():
253
- temperature = gr.Slider(
254
- minimum=0.1,
255
- maximum=1.5,
256
- value=0.7,
257
- step=0.1,
258
- label="Creativity"
259
- )
260
- max_tokens = gr.Slider(
261
- minimum=50,
262
- maximum=400,
263
- value=200,
264
- step=50,
265
- label="Response length"
266
- )
267
-
268
  with gr.Row():
269
  good_btn = gr.Button("πŸ‘ Good", variant="secondary")
270
  bad_btn = gr.Button("πŸ‘Ž Bad", variant="secondary")
271
  clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")
272
-
273
  feedback_msg = gr.Textbox(label="Status", lines=1, interactive=False)
274
-
275
  send_btn.click(
276
  respond,
277
  inputs=[msg, chatbot, temperature, max_tokens],
278
- outputs=[msg, chatbot]
279
  )
280
-
281
  msg.submit(
282
  respond,
283
  inputs=[msg, chatbot, temperature, max_tokens],
284
- outputs=[msg, chatbot]
285
  )
286
-
287
  good_btn.click(feedback_good, outputs=feedback_msg)
288
  bad_btn.click(feedback_bad, outputs=feedback_msg)
289
  clear_btn.click(clear_chat, outputs=[chatbot, feedback_msg])
290
-
291
  gr.Markdown("### πŸ’‘ Try these examples:")
292
  gr.Examples(
293
  examples=[
 
294
  ["Hello! What can you do?"],
295
  ["What is Python?"],
296
  ["Write a function to calculate factorial"],
@@ -298,34 +353,30 @@ with gr.Blocks(title="Veda Programming Assistant") as demo:
298
  ["How do I read a file in Python?"],
299
  ["Write a bubble sort algorithm"],
300
  ],
301
- inputs=msg
302
  )
303
-
304
  with gr.TabItem("πŸŽ“ Training"):
305
- gr.Markdown("""
306
- ### Improve the Assistant
307
-
308
- 1. Chat with the assistant
309
- 2. Rate good responses with πŸ‘
310
- 3. Click "Retrain Model" to learn from good conversations
311
- """)
312
-
313
- train_epochs = gr.Slider(
314
- minimum=5,
315
- maximum=20,
316
- value=10,
317
- step=1,
318
- label="Training Epochs"
319
  )
 
 
320
  train_btn = gr.Button("πŸ”„ Retrain Model", variant="primary")
321
  train_output = gr.Markdown()
322
  train_btn.click(retrain, inputs=[train_epochs], outputs=train_output)
323
-
324
  with gr.TabItem("πŸ“Š Statistics"):
325
  stats_out = gr.Markdown()
326
  refresh_btn = gr.Button("πŸ”„ Refresh Statistics")
327
  refresh_btn.click(get_stats, outputs=stats_out)
328
-
329
  gr.Markdown("---\n**Veda Programming Assistant** - Learning from every conversation!")
330
 
331
 
 
1
+ """Gradio App for Veda Programming Assistant - Gradio 6.x compatible"""
2
 
3
  import gradio as gr
4
  import tensorflow as tf
 
12
  from config import MODEL_DIR
13
 
14
 
15
+ # --------- Globals ----------
16
  model = None
17
  tokenizer = None
18
+ conversation_history = [] # used for building prompt context for the model
19
  current_conv_id = -1
20
 
21
 
22
+ # --------- Helpers (IMPORTANT FIX) ----------
23
+ def extract_text(message):
24
+ """
25
+ Convert Gradio multimodal / messages objects -> plain string.
26
+ Handles:
27
+ - str
28
+ - dict: {"text": "..."} or {"content": "..."}
29
+ - list of parts: [{"type":"text","text":"..."}]
30
+ """
31
+ if message is None:
32
+ return ""
33
+ if isinstance(message, str):
34
+ return message
35
+
36
+ if isinstance(message, dict):
37
+ if "text" in message:
38
+ return str(message.get("text", ""))
39
+ if "content" in message:
40
+ return extract_text(message["content"])
41
+ return ""
42
+
43
+ if isinstance(message, list):
44
+ parts = []
45
+ for part in message:
46
+ if isinstance(part, dict):
47
+ if part.get("type") == "text":
48
+ parts.append(str(part.get("text", "")))
49
+ elif isinstance(part, str):
50
+ parts.append(part)
51
+ return "".join(parts).strip()
52
+
53
+ return str(message)
54
+
55
+
56
+ def ensure_messages_history(history):
57
+ """
58
+ Ensure Chatbot history is ALWAYS messages format:
59
+ [{"role":"user","content":"..."}, {"role":"assistant","content":"..."}]
60
+
61
+ Also converts old tuple format [(user, bot), ...] -> messages.
62
+ """
63
+ if history is None:
64
+ return []
65
+
66
+ # Already messages format
67
+ if len(history) > 0 and isinstance(history[0], dict) and "role" in history[0] and "content" in history[0]:
68
+ fixed = []
69
+ for m in history:
70
+ fixed.append({"role": m["role"], "content": extract_text(m["content"])})
71
+ return fixed
72
+
73
+ # Tuple/pair format -> messages format
74
+ fixed = []
75
+ for pair in history:
76
+ if isinstance(pair, (list, tuple)) and len(pair) == 2:
77
+ fixed.append({"role": "user", "content": extract_text(pair[0])})
78
+ fixed.append({"role": "assistant", "content": extract_text(pair[1])})
79
+ return fixed
80
+
81
+
82
+ # --------- Model init ----------
83
  def initialize():
84
+ """Initialize the assistant (load if exists, else train once)."""
85
  global model, tokenizer
86
+
87
  print("Initializing Veda Programming Assistant...")
88
+
89
  config_path = os.path.join(MODEL_DIR, "config.json")
90
+
91
  if os.path.exists(config_path):
92
  print("Loading existing model...")
93
+
94
+ with open(config_path, "r") as f:
95
  config = json.load(f)
96
+
97
  tokenizer = VedaTokenizer()
98
  tokenizer.load(os.path.join(MODEL_DIR, "tokenizer.json"))
99
+
100
  model = VedaProgrammingLLM(
101
+ vocab_size=config["vocab_size"],
102
+ max_length=config["max_length"],
103
+ d_model=config["d_model"],
104
+ num_heads=config["num_heads"],
105
+ num_layers=config["num_layers"],
106
+ ff_dim=config["ff_dim"],
107
  )
108
+
109
+ dummy = tf.zeros((1, config["max_length"]), dtype=tf.int32)
110
  model(dummy)
111
  model.load_weights(os.path.join(MODEL_DIR, "weights.h5"))
112
+
113
  print("Model loaded!")
114
  else:
115
+ print("No saved model found. Training a new model...")
116
  trainer = VedaTrainer()
117
  trainer.train(epochs=15)
118
  model = trainer.model
 
121
 
122
 
123
  def clean_response(text: str) -> str:
124
+ """Clean the response text for display."""
125
  text = text.replace("<CODE>", "\n```python\n")
126
  text = text.replace("<ENDCODE>", "\n```\n")
127
+
128
  for token in ["<PAD>", "<UNK>", "<START>", "<END>", "<USER>", "<ASSISTANT>"]:
129
  text = text.replace(token, "")
130
+
131
+ lines = text.split("\n")
132
  cleaned = []
133
  empty_count = 0
134
+
135
  for line in lines:
136
+ if line.strip() == "":
137
  empty_count += 1
138
  if empty_count <= 2:
139
  cleaned.append(line)
140
  else:
141
  empty_count = 0
142
  cleaned.append(line)
143
+
144
+ return "\n".join(cleaned).strip()
145
 
146
 
147
  def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int = 200) -> str:
148
+ """Generate a response from the model."""
149
+ global current_conv_id, conversation_history
150
+
151
  if model is None:
152
  return "Model is loading, please wait..."
153
+
154
+ user_input = extract_text(user_input).strip()
155
+ if not user_input:
156
  return "Please type a message!"
157
+
158
  try:
159
+ # Build context from last few turns (stored as plain strings)
160
  context = ""
161
  for msg in conversation_history[-3:]:
162
  context += f"<USER> {msg['user']}\n<ASSISTANT> {msg['assistant']}\n"
163
+
164
  prompt = context + f"<USER> {user_input}\n<ASSISTANT>"
165
+
166
  tokens = tokenizer.encode(prompt)
167
+
168
+ # Truncate to leave room for generation
169
  if len(tokens) > model.max_length - max_tokens:
170
  tokens = tokens[-(model.max_length - max_tokens):]
171
+
172
  generated = model.generate(
173
  tokens,
174
  max_new_tokens=max_tokens,
175
  temperature=temperature,
176
  top_k=50,
177
  top_p=0.9,
178
+ repetition_penalty=1.2,
179
  )
180
+
181
  response = tokenizer.decode(generated)
182
+
183
+ # Extract assistant portion only
184
  if "<ASSISTANT>" in response:
185
+ response = response.split("<ASSISTANT>")[-1].strip()
 
 
186
  if "<USER>" in response:
187
  response = response.split("<USER>")[0].strip()
188
+
189
  response = clean_response(response)
190
+
191
  if not response:
192
  response = "I'm not sure how to respond to that. Could you try rephrasing?"
193
+
194
+ # Save for future context
195
+ conversation_history.append({"user": user_input, "assistant": response})
196
+
197
+ # Save in DB
 
198
  current_conv_id = db.save_conversation(user_input, response)
199
+
200
  return response
201
+
202
  except Exception as e:
203
  import traceback
204
  traceback.print_exc()
205
  return f"Error: {str(e)}"
206
 
207
 
208
+ # --------- Gradio handlers ----------
209
  def respond(message, history, temperature, max_tokens):
210
+ """
211
+ Chat function for Gradio Chatbot.
212
+ IMPORTANT: Always return messages-format history.
213
+ """
214
+ history = ensure_messages_history(history)
215
+
216
+ user_text = extract_text(message).strip()
217
+ if not user_text:
218
+ return "", history
219
+
220
+ bot_message = generate_response(user_text, temperature, max_tokens)
221
+
222
+ history.append({"role": "user", "content": user_text})
223
+ history.append({"role": "assistant", "content": bot_message})
224
+
225
+ return "", history
226
 
227
 
228
  def feedback_good():
229
+ global current_conv_id
230
  if current_conv_id > 0:
231
  db.update_feedback(current_conv_id, 1)
232
  return "πŸ‘ Thanks for the positive feedback!"
 
234
 
235
 
236
  def feedback_bad():
237
+ global current_conv_id
238
  if current_conv_id > 0:
239
  db.update_feedback(current_conv_id, -1)
240
  return "πŸ‘Ž Thanks! I'll try to improve."
 
248
 
249
 
250
  def retrain(epochs):
251
+ """Retrain with good conversations."""
252
  global model, tokenizer
253
+
254
  good_convs = db.get_good_conversations()
255
+
256
  if not good_convs:
257
  return "No approved conversations yet. Rate some responses as 'Good' first!"
258
+
259
  extra_data = ""
260
  for conv in good_convs:
261
  extra_data += f"<USER> {conv['user_input']}\n"
262
  extra_data += f"<ASSISTANT> {conv['assistant_response']}\n\n"
263
+
264
  trainer = VedaTrainer()
265
  history = trainer.train(epochs=int(epochs), extra_data=extra_data)
266
+
267
  model = trainer.model
268
  tokenizer = trainer.tokenizer
269
+
270
+ loss = history.history["loss"][-1]
271
  return f"βœ… Training complete! Loss: {loss:.4f}, Used {len(good_convs)} conversations"
272
 
273
 
 
283
  """
284
 
285
 
286
+ # --------- Startup ----------
287
  print("Starting initialization...")
288
  initialize()
289
  print("Initialization complete!")
290
 
291
 
292
+ # --------- UI ----------
293
  with gr.Blocks(title="Veda Programming Assistant") as demo:
294
+ gr.Markdown(
295
+ """
296
+ # πŸ•‰οΈ Veda Programming Assistant
297
+
298
+ I can **chat**, **write code**, **explain concepts**, and **answer questions**!
299
+ """
300
+ )
301
+
302
  with gr.Tabs():
 
303
  with gr.TabItem("πŸ’¬ Chat"):
304
  chatbot = gr.Chatbot(
305
  label="Conversation",
306
  height=400,
307
+ value=[],
308
  )
309
+
310
  with gr.Row():
311
  msg = gr.Textbox(
312
  label="Your message",
313
  placeholder="Ask me anything about programming...",
314
  lines=2,
315
+ scale=4,
316
  )
317
  send_btn = gr.Button("Send", variant="primary", scale=1)
318
+
319
  with gr.Row():
320
+ temperature = gr.Slider(0.1, 1.5, 0.7, step=0.1, label="Creativity")
321
+ max_tokens = gr.Slider(50, 400, 200, step=50, label="Response length")
322
+
 
 
 
 
 
 
 
 
 
 
 
 
323
  with gr.Row():
324
  good_btn = gr.Button("πŸ‘ Good", variant="secondary")
325
  bad_btn = gr.Button("πŸ‘Ž Bad", variant="secondary")
326
  clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")
327
+
328
  feedback_msg = gr.Textbox(label="Status", lines=1, interactive=False)
329
+
330
  send_btn.click(
331
  respond,
332
  inputs=[msg, chatbot, temperature, max_tokens],
333
+ outputs=[msg, chatbot],
334
  )
 
335
  msg.submit(
336
  respond,
337
  inputs=[msg, chatbot, temperature, max_tokens],
338
+ outputs=[msg, chatbot],
339
  )
340
+
341
  good_btn.click(feedback_good, outputs=feedback_msg)
342
  bad_btn.click(feedback_bad, outputs=feedback_msg)
343
  clear_btn.click(clear_chat, outputs=[chatbot, feedback_msg])
344
+
345
  gr.Markdown("### πŸ’‘ Try these examples:")
346
  gr.Examples(
347
  examples=[
348
+ ["2+2=?"],
349
  ["Hello! What can you do?"],
350
  ["What is Python?"],
351
  ["Write a function to calculate factorial"],
 
353
  ["How do I read a file in Python?"],
354
  ["Write a bubble sort algorithm"],
355
  ],
356
+ inputs=msg,
357
  )
358
+
359
  with gr.TabItem("πŸŽ“ Training"):
360
+ gr.Markdown(
361
+ """
362
+ ### Improve the Assistant
363
+
364
+ 1. Chat with the assistant
365
+ 2. Rate good responses with πŸ‘
366
+ 3. Click "Retrain Model" to learn from good conversations
367
+ """
 
 
 
 
 
 
368
  )
369
+
370
+ train_epochs = gr.Slider(5, 20, 10, step=1, label="Training Epochs")
371
  train_btn = gr.Button("πŸ”„ Retrain Model", variant="primary")
372
  train_output = gr.Markdown()
373
  train_btn.click(retrain, inputs=[train_epochs], outputs=train_output)
374
+
375
  with gr.TabItem("πŸ“Š Statistics"):
376
  stats_out = gr.Markdown()
377
  refresh_btn = gr.Button("πŸ”„ Refresh Statistics")
378
  refresh_btn.click(get_stats, outputs=stats_out)
379
+
380
  gr.Markdown("---\n**Veda Programming Assistant** - Learning from every conversation!")
381
 
382