Spaces:
Running on Zero
Running on Zero
Rewriter Arena: 9B vs 0.8B vs 2B rewriters side by side
Browse files- README.md +32 -7
- app.py +202 -0
- requirements.txt +7 -0
- rewriters.py +160 -0
- sheets.json +282 -0
README.md
CHANGED
|
@@ -1,13 +1,38 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 6.28.0
|
| 8 |
-
python_version:
|
| 9 |
app_file: app.py
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
---
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Qwen-Image 2.1 Rewriter Arena
|
| 3 |
+
emoji: ⚖️
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: pink
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 6.28.0
|
| 8 |
+
python_version: "3.12"
|
| 9 |
app_file: app.py
|
| 10 |
+
startup_duration_timeout: 1h
|
| 11 |
+
short_description: 9B vs 0.8B vs 2B prompt rewriters, rendered side by side
|
| 12 |
+
license: other
|
| 13 |
+
license_name: qwen-research
|
| 14 |
+
models:
|
| 15 |
+
- Qwen/Qwen-Image-2.1
|
| 16 |
+
- Qwen/Qwen-Image-2.1-PE-T2I
|
| 17 |
+
- ysharma/image21-pocket-rewriter-0.8B
|
| 18 |
+
- ysharma/image21-pocket-rewriter-2B
|
| 19 |
+
datasets:
|
| 20 |
+
- ysharma/image21-rewriter-distill
|
| 21 |
+
tags:
|
| 22 |
+
- text-to-image
|
| 23 |
+
- prompt-rewriting
|
| 24 |
+
- distillation
|
| 25 |
+
- benchmark
|
| 26 |
---
|
| 27 |
|
| 28 |
+
# Qwen-Image 2.1 Rewriter Arena
|
| 29 |
+
|
| 30 |
+
One request goes through the official 9B prompt rewriter
|
| 31 |
+
([Qwen/Qwen-Image-2.1-PE-T2I](https://huggingface.co/Qwen/Qwen-Image-2.1-PE-T2I)), the two pocket distillations
|
| 32 |
+
([0.8B](https://huggingface.co/ysharma/image21-pocket-rewriter-0.8B), [2B](https://huggingface.co/ysharma/image21-pocket-rewriter-2B)),
|
| 33 |
+
and optionally no rewriter at all. Every rewrite is rendered by [Qwen-Image 2.1](https://huggingface.co/Qwen/Qwen-Image-2.1) with a
|
| 34 |
+
shared seed and shown in a grid with its prompt, token count and rewrite time. A second tab shows the 40-request evaluation
|
| 35 |
+
contact sheets from [ysharma/image21-rewriter-distill](https://huggingface.co/datasets/ysharma/image21-rewriter-distill)
|
| 36 |
+
without using any GPU.
|
| 37 |
+
|
| 38 |
+
Built with Qwen. All models are under the Qwen Research License (non-commercial research use).
|
app.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import spaces # must be imported before torch on ZeroGPU
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import os
|
| 5 |
+
import random
|
| 6 |
+
|
| 7 |
+
import gradio as gr
|
| 8 |
+
import torch
|
| 9 |
+
from diffusers import QwenImage21Pipeline
|
| 10 |
+
|
| 11 |
+
from rewriters import STUDENT_IDS, TEACHER_ID, load_student, load_teacher, size_for, student_rewrite, teacher_rewrite
|
| 12 |
+
|
| 13 |
+
IMAGE_ID = "Qwen/Qwen-Image-2.1"
|
| 14 |
+
DATASET_ID = "ysharma/image21-rewriter-distill"
|
| 15 |
+
MAX_SEED = 2**31 - 1
|
| 16 |
+
ARMS = ["Raw request (no rewriter)", "Official 9B rewriter", "0.8B pocket rewriter", "2B pocket rewriter"]
|
| 17 |
+
DEFAULT_ARMS = ARMS[1:]
|
| 18 |
+
HERE = os.path.dirname(os.path.abspath(__file__))
|
| 19 |
+
|
| 20 |
+
with open(os.path.join(HERE, "sheets.json"), encoding="utf-8") as f:
|
| 21 |
+
SHEETS = json.load(f) # [{"id","request","lang","category","sheet_url"}]
|
| 22 |
+
SHEET_CHOICES = [(f"[{s['lang']}] {s['request'][:90]}", s["id"]) for s in SHEETS]
|
| 23 |
+
OVERVIEW_URL = f"https://huggingface.co/datasets/{DATASET_ID}/resolve/main/renders/sheets/sheet_overview.png"
|
| 24 |
+
|
| 25 |
+
# ----------------------------------------------------------------- models (module scope, eager)
|
| 26 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 27 |
+
pipe = QwenImage21Pipeline.from_pretrained(IMAGE_ID, dtype=torch.bfloat16).to(device)
|
| 28 |
+
teacher_tok, teacher, teacher_system = load_teacher(device)
|
| 29 |
+
students = {size: load_student(size, device) for size in STUDENT_IDS}
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def est_seconds(arms, steps, megapixels, teacher_tokens) -> int:
|
| 33 |
+
t = 10
|
| 34 |
+
if ARMS[1] in arms:
|
| 35 |
+
t += 20 + int(teacher_tokens) * 0.035 # 9B with thinking
|
| 36 |
+
t += 8 * sum(a in arms for a in ARMS[2:]) # students
|
| 37 |
+
t += len(arms) * (10 + int(steps) * 0.6 * float(megapixels))
|
| 38 |
+
return int(t)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def compare_duration(request, arms=DEFAULT_ARMS, steps=28, megapixels=1.0, seed=0, randomize_seed=True,
|
| 42 |
+
teacher_tokens=3072, *a, **k):
|
| 43 |
+
return est_seconds(arms, steps, megapixels, teacher_tokens)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _rewrite(arm, request, seed, teacher_tokens):
|
| 47 |
+
if arm == ARMS[0]:
|
| 48 |
+
return {"prompt": request, "ratio": "3:2", "parse_ok": True, "tokens": 0, "seconds": 0.0, "thinking": ""}
|
| 49 |
+
if arm == ARMS[1]:
|
| 50 |
+
return teacher_rewrite(teacher_tok, teacher, teacher_system, request, seed=seed, max_new_tokens=int(teacher_tokens))
|
| 51 |
+
tok, model = students["0.8B" if arm == ARMS[2] else "2B"]
|
| 52 |
+
return student_rewrite(tok, model, request, seed=seed)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def _stats(arm, r, w=None, h=None):
|
| 56 |
+
if arm == ARMS[0]:
|
| 57 |
+
s = "No rewrite."
|
| 58 |
+
else:
|
| 59 |
+
s = f"{r['tokens']} tokens in {r['seconds']:.1f} s"
|
| 60 |
+
if r.get("thinking"):
|
| 61 |
+
s += f" (thinking included)"
|
| 62 |
+
s += f". Ratio {r['ratio']}."
|
| 63 |
+
if not r["parse_ok"]:
|
| 64 |
+
s += " Not valid JSON; raw text used."
|
| 65 |
+
if w:
|
| 66 |
+
s += f" Rendered {w}x{h}."
|
| 67 |
+
return s
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
@spaces.GPU(size="xlarge", duration=compare_duration)
|
| 71 |
+
def compare(request: str, arms: list = DEFAULT_ARMS, steps: int = 28, megapixels: float = 1.0, seed: int = 0,
|
| 72 |
+
randomize_seed: bool = True, teacher_tokens: int = 3072):
|
| 73 |
+
"""Rewrite one request with each selected rewriter, then render every rewrite with Qwen-Image 2.1 at the same seed.
|
| 74 |
+
Yields progressively: prompts first, then one image per arm."""
|
| 75 |
+
request = (request or "").strip()
|
| 76 |
+
if not request:
|
| 77 |
+
raise gr.Error("Type an image request first.")
|
| 78 |
+
if not arms:
|
| 79 |
+
raise gr.Error("Select at least one arm.")
|
| 80 |
+
if randomize_seed:
|
| 81 |
+
seed = random.randint(0, MAX_SEED)
|
| 82 |
+
seed = int(seed)
|
| 83 |
+
cols = {a: {"image": None, "prompt": "", "stats": "waiting" if a in arms else "not selected"} for a in ARMS}
|
| 84 |
+
|
| 85 |
+
def emit(msg):
|
| 86 |
+
return tuple([cols[a]["image"] for a in ARMS] + [cols[a]["prompt"] for a in ARMS]
|
| 87 |
+
+ [cols[a]["stats"] for a in ARMS] + [seed, msg])
|
| 88 |
+
|
| 89 |
+
rewrites = {}
|
| 90 |
+
for a in ARMS:
|
| 91 |
+
if a not in arms:
|
| 92 |
+
continue
|
| 93 |
+
cols[a]["stats"] = "rewriting..."
|
| 94 |
+
yield emit(f"Rewriting with {a}...")
|
| 95 |
+
r = _rewrite(a, request, seed, teacher_tokens)
|
| 96 |
+
rewrites[a] = r
|
| 97 |
+
cols[a]["prompt"], cols[a]["stats"] = r["prompt"], _stats(a, r)
|
| 98 |
+
yield emit(f"Rewrote with {a}.")
|
| 99 |
+
for a in ARMS:
|
| 100 |
+
if a not in arms:
|
| 101 |
+
continue
|
| 102 |
+
cols[a]["stats"] += " Rendering..."
|
| 103 |
+
yield emit(f"Rendering {a}...")
|
| 104 |
+
r = rewrites[a]
|
| 105 |
+
w, h = size_for(r["ratio"], megapixels)
|
| 106 |
+
image = pipe(prompt=r["prompt"], width=w, height=h, num_inference_steps=int(steps),
|
| 107 |
+
generator=torch.Generator(device="cuda").manual_seed(seed)).images[0]
|
| 108 |
+
cols[a]["image"], cols[a]["stats"] = image, _stats(a, r, w, h)
|
| 109 |
+
yield emit(f"Rendered {a}.")
|
| 110 |
+
yield emit(f"Done. Seed {seed}, {int(steps)} steps, about {megapixels} megapixels per image.")
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def show_sheet(sheet_id):
|
| 114 |
+
s = next((x for x in SHEETS if x["id"] == sheet_id), None)
|
| 115 |
+
if not s:
|
| 116 |
+
return None, ""
|
| 117 |
+
return s["sheet_url"], f"**Request ({s['lang']}, {s['category']}):** {s['request']}"
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
# ----------------------------------------------------------------- UI
|
| 121 |
+
CSS = """
|
| 122 |
+
#col-container { max-width: 1500px; margin: 0 auto; }
|
| 123 |
+
.dark .gradio-container { color: var(--body-text-color); }
|
| 124 |
+
"""
|
| 125 |
+
|
| 126 |
+
INTRO = f"""
|
| 127 |
+
# ⚖️ Qwen-Image 2.1 Rewriter Arena
|
| 128 |
+
One request, several prompt rewriters, same seed, side by side. Compare the **official 9B rewriter**
|
| 129 |
+
([{TEACHER_ID}](https://huggingface.co/{TEACHER_ID}): 1,700-word system prompt, thinking on, about 1,600 tokens per rewrite) against
|
| 130 |
+
its two pocket distillations, [0.8B](https://huggingface.co/{STUDENT_IDS['0.8B']}) and [2B](https://huggingface.co/{STUDENT_IDS['2B']})
|
| 131 |
+
(no system prompt, no thinking, about 450 tokens), and the raw request with no rewriting. Each rewrite is rendered by
|
| 132 |
+
[Qwen-Image 2.1](https://huggingface.co/{IMAGE_ID}) at the ratio that rewriter chose.
|
| 133 |
+
|
| 134 |
+
A live run with the 9B arm takes 2 to 3 minutes of GPU time. The **Pre-rendered comparisons** tab shows the 40-request evaluation
|
| 135 |
+
grid at no cost. Research demo under the Qwen Research License (non-commercial). Built with Qwen.
|
| 136 |
+
"""
|
| 137 |
+
|
| 138 |
+
ABOUT = """
|
| 139 |
+
**What the 40-request evaluation found.** Rendered-text OCR word accuracy: raw request 0.46, official 9B rewriter 0.80,
|
| 140 |
+
0.8B student 0.57, 2B student 0.55. The students keep roughly a quarter to a third of the teacher's gain, close to the teacher on Latin
|
| 141 |
+
text and further behind on Chinese and Japanese. A pairwise vision-model judge could not separate the arms.
|
| 142 |
+
On text-level checks over 300 held-out requests the students match the teacher on valid JSON and allowed ratios (99 to 100%) and on
|
| 143 |
+
keeping the user's quoted text (53% and 60% versus 53%), at about 28% of the tokens.
|
| 144 |
+
|
| 145 |
+
**How to read a live run.** Look for the quoted text in each image, whether the ratio suits the subject, and whether the rewrite
|
| 146 |
+
invented things the request did not ask for. The seed is shared, but each arm renders at its own ratio, so compositions differ.
|
| 147 |
+
|
| 148 |
+
**Fairness notes.** The teacher runs with its official protocol: system prompt, thinking, presence penalty 1.5, sampling at
|
| 149 |
+
temperature 1.0. The token cap for the teacher is adjustable; its mean is about 1,600 and a few requests need more. The students use the
|
| 150 |
+
same sampling with no system prompt. All arms use 28 steps here for speed; the evaluation used 40.
|
| 151 |
+
|
| 152 |
+
Data, predictions and all 41 contact sheets: [ysharma/image21-rewriter-distill](https://huggingface.co/datasets/ysharma/image21-rewriter-distill).
|
| 153 |
+
The students were trained end to end by ML Intern in HuggingChat for about 16 USD.
|
| 154 |
+
"""
|
| 155 |
+
|
| 156 |
+
EXAMPLES = [[s["request"]] for s in SHEETS[:12]]
|
| 157 |
+
|
| 158 |
+
with gr.Blocks(title="Qwen-Image 2.1 Rewriter Arena") as demo:
|
| 159 |
+
with gr.Column(elem_id="col-container"):
|
| 160 |
+
gr.Markdown(INTRO)
|
| 161 |
+
with gr.Tabs():
|
| 162 |
+
with gr.Tab("Live comparison"):
|
| 163 |
+
with gr.Row():
|
| 164 |
+
request = gr.Textbox(label="Your request (any language)", lines=2, scale=4,
|
| 165 |
+
placeholder='a man at a bus stop "next bus 15 min"')
|
| 166 |
+
run = gr.Button("Compare", variant="primary", scale=1)
|
| 167 |
+
arms = gr.CheckboxGroup(ARMS, value=DEFAULT_ARMS, label="Arms to run")
|
| 168 |
+
with gr.Accordion("Settings", open=False):
|
| 169 |
+
steps = gr.Slider(8, 50, value=28, step=1, label="Steps")
|
| 170 |
+
megapixels = gr.Slider(0.5, 1.5, value=1.0, step=0.25, label="Megapixels per image")
|
| 171 |
+
teacher_tokens = gr.Slider(1024, 6144, value=3072, step=256, label="Token cap for the 9B rewriter",
|
| 172 |
+
info="Its rewrite plus thinking averages about 1,600 tokens")
|
| 173 |
+
seed = gr.Slider(0, MAX_SEED, value=0, step=1, label="Seed (shared by all arms)")
|
| 174 |
+
randomize_seed = gr.Checkbox(True, label="Randomize seed")
|
| 175 |
+
status = gr.Markdown("")
|
| 176 |
+
images, prompts, stats = [], [], []
|
| 177 |
+
with gr.Row():
|
| 178 |
+
for a in ARMS:
|
| 179 |
+
with gr.Column():
|
| 180 |
+
images.append(gr.Image(label=a, format="png", image_mode="RGBA", height=360))
|
| 181 |
+
stats.append(gr.Markdown(""))
|
| 182 |
+
prompts.append(gr.Textbox(label="Prompt sent to the image model", lines=6, interactive=False))
|
| 183 |
+
gr.Examples(examples=EXAMPLES, inputs=[request], label="Held-out evaluation requests (fills the box; press Compare)",
|
| 184 |
+
cache_examples=False)
|
| 185 |
+
gr.on([run.click, request.submit], compare,
|
| 186 |
+
[request, arms, steps, megapixels, seed, randomize_seed, teacher_tokens],
|
| 187 |
+
images + prompts + stats + [seed, status], api_name="compare")
|
| 188 |
+
with gr.Tab("Pre-rendered comparisons (no GPU)"):
|
| 189 |
+
gr.Markdown("The 40 evaluation requests rendered at 40 steps, seed 0, with the raw request, the 9B teacher and both "
|
| 190 |
+
"students. Columns follow the sheet's own header.")
|
| 191 |
+
sheet_pick = gr.Dropdown(SHEET_CHOICES, value=SHEET_CHOICES[0][1], label="Request")
|
| 192 |
+
sheet_caption = gr.Markdown("")
|
| 193 |
+
sheet_img = gr.Image(label="Contact sheet", height=760)
|
| 194 |
+
sheet_pick.change(show_sheet, sheet_pick, [sheet_img, sheet_caption], api_visibility="private")
|
| 195 |
+
demo.load(show_sheet, sheet_pick, [sheet_img, sheet_caption], api_visibility="private")
|
| 196 |
+
with gr.Accordion("Overview sheet (all 40 requests)", open=False):
|
| 197 |
+
gr.Image(value=OVERVIEW_URL, label="Overview", height=900)
|
| 198 |
+
with gr.Accordion("About the numbers and fairness", open=False):
|
| 199 |
+
gr.Markdown(ABOUT)
|
| 200 |
+
|
| 201 |
+
if __name__ == "__main__":
|
| 202 |
+
demo.queue(max_size=20).launch(theme=gr.themes.Citrus(), css=CSS)
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
diffusers @ git+https://github.com/huggingface/diffusers.git
|
| 2 |
+
transformers>=5.17.0
|
| 3 |
+
accelerate
|
| 4 |
+
torchvision
|
| 5 |
+
safetensors
|
| 6 |
+
pillow
|
| 7 |
+
json_repair
|
rewriters.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Prompt rewriters for Qwen-Image 2.1: the official 9B teacher and the two pocket students.
|
| 2 |
+
|
| 3 |
+
Teacher protocol follows QwenLM/Qwen-Image-2.1 prompt_rewrite/ (system prompt, thinking on,
|
| 4 |
+
presence penalty 1.5, JSON answer parsed last-span-first). Student protocol follows the
|
| 5 |
+
model cards: raw request as the only user turn, no system prompt, thinking disabled.
|
| 6 |
+
"""
|
| 7 |
+
import json
|
| 8 |
+
import time
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
from huggingface_hub import hf_hub_download
|
| 12 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, LogitsProcessor, LogitsProcessorList
|
| 13 |
+
|
| 14 |
+
try:
|
| 15 |
+
import json_repair
|
| 16 |
+
except ImportError: # pragma: no cover
|
| 17 |
+
json_repair = None
|
| 18 |
+
|
| 19 |
+
TEACHER_ID = "Qwen/Qwen-Image-2.1-PE-T2I"
|
| 20 |
+
STUDENT_IDS = {
|
| 21 |
+
"0.8B": "ysharma/image21-pocket-rewriter-0.8B",
|
| 22 |
+
"2B": "ysharma/image21-pocket-rewriter-2B",
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
# ~1 megapixel sizes per ratio, multiples of 32 (same table as the distillation image eval).
|
| 26 |
+
RATIO_SIZES = {
|
| 27 |
+
"1:1": (1024, 1024), "3:2": (1248, 832), "2:3": (832, 1248),
|
| 28 |
+
"16:9": (1376, 768), "9:16": (768, 1376), "4:3": (1184, 896),
|
| 29 |
+
"3:4": (896, 1184), "2:1": (1472, 736), "1:2": (736, 1472),
|
| 30 |
+
"21:9": (1568, 672), "9:21": (672, 1568), "4:5": (928, 1152),
|
| 31 |
+
"5:4": (1152, 928), "3:1": (1728, 576), "1:3": (576, 1760),
|
| 32 |
+
}
|
| 33 |
+
DEFAULT_RATIO = "3:2"
|
| 34 |
+
SAMPLING = dict(do_sample=True, temperature=1.0, top_p=0.95, top_k=20)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def size_for(ratio: str, megapixels: float = 1.0) -> tuple[int, int]:
|
| 38 |
+
"""(width, height) for a ratio, scaled to about `megapixels`, multiples of 32."""
|
| 39 |
+
w, h = RATIO_SIZES.get(ratio, RATIO_SIZES[DEFAULT_RATIO])
|
| 40 |
+
s = (megapixels * 1_000_000 / (w * h)) ** 0.5
|
| 41 |
+
return max(256, int(w * s) // 32 * 32), max(256, int(h * s) // 32 * 32)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# ----------------------------------------------------------------------------- parsing (from pe_core.py)
|
| 45 |
+
def split_thinking(text: str) -> tuple[str, str]:
|
| 46 |
+
if "</think>" in text:
|
| 47 |
+
think, _, answer = text.partition("</think>")
|
| 48 |
+
if "<think>" in think:
|
| 49 |
+
think = think.partition("<think>")[2]
|
| 50 |
+
return think.strip(), answer.strip()
|
| 51 |
+
if "<think>" in text:
|
| 52 |
+
return text.partition("<think>")[2].strip(), ""
|
| 53 |
+
return "", text.strip()
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _balanced_spans(answer: str) -> list[str]:
|
| 57 |
+
spans, depth, start = [], 0, -1
|
| 58 |
+
for i, ch in enumerate(answer):
|
| 59 |
+
if ch == "{":
|
| 60 |
+
if depth == 0:
|
| 61 |
+
start = i
|
| 62 |
+
depth += 1
|
| 63 |
+
elif ch == "}" and depth:
|
| 64 |
+
depth -= 1
|
| 65 |
+
if depth == 0 and start >= 0:
|
| 66 |
+
spans.append(answer[start:i + 1])
|
| 67 |
+
return spans
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _as_obj(candidate: str):
|
| 71 |
+
try:
|
| 72 |
+
obj = json.loads(candidate)
|
| 73 |
+
except json.JSONDecodeError:
|
| 74 |
+
if json_repair is None:
|
| 75 |
+
return None
|
| 76 |
+
obj = json_repair.repair_json(candidate, return_objects=True)
|
| 77 |
+
if isinstance(obj, list):
|
| 78 |
+
obj = obj[0] if obj else None
|
| 79 |
+
return obj if isinstance(obj, dict) else None
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def parse_answer(answer: str) -> dict:
|
| 83 |
+
answer = (answer or "").strip()
|
| 84 |
+
for candidate in reversed(_balanced_spans(answer)):
|
| 85 |
+
obj = _as_obj(candidate)
|
| 86 |
+
if obj is None:
|
| 87 |
+
continue
|
| 88 |
+
rewritten = obj.get("rewritten_prompt") or obj.get("rewrited_prompt")
|
| 89 |
+
if not isinstance(rewritten, str) or not rewritten.strip():
|
| 90 |
+
continue
|
| 91 |
+
ratio = str(obj.get("wh_ratio") or "").strip()
|
| 92 |
+
return {"prompt": rewritten.strip(), "ratio": ratio if ratio in RATIO_SIZES else DEFAULT_RATIO,
|
| 93 |
+
"ratio_raw": ratio, "parse_ok": True}
|
| 94 |
+
return {"prompt": answer, "ratio": DEFAULT_RATIO, "ratio_raw": "", "parse_ok": False}
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
class PresencePenalty(LogitsProcessor):
|
| 98 |
+
"""vLLM-style presence penalty: subtract a constant from every already-generated token."""
|
| 99 |
+
|
| 100 |
+
def __init__(self, penalty: float, prompt_len: int):
|
| 101 |
+
self.penalty, self.prompt_len = penalty, prompt_len
|
| 102 |
+
|
| 103 |
+
def __call__(self, input_ids, scores):
|
| 104 |
+
for b in range(input_ids.shape[0]):
|
| 105 |
+
generated = input_ids[b, self.prompt_len:]
|
| 106 |
+
if generated.numel():
|
| 107 |
+
scores[b, generated.unique()] -= self.penalty
|
| 108 |
+
return scores
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
# ----------------------------------------------------------------------------- loading
|
| 112 |
+
def load_student(size: str, device):
|
| 113 |
+
rid = STUDENT_IDS[size]
|
| 114 |
+
tok = AutoTokenizer.from_pretrained(rid)
|
| 115 |
+
model = AutoModelForCausalLM.from_pretrained(rid, dtype=torch.bfloat16).to(device).eval()
|
| 116 |
+
return tok, model
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def load_teacher(device):
|
| 120 |
+
tok = AutoTokenizer.from_pretrained(TEACHER_ID)
|
| 121 |
+
model = AutoModelForCausalLM.from_pretrained(TEACHER_ID, dtype=torch.bfloat16).to(device).eval()
|
| 122 |
+
system_prompt = open(hf_hub_download(TEACHER_ID, "system_prompt.txt"), encoding="utf-8").read().strip()
|
| 123 |
+
return tok, model, system_prompt
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
# ----------------------------------------------------------------------------- rewriting (call inside @spaces.GPU)
|
| 127 |
+
@torch.inference_mode()
|
| 128 |
+
def student_rewrite(tok, model, request: str, seed: int = 0, max_new_tokens: int = 1024) -> dict:
|
| 129 |
+
prompt = tok.apply_chat_template([{"role": "user", "content": request}], add_generation_prompt=True, tokenize=False)
|
| 130 |
+
ids = tok(prompt, return_tensors="pt").to(model.device)
|
| 131 |
+
torch.manual_seed(seed)
|
| 132 |
+
t = time.time()
|
| 133 |
+
out = model.generate(**ids, max_new_tokens=max_new_tokens, pad_token_id=tok.pad_token_id or tok.eos_token_id, **SAMPLING)
|
| 134 |
+
gen = out[0, ids["input_ids"].shape[1]:]
|
| 135 |
+
text = tok.decode(gen, skip_special_tokens=True)
|
| 136 |
+
_, answer = split_thinking(text) # the template pre-fills an empty think block; strip it if echoed
|
| 137 |
+
res = parse_answer(answer or text)
|
| 138 |
+
res.update(seconds=time.time() - t, tokens=int(gen.numel()), thinking="", raw=text)
|
| 139 |
+
return res
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
@torch.inference_mode()
|
| 143 |
+
def teacher_rewrite(tok, model, system_prompt: str, request: str, seed: int = 0, max_new_tokens: int = 3072) -> dict:
|
| 144 |
+
prompt = tok.apply_chat_template(
|
| 145 |
+
[{"role": "system", "content": system_prompt}, {"role": "user", "content": request}],
|
| 146 |
+
add_generation_prompt=True, tokenize=False, enable_thinking=True)
|
| 147 |
+
ids = tok(prompt, return_tensors="pt").to(model.device)
|
| 148 |
+
prompt_len = ids["input_ids"].shape[1]
|
| 149 |
+
torch.manual_seed(seed)
|
| 150 |
+
t = time.time()
|
| 151 |
+
out = model.generate(**ids, max_new_tokens=max_new_tokens, pad_token_id=tok.eos_token_id,
|
| 152 |
+
logits_processor=LogitsProcessorList([PresencePenalty(1.5, prompt_len)]), **SAMPLING)
|
| 153 |
+
gen = out[0, prompt_len:]
|
| 154 |
+
text = tok.decode(gen, skip_special_tokens=True)
|
| 155 |
+
thinking, answer = split_thinking(text)
|
| 156 |
+
res = parse_answer(answer)
|
| 157 |
+
if not answer: # ran out of tokens inside the think block
|
| 158 |
+
res.update(prompt=request, parse_ok=False)
|
| 159 |
+
res.update(seconds=time.time() - t, tokens=int(gen.numel()), thinking=thinking, raw=text)
|
| 160 |
+
return res
|
sheets.json
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"id": "r06876",
|
| 4 |
+
"request": "صورة واسعة لمنظر طبيعي في جبال تايبه، مع شمس تشرق، تظهر في الصورة علامة تُكتب: \"الشمس تُشعل الجبال\".",
|
| 5 |
+
"lang": "ar",
|
| 6 |
+
"category": "scene",
|
| 7 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r06876.png"
|
| 8 |
+
},
|
| 9 |
+
{
|
| 10 |
+
"id": "r06236",
|
| 11 |
+
"request": "أظهر واجهة تطبيق موبايل عصرية تُظهر تطبيقًا لصحة الأذن، مع خلفية بيضاء وعناصر تفاعلية، ووضع العنوان بوضوح: \"تتبع صحة الأذن بشكل دقيق وسريع\".",
|
| 12 |
+
"lang": "ar",
|
| 13 |
+
"category": "ui_screen",
|
| 14 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r06236.png"
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"id": "r02923",
|
| 18 |
+
"request": "生成一个带有“快乐星球”的圆形贴纸图标",
|
| 19 |
+
"lang": "zh",
|
| 20 |
+
"category": "sticker",
|
| 21 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r02923.png"
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"id": "r07058",
|
| 25 |
+
"request": "一位老人在公园长椅上阅读,\"今日好书推荐:《平凡的世界》\"",
|
| 26 |
+
"lang": "zh",
|
| 27 |
+
"category": "photo",
|
| 28 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r07058.png"
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"id": "r08005",
|
| 32 |
+
"request": "\"प्रोडक्ट के नाम: स्मार्ट वॉटर बॉटल\" के साथ एक फिजिकल प्रोडक्ट का कमरे में शॉट बनाएं",
|
| 33 |
+
"lang": "hi",
|
| 34 |
+
"category": "product_shot",
|
| 35 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r08005.png"
|
| 36 |
+
},
|
| 37 |
+
{
|
| 38 |
+
"id": "r02789",
|
| 39 |
+
"request": "「未来の街」を表すシンプルなboldな形のスタンプタイプの絵文字風グラフィックを作成してください。図形は円で、内側に「未来の街」の文字を明確に配置してください。",
|
| 40 |
+
"lang": "ja",
|
| 41 |
+
"category": "sticker",
|
| 42 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r02789.png"
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"id": "r08309",
|
| 46 |
+
"request": "リアルな写真に「北海道の冬の風景」を表示してください。雪景色の山々と道の駅の前で、人々が歩いている様子を撮影してください。",
|
| 47 |
+
"lang": "ja",
|
| 48 |
+
"category": "photo",
|
| 49 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r08309.png"
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"id": "r00535",
|
| 53 |
+
"request": "「未来の街」をテーマにしたデジタルアート。空が青く、建物はスカイラインで織りなされる。光が差し込み、歩く人々がいる。背景に「未来都市の夢」を表示。",
|
| 54 |
+
"lang": "ja",
|
| 55 |
+
"category": "illustration",
|
| 56 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r00535.png"
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"id": "r02651",
|
| 60 |
+
"request": "Affichez l'interface d'un jeu mobile moderne sur un écran, avec en haut une bandeau en lettres blanches sur fond noir : \"Bataille des Étoiles – Mode Épreuve\".",
|
| 61 |
+
"lang": "fr",
|
| 62 |
+
"category": "ui_screen",
|
| 63 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r02651.png"
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
"id": "r09463",
|
| 67 |
+
"request": "Un produit électronique sur fond blanc avec une affiche en double quotes\"Alimentation rapide 30 minutes\" double quotes.",
|
| 68 |
+
"lang": "fr",
|
| 69 |
+
"category": "product_shot",
|
| 70 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r09463.png"
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"id": "r01195",
|
| 74 |
+
"request": "Create a diagram showing the water cycle with \"Evaporation, Condensation, Precipitation\" labeled in green.",
|
| 75 |
+
"lang": "en",
|
| 76 |
+
"category": "infographic",
|
| 77 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r01195.png"
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"id": "r09188",
|
| 81 |
+
"request": "A futuristic cyberpunk woman with glowing eyes and neon clothing, standing in a rain-soaked city, wearing a digital tattoo with \"NEON WARDEN\" on her arm.",
|
| 82 |
+
"lang": "en",
|
| 83 |
+
"category": "portrait",
|
| 84 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r09188.png"
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"id": "r06943",
|
| 88 |
+
"request": "A breathtaking sunset over a sprawling desert city at dusk, with towering neon skyscrapers and flying drones, 3:2, featuring in the foreground a large holographic sign that reads \"FUTURE SKIES\".",
|
| 89 |
+
"lang": "en",
|
| 90 |
+
"category": "scene",
|
| 91 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r06943.png"
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"id": "r01048",
|
| 95 |
+
"request": "A close-up portrait of a young woman with glowing eyes and a cosmic blue aura. \"Starborn Voyager\" the type must be perfectly legible.",
|
| 96 |
+
"lang": "en",
|
| 97 |
+
"category": "portrait",
|
| 98 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r01048.png"
|
| 99 |
+
},
|
| 100 |
+
{
|
| 101 |
+
"id": "r07829",
|
| 102 |
+
"request": "A realistic photograph of a bustling street market in Tokyo, with vendors selling fresh seafood and vegetables, showing a sign that reads \"Fresh Sushi & Seafood Daily.\"",
|
| 103 |
+
"lang": "en",
|
| 104 |
+
"category": "photo",
|
| 105 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r07829.png"
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"id": "r05306",
|
| 109 |
+
"request": "A sleek wireless earbud on a white background with \"SoundBloom Pro\" keep the lettering crisp and readable.",
|
| 110 |
+
"lang": "en",
|
| 111 |
+
"category": "product_shot",
|
| 112 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r05306.png"
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"id": "r00409",
|
| 116 |
+
"request": "A sunset city skyline with \"Future Horizon\" displayed on a digital billboard.",
|
| 117 |
+
"lang": "en",
|
| 118 |
+
"category": "scene",
|
| 119 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r00409.png"
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
"id": "r02853",
|
| 123 |
+
"request": "A modern mobile app interface with a dark theme, showing a chat window and notifications, with the text \"Active Chat Session\" displayed prominently at the top of the screen.",
|
| 124 |
+
"lang": "en",
|
| 125 |
+
"category": "ui_screen",
|
| 126 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r02853.png"
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"id": "r03194",
|
| 130 |
+
"request": "Create a bold, die-cut sticker badge with a simple circular shape and a bright green outline. The text \"ACCESS GRANTED\" is centered in the badge. Aspect ratio: 2:3.",
|
| 131 |
+
"lang": "en",
|
| 132 |
+
"category": "sticker",
|
| 133 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r03194.png"
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"id": "r06208",
|
| 137 |
+
"request": "Create a bold die-cut sticker with a simple geometric shape resembling a star. Display the text \"NEVER GIVE UP\" in large, clean letters on the sticker surface.",
|
| 138 |
+
"lang": "en",
|
| 139 |
+
"category": "sticker",
|
| 140 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r06208.png"
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"id": "r08023",
|
| 144 |
+
"request": "\"Rise of the Future\" wide poster with tech elements and vibrant colors",
|
| 145 |
+
"lang": "en",
|
| 146 |
+
"category": "poster",
|
| 147 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r08023.png"
|
| 148 |
+
},
|
| 149 |
+
{
|
| 150 |
+
"id": "r07272",
|
| 151 |
+
"request": "A cyberpunk cityscape in digital art style, 2:1, with glowing neon signs; \"FUTURE NOVA\" written in bold neon blue on a rooftop billboard.",
|
| 152 |
+
"lang": "en",
|
| 153 |
+
"category": "illustration",
|
| 154 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r07272.png"
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"id": "r09762",
|
| 158 |
+
"request": "Create a diagram showing the water cycle with \"Evaporation\" clearly labeled in the top section.",
|
| 159 |
+
"lang": "en",
|
| 160 |
+
"category": "infographic",
|
| 161 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r09762.png"
|
| 162 |
+
},
|
| 163 |
+
{
|
| 164 |
+
"id": "r08914",
|
| 165 |
+
"request": "A sleek wireless charger on a white background with \"Quick Charge 30W\" displayed.",
|
| 166 |
+
"lang": "en",
|
| 167 |
+
"category": "product_shot",
|
| 168 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r08914.png"
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"id": "r05251",
|
| 172 |
+
"request": "a man at a bus stop \"next bus 15 min\"",
|
| 173 |
+
"lang": "en",
|
| 174 |
+
"category": "photo",
|
| 175 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r05251.png"
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"id": "r03071",
|
| 179 |
+
"request": "\"Rise of the Future\" landscape poster with tech and humans merging",
|
| 180 |
+
"lang": "en",
|
| 181 |
+
"category": "poster",
|
| 182 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r03071.png"
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"id": "r05643",
|
| 186 |
+
"request": "A sunset over a bustling city skyline with neon lights; \"Future Urban Hub\" no spelling mistakes.",
|
| 187 |
+
"lang": "en",
|
| 188 |
+
"category": "scene",
|
| 189 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r05643.png"
|
| 190 |
+
},
|
| 191 |
+
{
|
| 192 |
+
"id": "r05855",
|
| 193 |
+
"request": "भारत के गंगा नदी के किनारे खुली जंगली चट्टानों के बीच सुंदर दृश्य, रात के समय धुएं वाली दूर से चमकती दृश्य एवं गांव के लोगों के दृ���्य।",
|
| 194 |
+
"lang": "hi",
|
| 195 |
+
"category": "scene",
|
| 196 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r05855.png"
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"id": "r03918",
|
| 200 |
+
"request": "Diagrama de barras con datos del 2020 al 2023",
|
| 201 |
+
"lang": "es",
|
| 202 |
+
"category": "infographic",
|
| 203 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r03918.png"
|
| 204 |
+
},
|
| 205 |
+
{
|
| 206 |
+
"id": "r03912",
|
| 207 |
+
"request": "رقم عظيم لصورة واسعة من ممرات مدينة عصرية في الصباح، تظهر المباني العالية والشوارع المزدحمة بالكثير من الناس والسيارات المضيئة.",
|
| 208 |
+
"lang": "ar",
|
| 209 |
+
"category": "scene",
|
| 210 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r03912.png"
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"id": "r07792",
|
| 214 |
+
"request": "Solar power: bright future, clean energy, green skies",
|
| 215 |
+
"lang": "en",
|
| 216 |
+
"category": "poster",
|
| 217 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r07792.png"
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
"id": "r00050",
|
| 221 |
+
"request": "Bold yellow circle sticker with a smiling face inside",
|
| 222 |
+
"lang": "en",
|
| 223 |
+
"category": "sticker",
|
| 224 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r00050.png"
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"id": "r09743",
|
| 228 |
+
"request": "A futuristic app dashboard on a smartphone screen showing real-time data, charts, and interactive buttons in a sleek, dark theme.",
|
| 229 |
+
"lang": "en",
|
| 230 |
+
"category": "ui_screen",
|
| 231 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r09743.png"
|
| 232 |
+
},
|
| 233 |
+
{
|
| 234 |
+
"id": "r01846",
|
| 235 |
+
"request": "Create a labeled diagram showing the water cycle with clear headings, numbered steps, and callouts for evaporation, condensation, precipitation, and collection. Include a simple flowchart style with arrows and icons.",
|
| 236 |
+
"lang": "en",
|
| 237 |
+
"category": "infographic",
|
| 238 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r01846.png"
|
| 239 |
+
},
|
| 240 |
+
{
|
| 241 |
+
"id": "r08972",
|
| 242 |
+
"request": "A sleek silver wireless charger placed on a minimalist white background with soft natural light and clean product presentation.",
|
| 243 |
+
"lang": "en",
|
| 244 |
+
"category": "product_shot",
|
| 245 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r08972.png"
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"id": "r05594",
|
| 249 |
+
"request": "A bold red circle die-cut sticker, emoji-like, simple, small badge, clean outline, white background",
|
| 250 |
+
"lang": "en",
|
| 251 |
+
"category": "sticker",
|
| 252 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r05594.png"
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"id": "r01832",
|
| 256 |
+
"request": "A man walking through a snow-covered forest at dawn.",
|
| 257 |
+
"lang": "en",
|
| 258 |
+
"category": "photo",
|
| 259 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r01832.png"
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"id": "r02456",
|
| 263 |
+
"request": "A vibrant sunset over a sprawling desert city with golden towers and flying drones.",
|
| 264 |
+
"lang": "en",
|
| 265 |
+
"category": "scene",
|
| 266 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r02456.png"
|
| 267 |
+
},
|
| 268 |
+
{
|
| 269 |
+
"id": "r01193",
|
| 270 |
+
"request": "A sleek silver smartphone lying on a minimalist white background, clean product shot, studio lighting, sharp focus, realistic, high detail, product catalog style.",
|
| 271 |
+
"lang": "en",
|
| 272 |
+
"category": "product_shot",
|
| 273 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r01193.png"
|
| 274 |
+
},
|
| 275 |
+
{
|
| 276 |
+
"id": "r07065",
|
| 277 |
+
"request": "A sunset over a snow-capped mountain range. the type must be perfectly legible",
|
| 278 |
+
"lang": "en",
|
| 279 |
+
"category": "scene",
|
| 280 |
+
"sheet_url": "https://huggingface.co/datasets/ysharma/image21-rewriter-distill/resolve/main/renders/sheets/sheet_r07065.png"
|
| 281 |
+
}
|
| 282 |
+
]
|