multimodalart HF Staff commited on
Commit
673ec6c
·
verified ·
1 Parent(s): 3f0f698

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +37 -11
app.py CHANGED
@@ -136,20 +136,42 @@ print("[dgemma] adapters loaded:", list(_NAME.values()), flush=True)
136
  model.to("cuda")
137
  print("[dgemma] model registered on cuda (ZeroGPU will stream on first call)", flush=True)
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  _THINK = re.compile(r"<think>(.*?)</think>", re.S)
140
  _ANSWER = re.compile(r"<answer>(.*?)</answer>", re.S)
 
 
 
141
 
142
 
143
  def _strip_cot(text: str) -> str:
144
  """Pull the <answer> (and <think> findings) out of a CoT response."""
145
  t = _THINK.search(text)
146
  a = _ANSWER.search(text)
147
- if not t and not a:
148
- return (text.replace("<think>", "").replace("</think>", "")
149
- .replace("<answer>", "").replace("</answer>", "").strip())
150
- findings = t.group(1).strip() if t else ""
151
- impression = a.group(1).strip() if a else ""
152
- return (findings + "\n" + impression).strip()
 
 
 
 
153
 
154
 
155
  def _prompt_inputs(image, instruction):
@@ -284,15 +306,19 @@ def infill_report(image: Image.Image, template: str, adapter_label: str,
284
  image = image.convert("RGB")
285
 
286
  tok = processor.tokenizer
287
- L = int(max_new_tokens)
 
 
288
  pad = tok.pad_token_id or 0
289
 
290
  # Split around the blank and locate its token span on the canvas.
291
  before, after = template.split(BLANK, 1)
292
  before_ids = tok(before, add_special_tokens=False)["input_ids"]
293
  after_ids = tok(after, add_special_tokens=False)["input_ids"]
294
- # Reserve room in the middle for the fill; scale by remaining canvas space.
295
- hole_len = max(1, min(48, L - len(before_ids) - len(after_ids) - 2))
 
 
296
  h0 = min(len(before_ids), L - 1)
297
  h1 = min(h0 + hole_len, L - 1)
298
 
@@ -403,8 +429,8 @@ with gr.Blocks(title="DiffusionGemma Radiology VQA") as demo:
403
  with gr.Column():
404
  inf_out = gr.Textbox(label="Filled span", lines=8)
405
  with gr.Accordion("Advanced", open=False):
406
- inf_tokens = gr.Slider(32, 256, value=MAX_NEW_TOKENS, step=16,
407
- label="Canvas length (max new tokens)")
408
  gr.Examples(
409
  examples=[
410
  ["cxr_aorta.png", "The lungs are clear. [BLANK] No pleural effusion is seen.", ADAPTER_LABELS[0], True],
 
136
  model.to("cuda")
137
  print("[dgemma] model registered on cuda (ZeroGPU will stream on first call)", flush=True)
138
 
139
+ # The discrete-diffusion backbone denoises a fixed-length canvas whose size is set by the
140
+ # base config (canvas_length=256), independent of the `max_new_tokens` request. Infill masks
141
+ # MUST be sized to this or the canvas-clamp hook mismatches the model's internal tensor.
142
+ def _canvas_length():
143
+ for obj in (model, getattr(model, "base_model", None)):
144
+ cfg = getattr(obj, "config", None)
145
+ v = getattr(cfg, "canvas_length", None)
146
+ if v:
147
+ return int(v)
148
+ return 256
149
+
150
+
151
+ CANVAS_LEN = _canvas_length()
152
+ print(f"[dgemma] canvas length = {CANVAS_LEN}", flush=True)
153
+
154
  _THINK = re.compile(r"<think>(.*?)</think>", re.S)
155
  _ANSWER = re.compile(r"<answer>(.*?)</answer>", re.S)
156
+ # Some finetunes emit an OpenAI-Harmony-style channel prefix, e.g. "<|channel|>thought\n..."
157
+ # or a bare "thought\n..." / "analysis\n..." lead-in before the actual answer. Strip it.
158
+ _CHANNEL = re.compile(r"^\s*(?:<\|[^>]*\|>)*\s*(?:thought|analysis|final|channel)\s*\n+", re.I)
159
 
160
 
161
  def _strip_cot(text: str) -> str:
162
  """Pull the <answer> (and <think> findings) out of a CoT response."""
163
  t = _THINK.search(text)
164
  a = _ANSWER.search(text)
165
+ if t or a:
166
+ findings = t.group(1).strip() if t else ""
167
+ impression = a.group(1).strip() if a else ""
168
+ return (findings + "\n" + impression).strip()
169
+ # No explicit CoT tags — clean up channel prefixes and any stray tag tokens.
170
+ t = re.sub(r"<\|[^>]*\|>", " ", text)
171
+ t = _CHANNEL.sub("", t)
172
+ t = (t.replace("<think>", "").replace("</think>", "")
173
+ .replace("<answer>", "").replace("</answer>", ""))
174
+ return t.strip()
175
 
176
 
177
  def _prompt_inputs(image, instruction):
 
306
  image = image.convert("RGB")
307
 
308
  tok = processor.tokenizer
309
+ # The model's denoising canvas is always CANVAS_LEN long, regardless of the
310
+ # max_new_tokens request; the clamp mask must match that exact size.
311
+ L = CANVAS_LEN
312
  pad = tok.pad_token_id or 0
313
 
314
  # Split around the blank and locate its token span on the canvas.
315
  before, after = template.split(BLANK, 1)
316
  before_ids = tok(before, add_special_tokens=False)["input_ids"]
317
  after_ids = tok(after, add_special_tokens=False)["input_ids"]
318
+ # Reserve room in the middle for the fill; cap by the user's requested span length
319
+ # and by the remaining canvas space.
320
+ max_fill = max(1, min(int(max_new_tokens), 96))
321
+ hole_len = max(1, min(max_fill, L - len(before_ids) - len(after_ids) - 2))
322
  h0 = min(len(before_ids), L - 1)
323
  h1 = min(h0 + hole_len, L - 1)
324
 
 
429
  with gr.Column():
430
  inf_out = gr.Textbox(label="Filled span", lines=8)
431
  with gr.Accordion("Advanced", open=False):
432
+ inf_tokens = gr.Slider(4, 96, value=48, step=4,
433
+ label="Max fill span (tokens)")
434
  gr.Examples(
435
  examples=[
436
  ["cxr_aorta.png", "The lungs are clear. [BLANK] No pleural effusion is seen.", ADAPTER_LABELS[0], True],