Spaces:
Running on Zero
Running on Zero
Upload app.py with huggingface_hub
Browse files
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
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
| 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;
|
| 295 |
-
|
|
|
|
|
|
|
| 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(
|
| 407 |
-
label="
|
| 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],
|