Instructions to use tugrulv89/image21-evaluation-cache with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use tugrulv89/image21-evaluation-cache with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("tugrulv89/image21-evaluation-cache", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- Draw Things
- DiffusionBee
Use official CPU offload and verified pipeline signature for 48 GB evaluation
Browse files
EVALUATION_PROVENANCE.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"source": "Qwen/Qwen-Image-2.1",
|
| 3 |
"source_revision": "d26bb61231c349cf6b7896fa83353113880e1ba3",
|
| 4 |
-
"handler_git": "
|
| 5 |
-
"handler_sha256": "
|
| 6 |
"use": "Isolated research/evaluation only; no production promotion"
|
| 7 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"source": "Qwen/Qwen-Image-2.1",
|
| 3 |
"source_revision": "d26bb61231c349cf6b7896fa83353113880e1ba3",
|
| 4 |
+
"handler_git": "cf13cfff6d29586858d45a7e0d7972d0b88fd98f",
|
| 5 |
+
"handler_sha256": "126ca057f75fbc25185a75fb00cb9041942d9744f0489dd64f6685b5faa50877",
|
| 6 |
"use": "Isolated research/evaluation only; no production promotion"
|
| 7 |
}
|
handler/qwen21/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
| 2 |
|
| 3 |
Research only. Root 2511 handler, Dockerfile and production endpoint stay unchanged.
|
| 4 |
The official base model is tested at 40 steps, CFG 1 and BF16, with prefix KV cache.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
This is a base-model quality comparison; it is not an 8-step Turbo benchmark.
|
| 6 |
|
| 7 |
Build from the repository root using `qwen21/Dockerfile`. Set
|
|
|
|
| 2 |
|
| 3 |
Research only. Root 2511 handler, Dockerfile and production endpoint stay unchanged.
|
| 4 |
The official base model is tested at 40 steps, CFG 1 and BF16, with prefix KV cache.
|
| 5 |
+
Reference conditioning uses the upstream `output_resolution=1024` default;
|
| 6 |
+
the requested final image is 1024x1536. Full-resident BF16 failed with CUDA OOM
|
| 7 |
+
on the actual 48 GB worker. The official `enable_model_cpu_offload()` method
|
| 8 |
+
keeps BF16 and moves components in sequence without requiring a 96 GB GPU.
|
| 9 |
This is a base-model quality comparison; it is not an 8-step Turbo benchmark.
|
| 10 |
|
| 11 |
Build from the repository root using `qwen21/Dockerfile`. Set
|
handler/qwen21/handler.py
CHANGED
|
@@ -3,6 +3,7 @@ import io
|
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
import time
|
|
|
|
| 6 |
import uuid
|
| 7 |
from pathlib import Path
|
| 8 |
|
|
@@ -32,7 +33,8 @@ def sampling(job):
|
|
| 32 |
raise ValueError('An explicit editing prompt is required')
|
| 33 |
return {'prompt': job['prompt'], 'negative_prompt': job.get('negative_prompt'),
|
| 34 |
'width': width, 'height': height, 'num_inference_steps': steps,
|
| 35 |
-
'true_cfg_scale': cfg, 'use_kv_cache': True
|
|
|
|
| 36 |
|
| 37 |
|
| 38 |
def cached_model_path():
|
|
@@ -51,7 +53,8 @@ def pipeline():
|
|
| 51 |
from diffusers import QwenImage21Pipeline
|
| 52 |
_pipe = QwenImage21Pipeline.from_pretrained(
|
| 53 |
cached_model_path(), local_files_only=True,
|
| 54 |
-
torch_dtype=torch.bfloat16)
|
|
|
|
| 55 |
return _pipe
|
| 56 |
|
| 57 |
|
|
@@ -108,7 +111,7 @@ def handler(event):
|
|
| 108 |
'peak_reserved_gib': round(torch.cuda.max_memory_reserved() / 1024**3, 2),
|
| 109 |
'model_revision': os.environ['QWEN21_MODEL_REVISION']})
|
| 110 |
except Exception as exc:
|
| 111 |
-
detail =
|
| 112 |
for key in ('HF_TOKEN', 'JSON_PATH_KEY'):
|
| 113 |
if os.environ.get(key):
|
| 114 |
detail = detail.replace(os.environ[key], '[REDACTED]')
|
|
|
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
import time
|
| 6 |
+
import traceback
|
| 7 |
import uuid
|
| 8 |
from pathlib import Path
|
| 9 |
|
|
|
|
| 33 |
raise ValueError('An explicit editing prompt is required')
|
| 34 |
return {'prompt': job['prompt'], 'negative_prompt': job.get('negative_prompt'),
|
| 35 |
'width': width, 'height': height, 'num_inference_steps': steps,
|
| 36 |
+
'true_cfg_scale': cfg, 'use_kv_cache': True,
|
| 37 |
+
'output_resolution': 1024}
|
| 38 |
|
| 39 |
|
| 40 |
def cached_model_path():
|
|
|
|
| 53 |
from diffusers import QwenImage21Pipeline
|
| 54 |
_pipe = QwenImage21Pipeline.from_pretrained(
|
| 55 |
cached_model_path(), local_files_only=True,
|
| 56 |
+
torch_dtype=torch.bfloat16)
|
| 57 |
+
_pipe.enable_model_cpu_offload()
|
| 58 |
return _pipe
|
| 59 |
|
| 60 |
|
|
|
|
| 111 |
'peak_reserved_gib': round(torch.cuda.max_memory_reserved() / 1024**3, 2),
|
| 112 |
'model_revision': os.environ['QWEN21_MODEL_REVISION']})
|
| 113 |
except Exception as exc:
|
| 114 |
+
detail = traceback.format_exc()
|
| 115 |
for key in ('HF_TOKEN', 'JSON_PATH_KEY'):
|
| 116 |
if os.environ.get(key):
|
| 117 |
detail = detail.replace(os.environ[key], '[REDACTED]')
|
handler/qwen21/tests/pipeline_contract.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"diffusers_commit": "85c9fa4caee33d1c5b473395784471d2d7957c1b",
|
| 3 |
+
"source": "src/diffusers/pipelines/qwenimage21/pipeline_qwenimage21.py",
|
| 4 |
+
"source_sha256": "e75e4ce38d38e194edaac818bba99b2115b4bb2bfdbd15ce03a2813b0fe8856c",
|
| 5 |
+
"call_parameters": [
|
| 6 |
+
"prompt",
|
| 7 |
+
"image",
|
| 8 |
+
"negative_prompt",
|
| 9 |
+
"true_cfg_scale",
|
| 10 |
+
"height",
|
| 11 |
+
"width",
|
| 12 |
+
"num_inference_steps",
|
| 13 |
+
"sigmas",
|
| 14 |
+
"num_images_per_prompt",
|
| 15 |
+
"generator",
|
| 16 |
+
"latents",
|
| 17 |
+
"prompt_embeds",
|
| 18 |
+
"prompt_embeds_mask",
|
| 19 |
+
"negative_prompt_embeds",
|
| 20 |
+
"negative_prompt_embeds_mask",
|
| 21 |
+
"output_type",
|
| 22 |
+
"return_dict",
|
| 23 |
+
"attention_kwargs",
|
| 24 |
+
"callback_on_step_end",
|
| 25 |
+
"callback_on_step_end_tensor_inputs",
|
| 26 |
+
"output_resolution",
|
| 27 |
+
"use_kv_cache"
|
| 28 |
+
]
|
| 29 |
+
}
|
handler/qwen21/tests/test_sampling.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import unittest
|
| 2 |
import os
|
| 3 |
import tempfile
|
|
|
|
| 4 |
from pathlib import Path
|
| 5 |
from unittest.mock import patch
|
| 6 |
|
|
@@ -29,9 +30,17 @@ class SamplingTests(unittest.TestCase):
|
|
| 29 |
self.assertEqual((args['width'], args['height'], args['num_inference_steps']), (1024, 1536, 40))
|
| 30 |
self.assertEqual(args['true_cfg_scale'], 1.0)
|
| 31 |
self.assertTrue(args['use_kv_cache'])
|
|
|
|
| 32 |
self.assertNotIn('guidance_scale', args)
|
| 33 |
self.assertNotIn('sigmas', args)
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
def test_invalid_controls_fail_before_loading_a_model(self):
|
| 36 |
with patch('qwen21.handler.pipeline') as load:
|
| 37 |
result = handler({'input': {'task': 'edit', 'jobs': [
|
|
|
|
| 1 |
import unittest
|
| 2 |
import os
|
| 3 |
import tempfile
|
| 4 |
+
import json
|
| 5 |
from pathlib import Path
|
| 6 |
from unittest.mock import patch
|
| 7 |
|
|
|
|
| 30 |
self.assertEqual((args['width'], args['height'], args['num_inference_steps']), (1024, 1536, 40))
|
| 31 |
self.assertEqual(args['true_cfg_scale'], 1.0)
|
| 32 |
self.assertTrue(args['use_kv_cache'])
|
| 33 |
+
self.assertEqual(args['output_resolution'], 1024)
|
| 34 |
self.assertNotIn('guidance_scale', args)
|
| 35 |
self.assertNotIn('sigmas', args)
|
| 36 |
|
| 37 |
+
def test_sampling_matches_the_pinned_official_pipeline_signature(self):
|
| 38 |
+
root = Path(__file__).parents[1]
|
| 39 |
+
contract = json.loads((root / 'tests/pipeline_contract.json').read_text())
|
| 40 |
+
self.assertIn(contract['diffusers_commit'], (root / 'requirements.txt').read_text())
|
| 41 |
+
self.assertLessEqual(set(sampling({'prompt': 'Keep the actual bag.'})),
|
| 42 |
+
set(contract['call_parameters']))
|
| 43 |
+
|
| 44 |
def test_invalid_controls_fail_before_loading_a_model(self):
|
| 45 |
with patch('qwen21.handler.pipeline') as load:
|
| 46 |
result = handler({'input': {'task': 'edit', 'jobs': [
|