Ruurd's picture
Deploy BYOD-Llama-3.1-8B full-precision demo
3329d00 verified
Raw
History Blame Contribute Delete
7.5 kB
"""Shared full-precision ZeroGPU demo for the four BYOD models."""
from __future__ import annotations
import json
import os
import secrets
import sys
import time
from pathlib import Path
import gradio as gr
import spaces
sys.path.insert(0, str(Path(__file__).parent / "src"))
from diffusion_lm.inference import denoise_stream, load_hub_adapter_session
SPACE = json.loads((Path(__file__).parent / "space_model.json").read_text())
MODEL_REPO_ID = os.getenv("MODEL_REPO_ID", SPACE["model_repo_id"])
DISPLAY_NAME = SPACE["display_name"]
# ZeroGPU recommends constructing and placing the root module on CUDA at module
# scope. No quantization is used: all four demos run with the saved BF16 setup.
print(f"Loading {MODEL_REPO_ID} in full precision...")
SESSION = load_hub_adapter_session(
MODEL_REPO_ID,
device_name="cuda",
quantization="none",
# A forward pass is only valid after @spaces.GPU has allocated hardware.
preflight=False,
)
print(f"Loaded {DISPLAY_NAME} ({SESSION.compute_dtype}, unquantized).")
def _duration(*args) -> int:
"""Reserve enough GPU time for the requested number of denoising steps."""
try:
steps = int(args[3])
pause_per_step = float(args[7])
except (IndexError, TypeError, ValueError):
steps = 64
pause_per_step = 0.0
return min(300, max(30, round(steps * (2.0 + pause_per_step))))
@spaces.GPU(size="large", duration=_duration)
def generate(
question: str,
system_prompt: str,
max_new_tokens: int,
num_steps: int,
block_length: int,
temperature: float,
top_k: int,
pause_per_step: float,
trajectory_color_mode: str,
remasking_strategy: str,
delay_eos_eot: bool,
early_stopping: bool,
):
"""Stream iterative masked-diffusion generation from the fixed model."""
question = question.strip() or "What do you know about Amsterdam?"
block_length = min(int(block_length), int(max_new_tokens))
seed = secrets.randbelow(2**63 - 1)
first_step = True
for text, status, trajectory_html in denoise_stream(
SESSION,
question=question,
system_prompt=system_prompt,
max_new_tokens=int(max_new_tokens),
num_steps=int(num_steps),
noise_level=1.0,
temperature=float(temperature),
top_k=int(top_k),
seed=int(seed),
permanent_unmask=True,
confidence_guided=remasking_strategy == "Confidence-guided",
proportional_unmask=False,
early_stopping=bool(early_stopping),
# This delays retention of predicted endings; it does not alter their
# sampling probability. Keep it optional so answers can end naturally.
confidence_eos_eot_inf=bool(delay_eos_eot),
freeze_retained_tokens=True,
repetition_penalty=1.0,
eos_eot_prediction_penalty=1.0,
include_pre_remask_prediction=False,
block_length=block_length,
trajectory_color_mode=trajectory_color_mode,
):
if not first_step and float(pause_per_step) > 0:
# The sleep occurs inside this one decorated generator invocation,
# so ZeroGPU remains allocated for the entire denoising run.
time.sleep(float(pause_per_step))
first_step = False
yield status, trajectory_html
def show_loading():
"""Immediately acknowledge a request while ZeroGPU prepares generation."""
return (
"⏳ Requesting a GPU and loading the model…",
"<div style='font-family:system-ui;padding:14px;border:1px solid #d1d5db;"
"border-radius:9px;background:#fafafa;color:#4b5563'>"
"Preparing generation… The first request may take a little longer while "
"the model is loaded.</div>",
)
with gr.Blocks(title=f"{DISPLAY_NAME} · masked diffusion") as demo:
gr.Markdown(
f"# {DISPLAY_NAME}\n"
"A full-precision masked-diffusion model converted from an "
"autoregressive language model with LoRA. This demo uses the exact "
"best training checkpoint and does **not** use 4-bit quantization."
)
with gr.Row():
with gr.Column(scale=3):
question = gr.Textbox(
label="Prompt",
value="What do you know about Amsterdam?",
lines=4,
)
run = gr.Button("Generate", variant="primary")
status = gr.Markdown("Ready")
trajectory = gr.HTML(label="Live denoising")
with gr.Column(scale=2):
system_prompt = gr.Textbox(
label="System prompt",
value="You are a helpful assistant.",
lines=2,
)
max_new_tokens = gr.Slider(16, 512, value=64, step=16, label="New tokens")
num_steps = gr.Slider(1, 512, value=64, step=1, label="Denoising steps")
block_length = gr.Slider(16, 512, value=64, step=16, label="Block length")
temperature = gr.Slider(0.0, 2.0, value=0.7, step=0.05, label="Temperature")
top_k = gr.Slider(1, 100, value=3, step=1, label="Top-k")
pause_per_step = gr.Slider(
0.0,
1.0,
value=0.0,
step=0.05,
label="Pause between denoising steps (seconds)",
info="Slows the visualization while keeping one GPU allocation for the full run.",
)
trajectory_color_mode = gr.Radio(
choices=["No coloring", "Prediction probability", "Prediction iteration"],
value="Prediction iteration",
label="Token coloring",
info="Hover over any token to see its position, prediction iteration, and probability.",
)
remasking_strategy = gr.Radio(
choices=["Confidence-guided", "Random"],
value="Confidence-guided",
label="Remasking strategy",
info="Confidence-guided retains the most confident predictions; random selects ordinary token positions randomly.",
)
delay_eos_eot = gr.Checkbox(
value=True,
label="Delay EOS/EOT retention (longer answers)",
info="Preferentially re-masks predicted endings; it does not lower their prediction probability.",
)
early_stopping = gr.Checkbox(
value=True,
label="Early stopping",
info="Stop after the visible answer is unchanged for two consecutive iterations.",
)
gr.Markdown(
"The first request may take longer while the base model and adapter are loaded. "
f"[Model card](https://huggingface.co/{MODEL_REPO_ID}) · "
"[Source code](https://github.com/RuurdKuiper/lad-generic)"
)
inputs = [
question,
system_prompt,
max_new_tokens,
num_steps,
block_length,
temperature,
top_k,
pause_per_step,
trajectory_color_mode,
remasking_strategy,
delay_eos_eot,
early_stopping,
]
run_event = run.click(show_loading, outputs=[status, trajectory], queue=False)
run_event.then(generate, inputs=inputs, outputs=[status, trajectory])
submit_event = question.submit(show_loading, outputs=[status, trajectory], queue=False)
submit_event.then(generate, inputs=inputs, outputs=[status, trajectory])
demo.queue(default_concurrency_limit=1).launch(ssr_mode=False)