Spaces:
Running
Running
Commit
·
cae10fc
1
Parent(s):
f6475e3
update
Browse files
app.py
CHANGED
|
@@ -2,121 +2,125 @@ import gradio as gr
|
|
| 2 |
import requests
|
| 3 |
import fal_client
|
| 4 |
import os
|
| 5 |
-
import json
|
| 6 |
-
import time
|
| 7 |
import base64
|
| 8 |
-
import io
|
| 9 |
from PIL import Image
|
|
|
|
| 10 |
|
| 11 |
RUNPOD_API_KEY = os.getenv("RUNPOD_API_KEY")
|
| 12 |
FAL_KEY = os.getenv("FAL_KEY")
|
| 13 |
-
|
| 14 |
-
QWEN_ENDPOINT_ID = os.environ["ENDPOINTID"]
|
| 15 |
|
| 16 |
os.environ["FAL_KEY"] = FAL_KEY if FAL_KEY else ""
|
| 17 |
|
| 18 |
DEFAULT_PROMPT = "Add furnishings and accessories to this room as an interior designer would do for a real estate staging. The generated image shall have the exact same dimensions as the original image and architectural details. Respect doorways and windows and make sure they are consistent with the source image and not blocked by furniture. Use cute accessories and with appropriate wall space, add smart simple graphic paintings. Use neutral colors with light colored accents to match the colors of the room. Give the area an attractive glow."
|
| 19 |
|
| 20 |
-
def
|
| 21 |
-
"""
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
def run_banana(
|
| 26 |
url = "https://api.runpod.ai/v2/nano-banana-edit/runsync"
|
| 27 |
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {RUNPOD_API_KEY}"}
|
| 28 |
payload = {
|
| 29 |
"input": {
|
| 30 |
"prompt": prompt,
|
| 31 |
-
"images": [
|
| 32 |
"enable_safety_checker": True
|
| 33 |
}
|
| 34 |
}
|
| 35 |
try:
|
| 36 |
response = requests.post(url, headers=headers, json=payload, timeout=90)
|
| 37 |
return response.json()["output"][0]
|
| 38 |
-
except
|
| 39 |
return None
|
| 40 |
|
| 41 |
-
def run_qwen(
|
| 42 |
-
"""Updated to use endpoint jzpm1xin5cprff with base64 logic"""
|
| 43 |
url = f"https://api.runpod.ai/v2/{QWEN_ENDPOINT_ID}/runsync"
|
| 44 |
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {RUNPOD_API_KEY}"}
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
"
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
"use_lightning": True,
|
| 54 |
-
"true_guidance_scale": 2.5,
|
| 55 |
-
"num_inference_steps": 4
|
| 56 |
-
}
|
| 57 |
}
|
|
|
|
|
|
|
| 58 |
response = requests.post(url, headers=headers, json=payload, timeout=90)
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
img_data = res_data["output"]["images"][0]
|
| 62 |
return f"data:image/png;base64,{img_data}"
|
| 63 |
-
except
|
| 64 |
-
print(f"Qwen Error: {e}")
|
| 65 |
return None
|
| 66 |
|
| 67 |
-
def run_fal_flux(
|
| 68 |
try:
|
| 69 |
handler = fal_client.submit(
|
| 70 |
"fal-ai/flux-2/edit",
|
| 71 |
-
arguments={
|
| 72 |
-
"prompt": prompt,
|
| 73 |
-
"image_urls": [image_url]
|
| 74 |
-
}
|
| 75 |
)
|
| 76 |
result = handler.get()
|
| 77 |
return result['images'][0]['url']
|
| 78 |
-
except
|
| 79 |
return None
|
| 80 |
|
| 81 |
-
def compare_models(image_url, prompt):
|
| 82 |
-
|
|
|
|
|
|
|
| 83 |
return None, None, None
|
| 84 |
-
res_banana = run_banana(image_url, prompt)
|
| 85 |
-
res_qwen = run_qwen(image_url, prompt)
|
| 86 |
-
res_fal = run_fal_flux(image_url, prompt)
|
| 87 |
-
return res_banana, res_qwen, res_fal
|
| 88 |
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
gr.Markdown("# 🛋️ Interior Design Model Arena")
|
| 91 |
-
gr.Markdown("Compare specialized staging models side-by-side.")
|
| 92 |
|
| 93 |
with gr.Row():
|
| 94 |
with gr.Column(scale=1):
|
| 95 |
-
|
| 96 |
-
|
|
|
|
| 97 |
run_btn = gr.Button("Generate Comparison", variant="primary")
|
| 98 |
|
| 99 |
with gr.Row():
|
| 100 |
with gr.Column():
|
| 101 |
-
gr.Markdown("### Qwen-Edit
|
| 102 |
-
gr.Markdown("**Price: $0.004 - $0.008 /req**")
|
| 103 |
out_qwen = gr.Image(label="Qwen Result", interactive=False)
|
| 104 |
|
| 105 |
with gr.Column():
|
| 106 |
-
gr.Markdown("### Flux-2 Edit")
|
| 107 |
-
gr.Markdown("**Price: $0.024 /req**")
|
| 108 |
out_fal = gr.Image(label="Flux Result", interactive=False)
|
| 109 |
|
| 110 |
with gr.Column():
|
| 111 |
-
gr.Markdown("### Nano-Banana")
|
| 112 |
-
gr.Markdown("**Price: $0.039 /req**")
|
| 113 |
out_banana = gr.Image(label="Banana Result", interactive=False)
|
| 114 |
|
| 115 |
run_btn.click(
|
| 116 |
fn=compare_models,
|
| 117 |
-
inputs=[input_url, input_prompt],
|
| 118 |
-
outputs=[
|
| 119 |
)
|
| 120 |
|
| 121 |
-
|
| 122 |
-
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 2 |
import requests
|
| 3 |
import fal_client
|
| 4 |
import os
|
|
|
|
|
|
|
| 5 |
import base64
|
|
|
|
| 6 |
from PIL import Image
|
| 7 |
+
import io
|
| 8 |
|
| 9 |
RUNPOD_API_KEY = os.getenv("RUNPOD_API_KEY")
|
| 10 |
FAL_KEY = os.getenv("FAL_KEY")
|
| 11 |
+
QWEN_ENDPOINT_ID = "jzpm1xin5cprff"
|
|
|
|
| 12 |
|
| 13 |
os.environ["FAL_KEY"] = FAL_KEY if FAL_KEY else ""
|
| 14 |
|
| 15 |
DEFAULT_PROMPT = "Add furnishings and accessories to this room as an interior designer would do for a real estate staging. The generated image shall have the exact same dimensions as the original image and architectural details. Respect doorways and windows and make sure they are consistent with the source image and not blocked by furniture. Use cute accessories and with appropriate wall space, add smart simple graphic paintings. Use neutral colors with light colored accents to match the colors of the room. Give the area an attractive glow."
|
| 16 |
|
| 17 |
+
def process_image_source(image_file, image_url):
|
| 18 |
+
"""
|
| 19 |
+
Determines if we should use the uploaded file or the URL.
|
| 20 |
+
Returns base64 for Qwen and a URL (or data URI) for others.
|
| 21 |
+
"""
|
| 22 |
+
if image_file is not None:
|
| 23 |
+
with open(image_file, "rb") as f:
|
| 24 |
+
file_bytes = f.read()
|
| 25 |
+
b64_str = base64.b64encode(file_bytes).decode('utf-8')
|
| 26 |
+
fal_url = fal_client.upload_file(image_file)
|
| 27 |
+
return b64_str, fal_url, f"data:image/png;base64,{b64_str}"
|
| 28 |
+
|
| 29 |
+
elif image_url and image_url.strip():
|
| 30 |
+
response = requests.get(image_url)
|
| 31 |
+
if response.status_code == 200:
|
| 32 |
+
b64_str = base64.b64encode(response.content).decode('utf-8')
|
| 33 |
+
return b64_str, image_url, image_url
|
| 34 |
+
|
| 35 |
+
return None, None, None
|
| 36 |
|
| 37 |
+
def run_banana(image_source_url, prompt):
|
| 38 |
url = "https://api.runpod.ai/v2/nano-banana-edit/runsync"
|
| 39 |
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {RUNPOD_API_KEY}"}
|
| 40 |
payload = {
|
| 41 |
"input": {
|
| 42 |
"prompt": prompt,
|
| 43 |
+
"images": [image_source_url],
|
| 44 |
"enable_safety_checker": True
|
| 45 |
}
|
| 46 |
}
|
| 47 |
try:
|
| 48 |
response = requests.post(url, headers=headers, json=payload, timeout=90)
|
| 49 |
return response.json()["output"][0]
|
| 50 |
+
except:
|
| 51 |
return None
|
| 52 |
|
| 53 |
+
def run_qwen(b64_img, prompt):
|
|
|
|
| 54 |
url = f"https://api.runpod.ai/v2/{QWEN_ENDPOINT_ID}/runsync"
|
| 55 |
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {RUNPOD_API_KEY}"}
|
| 56 |
+
payload = {
|
| 57 |
+
"input": {
|
| 58 |
+
"image": b64_img,
|
| 59 |
+
"prompt": prompt,
|
| 60 |
+
"seed": 42,
|
| 61 |
+
"use_lightning": True,
|
| 62 |
+
"true_guidance_scale": 2.5,
|
| 63 |
+
"num_inference_steps": 4
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
}
|
| 65 |
+
}
|
| 66 |
+
try:
|
| 67 |
response = requests.post(url, headers=headers, json=payload, timeout=90)
|
| 68 |
+
img_data = response.json()["output"]["images"][0]
|
|
|
|
|
|
|
| 69 |
return f"data:image/png;base64,{img_data}"
|
| 70 |
+
except:
|
|
|
|
| 71 |
return None
|
| 72 |
|
| 73 |
+
def run_fal_flux(fal_hosted_url, prompt):
|
| 74 |
try:
|
| 75 |
handler = fal_client.submit(
|
| 76 |
"fal-ai/flux-2/edit",
|
| 77 |
+
arguments={"prompt": prompt, "image_urls": [fal_hosted_url]}
|
|
|
|
|
|
|
|
|
|
| 78 |
)
|
| 79 |
result = handler.get()
|
| 80 |
return result['images'][0]['url']
|
| 81 |
+
except:
|
| 82 |
return None
|
| 83 |
|
| 84 |
+
def compare_models(image_file, image_url, prompt):
|
| 85 |
+
b64_img, fal_url, general_url = process_image_source(image_file, image_url)
|
| 86 |
+
|
| 87 |
+
if not b64_img:
|
| 88 |
return None, None, None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
+
res_qwen = run_qwen(b64_img, prompt)
|
| 91 |
+
res_fal = run_fal_flux(fal_url, prompt)
|
| 92 |
+
res_banana = run_banana(general_url, prompt)
|
| 93 |
+
|
| 94 |
+
return res_qwen, res_fal, res_banana
|
| 95 |
+
|
| 96 |
+
# UI
|
| 97 |
+
with gr.Blocks() as demo:
|
| 98 |
gr.Markdown("# 🛋️ Interior Design Model Arena")
|
|
|
|
| 99 |
|
| 100 |
with gr.Row():
|
| 101 |
with gr.Column(scale=1):
|
| 102 |
+
input_file = gr.Image(label="Upload Room Image", type="filepath")
|
| 103 |
+
input_url = gr.Textbox(label="OR: Source Image URL", placeholder="https://...")
|
| 104 |
+
input_prompt = gr.Textbox(label="Edit Prompt", value=DEFAULT_PROMPT, lines=4)
|
| 105 |
run_btn = gr.Button("Generate Comparison", variant="primary")
|
| 106 |
|
| 107 |
with gr.Row():
|
| 108 |
with gr.Column():
|
| 109 |
+
gr.Markdown("### Qwen-Edit\n**Price: $0.004 - $0.008**")
|
|
|
|
| 110 |
out_qwen = gr.Image(label="Qwen Result", interactive=False)
|
| 111 |
|
| 112 |
with gr.Column():
|
| 113 |
+
gr.Markdown("### Flux-2 Edit\n**Price: $0.024**")
|
|
|
|
| 114 |
out_fal = gr.Image(label="Flux Result", interactive=False)
|
| 115 |
|
| 116 |
with gr.Column():
|
| 117 |
+
gr.Markdown("### Nano-Banana\n**Price: $0.039**")
|
|
|
|
| 118 |
out_banana = gr.Image(label="Banana Result", interactive=False)
|
| 119 |
|
| 120 |
run_btn.click(
|
| 121 |
fn=compare_models,
|
| 122 |
+
inputs=[input_file, input_url, input_prompt],
|
| 123 |
+
outputs=[out_qwen, out_fal, out_banana]
|
| 124 |
)
|
| 125 |
|
| 126 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|