NanoBanana / app.py
Xhaheen's picture
Update app.py
d989bfa verified
# app.py
import os
import gradio as gr
from openai import OpenAI
from PIL import Image
from io import BytesIO
import base64
# --- Config ---
MODEL = "google/gemini-2.5-flash-image-preview"
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY") # set in HF Space secrets
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=OPENROUTER_API_KEY,
)
def analyze(prompt, img):
msg_content = [{"type": "text", "text": prompt}]
if img:
# img is a file path → open and encode as base64
with open(img, "rb") as f:
b64data = base64.b64encode(f.read()).decode("utf-8")
image_url = f"data:image/png;base64,{b64data}" # assumes PNG
msg_content.append({
"type": "image_url",
"image_url": {"url": image_url}
})
try:
# 👇 Print user input
print("=== USER PROMPT ===")
print(prompt)
print("Has image?", bool(img))
completion = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": msg_content}],
)
response_text = completion.choices[0].message.content
# 👇 Print raw response
print("=== MODEL RESPONSE ===")
print(response_text)
# --- Extract image if present ---
image_obj = None
msg = completion.choices[0].message
if hasattr(msg, "images") and msg.images:
first_img = msg.images[0]
url = first_img.get("image_url", {}).get("url")
if url and url.startswith("data:image"):
header, b64data = url.split(",", 1)
image_bytes = base64.b64decode(b64data)
image_obj = Image.open(BytesIO(image_bytes))
return response_text, image_obj
except Exception as e:
return f"Error: {e}", None
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("## Gemini 2.5 Flash Image (Preview) — via OpenRouter")
gr.Markdown(
"Generate **and** edit images with Google’s latest Gemini 2.5 Flash Image model "
"(a.k.a. *nano-banana*). Try text-based edits (remove objects, restyle, relight), "
"maintain character consistency, or **fuse multiple images** into one.\n\n"
"**Notes:** The model is in preview; quality and output format may evolve. "
"Images include Google’s SynthID watermark for provenance.\n\n"
"— built with ❤️ by [xhaheen](https://www.linkedin.com/in/sallu-mandya/)"
)
with gr.Row():
chatbot = gr.Chatbot(label="Conversation", show_copy_button=True)
with gr.Row():
txt = gr.Textbox(label="Prompt", scale=4)
img = gr.Image(type="filepath", label="Optional Image", scale=1)
send_btn = gr.Button("Send")
output_image = gr.Image(label="Generated Image", interactive=False)
def user_interact(history, prompt, image):
if not prompt and not image:
return gr.update(value=history), None, ""
response, gen_img = analyze(prompt, image)
history = history or []
history.append((prompt, response))
return history, gen_img, ""
send_btn.click(
user_interact,
inputs=[chatbot, txt, img],
outputs=[chatbot, output_image, txt],
)
if __name__ == "__main__":
demo.queue()
demo.launch(debug=True)