vedaco commited on
Commit
fa4ebed
·
verified ·
1 Parent(s): 4873762

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -44
app.py CHANGED
@@ -1,10 +1,14 @@
1
- """Gradio App for Veda Programming Assistant - Gradio 6.x compatible"""
2
 
3
  import gradio as gr
4
  import tensorflow as tf
5
  import os
6
  import json
7
 
 
 
 
 
8
  from model import VedaProgrammingLLM
9
  from tokenizer import VedaTokenizer
10
  from database import db
@@ -19,7 +23,7 @@ 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.
@@ -43,9 +47,8 @@ def extract_text(message):
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()
@@ -64,7 +67,12 @@ def ensure_messages_history(history):
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"])})
@@ -79,6 +87,69 @@ def ensure_messages_history(history):
79
  return fixed
80
 
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  # --------- Model init ----------
83
  def initialize():
84
  """Initialize the assistant (load if exists, else train once)."""
@@ -145,18 +216,27 @@ def clean_response(text: str) -> str:
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"
@@ -165,7 +245,6 @@ def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int
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
 
@@ -180,7 +259,6 @@ def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int
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:
@@ -191,10 +269,7 @@ def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int
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
@@ -207,10 +282,7 @@ def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int
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()
@@ -252,7 +324,6 @@ def retrain(epochs):
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
 
@@ -295,22 +366,18 @@ with gr.Blocks(title="Veda Programming Assistant") as demo:
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
  )
@@ -327,31 +394,22 @@ I can **chat**, **write code**, **explain concepts**, and **answer questions**!
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"],
352
- ["Explain what recursion is"],
353
- ["How do I read a file in Python?"],
354
- ["Write a bubble sort algorithm"],
355
  ],
356
  inputs=msg,
357
  )
@@ -377,7 +435,7 @@ I can **chat**, **write code**, **explain concepts**, and **answer questions**!
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
 
383
  if __name__ == "__main__":
 
1
+ """Gradio App for Veda Programming Assistant - Gradio 6.x compatible (with math solving)"""
2
 
3
  import gradio as gr
4
  import tensorflow as tf
5
  import os
6
  import json
7
 
8
+ import re
9
+ import ast
10
+ import operator as op
11
+
12
  from model import VedaProgrammingLLM
13
  from tokenizer import VedaTokenizer
14
  from database import db
 
23
  current_conv_id = -1
24
 
25
 
26
+ # --------- Helpers (Gradio message parsing) ----------
27
  def extract_text(message):
