Skip to content

Commit 8b37c43

Browse files
llcourageLIT team
authored andcommitted
LIT Dalle-Mini demo.
PiperOrigin-RevId: 739971574
1 parent 21466fa commit 8b37c43

5 files changed

Lines changed: 260 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Dalle_Mini Demo for the Learning Interpretability Tool
2+
=======================================================
3+
4+
This demo showcases how LIT can be used in text-to-generation mode. It is based
5+
on the mini-dalle Mini model
6+
(https://www.piwheels.org/project/dalle-mini/).
7+
8+
You will need a standalone virtual environment for the Python libraries, which
9+
you can set up using the following commands from the root of the LIT repo.
10+
11+
```sh
12+
# Create the virtual environment. You may want to use python3 or python3.10
13+
# depends on how many Python versions you have installed and their aliases.
14+
python -m venv .dalle-mini
15+
source .dalle-mini/bin/activate
16+
# This requirements.txt file will also install the core LIT library deps.
17+
pip install -r ./lit_nlp/examples/dalle_mini/requirements.txt
18+
# The LIT web app still needs to be built in the usual way.
19+
(cd ./lit_nlp && yarn && yarn build)
20+
```
21+
22+
Once your virtual environment is setup, you can launch the demo with the
23+
following command.
24+
25+
```sh
26+
python -m lit_nlp.examples.dalle_mini.demo
27+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Data loaders for dalle-mini model."""
2+
3+
from lit_nlp.api import dataset as lit_dataset
4+
from lit_nlp.api import types as lit_types
5+
6+
7+
class DallePrompts(lit_dataset.Dataset):
8+
9+
def __init__(self):
10+
self.examples = []
11+
12+
def spec(self) -> lit_types.Spec:
13+
return {"prompt": lit_types.TextSegment()}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
r"""Example for dalle-mini demo model.
2+
3+
To run locally with a small number of examples:
4+
python -m lit_nlp.examples.dalle_mini.demo
5+
6+
7+
Then navigate to localhost:5432 to access the demo UI.
8+
"""
9+
10+
from collections.abc import Sequence
11+
import os
12+
import sys
13+
from typing import Optional
14+
15+
from absl import app
16+
from absl import flags
17+
from lit_nlp import dev_server
18+
from lit_nlp import server_flags
19+
from lit_nlp.api import layout
20+
from lit_nlp.examples.dalle_mini import data as dalle_data
21+
from lit_nlp.examples.dalle_mini import model as dalle_model
22+
23+
24+
# NOTE: additional flags defined in server_flags.py
25+
_FLAGS = flags.FLAGS
26+
_FLAGS.set_default("development_demo", True)
27+
_FLAGS.set_default("default_layout", "DALLE_LAYOUT")
28+
29+
30+
_MODELS = flags.DEFINE_list("models", ["dalle-mini"], "Models to load")
31+
32+
33+
_MAX_EXAMPLES = flags.DEFINE_integer(
34+
"max_examples",
35+
5,
36+
"Maximum number of examples to load from each evaluation set. Set to None "
37+
"to load the full set.",
38+
)
39+
40+
41+
# Custom frontend layout; see api/layout.py
42+
_modules = layout.LitModuleName
43+
_DALLE_LAYOUT = layout.LitCanonicalLayout(
44+
upper={
45+
"Main": [
46+
_modules.DataTableModule,
47+
_modules.DatapointEditorModule,
48+
]
49+
},
50+
lower={
51+
"Predictions": [
52+
_modules.GeneratedImageModule,
53+
_modules.GeneratedTextModule,
54+
],
55+
},
56+
description="Custom layout for Text to Image models.",
57+
)
58+
59+
60+
CUSTOM_LAYOUTS = layout.DEFAULT_LAYOUTS | {"DALLE_LAYOUT": _DALLE_LAYOUT}
61+
62+
63+
def get_wsgi_app() -> Optional[dev_server.LitServerType]:
64+
_FLAGS.set_default("server_type", "external")
65+
_FLAGS.set_default("demo_mode", True)
66+
# Parse flags without calling app.run(main), to avoid conflict with
67+
# gunicorn command line flags.
68+
unused = _FLAGS(sys.argv, known_only=True)
69+
return main(unused)
70+
71+
72+
def main(argv: Sequence[str]) -> Optional[dev_server.LitServerType]:
73+
if len(argv) > 1:
74+
raise app.UsageError("Too many command-line arguments.")
75+
76+
# Load models, according to the --models flag.
77+
models = {}
78+
for model_name_or_path in _MODELS.value:
79+
# Ignore path prefix, if using /path/to/<model_name> to load from a
80+
# specific directory rather than the default shortcut.
81+
model_name = os.path.basename(model_name_or_path)
82+
models[model_name] = dalle_model.DalleMiniModel(
83+
model_name=model_name_or_path
84+
)
85+
86+
datasets = {"Prompts": dalle_data.DallePrompts()}
87+
88+
lit_demo = dev_server.Server(
89+
models,
90+
datasets,
91+
layouts=CUSTOM_LAYOUTS,
92+
**server_flags.get_flags(),
93+
)
94+
return lit_demo.serve()
95+
96+
97+
if __name__ == "__main__":
98+
app.run(main)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""LIT wrappers for MiniDalleModel."""
2+
3+
from collections.abc import Iterable
4+
5+
from lit_nlp.api import model as lit_model
6+
from lit_nlp.api import types as lit_types
7+
from lit_nlp.lib import image_utils
8+
from min_dalle import MinDalle
9+
import numpy as np
10+
from PIL import Image
11+
import torch
12+
13+
14+
class DalleMiniModel(lit_model.Model):
15+
"""LIT model wrapper for Dalle-Mini Text-to-Image model.
16+
17+
This wrapper simplifies the pipeline using Dalle-Mini for text-to-image
18+
generation.
19+
20+
21+
The basic flow within this model wrapper's predict() function is:
22+
23+
24+
1. Dalle-Mini processes the text prompt.
25+
2. Images are directly generated by Dalle-Mini.
26+
"""
27+
28+
def __init__(
29+
self,
30+
model_name: str = "dalle-mini",
31+
device: str = "cuda", # Use "cuda" for GPU or "cpu" for CPU
32+
predictions: int = 1,
33+
):
34+
super().__init__()
35+
self.model_name = model_name
36+
self.device = device
37+
self.n_predictions = predictions
38+
39+
# Load Dalle-Mini model
40+
self.model = MinDalle(
41+
models_root="./pretrained",
42+
dtype=torch.float32,
43+
device="cuda",
44+
is_mega=True,
45+
is_reusable=True,
46+
)
47+
48+
def max_minibatch_size(self) -> int:
49+
return 8
50+
51+
def predict(
52+
self, inputs: Iterable[lit_types.JsonDict], **unused_kw
53+
) -> Iterable[lit_types.JsonDict]:
54+
"""Generate images based on the input prompts."""
55+
56+
def tensor_to_pil_image(tensor):
57+
img_np = tensor.detach().cpu().numpy()
58+
img_np = np.squeeze(img_np)
59+
if img_np.ndim == 2:
60+
img_np = np.stack([img_np] * 3, axis=-1)
61+
elif img_np.ndim != 3 or img_np.shape[2] != 3:
62+
raise ValueError(
63+
f"Unexpected image shape: {img_np.shape}. Expected (H, W, 3)."
64+
)
65+
66+
img_np = (img_np - img_np.min()) / (img_np.max() - img_np.min()) * 255
67+
img_np = img_np.clip(0, 255).astype(np.uint8)
68+
return Image.fromarray(img_np)
69+
70+
prompts = [ex["prompt"] for ex in inputs]
71+
images = []
72+
for prompt in prompts:
73+
# Generate images using the model
74+
generated_images = self.model.generate_images(
75+
text=prompt,
76+
seed=-1,
77+
grid_size=4,
78+
is_seamless=False,
79+
temperature=0.5,
80+
top_k=256,
81+
supercondition_factor=32,
82+
is_verbose=False,
83+
)
84+
pil_images = []
85+
for img_tensor in generated_images:
86+
pil_images.append(tensor_to_pil_image(img_tensor))
87+
images.append({
88+
"image": [
89+
image_utils.convert_pil_to_image_str(img) for img in pil_images
90+
],
91+
"prompt": prompt,
92+
})
93+
94+
return images
95+
96+
def input_spec(self):
97+
return {"prompt": lit_types.TextSegment()}
98+
99+
def output_spec(self):
100+
return {
101+
"image": lit_types.ImageBytesList(),
102+
"prompt": lit_types.TextSegment(),
103+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
16+
-r ../../../requirements.txt
17+
18+
# Dalle-Mini dependencies
19+
min_dalle==0.1.5

0 commit comments

Comments
 (0)