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

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. README.md +9 -7
  2. app.py +12 -3
README.md CHANGED
@@ -15,18 +15,20 @@ tags:
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.
 
15
 
16
  # GSE Labs Chat (ZeroGPU)
17
 
18
+ A personal Gradio chat UI running **Qwen2.5-72B-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, GPU
24
+ time requested per reply scales with how many tokens you ask for
25
+ (`_duration()` in `app.py`), attention uses `sdpa`, sampling uses
26
+ `top_p`/`repetition_penalty` for quality, and chat history is capped at the
27
+ last 12 turns to keep long sessions from exceeding context/GPU limits.
28
 
29
  ## Swapping the model
30
 
31
  Change `MODEL_ID` in `app.py` to any other instruct-tuned model on the Hub.
32
+ Verified working sizes so far (4-bit, packed footprint): 32B → ~20.7GB,
33
+ 72B → check the Space's build logs after a push. If a bigger model OOMs or
34
+ times out, the previous known-good `MODEL_ID` is `Qwen/Qwen2.5-32B-Instruct`.
app.py CHANGED
@@ -10,7 +10,8 @@ from transformers import (
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(
@@ -21,6 +22,7 @@ model = AutoModelForCausalLM.from_pretrained(
21
  bnb_4bit_compute_dtype=torch.bfloat16,
22
  ),
23
  device_map="auto",
 
24
  )
25
 
26
 
@@ -30,6 +32,8 @@ def _duration(message, history, system_prompt, max_new_tokens, temperature):
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:
35
  messages.append({"role": turn["role"], "content": turn["content"]})
@@ -42,14 +46,19 @@ def generate(message, history, system_prompt, max_new_tokens, temperature):
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
 
 
10
  TextIteratorStreamer,
11
  )
12
 
13
+ MODEL_ID = "Qwen/Qwen2.5-72B-Instruct"
14
+ MAX_HISTORY_TURNS = 12
15
 
16
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
17
  model = AutoModelForCausalLM.from_pretrained(
 
22
  bnb_4bit_compute_dtype=torch.bfloat16,
23
  ),
24
  device_map="auto",
25
+ attn_implementation="sdpa",
26
  )
27
 
28
 
 
32
 
33
  @spaces.GPU(duration=_duration)
34
  def generate(message, history, system_prompt, max_new_tokens, temperature):
35
+ history = history[-(MAX_HISTORY_TURNS * 2):]
36
+
37
  messages = [{"role": "system", "content": system_prompt}] if system_prompt else []
38
  for turn in history:
39
  messages.append({"role": turn["role"], "content": turn["content"]})
 
46
  streamer = TextIteratorStreamer(
47
  tokenizer, skip_prompt=True, skip_special_tokens=True
48
  )
49
+ do_sample = temperature > 0
50
  gen_kwargs = dict(
51
  **inputs,
52
  max_new_tokens=int(max_new_tokens),
53
+ do_sample=do_sample,
54
+ repetition_penalty=1.05,
55
  pad_token_id=tokenizer.eos_token_id,
56
  streamer=streamer,
57
  )
58
+ if do_sample:
59
+ gen_kwargs["temperature"] = float(temperature)
60
+ gen_kwargs["top_p"] = 0.9
61
+
62
  thread = threading.Thread(target=model.generate, kwargs=gen_kwargs)
63
  thread.start()
64