DragonForgeStudios commited on
Commit
a83d0f3
·
verified ·
1 Parent(s): cf6986c

forge: warm model on CPU at startup; GPU window 40s; move to cuda per call

Browse files
Files changed (1) hide show
  1. app.py +19 -3
app.py CHANGED
@@ -40,7 +40,7 @@ def _load():
40
  model = AutoModelForCausalLM.from_pretrained(
41
  MODEL_ID, quantization_config=qcfg,
42
  torch_dtype=torch.float16, low_cpu_mem_usage=True,
43
- device_map="auto")
44
  model.eval()
45
  _state["model"], _state["tok"] = model, tok
46
  except Exception as exc:
@@ -49,7 +49,7 @@ def _load():
49
  return _state["model"], _state["tok"]
50
 
51
 
52
- @spaces.GPU(duration=150)
53
  def forge(system_prompt: str, user_prompt: str, max_tokens: float) -> str:
54
  """One generation. Exposed as Gradio api_name='forge'."""
55
  model, tok = _load()
@@ -57,18 +57,34 @@ def forge(system_prompt: str, user_prompt: str, max_tokens: float) -> str:
57
  if system_prompt:
58
  messages.append({"role": "system", "content": system_prompt})
59
  messages.append({"role": "user", "content": user_prompt})
 
 
 
 
 
 
60
  text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
61
  inputs = tok(text, return_tensors="pt").to(model.device)
62
  with torch.inference_mode():
63
  out = model.generate(**inputs, max_new_tokens=int(max_tokens),
64
  do_sample=False, pad_token_id=tok.eos_token_id)
65
- return tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
 
 
 
 
 
 
66
 
67
 
68
  def status() -> str:
69
  return "model=%s loaded=%s error=%s" % (MODEL_ID, _state["model"] is not None, _state["err"])
70
 
71
 
 
 
 
 
72
  with gr.Blocks(title="Forge model server") as demo:
73
  gr.Markdown("## Forge model server\n"
74
  "OpenAI-compatible routes are impossible here (see app.py header). "
 
40
  model = AutoModelForCausalLM.from_pretrained(
41
  MODEL_ID, quantization_config=qcfg,
42
  torch_dtype=torch.float16, low_cpu_mem_usage=True,
43
+ device_map="cpu")
44
  model.eval()
45
  _state["model"], _state["tok"] = model, tok
46
  except Exception as exc:
 
49
  return _state["model"], _state["tok"]
50
 
51
 
52
+ @spaces.GPU(duration=40)
53
  def forge(system_prompt: str, user_prompt: str, max_tokens: float) -> str:
54
  """One generation. Exposed as Gradio api_name='forge'."""
55
  model, tok = _load()
 
57
  if system_prompt:
58
  messages.append({"role": "system", "content": system_prompt})
59
  messages.append({"role": "user", "content": user_prompt})
60
+ moved = False
61
+ if torch.cuda.is_available():
62
+ try:
63
+ model.to("cuda"); moved = True
64
+ except Exception as exc:
65
+ print("cuda move failed:", repr(exc), flush=True)
66
  text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
67
  inputs = tok(text, return_tensors="pt").to(model.device)
68
  with torch.inference_mode():
69
  out = model.generate(**inputs, max_new_tokens=int(max_tokens),
70
  do_sample=False, pad_token_id=tok.eos_token_id)
71
+ res = tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
72
+ if moved:
73
+ try:
74
+ model.to("cpu"); torch.cuda.empty_cache()
75
+ except Exception:
76
+ pass
77
+ return res
78
 
79
 
80
  def status() -> str:
81
  return "model=%s loaded=%s error=%s" % (MODEL_ID, _state["model"] is not None, _state["err"])
82
 
83
 
84
+ # Warm at startup: the ~2.5 GB download + 4-bit load happen on CPU, outside the GPU
85
+ # window. A free ZeroGPU window is capped (~60 s), far too small to download a model in.
86
+ threading.Thread(target=_load, daemon=True).start()
87
+
88
  with gr.Blocks(title="Forge model server") as demo:
89
  gr.Markdown("## Forge model server\n"
90
  "OpenAI-compatible routes are impossible here (see app.py header). "