catpokemon commited on
Commit
f1233e7
·
verified ·
1 Parent(s): 8ff9d68

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +180 -0
app.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import spaces
4
+ import torch
5
+ import random
6
+ from PIL import Image
7
+
8
+ from diffusers import FluxPipeline, FluxTransformer2DModel, GGUFQuantizationConfig
9
+ from diffusers.utils import load_image
10
+
11
+ MAX_SEED = np.iinfo(np.int32).max
12
+
13
+ # Load GGUF transformer model from Hugging Face
14
+ gguf_path = "https://huggingface.co/bullerwins/FLUX.1-Kontext-dev-GGUF/resolve/main/flux1-kontext-dev-Q8_0.gguf"
15
+
16
+ transformer = FluxTransformer2DModel.from_single_file(
17
+ gguf_path,
18
+ quantization_config=GGUFQuantizationConfig(compute_dtype=torch.bfloat16),
19
+ torch_dtype=torch.bfloat16,
20
+ )
21
+
22
+ # Create pipeline with GGUF transformer
23
+ pipe = FluxPipeline.from_pretrained(
24
+ "black-forest-labs/FLUX.1-dev",
25
+ transformer=transformer,
26
+ torch_dtype=torch.bfloat16,
27
+ ).to("cuda")
28
+
29
+ @spaces.GPU
30
+ def infer(input_image, prompt, seed=42, randomize_seed=False, guidance_scale=2.5, steps=28, progress=gr.Progress(track_tqdm=True)):
31
+ """
32
+ Perform image editing using the FLUX.1 Kontext pipeline.
33
+
34
+ This function takes an input image and a text prompt to generate a modified version
35
+ of the image based on the provided instructions. It uses the FLUX.1 Kontext model
36
+ for contextual image editing tasks.
37
+
38
+ Args:
39
+ input_image (PIL.Image.Image): The input image to be edited. Will be converted
40
+ to RGB format if not already in that format.
41
+ prompt (str): Text description of the desired edit to apply to the image.
42
+ Examples: "Remove glasses", "Add a hat", "Change background to beach".
43
+ seed (int, optional): Random seed for reproducible generation. Defaults to 42.
44
+ Must be between 0 and MAX_SEED (2^31 - 1).
45
+ randomize_seed (bool, optional): If True, generates a random seed instead of
46
+ using the provided seed value. Defaults to False.
47
+ guidance_scale (float, optional): Controls how closely the model follows the
48
+ prompt. Higher values mean stronger adherence to the prompt but may reduce
49
+ image quality. Range: 1.0-10.0. Defaults to 2.5.
50
+ steps (int, optional): Controls how many steps to run the diffusion model for.
51
+ Range: 1-30. Defaults to 28.
52
+ progress (gr.Progress, optional): Gradio progress tracker for monitoring
53
+ generation progress. Defaults to gr.Progress(track_tqdm=True).
54
+
55
+ Returns:
56
+ tuple: A 3-tuple containing:
57
+ - PIL.Image.Image: The generated/edited image
58
+ - int: The seed value used for generation (useful when randomize_seed=True)
59
+ - gr.update: Gradio update object to make the reuse button visible
60
+
61
+ Example:
62
+ >>> edited_image, used_seed, button_update = infer(
63
+ ... input_image=my_image,
64
+ ... prompt="Add sunglasses",
65
+ ... seed=123,
66
+ ... randomize_seed=False,
67
+ ... guidance_scale=2.5
68
+ ... )
69
+ """
70
+ if randomize_seed:
71
+ seed = random.randint(0, MAX_SEED)
72
+
73
+ if input_image:
74
+ input_image = input_image.convert("RGB")
75
+ image = pipe(
76
+ image=input_image,
77
+ prompt=prompt,
78
+ guidance_scale=guidance_scale,
79
+ width = input_image.size[0],
80
+ height = input_image.size[1],
81
+ num_inference_steps=steps,
82
+ generator=torch.Generator().manual_seed(seed),
83
+ ).images[0]
84
+ else:
85
+ image = pipe(
86
+ prompt=prompt,
87
+ guidance_scale=guidance_scale,
88
+ num_inference_steps=steps,
89
+ generator=torch.Generator().manual_seed(seed),
90
+ ).images[0]
91
+ return image, seed, gr.Button(visible=True)
92
+
93
+ @spaces.GPU
94
+ def infer_example(input_image, prompt):
95
+ image, seed, _ = infer(input_image, prompt)
96
+ return image, seed
97
+
98
+ css="""
99
+ #col-container {
100
+ margin: 0 auto;
101
+ max-width: 960px;
102
+ }
103
+ """
104
+
105
+ with gr.Blocks(css=css) as demo:
106
+
107
+ with gr.Column(elem_id="col-container"):
108
+ gr.Markdown(f"""# FLUX.1 Kontext [dev]
109
+ Image editing and manipulation model guidance-distilled from FLUX.1 Kontext [pro], [[blog]](https://bfl.ai/announcements/flux-1-kontext-dev) [[model]](https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev)
110
+ """)
111
+ with gr.Row():
112
+ with gr.Column():
113
+ input_image = gr.Image(label="Upload the image for editing", type="pil")
114
+ with gr.Row():
115
+ prompt = gr.Text(
116
+ label="Prompt",
117
+ show_label=False,
118
+ max_lines=1,
119
+ placeholder="Enter your prompt for editing (e.g., 'Remove glasses', 'Add a hat')",
120
+ container=False,
121
+ )
122
+ run_button = gr.Button("Run", scale=0)
123
+ with gr.Accordion("Advanced Settings", open=False):
124
+
125
+ seed = gr.Slider(
126
+ label="Seed",
127
+ minimum=0,
128
+ maximum=MAX_SEED,
129
+ step=1,
130
+ value=0,
131
+ )
132
+
133
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
134
+
135
+ guidance_scale = gr.Slider(
136
+ label="Guidance Scale",
137
+ minimum=1,
138
+ maximum=10,
139
+ step=0.1,
140
+ value=2.5,
141
+ )
142
+
143
+ steps = gr.Slider(
144
+ label="Steps",
145
+ minimum=1,
146
+ maximum=30,
147
+ value=28,
148
+ step=1
149
+ )
150
+
151
+ with gr.Column():
152
+ result = gr.Image(label="Result", show_label=False, interactive=False)
153
+ reuse_button = gr.Button("Reuse this image", visible=False)
154
+
155
+
156
+ examples = gr.Examples(
157
+ examples=[
158
+ ["flowers.png", "turn the flowers into sunflowers"],
159
+ ["monster.png", "make this monster ride a skateboard on the beach"],
160
+ ["cat.png", "make this cat happy"]
161
+ ],
162
+ inputs=[input_image, prompt],
163
+ outputs=[result, seed],
164
+ fn=infer_example,
165
+ cache_examples="lazy"
166
+ )
167
+
168
+ gr.on(
169
+ triggers=[run_button.click, prompt.submit],
170
+ fn = infer,
171
+ inputs = [input_image, prompt, seed, randomize_seed, guidance_scale, steps],
172
+ outputs = [result, seed, reuse_button]
173
+ )
174
+ reuse_button.click(
175
+ fn = lambda image: image,
176
+ inputs = [result],
177
+ outputs = [input_image]
178
+ )
179
+
180
+ demo.launch(mcp_server=True)