28
  """
29
  Convert Gradio multimodal / messages objects -> plain string.
 
47
  if isinstance(message, list):
48
  parts = []
49
  for part in message:
50
+ if isinstance(part, dict) and part.get("type") == "text":
51
+ parts.append(str(part.get("text", "")))
 
52
  elif isinstance(part, str):
53
  parts.append(part)
54
  return "".join(parts).strip()
 
67
  return []
68
 
69
  # Already messages format
70
+ if (
71
+ len(history) > 0
72
+ and isinstance(history[0], dict)
73
+ and "role" in history[0]
74
+ and "content" in history[0]
75
+ ):
76
  fixed = []
77
  for m in history:
78
  fixed.append({"role": m["role"], "content": extract_text(m["content"])})
 
87
  return fixed
88
 
89
 
90
+ # --------- Safe Math Solver ----------
91
+ _ALLOWED_OPS = {
92
+ ast.Add: op.add,
93
+ ast.Sub: op.sub,
94
+ ast.Mult: op.mul,
95
+ ast.Div: op.truediv,
96
+ ast.Mod: op.mod,
97
+ ast.Pow: op.pow,
98
+ ast.USub: op.neg,
99
+ ast.UAdd: op.pos,
100
+ }
101
+
102
+
103
+ def safe_eval_math(expr: str):
104
+ """
105
+ Safely evaluate arithmetic expression (no variables, no function calls).
106
+ Supports: + - * / % ** and parentheses, integers/floats.
107
+ """
108
+ node = ast.parse(expr, mode="eval").body
109
+
110
+ def _eval(n):
111
+ if isinstance(n, ast.Constant) and isinstance(n.value, (int, float)):
112
+ return n.value
113
+ if isinstance(n, ast.BinOp) and type(n.op) in _ALLOWED_OPS:
114
+ return _ALLOWED_OPS[type(n.op)](_eval(n.left), _eval(n.right))
115
+ if isinstance(n, ast.UnaryOp) and type(n.op) in _ALLOWED_OPS:
116
+ return _ALLOWED_OPS[type(n.op)](_eval(n.operand))
117
+ raise ValueError("Unsupported expression")
118
+
119
+ return _eval(node)
120
+
121
+
122
+ def try_math_answer(user_text: str):
123
+ """
124
+ If user text looks like a pure math expression, return computed answer as string.
125
+ Otherwise return None.
126
+ Examples:
127
+ "2+2=?" -> "4"
128
+ "2^5" -> "32"
129
+ "(10+5)/3" -> "5"
130
+ """
131
+ if not user_text:
132
+ return None
133
+
134
+ # Normalize common decorations
135
+ s = user_text.strip()
136
+ s = s.replace("=", "").replace("?", "").strip()
137
+ s = s.replace("^", "**") # allow ^ as power
138
+
139
+ # Only allow digits/operators/parentheses/dots/spaces
140
+ if not re.fullmatch(r"[0-9\.\s\+\-\*\/\(\)%]+", s):
141
+ return None
142
+
143
+ try:
144
+ val = safe_eval_math(s)
145
+ # pretty formatting: 4.0 -> 4
146
+ if isinstance(val, float) and val.is_integer():
147
+ val = int(val)
148
+ return str(val)
149
+ except Exception:
150
+ return None
151
+
152
+
153
  # --------- Model init ----------
154
  def initialize():
155
  """Initialize the assistant (load if exists, else train once)."""
 
216
 
217
 
218
  def generate_response(user_input: str, temperature: float = 0.7, max_tokens: int = 200) -> str:
219
+ """Generate a response from the model OR solve math deterministically."""
220
  global current_conv_id, conversation_history
221
 
222
+ # Convert Gradio multimodal -> text
 
 
223
  user_input = extract_text(user_input).strip()
224
  if not user_input:
225
  return "Please type a message!"
226
 
227
+ # 1) Try math solver first
228
+ math_ans = try_math_answer(user_input)
229
+ if math_ans is not None:
230
+ # Save conversation too (optional)
231
+ conversation_history.append({"user": user_input, "assistant": math_ans})
232
+ current_conv_id = db.save_conversation(user_input, math_ans)
233
+ return math_ans
234
+
235
+ # 2) Otherwise use model
236
+ if model is None:
237
+ return "Model is loading, please wait..."
238
+
239
  try:
 
240
  context = ""
241
  for msg in conversation_history[-3:]:
242
  context += f"<USER> {msg['user']}\n<ASSISTANT> {msg['assistant']}\n"
 
245
 
246
  tokens = tokenizer.encode(prompt)
247
 
 
248
  if len(tokens) > model.max_length - max_tokens:
249
  tokens = tokens[-(model.max_length - max_tokens):]
250
 
 
259
 
260
  response = tokenizer.decode(generated)
261
 
 
262
  if "<ASSISTANT>" in response:
263
  response = response.split("<ASSISTANT>")[-1].strip()
264
  if "<USER>" in response:
 
269
  if not response:
270
  response = "I'm not sure how to respond to that. Could you try rephrasing?"
271
 
 
272
  conversation_history.append({"user": user_input, "assistant": response})
 
 
273
  current_conv_id = db.save_conversation(user_input, response)
274
 
275
  return response
 
282
 
283
  # --------- Gradio handlers ----------
284
  def respond(message, history, temperature, max_tokens):
285
+ """Always return messages-format history."""
 
 
 
286
  history = ensure_messages_history(history)
287
 
288
  user_text = extract_text(message).strip()
 
324
  global model, tokenizer
325
 
326
  good_convs = db.get_good_conversations()
 
327
  if not good_convs:
328
  return "No approved conversations yet. Rate some responses as 'Good' first!"
329
 
 
366
  """
367
  # 🕉️ Veda Programming Assistant
368
 
369
+ Now supports **math** (e.g., `2+2=?`, `(10+5)/3`, `2^5`) plus coding/chatting.
370
  """
371
  )
372
 
373
  with gr.Tabs():
374
  with gr.TabItem("💬 Chat"):
375
+ chatbot = gr.Chatbot(label="Conversation", height=400, value=[])
 
 
 
 
376
 
377
  with gr.Row():
378
  msg = gr.Textbox(
379
  label="Your message",
380
+ placeholder="Ask me anything about programming... or type math like 2+2=?",
381
  lines=2,
382
  scale=4,
383
  )
 
394
 
395
  feedback_msg = gr.Textbox(label="Status", lines=1, interactive=False)
396
 
397
+ send_btn.click(respond, inputs=[msg, chatbot, temperature, max_tokens], outputs=[msg, chatbot])
398
+ msg.submit(respond, inputs=[msg, chatbot, temperature, max_tokens], outputs=[msg, chatbot])
 
 
 
 
 
 
 
 
399
 
400
  good_btn.click(feedback_good, outputs=feedback_msg)
401
  bad_btn.click(feedback_bad, outputs=feedback_msg)
402
  clear_btn.click(clear_chat, outputs=[chatbot, feedback_msg])
403
 
404
+ gr.Markdown("### 💡 Examples")
405
  gr.Examples(
406
  examples=[
407
  ["2+2=?"],
408
+ ["(10+5)/3"],
409
+ ["2^8"],
410
  ["What is Python?"],
411
  ["Write a function to calculate factorial"],
412
+ ["Explain recursion"],
 
 
413
  ],
414
  inputs=msg,
415
  )
 
435
  refresh_btn = gr.Button("🔄 Refresh Statistics")
436
  refresh_btn.click(get_stats, outputs=stats_out)
437
 
438
+ gr.Markdown("---\n**Veda Programming Assistant**")
439
 
440
 
441
  if __name__ == "__main__":