From 4ffc1b6097dda7239e67b61b05bc75d7cf004827 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 13 Nov 2025 13:14:55 -0500 Subject: [PATCH] add nano-banana Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 11 +- html/reference.json | 8 ++ javascript/extraNetworks.js | 4 + javascript/settings.js | 2 +- models/Reference/gemini-2.5-flash-image.jpg | Bin 0 -> 43455 bytes modules/modeldata.py | 3 + modules/processing_args.py | 2 + modules/sd_detect.py | 2 + modules/sd_models.py | 6 ++ modules/ui_extra_networks.py | 5 +- modules/ui_extra_networks_checkpoints.py | 19 ++-- pipelines/model_google.py | 105 ++++++++++++++++++++ 12 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 models/Reference/gemini-2.5-flash-image.jpg create mode 100644 pipelines/model_google.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 83738aebe..b55b180d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,19 @@ ### Highlights for 2025-11-13 -TBD +New native [kanvas](https://vladmandic.github.io/sdnext-docs/Kanvas/) module for image manipulation that fully replaces img2img, inpaint and outpaint controls +And a first cloud model with **Google's Nano Banana** + +![Screenshot](https://github.com/user-attachments/assets/54b25586-b611-4d70-a28f-ee3360944034) + +[ReadMe](https://github.com/vladmandic/automatic/blob/master/README.md) | [ChangeLog](https://github.com/vladmandic/automatic/blob/master/CHANGELOG.md) | [Docs](https://vladmandic.github.io/sdnext-docs/) | [WiKi](https://github.com/vladmandic/automatic/wiki) | [Discord](https://discord.com/invite/sd-next-federal-batch-inspectors-1101998836328697867) | [Sponsor](https://github.com/sponsors/vladmandic) ### Details for 2025-11-13 +- **Models** + - [Google Gemini 2.5 Flash Nano Banana](https://blog.google/products/gemini/gemini-nano-banana-examples/) + first cloud-based model directly supported in SD.Next UI + *note*: need to set `GOOGLE_API_KEY` environment variable with your key to use this model - **Features** - **kanvas**: new module for native canvas-based image manipulation kanvas is a full replacement for *img2img, inpaint and outpaint* controls diff --git a/html/reference.json b/html/reference.json index c11d627fc..eaf9428e5 100644 --- a/html/reference.json +++ b/html/reference.json @@ -1190,6 +1190,14 @@ "preview": "shuttleai--shuttle-jaguar.jpg", "tags": "community", "skip": true + }, + + "Google Gemini 2.5 Flash Nano Banana": { + "path": "gemini-2.5-flash-image", + "desc": "Gemini can generate and process images conversationally. You can prompt Gemini with text, images, or a combination of both allowing you to create, edit, and iterate on visuals with unprecedented control.", + "preview": "gemini-2.5-flash-image.jpg", + "tags": "cloud", + "skip": true } } diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index 5e884dba5..0143210ea 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -153,6 +153,10 @@ async function filterExtraNetworksForTab(searchTerm) { cards.forEach((elem) => elem.style.display = elem.dataset.tags .toLowerCase() .includes('community') ? '' : 'none'); + } else if (searchTerm === 'cloud/') { + cards.forEach((elem) => elem.style.display = elem.dataset.tags + .toLowerCase() + .includes('cloud') ? '' : 'none'); } else if (searchTerm === 'quantized/') { cards.forEach((elem) => elem.style.display = elem.dataset.tags .toLowerCase() diff --git a/javascript/settings.js b/javascript/settings.js index 96bdd24a9..1ffe449e9 100644 --- a/javascript/settings.js +++ b/javascript/settings.js @@ -178,7 +178,7 @@ async function initModels() { if (en.classList.contains('hide')) gradioApp().getElementById('txt2img_extra_networks_btn').click(); const repeat = setInterval(() => { const buttons = Array.from(gradioApp().querySelectorAll('#txt2img_model_subdirs > button')) || []; - const reference = buttons.find((b) => (b.innerText === 'Reference') || (b.innerText === 'Distilled') || (b.innerText === 'Community') || (b.innerText === 'Quantized')); + const reference = buttons.find((b) => (b.innerText === 'Reference') || (b.innerText === 'Distilled') || (b.innerText === 'Community') || (b.innerText === 'Quantized') || (b.innerText === 'Cloud')); if (reference) { clearInterval(repeat); reference.click(); diff --git a/models/Reference/gemini-2.5-flash-image.jpg b/models/Reference/gemini-2.5-flash-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ed6ec95c744b620293e5fc715557ac4360b0cc8 GIT binary patch literal 43455 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
mp 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 O- 0): task_args['reference_images'] = p.init_images + if ('GoogleNanoBananaPipeline' in model_cls) and (p.init_images is not None) and (len(p.init_images) > 0): + task_args['image'] = p.init_images[0] if 'BlipDiffusionPipeline' in model_cls: if len(p.init_images) == 0: shared.log.error('BLiP diffusion requires init image') diff --git a/modules/sd_detect.py b/modules/sd_detect.py index 2e2bfb40a..30c7d52e9 100644 --- a/modules/sd_detect.py +++ b/modules/sd_detect.py @@ -129,6 +129,8 @@ def guess_by_name(fn, current_guess): new_guess = 'Stable Diffusion XL' elif 'stable-video-diffusion' in fn.lower(): new_guess = 'StableVideoDiffusion' + elif 'gemini-2.5-flash-image' in fn.lower(): + new_guess = 'NanoBanana' if debug_load: shared.log.trace(f'Autodetect: method=name file="{fn}" previous="{current_guess}" current="{new_guess}"') return new_guess or current_guess diff --git a/modules/sd_models.py b/modules/sd_models.py index e6fc1fb71..bd01482f5 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -49,6 +49,7 @@ pipe_switch_task_exclude = [ 'HunyuanImagePipeline', 'AuraFlowPipeline', 'ChronoEditPipeline', + 'GoogleNanoBananaPipeline', ] i2i_pipes = [ 'LEditsPPPipelineStableDiffusion', 'LEditsPPPipelineStableDiffusionXL', @@ -421,6 +422,10 @@ def load_diffuser_force(model_type, checkpoint_info, diffusers_load_config, op=' from pipelines.model_xomni import load_xomni sd_model = load_xomni(checkpoint_info, diffusers_load_config) # pylint: disable=assignment-from-none allow_post_quant = False + elif model_type in ['NanoBanana']: + from pipelines.model_google import load_nanobanana + sd_model = load_nanobanana(checkpoint_info, diffusers_load_config) + allow_post_quant = False except Exception as e: shared.log.error(f'Load {op}: path="{checkpoint_info.path}" {e}') if debug_load: @@ -863,6 +868,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di modelstats.analyze() shared.log.info(f"Load {op}: family={shared.sd_model_type} time={timer.load.dct()} native={get_native(sd_model)} memory={memory_stats()}") + shared.opts.save(silent=True) class DiffusersTaskType(Enum): diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index cf7035847..7ba05c907 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -294,6 +294,7 @@ class ExtraNetworksPage: subdirs['Distilled'] = 1 subdirs['Quantized'] = 1 subdirs['Community'] = 1 + subdirs['Cloud'] = 1 subdirs[diffusers_base] = 1 if self.name == 'style' and shared.opts.extra_networks_styles: subdirs['Local'] = 1 @@ -313,11 +314,13 @@ class ExtraNetworksPage: subdirs.move_to_end('Quantized', last=True) if 'Community' in subdirs: subdirs.move_to_end('Community', last=True) + if 'Cloud' in subdirs: + subdirs.move_to_end('Cloud', last=True) subdirs_html = '' for subdir in subdirs: if len(subdir) == 0: continue - if subdir in ['All', 'Local', 'Diffusers', 'Reference', 'Distilled', 'Quantized', 'Community']: + if subdir in ['All', 'Local', 'Diffusers', 'Reference', 'Distilled', 'Quantized', 'Community', 'Cloud']: style = 'network-reference' else: style = 'network-folder' diff --git a/modules/ui_extra_networks_checkpoints.py b/modules/ui_extra_networks_checkpoints.py index 2fe4db376..26d81121a 100644 --- a/modules/ui_extra_networks_checkpoints.py +++ b/modules/ui_extra_networks_checkpoints.py @@ -68,13 +68,6 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): else: path = f'{v.get("path", "")}' - ready = reference_downloaded(url) - if not ready and shared.opts.offline_mode: - count['hidden'] += 1 - continue - if ready: - count['ready'] += 1 - tag = v.get('tags', '') if tag in count: count[tag] += 1 @@ -83,6 +76,16 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): else: count['base'] += 1 + ready = reference_downloaded(url) + version = "ready" if ready else "download" + if tag == 'cloud': + version = 'cloud' + if not ready and shared.opts.offline_mode: + count['hidden'] += 1 + continue + if ready: + count['ready'] += 1 + yield { "type": 'Model', "name": name, @@ -97,7 +100,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): "info": {}, "metadata": {}, "description": v.get('desc', ''), - "version": "ready" if ready else "download", + "version": version, "tags": tag, } shared.log.debug(f'Networks: type="reference" items={count}') diff --git a/pipelines/model_google.py b/pipelines/model_google.py new file mode 100644 index 000000000..b08a28222 --- /dev/null +++ b/pipelines/model_google.py @@ -0,0 +1,105 @@ +import io +import os +from PIL import Image +from installer import install, reload, log + + +image_size_buckets = { + '1M': 1024*1024, + '2M': 2048*1024, + '4M': 4096*1024, +} +aspect_ratios_buckets = { + '1:1': 1/1, + '2:3': 2/3, + '3:2': 3/2, + '4:3': 4/3, + '3:4': 3/4, + '4:5': 4/5, + '5:4': 5/4, + '16:9': 16/9, + '9:16': 9/16, + '21:9': 21/9, + '9:21': 9/21, +} + + +def get_size_buckets(width: int, height: int) -> str: + aspect_ratio = width / height + closest_aspect_ratio = min(aspect_ratios_buckets.items(), key=lambda x: abs(x[1] - aspect_ratio))[0] + pixel_count = width * height + closest_size = min(image_size_buckets.items(), key=lambda x: abs(x[1] - pixel_count))[0] + closest_aspect_ratio = min(aspect_ratios_buckets.items(), key=lambda x: abs(x[1] - aspect_ratio))[0] + return closest_size, closest_aspect_ratio + + +class GoogleNanoBananaPipeline(): + def __init__(self, model_name: str): + self.model = model_name + self.client = None + self.config = None + install('google-genai') + install('pydantic==2.11.7', ignore=True, quiet=True) + reload('pydantic', '2.11.7') + log.debug(f'Load model: type=NanoBanana model="{model_name}"') + + def txt2img(self, prompt): + return self.client.models.generate_content( + model=self.model, + config=self.config, + contents=prompt, + ) + + def img2img(self, prompt, image): + from google import genai + image_bytes = io.BytesIO() + image.save(image_bytes, format='JPEG') + return self.client.models.generate_content( + model=self.model, + config=self.config, + contents=[ + genai.types.Part.from_bytes(data=image_bytes.getvalue(), mime_type='image/jpeg'), + prompt, + ], + ) + + def __call__(self, prompt: list[str], width: int, height: int, image: Image.Image = None): + from google import genai + if self.client is None: + api_key = os.getenv("GOOGLE_API_KEY", None) + if api_key is None: + log.error(f'Cloud: model="{self.model}" GOOGLE_API_KEY environment variable not set') + return None + self.client = genai.Client(api_key=api_key, vertexai=False) + + image_size, aspect_ratio = get_size_buckets(width, height) + log.debug(f'Cloud: prompt={prompt} size={image_size} ar={aspect_ratio} image={image} model="{self.model}"') + self.config=genai.types.GenerateContentConfig( + response_modalities=["IMAGE"], + image_config=genai.types.ImageConfig(aspect_ratio=aspect_ratio, image_size=image_size) + ) + + try: + if image is not None: + response = self.img2img(prompt, image) + else: + response = self.txt2img(prompt) + except Exception as e: + log.error(f'Cloud: model="{self.model}" {e}') + return None + + image = None + if getattr(response, 'prompt_feedback', None) is not None: + log.error(f'Cloud: model="{self.model}" {response.prompt_feedback}') + if not hasattr(response, 'candidates') or (response.candidates is None) or (len(response.candidates) == 0): + log.error(f'Cloud: model="{self.model}" no images received') + return None + for part in response.candidates[0].content.parts: + if part.inline_data is not None: + image = Image.open(io.BytesIO(part.inline_data.data)) + return image + + +def load_nanobanana(checkpoint_info, diffusers_load_config): # pylint: disable=unused-argument + pipe = GoogleNanoBananaPipeline(model_name = checkpoint_info.filename) + return pipe