xxbanditxx commited on
Commit
249c64d
·
verified ·
1 Parent(s): dbfc1ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -80
app.py CHANGED
@@ -7,6 +7,7 @@ import shutil
7
  import torch
8
  import psutil
9
  import time
 
10
 
11
  # Define path for HF cache to clean
12
  HF_CACHE_DIR = os.path.expanduser("~/.cache/huggingface/hub")
@@ -25,43 +26,44 @@ MODELS = [
25
  'MihaiPopa-1/CinnabarLM-1.5M-Base', 'Harley-ml/Dillionv2-1.3M', 'Eclipse-Senpai/KeyLM-75M',
26
  'SupraLabs/Supra-Mini-v6-1M', 'AxiomicLabs/GPT-S-1.4M', 'GODELEV/Archaea-74M',
27
  'Sandroeth/cali-0.1B', 'veyra-ai/veyra3-5m-base', 'veyra-ai/veyra-30m-base-5b-tokens',
28
- 'ThingAI/Quark-50m', 'ThingAI/Quark-135m', 'HuggingFaceTB/SmolLM2-135M-Instruct',
29
  'Aravindan/awesome-gpt-2-coder', 'Qwen/Qwen2.5-Coder-0.5B', 'SupraLabs/Supra-50M-Reasoning'
30
  ]
31
 
32
  ACTIVE_SESSIONS = {}
33
  SESSION_TIMEOUT = 60
34
 
 
35
  def live_count(request: gr.Request):
36
  current_time = time.time()
37
  if request:
38
  ACTIVE_SESSIONS[request.session_hash] = current_time
39
-
40
- # Prune
41
  expired = [s for s, t in ACTIVE_SESSIONS.items() if current_time - t > SESSION_TIMEOUT]
42
  for s in expired:
43
  ACTIVE_SESSIONS.pop(s, None)
44
-
45
  return len(ACTIVE_SESSIONS)
46
 
47
- # Global class to safely manage the loaded model and tokenizer in memory
48
  class ModelManager:
49
  def __init__(self):
50
  self.model = None
51
  self.tokenizer = None
52
  self.model_id = None
53
- self.stop_generation = False # Added flag to instantly kill generation
54
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
55
 
 
56
  model_manager = ModelManager()
57
 
58
- # Custom stopping criteria to halt the generation thread when loading a new model
59
  class StopOnFlag(StoppingCriteria):
60
  def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
61
  return model_manager.stop_generation
62
 
 
63
  def get_system_stats(request: gr.Request = None):
64
- """Returns a dictionary of current system metrics with formatted strings."""
65
  mem = psutil.virtual_memory()
66
  disk = psutil.disk_usage('/')
67
  return (
@@ -71,50 +73,62 @@ def get_system_stats(request: gr.Request = None):
71
  f"Active\t: \t{len(ACTIVE_SESSIONS) if request is None else live_count(request)} session(s)"
72
  )
73
 
 
74
  def load_new_model(model_id):
75
- """Loads the model and tokenizer dynamically into the global manager."""
76
- # Stop any ongoing generation immediately
77
  model_manager.stop_generation = True
78
-
79
- # Clear old model from memory
80
  model_manager.model = None
81
  model_manager.tokenizer = None
82
  model_manager.model_id = None
 
83
  yield f"Loading {model_id}..."
 
84
  gc.collect()
85
  if torch.cuda.is_available():
86
  torch.cuda.empty_cache()
87
-
88
  try:
89
- # Load explicitly for streaming purposes instead of pipeline
90
  tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
91
  model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True).to(model_manager.device)
92
-
93
  model_manager.tokenizer = tokenizer
94
  model_manager.model = model
95
  model_manager.model_id = model_id
96
-
97
  yield f"Successfully loaded {model_id} on {model_manager.device.upper()}"
 
98
  except Exception as e:
99
  yield f"Error loading model: {str(e)}"
100
 
 
101
  def run_inference(user_prompt, max_tokens, temperature, top_k, top_p, rep_penalty, ngram_size, do_sample):
102
- """Generates text via streaming generator."""
103
  if model_manager.model is None or model_manager.tokenizer is None:
104
  yield "Please load a model first.", "Model not loaded"
105
  return
106
-
107
- # Reset the stop flag for the new generation run
108
  model_manager.stop_generation = False
109
-
110
  tokenizer = model_manager.tokenizer
111
  model = model_manager.model
112
  model_id = model_manager.model_id
113
-
 
 
 
 
 
 
 
 
 
 
114
  is_supra_reasoning = "Supra-50M-Reasoning" in model_id if model_id else False
115
-
116
  if is_supra_reasoning:
117
- SYSTEM_PROMPT = "Your role as an assistant involves thoroughly exploring questions through a systematic long thinking process before providing the final precise and accurate solutions."
 
 
 
118
  prompt_to_encode = (
119
  f"[SYSTEM]: {SYSTEM_PROMPT}\n\n"
120
  f"[USER]: {user_prompt}\n\n"
@@ -125,17 +139,18 @@ def run_inference(user_prompt, max_tokens, temperature, top_k, top_p, rep_penalt
125
  prompt_to_encode = user_prompt
126
  skip_special = True
127
 
128
- # Tokenize input
129
  inputs = tokenizer([prompt_to_encode], return_tensors="pt").to(model_manager.device)
130
-
131
- # Set up the streamer
132
- streamer = TextIteratorStreamer(tokenizer, timeout=60.0, skip_prompt=True, skip_special_tokens=skip_special)
133
-
134
- # Adjust variables based on the do_sample logic
 
 
 
135
  if not do_sample:
136
- temperature = 1.0 # Temperature is ignored if do_sample=False, but setting it > 0 avoids config errors
137
 
138
- # Generation arguments
139
  generate_kwargs = dict(
140
  **inputs,
141
  streamer=streamer,
@@ -146,42 +161,41 @@ def run_inference(user_prompt, max_tokens, temperature, top_k, top_p, rep_penalt
146
  repetition_penalty=float(rep_penalty),
147
  no_repeat_ngram_size=int(ngram_size),
148
  do_sample=do_sample,
149
- pad_token_id=tokenizer.eos_token_id, # Prevents padding warnings
150
- stopping_criteria=StoppingCriteriaList([StopOnFlag()]) # Attach the stopping criteria
151
  )
152
 
153
  start_time = time.time()
154
- # Start generation in a separate background thread
155
  thread = Thread(target=model.generate, kwargs=generate_kwargs)
156
  thread.start()
157
-
158
  if is_supra_reasoning:
159
- # Use plain text formatting rather than markdown symbols inside gr.Textbox
160
- base_display = f"Prompt: {user_prompt}\n\n----------------------------------------\n\n"
161
  generated_text = ""
162
  else:
163
  base_display = ""
164
- generated_text = user_prompt
165
 
166
- # Yield output iteratively for the streaming effect
167
  token_count = 0
 
168
  for new_text in streamer:
169
- # Immediately break out of the UI update loop if a new model is loaded
170
  if model_manager.stop_generation:
171
  break
172
-
173
  generated_text += new_text
174
  token_count += 1
 
175
  duration = time.time() - start_time
176
  tps = token_count / duration if duration > 0 else 0
177
-
178
  display_text = generated_text
179
-
180
  if is_supra_reasoning:
181
  display_text = display_text.replace("<s>", "").replace("</s>", "")
 
182
  if not display_text.startswith("🧠 Thinking Process:"):
183
  display_text = "🧠 Thinking Process:\n" + display_text
184
-
185
  display_text = display_text.replace("<|begin_of_thought|>", "🧠 Thinking Process:\n")
186
  display_text = display_text.replace("<|end_of_thought|>", "\n\n")
187
  display_text = display_text.replace("<|begin_of_solution|>", "✅ Final Answer:\n\n")
@@ -189,6 +203,7 @@ def run_inference(user_prompt, max_tokens, temperature, top_k, top_p, rep_penalt
189
 
190
  yield base_display + display_text, f"Speed: {tps:.2f} tokens/sec"
191
 
 
192
  def clean_cache():
193
  if os.path.exists(HF_CACHE_DIR):
194
  shutil.rmtree(HF_CACHE_DIR)
@@ -196,73 +211,126 @@ def clean_cache():
196
  return "Cache cleaned successfully!"
197
  return "Cache directory not found."
198
 
199
- # Gradio Interface
200
- with gr.Blocks(title="Small MF Model Tester", theme=gr.themes.Soft()) as app:
201
-
202
- gr.Markdown("# 🚀 Small Model Evaluation Hub with Streaming")
203
 
204
  with gr.Row():
205
- # Left column: Settings & Monitoring
206
  with gr.Column(scale=1):
207
-
208
  with gr.Accordion("System Monitoring", open=True):
209
  stats_output = gr.Textbox(label="Live System Stats", show_label=False)
210
  gr.Timer(2).tick(get_system_stats, None, stats_output)
211
 
212
  with gr.Group():
213
- gr.Markdown("### Select or Paste custom model id here")
214
  with gr.Row():
215
- model_id_input = gr.Dropdown(choices=MODELS, label="Model", allow_custom_value=True, show_label=False, scale=3)
 
 
 
 
 
 
216
  load_btn = gr.Button("Load", variant="secondary", scale=1)
217
-
218
  clean_btn = gr.Button("Clean HF Cache", variant="stop", size="sm")
219
 
220
  with gr.Accordion("Generation Configuration", open=False):
221
- do_sample_input = gr.Checkbox(label="Enable Sampling (do_sample)", value=True, info="Uncheck for greedy decoding")
222
- max_tokens_input = gr.Slider(minimum=10, maximum=2048, value=256, step=1, label="Max Output Tokens")
223
- temperature_input = gr.Slider(minimum=0.1, maximum=2.0, value=0.7, step=0.1, label="Temperature", info="Higher = more creative")
224
-
225
- top_k_input = gr.Slider(minimum=0, maximum=100, value=50, step=1, label="Top-K", info="0 = disabled")
226
- top_p_input = gr.Slider(minimum=0.1, maximum=1.0, value=0.9, step=0.05, label="Top-P (Nucleus)", info="1.0 = disabled")
227
- rep_penalty_input = gr.Slider(minimum=1.0, maximum=2.0, value=1.1, step=0.05, label="Repetition Penalty", info="1.0 = disabled")
228
- ngram_size_input = gr.Slider(minimum=0, maximum=10, value=0, step=1, label="No Repeat N-Gram Size", info="0 = disabled")
229
-
230
- # Right column: Interaction
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  with gr.Column(scale=2):
232
  user_prompt = gr.Textbox(
233
- label="Prompt",
234
- value="Once upon a time in a digital kingdom,",
235
- placeholder="Enter your prompt here...",
236
  lines=5
237
  )
 
238
  run_btn = gr.Button("Generate text", variant="primary", size="lg")
239
  status_output = gr.Markdown("Status: *Waiting to load model...*")
240
- output_text = gr.Textbox(label="Result", lines=15, buttons=["copy"], autoscroll=True)
241
-
242
- # Events
 
 
 
 
243
  load_btn.click(
244
- fn=load_new_model,
245
- inputs=[model_id_input],
246
  outputs=[status_output]
247
  )
248
-
249
- # We use `.click` targeting a generator function, which Gradio naturally treats as a streaming output
250
  run_btn.click(
251
  fn=run_inference,
252
  inputs=[
253
- user_prompt,
254
- max_tokens_input,
255
- temperature_input,
256
- top_k_input,
257
- top_p_input,
258
- rep_penalty_input,
259
  ngram_size_input,
260
  do_sample_input
261
  ],
262
  outputs=[output_text, status_output]
263
  )
264
-
265
  clean_btn.click(fn=clean_cache, outputs=[status_output])
266
 
 
267
  if __name__ == "__main__":
268
  app.launch()
 
7
  import torch
8
  import psutil
9
  import time
10
+ from orbit import orbit
11
 
12
  # Define path for HF cache to clean
13
  HF_CACHE_DIR = os.path.expanduser("~/.cache/huggingface/hub")
 
26
  'MihaiPopa-1/CinnabarLM-1.5M-Base', 'Harley-ml/Dillionv2-1.3M', 'Eclipse-Senpai/KeyLM-75M',
27
  'SupraLabs/Supra-Mini-v6-1M', 'AxiomicLabs/GPT-S-1.4M', 'GODELEV/Archaea-74M',
28
  'Sandroeth/cali-0.1B', 'veyra-ai/veyra3-5m-base', 'veyra-ai/veyra-30m-base-5b-tokens',
29
+ 'ThingAI/Quark-50m', 'ThingAI/Quark-135m', 'HuggingFaceTB/SmolLM2-135M-Instruct',
30
  'Aravindan/awesome-gpt-2-coder', 'Qwen/Qwen2.5-Coder-0.5B', 'SupraLabs/Supra-50M-Reasoning'
31
  ]
32
 
33
  ACTIVE_SESSIONS = {}
34
  SESSION_TIMEOUT = 60
35
 
36
+
37
  def live_count(request: gr.Request):
38
  current_time = time.time()
39
  if request:
40
  ACTIVE_SESSIONS[request.session_hash] = current_time
41
+
 
42
  expired = [s for s, t in ACTIVE_SESSIONS.items() if current_time - t > SESSION_TIMEOUT]
43
  for s in expired:
44
  ACTIVE_SESSIONS.pop(s, None)
45
+
46
  return len(ACTIVE_SESSIONS)
47
 
48
+
49
  class ModelManager:
50
  def __init__(self):
51
  self.model = None
52
  self.tokenizer = None
53
  self.model_id = None
54
+ self.stop_generation = False
55
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
56
 
57
+
58
  model_manager = ModelManager()
59
 
60
+
61
  class StopOnFlag(StoppingCriteria):
62
  def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
63
  return model_manager.stop_generation
64
 
65
+
66
  def get_system_stats(request: gr.Request = None):
 
67
  mem = psutil.virtual_memory()
68
  disk = psutil.disk_usage('/')
69
  return (
 
73
  f"Active\t: \t{len(ACTIVE_SESSIONS) if request is None else live_count(request)} session(s)"
74
  )
75
 
76
+
77
  def load_new_model(model_id):
 
 
78
  model_manager.stop_generation = True
79
+
 
80
  model_manager.model = None
81
  model_manager.tokenizer = None
82
  model_manager.model_id = None
83
+
84
  yield f"Loading {model_id}..."
85
+
86
  gc.collect()
87
  if torch.cuda.is_available():
88
  torch.cuda.empty_cache()
89
+
90
  try:
 
91
  tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
92
  model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True).to(model_manager.device)
93
+
94
  model_manager.tokenizer = tokenizer
95
  model_manager.model = model
96
  model_manager.model_id = model_id
97
+
98
  yield f"Successfully loaded {model_id} on {model_manager.device.upper()}"
99
+
100
  except Exception as e:
101
  yield f"Error loading model: {str(e)}"
102
 
103
+
104
  def run_inference(user_prompt, max_tokens, temperature, top_k, top_p, rep_penalty, ngram_size, do_sample):
 
105
  if model_manager.model is None or model_manager.tokenizer is None:
106
  yield "Please load a model first.", "Model not loaded"
107
  return
108
+
 
109
  model_manager.stop_generation = False
110
+
111
  tokenizer = model_manager.tokenizer
112
  model = model_manager.model
113
  model_id = model_manager.model_id
114
+
115
+ # ORBIT GOVERNOR INTERCEPT
116
+ original_prompt = user_prompt
117
+ decision = orbit.as_dict(user_prompt)
118
+
119
+ if not decision["allow"]:
120
+ yield decision["message"], "Orbit blocked prompt"
121
+ return
122
+
123
+ user_prompt = decision["prompt"]
124
+
125
  is_supra_reasoning = "Supra-50M-Reasoning" in model_id if model_id else False
126
+
127
  if is_supra_reasoning:
128
+ SYSTEM_PROMPT = (
129
+ "Your role as an assistant involves thoroughly exploring questions through "
130
+ "a systematic long thinking process before providing the final precise and accurate solutions."
131
+ )
132
  prompt_to_encode = (
133
  f"[SYSTEM]: {SYSTEM_PROMPT}\n\n"
134
  f"[USER]: {user_prompt}\n\n"
 
139
  prompt_to_encode = user_prompt
140
  skip_special = True
141
 
 
142
  inputs = tokenizer([prompt_to_encode], return_tensors="pt").to(model_manager.device)
143
+
144
+ streamer = TextIteratorStreamer(
145
+ tokenizer,
146
+ timeout=60.0,
147
+ skip_prompt=True,
148
+ skip_special_tokens=skip_special
149
+ )
150
+
151
  if not do_sample:
152
+ temperature = 1.0
153
 
 
154
  generate_kwargs = dict(
155
  **inputs,
156
  streamer=streamer,
 
161
  repetition_penalty=float(rep_penalty),
162
  no_repeat_ngram_size=int(ngram_size),
163
  do_sample=do_sample,
164
+ pad_token_id=tokenizer.eos_token_id,
165
+ stopping_criteria=StoppingCriteriaList([StopOnFlag()])
166
  )
167
 
168
  start_time = time.time()
 
169
  thread = Thread(target=model.generate, kwargs=generate_kwargs)
170
  thread.start()
171
+
172
  if is_supra_reasoning:
173
+ base_display = f"Prompt: {original_prompt}\n\n----------------------------------------\n\n"
 
174
  generated_text = ""
175
  else:
176
  base_display = ""
177
+ generated_text = ""
178
 
 
179
  token_count = 0
180
+
181
  for new_text in streamer:
 
182
  if model_manager.stop_generation:
183
  break
184
+
185
  generated_text += new_text
186
  token_count += 1
187
+
188
  duration = time.time() - start_time
189
  tps = token_count / duration if duration > 0 else 0
190
+
191
  display_text = generated_text
192
+
193
  if is_supra_reasoning:
194
  display_text = display_text.replace("<s>", "").replace("</s>", "")
195
+
196
  if not display_text.startswith("🧠 Thinking Process:"):
197
  display_text = "🧠 Thinking Process:\n" + display_text
198
+
199
  display_text = display_text.replace("<|begin_of_thought|>", "🧠 Thinking Process:\n")
200
  display_text = display_text.replace("<|end_of_thought|>", "\n\n")
201
  display_text = display_text.replace("<|begin_of_solution|>", "✅ Final Answer:\n\n")
 
203
 
204
  yield base_display + display_text, f"Speed: {tps:.2f} tokens/sec"
205
 
206
+
207
  def clean_cache():
208
  if os.path.exists(HF_CACHE_DIR):
209
  shutil.rmtree(HF_CACHE_DIR)
 
211
  return "Cache cleaned successfully!"
212
  return "Cache directory not found."
213
 
214
+
215
+ with gr.Blocks(title="Small MF Model Tester + Orbit Governor", theme=gr.themes.Soft()) as app:
216
+
217
+ gr.Markdown("# 🚀 Small Model Evaluation Hub with Orbit Governor")
218
 
219
  with gr.Row():
 
220
  with gr.Column(scale=1):
221
+
222
  with gr.Accordion("System Monitoring", open=True):
223
  stats_output = gr.Textbox(label="Live System Stats", show_label=False)
224
  gr.Timer(2).tick(get_system_stats, None, stats_output)
225
 
226
  with gr.Group():
227
+ gr.Markdown("### Select or paste custom model ID here")
228
  with gr.Row():
229
+ model_id_input = gr.Dropdown(
230
+ choices=MODELS,
231
+ label="Model",
232
+ allow_custom_value=True,
233
+ show_label=False,
234
+ scale=3
235
+ )
236
  load_btn = gr.Button("Load", variant="secondary", scale=1)
237
+
238
  clean_btn = gr.Button("Clean HF Cache", variant="stop", size="sm")
239
 
240
  with gr.Accordion("Generation Configuration", open=False):
241
+ do_sample_input = gr.Checkbox(
242
+ label="Enable Sampling (do_sample)",
243
+ value=True,
244
+ info="Uncheck for greedy decoding"
245
+ )
246
+ max_tokens_input = gr.Slider(
247
+ minimum=10,
248
+ maximum=2048,
249
+ value=256,
250
+ step=1,
251
+ label="Max Output Tokens"
252
+ )
253
+ temperature_input = gr.Slider(
254
+ minimum=0.1,
255
+ maximum=2.0,
256
+ value=0.7,
257
+ step=0.1,
258
+ label="Temperature",
259
+ info="Higher = more creative"
260
+ )
261
+ top_k_input = gr.Slider(
262
+ minimum=0,
263
+ maximum=100,
264
+ value=50,
265
+ step=1,
266
+ label="Top-K",
267
+ info="0 = disabled"
268
+ )
269
+ top_p_input = gr.Slider(
270
+ minimum=0.1,
271
+ maximum=1.0,
272
+ value=0.9,
273
+ step=0.05,
274
+ label="Top-P (Nucleus)",
275
+ info="1.0 = disabled"
276
+ )
277
+ rep_penalty_input = gr.Slider(
278
+ minimum=1.0,
279
+ maximum=2.0,
280
+ value=1.1,
281
+ step=0.05,
282
+ label="Repetition Penalty",
283
+ info="1.0 = disabled"
284
+ )
285
+ ngram_size_input = gr.Slider(
286
+ minimum=0,
287
+ maximum=10,
288
+ value=0,
289
+ step=1,
290
+ label="No Repeat N-Gram Size",
291
+ info="0 = disabled"
292
+ )
293
+
294
  with gr.Column(scale=2):
295
  user_prompt = gr.Textbox(
296
+ label="Prompt",
297
+ value="Once upon a time in a digital kingdom,",
298
+ placeholder="Enter your prompt here...",
299
  lines=5
300
  )
301
+
302
  run_btn = gr.Button("Generate text", variant="primary", size="lg")
303
  status_output = gr.Markdown("Status: *Waiting to load model...*")
304
+ output_text = gr.Textbox(
305
+ label="Result",
306
+ lines=15,
307
+ buttons=["copy"],
308
+ autoscroll=True
309
+ )
310
+
311
  load_btn.click(
312
+ fn=load_new_model,
313
+ inputs=[model_id_input],
314
  outputs=[status_output]
315
  )
316
+
 
317
  run_btn.click(
318
  fn=run_inference,
319
  inputs=[
320
+ user_prompt,
321
+ max_tokens_input,
322
+ temperature_input,
323
+ top_k_input,
324
+ top_p_input,
325
+ rep_penalty_input,
326
  ngram_size_input,
327
  do_sample_input
328
  ],
329
  outputs=[output_text, status_output]
330
  )
331
+
332
  clean_btn.click(fn=clean_cache, outputs=[status_output])
333
 
334
+
335
  if __name__ == "__main__":
336
  app.launch()