Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -2,44 +2,44 @@ import gradio as gr
|
|
2 |
import numpy as np
|
3 |
import random
|
4 |
import os
|
5 |
-
import
|
|
|
|
|
6 |
from PIL import Image, ImageOps
|
7 |
import pillow_heif # For HEIF/AVIF support
|
8 |
-
from huggingface_hub import InferenceClient
|
9 |
-
import io
|
10 |
|
11 |
# --- Constants ---
|
12 |
MAX_SEED = np.iinfo(np.int32).max
|
|
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
def
|
18 |
-
"""
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
if hf_token:
|
27 |
-
client = InferenceClient(
|
28 |
-
provider="fal-ai",
|
29 |
-
api_key=hf_token,
|
30 |
-
bill_to="huggingface",
|
31 |
-
)
|
32 |
-
else:
|
33 |
-
raise gr.Error("HF_TOKEN environment variable not found. Please add your Hugging Face token to the Space settings.")
|
34 |
-
return client
|
35 |
|
36 |
# --- Core Inference Function for ChatInterface ---
|
37 |
def chat_fn(message, chat_history, seed, randomize_seed, guidance_scale, steps, progress=gr.Progress()):
|
38 |
"""
|
39 |
Performs image generation or editing based on user input from the chat interface.
|
40 |
"""
|
41 |
-
#
|
42 |
-
|
43 |
|
44 |
prompt = message["text"]
|
45 |
files = message["files"]
|
@@ -50,7 +50,16 @@ def chat_fn(message, chat_history, seed, randomize_seed, guidance_scale, steps,
|
|
50 |
if randomize_seed:
|
51 |
seed = random.randint(0, MAX_SEED)
|
52 |
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
if files:
|
55 |
print(f"Received image: {files[0]}")
|
56 |
try:
|
@@ -62,38 +71,36 @@ def chat_fn(message, chat_history, seed, randomize_seed, guidance_scale, steps,
|
|
62 |
# Auto-orient the image based on EXIF data
|
63 |
input_image = ImageOps.exif_transpose(input_image)
|
64 |
|
65 |
-
# Convert PIL image to
|
66 |
img_byte_arr = io.BytesIO()
|
67 |
input_image.save(img_byte_arr, format='PNG')
|
68 |
-
|
|
|
|
|
|
|
|
|
69 |
|
70 |
except Exception as e:
|
71 |
raise gr.Error(f"Could not process the uploaded image: {str(e)}. Please try uploading a different image format (JPEG, PNG, WebP).")
|
72 |
|
73 |
-
# Use image_to_image for editing
|
74 |
progress(0.1, desc="Processing image...")
|
75 |
-
image = client.image_to_image(
|
76 |
-
input_image_bytes,
|
77 |
-
prompt=prompt,
|
78 |
-
model="black-forest-labs/FLUX.1-Kontext-dev",
|
79 |
-
# Note: guidance_scale and steps might not be supported by the API
|
80 |
-
# Check the API documentation for available parameters
|
81 |
-
)
|
82 |
-
progress(1.0, desc="Complete!")
|
83 |
else:
|
84 |
print(f"Received prompt for text-to-image: {prompt}")
|
85 |
-
#
|
86 |
progress(0.1, desc="Generating image...")
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
93 |
progress(1.0, desc="Complete!")
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
97 |
|
98 |
# --- UI Definition using gr.ChatInterface ---
|
99 |
|
@@ -102,14 +109,11 @@ randomize_checkbox = gr.Checkbox(label="Randomize seed", value=False)
|
|
102 |
guidance_slider = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=10.0, step=0.1, value=2.5)
|
103 |
steps_slider = gr.Slider(label="Steps", minimum=1, maximum=30, value=28, step=1)
|
104 |
|
105 |
-
# Note: The Inference Client API may not support all parameters like guidance_scale and steps
|
106 |
-
# Check the API documentation for supported parameters
|
107 |
-
|
108 |
demo = gr.ChatInterface(
|
109 |
fn=chat_fn,
|
110 |
-
title="FLUX.1 Kontext [dev] -
|
111 |
description="""<p style='text-align: center;'>
|
112 |
-
A simple chat UI for the <b>FLUX.1 Kontext</b> model using
|
113 |
<br>
|
114 |
To edit an image, upload it and type your instructions (e.g., "Add a hat").
|
115 |
<br>
|
|
|
2 |
import numpy as np
|
3 |
import random
|
4 |
import os
|
5 |
+
import base64
|
6 |
+
import requests
|
7 |
+
import io
|
8 |
from PIL import Image, ImageOps
|
9 |
import pillow_heif # For HEIF/AVIF support
|
|
|
|
|
10 |
|
11 |
# --- Constants ---
|
12 |
MAX_SEED = np.iinfo(np.int32).max
|
13 |
+
API_URL = "https://router.huggingface.co/fal-ai/fal-ai/flux-kontext/dev?_subdomain=queue"
|
14 |
|
15 |
+
def get_headers():
|
16 |
+
"""Get headers for API requests"""
|
17 |
+
hf_token = os.getenv("HF_TOKEN")
|
18 |
+
if not hf_token:
|
19 |
+
raise gr.Error("HF_TOKEN environment variable not found. Please add your Hugging Face token to the Space settings.")
|
20 |
+
|
21 |
+
return {
|
22 |
+
"Authorization": f"Bearer {hf_token}",
|
23 |
+
"X-HF-Bill-To": "huggingface"
|
24 |
+
}
|
25 |
|
26 |
+
def query_api(payload):
|
27 |
+
"""Send request to the API and return response"""
|
28 |
+
headers = get_headers()
|
29 |
+
response = requests.post(API_URL, headers=headers, json=payload)
|
30 |
+
|
31 |
+
if response.status_code != 200:
|
32 |
+
raise gr.Error(f"API request failed with status {response.status_code}: {response.text}")
|
33 |
+
|
34 |
+
return response.content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
# --- Core Inference Function for ChatInterface ---
|
37 |
def chat_fn(message, chat_history, seed, randomize_seed, guidance_scale, steps, progress=gr.Progress()):
|
38 |
"""
|
39 |
Performs image generation or editing based on user input from the chat interface.
|
40 |
"""
|
41 |
+
# Register HEIF opener with PIL for AVIF/HEIF support
|
42 |
+
pillow_heif.register_heif_opener()
|
43 |
|
44 |
prompt = message["text"]
|
45 |
files = message["files"]
|
|
|
50 |
if randomize_seed:
|
51 |
seed = random.randint(0, MAX_SEED)
|
52 |
|
53 |
+
# Prepare the payload
|
54 |
+
payload = {
|
55 |
+
"parameters": {
|
56 |
+
"prompt": prompt,
|
57 |
+
"seed": seed,
|
58 |
+
"guidance_scale": guidance_scale,
|
59 |
+
"num_inference_steps": steps
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
if files:
|
64 |
print(f"Received image: {files[0]}")
|
65 |
try:
|
|
|
71 |
# Auto-orient the image based on EXIF data
|
72 |
input_image = ImageOps.exif_transpose(input_image)
|
73 |
|
74 |
+
# Convert PIL image to base64 for the API
|
75 |
img_byte_arr = io.BytesIO()
|
76 |
input_image.save(img_byte_arr, format='PNG')
|
77 |
+
img_byte_arr.seek(0)
|
78 |
+
image_base64 = base64.b64encode(img_byte_arr.getvalue()).decode('utf-8')
|
79 |
+
|
80 |
+
# Add image to payload for image-to-image
|
81 |
+
payload["inputs"] = image_base64
|
82 |
|
83 |
except Exception as e:
|
84 |
raise gr.Error(f"Could not process the uploaded image: {str(e)}. Please try uploading a different image format (JPEG, PNG, WebP).")
|
85 |
|
|
|
86 |
progress(0.1, desc="Processing image...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
else:
|
88 |
print(f"Received prompt for text-to-image: {prompt}")
|
89 |
+
# For text-to-image, we don't need the inputs field
|
90 |
progress(0.1, desc="Generating image...")
|
91 |
+
|
92 |
+
try:
|
93 |
+
# Make API request
|
94 |
+
image_bytes = query_api(payload)
|
95 |
+
|
96 |
+
# Convert response bytes to PIL Image
|
97 |
+
image = Image.open(io.BytesIO(image_bytes))
|
98 |
+
|
99 |
progress(1.0, desc="Complete!")
|
100 |
+
return gr.Image(value=image)
|
101 |
+
|
102 |
+
except Exception as e:
|
103 |
+
raise gr.Error(f"Failed to generate image: {str(e)}")
|
104 |
|
105 |
# --- UI Definition using gr.ChatInterface ---
|
106 |
|
|
|
109 |
guidance_slider = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=10.0, step=0.1, value=2.5)
|
110 |
steps_slider = gr.Slider(label="Steps", minimum=1, maximum=30, value=28, step=1)
|
111 |
|
|
|
|
|
|
|
112 |
demo = gr.ChatInterface(
|
113 |
fn=chat_fn,
|
114 |
+
title="FLUX.1 Kontext [dev] - Direct API",
|
115 |
description="""<p style='text-align: center;'>
|
116 |
+
A simple chat UI for the <b>FLUX.1 Kontext</b> model using direct API calls with requests.
|
117 |
<br>
|
118 |
To edit an image, upload it and type your instructions (e.g., "Add a hat").
|
119 |
<br>
|