feat: nano banana image generation model integration

This commit is contained in:
shiva raj badu 2025-12-19 00:41:55 +05:45
parent ea8db1bfdd
commit f421260bfc
No known key found for this signature in database
7 changed files with 42 additions and 6 deletions

View file

@ -4,5 +4,6 @@ class ImageProvider(Enum):
PEXELS = "pexels"
PIXABAY = "pixabay"
GEMINI_FLASH = "gemini_flash"
NANOBANANA_PRO = "nanobanana_pro" # Google's gemini-3-pro-image-preview
DALLE3 = "dall-e-3"
COMFYUI = "comfyui"

View file

@ -18,6 +18,7 @@ from utils.image_provider import (
is_pixels_selected,
is_pixabay_selected,
is_gemini_flash_selected,
is_nanobanana_pro_selected,
is_dalle3_selected,
is_comfyui_selected,
)
@ -39,7 +40,9 @@ class ImageGenerationService:
elif is_pixels_selected():
return self.get_image_from_pexels
elif is_gemini_flash_selected():
return self.generate_image_google
return self.generate_image_gemini_flash
elif is_nanobanana_pro_selected():
return self.generate_image_nanobanana_pro
elif is_dalle3_selected():
return self.generate_image_openai
elif is_comfyui_selected():
@ -95,10 +98,11 @@ class ImageGenerationService:
print(f"Error generating image: {e}")
return "/static/images/placeholder.jpg"
async def generate_image_openai(self, prompt: str, output_directory: str) -> str:
async def generate_image_openai(self, prompt: str, output_directory: str,model: str = "dall-e-3") -> str:
client = AsyncOpenAI()
result = await client.images.generate(
model="dall-e-3",
model=model,
prompt=prompt,
n=1,
quality="standard",
@ -107,11 +111,12 @@ class ImageGenerationService:
image_url = result.data[0].url
return await download_file(image_url, output_directory)
async def generate_image_google(self, prompt: str, output_directory: str) -> str:
async def _generate_image_google(self, prompt: str, output_directory: str, model: str) -> str:
"""Base method for Google image generation models."""
client = genai.Client()
response = await asyncio.to_thread(
client.models.generate_content,
model="gemini-2.5-flash-image-preview",
model=model,
contents=[prompt],
config=GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
)
@ -126,6 +131,14 @@ class ImageGenerationService:
return image_path
async def generate_image_gemini_flash(self, prompt: str, output_directory: str) -> str:
"""Generate image using Gemini Flash (gemini-2.5-flash-image-preview)."""
return await self._generate_image_google(prompt, output_directory, "gemini-2.5-flash-image-preview")
async def generate_image_nanobanana_pro(self, prompt: str, output_directory: str) -> str:
"""Generate image using NanoBanana Pro (gemini-3-pro-image-preview)."""
return await self._generate_image_google(prompt, output_directory, "gemini-3-pro-image-preview")
async def get_image_from_pexels(self, prompt: str) -> str:
async with aiohttp.ClientSession(trust_env=True) as session:
response = await session.get(

View file

@ -27,6 +27,10 @@ def is_gemini_flash_selected() -> bool:
return ImageProvider.GEMINI_FLASH == get_selected_image_provider()
def is_nanobanana_pro_selected() -> bool:
return ImageProvider.NANOBANANA_PRO == get_selected_image_provider()
def is_dalle3_selected() -> bool:
return ImageProvider.DALLE3 == get_selected_image_provider()

View file

@ -65,7 +65,9 @@ export default function Home() {
}));
// API: save config
trackEvent(MixpanelEvent.Home_SaveConfiguration_API_Call);
// API CALL: save config
await handleSaveLLMConfig(llmConfig);
if (llmConfig.LLM === "ollama" && llmConfig.OLLAMA_MODEL) {
// API: check model pulled
trackEvent(MixpanelEvent.Home_CheckOllamaModelPulled_API_Call);

View file

@ -74,6 +74,7 @@ export default function LLMProviderSelection({
(
(llmConfig.IMAGE_PROVIDER === "dall-e-3" && !llmConfig.OPENAI_API_KEY) ||
(llmConfig.IMAGE_PROVIDER === "gemini_flash" && !llmConfig.GOOGLE_API_KEY) ||
(llmConfig.IMAGE_PROVIDER === "nanobanana_pro" && !llmConfig.GOOGLE_API_KEY) ||
(llmConfig.IMAGE_PROVIDER === "pexels" && !llmConfig.PEXELS_API_KEY) ||
(llmConfig.IMAGE_PROVIDER === "pixabay" && !llmConfig.PIXABAY_API_KEY)
);
@ -340,6 +341,10 @@ export default function LLMProviderSelection({
return <></>;
}
if (provider.value === "nanobanana_pro" && llmConfig.LLM === "google") {
return <></>;
}
// Show ComfyUI configuration
if (provider.value === "comfyui") {
return (

View file

@ -55,7 +55,16 @@ export const IMAGE_PROVIDERS: Record<string, ImageProviderOption> = {
gemini_flash: {
value: "gemini_flash",
label: "Gemini Flash",
description: "Google's primary image generation model",
description: "Google's fast image generation model",
icon: "/icons/google.png",
requiresApiKey: true,
apiKeyField: "GOOGLE_API_KEY",
apiKeyFieldLabel: "Google API Key"
},
nanobanana_pro: {
value: "nanobanana_pro",
label: "NanoBanana Pro",
description: "Google's advanced image generation (4K, better quality)",
icon: "/icons/google.png",
requiresApiKey: true,
apiKeyField: "GOOGLE_API_KEY",

View file

@ -73,6 +73,8 @@ export const hasValidLLMConfig = (llmConfig: LLMConfig) => {
return llmConfig.OPENAI_API_KEY && llmConfig.OPENAI_API_KEY !== "";
case "gemini_flash":
return llmConfig.GOOGLE_API_KEY && llmConfig.GOOGLE_API_KEY !== "";
case "nanobanana_pro":
return llmConfig.GOOGLE_API_KEY && llmConfig.GOOGLE_API_KEY !== "";
case "comfyui":
return llmConfig.COMFYUI_URL && llmConfig.COMFYUI_URL !== "";
default: