Beexly commited on
Commit
aa4e7a1
·
verified ·
1 Parent(s): 8e421ca

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +9 -6
  2. app.py +33 -10
  3. requirements.txt +1 -0
README.md CHANGED
@@ -15,15 +15,18 @@ tags:
15
 
16
  # GSE Labs Chat (ZeroGPU)
17
 
18
- A Gradio chat UI running **Qwen2.5-14B-Instruct** on Hugging Face's free
19
- **ZeroGPU** hardware (time-sliced Nvidia GPU, allocated per request).
 
20
 
21
  No API key, no per-token billing — inference runs on the Space's shared free
22
- GPU quota instead of a paid hosted API.
 
 
23
 
24
  ## Swapping the model
25
 
26
  Change `MODEL_ID` in `app.py` to any other instruct-tuned model on the Hub.
27
- Bigger models cost more GPU-seconds per reply and are more likely to hit
28
- ZeroGPU's per-call time limit (currently a few minutes) — if you go bigger,
29
- test with short prompts first.
 
15
 
16
  # GSE Labs Chat (ZeroGPU)
17
 
18
+ A personal Gradio chat UI running **Qwen2.5-32B-Instruct** (4-bit) on
19
+ Hugging Face's free **ZeroGPU** hardware (time-sliced Nvidia GPU, allocated
20
+ per request). Personal-use tool, not part of the GSE product surface.
21
 
22
  No API key, no per-token billing — inference runs on the Space's shared free
23
+ GPU quota instead of a paid hosted API. Responses stream token-by-token, and
24
+ the GPU time requested per reply scales with how many tokens you ask for
25
+ (`_duration()` in `app.py`), instead of a fixed cap.
26
 
27
  ## Swapping the model
28
 
29
  Change `MODEL_ID` in `app.py` to any other instruct-tuned model on the Hub.
30
+ Current footprint (~16GB in 4-bit) leaves headroom under the ~29.5GB that
31
+ already loaded successfully on this Space's hardware — going meaningfully
32
+ bigger than that is unverified and worth testing with short prompts first.
app.py CHANGED
@@ -1,19 +1,34 @@
 
 
1
  import spaces
2
  import torch
3
  import gradio as gr
4
- from transformers import AutoModelForCausalLM, AutoTokenizer
 
 
 
 
 
5
 
6
- MODEL_ID = "Qwen/Qwen2.5-14B-Instruct"
7
 
8
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
9
  model = AutoModelForCausalLM.from_pretrained(
10
  MODEL_ID,
11
- torch_dtype=torch.bfloat16,
 
 
 
 
12
  device_map="auto",
13
  )
14
 
15
 
16
- @spaces.GPU(duration=90)
 
 
 
 
17
  def generate(message, history, system_prompt, max_new_tokens, temperature):
18
  messages = [{"role": "system", "content": system_prompt}] if system_prompt else []
19
  for turn in history:
@@ -24,17 +39,25 @@ def generate(message, history, system_prompt, max_new_tokens, temperature):
24
  messages, add_generation_prompt=True, return_tensors="pt", return_dict=True
25
  ).to(model.device)
26
 
27
- output = model.generate(
 
 
 
28
  **inputs,
29
  max_new_tokens=int(max_new_tokens),
30
  temperature=float(temperature),
31
  do_sample=temperature > 0,
32
  pad_token_id=tokenizer.eos_token_id,
 
33
  )
34
- reply = tokenizer.decode(
35
- output[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True
36
- )
37
- return reply
 
 
 
 
38
 
39
 
40
  demo = gr.ChatInterface(
@@ -46,7 +69,7 @@ demo = gr.ChatInterface(
46
  gr.Slider(0.0, 1.5, value=0.7, step=0.1, label="Temperature"),
47
  ],
48
  title="GSE Labs Chat (ZeroGPU)",
49
- description=f"Running `{MODEL_ID}` on Hugging Face's free ZeroGPU hardware.",
50
  )
51
 
52
  if __name__ == "__main__":
 
1
+ import threading
2
+
3
  import spaces
4
  import torch
5
  import gradio as gr
6
+ from transformers import (
7
+ AutoModelForCausalLM,
8
+ AutoTokenizer,
9
+ BitsAndBytesConfig,
10
+ TextIteratorStreamer,
11
+ )
12
 
13
+ MODEL_ID = "Qwen/Qwen2.5-32B-Instruct"
14
 
15
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
16
  model = AutoModelForCausalLM.from_pretrained(
17
  MODEL_ID,
18
+ quantization_config=BitsAndBytesConfig(
19
+ load_in_4bit=True,
20
+ bnb_4bit_quant_type="nf4",
21
+ bnb_4bit_compute_dtype=torch.bfloat16,
22
+ ),
23
  device_map="auto",
24
  )
25
 
26
 
27
+ def _duration(message, history, system_prompt, max_new_tokens, temperature):
28
+ return min(120, 40 + int(max_new_tokens) // 10)
29
+
30
+
31
+ @spaces.GPU(duration=_duration)
32
  def generate(message, history, system_prompt, max_new_tokens, temperature):
33
  messages = [{"role": "system", "content": system_prompt}] if system_prompt else []
34
  for turn in history:
 
39
  messages, add_generation_prompt=True, return_tensors="pt", return_dict=True
40
  ).to(model.device)
41
 
42
+ streamer = TextIteratorStreamer(
43
+ tokenizer, skip_prompt=True, skip_special_tokens=True
44
+ )
45
+ gen_kwargs = dict(
46
  **inputs,
47
  max_new_tokens=int(max_new_tokens),
48
  temperature=float(temperature),
49
  do_sample=temperature > 0,
50
  pad_token_id=tokenizer.eos_token_id,
51
+ streamer=streamer,
52
  )
53
+ thread = threading.Thread(target=model.generate, kwargs=gen_kwargs)
54
+ thread.start()
55
+
56
+ partial = ""
57
+ for token in streamer:
58
+ partial += token
59
+ yield partial
60
+ thread.join()
61
 
62
 
63
  demo = gr.ChatInterface(
 
69
  gr.Slider(0.0, 1.5, value=0.7, step=0.1, label="Temperature"),
70
  ],
71
  title="GSE Labs Chat (ZeroGPU)",
72
+ description=f"Personal free-GPU chat — `{MODEL_ID}` (4-bit), streaming, on ZeroGPU.",
73
  )
74
 
75
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -3,3 +3,4 @@ gradio>=5.9.1
3
  transformers>=4.46.0
4
  accelerate>=1.1.0
5
  torch>=2.4.0
 
 
3
  transformers>=4.46.0
4
  accelerate>=1.1.0
5
  torch>=2.4.0
6
+ bitsandbytes>=0.44.0