zkmine commited on
Commit
29a0caf
·
verified ·
1 Parent(s): c368c95

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -22
app.py CHANGED
@@ -50,24 +50,37 @@ EXAMPLES = [
50
  "though with a concomitant increase in minor bleeding events.",
51
  ]
52
 
53
- # --- Load model once, at module scope, on CPU. On ZeroGPU there is NO GPU
54
- # available at startup a GPU is only attached inside @spaces.GPU
55
- # functions so we must not touch CUDA here. The model is moved to the
56
- # GPU lazily, on the first rewrite() call. Tokenizer comes from the
57
- # official base repo to avoid any adapter-side tokenizer.json mismatch. ---
58
- print("Loading tokenizer and model on CPU...")
59
  tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)
60
  tokenizer.pad_token = tokenizer.eos_token
 
61
 
62
- base_model = AutoModelForCausalLM.from_pretrained(
63
- BASE_MODEL,
64
- dtype=torch.float16,
65
- trust_remote_code=True,
66
- )
67
- model = PeftModel.from_pretrained(base_model, ADAPTER_ID, token=HF_TOKEN)
68
- model.eval()
69
- _on_gpu = False # tracks whether the model has been moved to CUDA yet
70
- print("Model loaded on CPU; will move to GPU on first request.")
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
 
73
  def _build_prompt(text: str) -> str:
@@ -87,7 +100,7 @@ def _decode(output_ids, input_len: int) -> str:
87
  return tokenizer.decode(gen, skip_special_tokens=True).strip()
88
 
89
 
90
- @spaces.GPU(duration=120)
91
  def rewrite(text: str):
92
  """
93
  Produce base ('before') and fine-tuned ('after') rewrites.
@@ -105,12 +118,9 @@ def rewrite(text: str):
105
  if not text or not text.strip():
106
  return "", "Please paste some medical text above first."
107
 
108
- # Move the model onto the ZeroGPU-attached GPU on first use. This runs
109
- # inside @spaces.GPU, so CUDA is available here (unlike at module scope).
110
- global _on_gpu
111
- if not _on_gpu:
112
- model.to("cuda")
113
- _on_gpu = True
114
 
115
  prompt = _build_prompt(text)
116
  inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
 
50
  "though with a concomitant increase in minor bleeding events.",
51
  ]
52
 
53
+ # --- On ZeroGPU, torch is patched at import time and there is NO GPU at
54
+ # module scope, so we cannot load model weights here (even a CPU load of
55
+ # safetensors gets intercepted and tries to reach CUDA). We load only the
56
+ # tokenizer eagerly, and defer ALL model loading to the first GPU call. ---
57
+ print("Loading tokenizer...")
 
58
  tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)
59
  tokenizer.pad_token = tokenizer.eos_token
60
+ print("Tokenizer ready; model loads on first request.")
61
 
62
+ _model = None # lazily populated inside the @spaces.GPU function
63
+
64
+
65
+ def _load_model():
66
+ """
67
+ Load base + LoRA adapter and place on CUDA. Called once, lazily, from
68
+ inside the @spaces.GPU function where a GPU is actually attached.
69
+ """
70
+ global _model
71
+ if _model is not None:
72
+ return _model
73
+
74
+ base_model = AutoModelForCausalLM.from_pretrained(
75
+ BASE_MODEL,
76
+ dtype=torch.float16,
77
+ trust_remote_code=True,
78
+ )
79
+ peft_model = PeftModel.from_pretrained(base_model, ADAPTER_ID, token=HF_TOKEN)
80
+ peft_model = peft_model.to("cuda")
81
+ peft_model.eval()
82
+ _model = peft_model
83
+ return _model
84
 
85
 
86
  def _build_prompt(text: str) -> str:
 
100
  return tokenizer.decode(gen, skip_special_tokens=True).strip()
101
 
102
 
103
+ @spaces.GPU(duration=300)
104
  def rewrite(text: str):
105
  """
106
  Produce base ('before') and fine-tuned ('after') rewrites.
 
118
  if not text or not text.strip():
119
  return "", "Please paste some medical text above first."
120
 
121
+ # Load the model on first use we are inside @spaces.GPU here, so a GPU
122
+ # is attached and CUDA is available (unlike at module scope).
123
+ model = _load_model()
 
 
 
124
 
125
  prompt = _build_prompt(text)
126
  inputs = tokenizer(prompt, return_tensors="pt").to("cuda")