Skip to content

Commit 1ebd248

Browse files
Copilotowndev
andcommitted
Add configurable aspect ratio and resolution for image generation
- Added IMAGE_GENERATION_ASPECT_RATIO valve (default: 1:1) - Added IMAGE_GENERATION_RESOLUTION valve (default: 2K) - Added validation methods for aspect_ratio and resolution - Integrated ImageConfig into _configure_generation when image generation is enabled - Updated documentation with new environment variables and usage examples - Updated version to 1.10.0 Co-authored-by: owndev <69784886+owndev@users.noreply.github.com>
1 parent e58ede1 commit 1ebd248

2 files changed

Lines changed: 208 additions & 1 deletion

File tree

docs/google-gemini-integration.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ GOOGLE_IMAGE_HISTORY_FIRST=true
128128
# Default: true
129129
GOOGLE_IMAGE_UPLOAD_FALLBACK=true
130130

131+
# Image generation configuration (for image-capable models like gemini-2.5-flash-image-preview)
132+
# Default aspect ratio for generated images
133+
# Valid values: "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"
134+
# Default: "1:1"
135+
GOOGLE_IMAGE_GENERATION_ASPECT_RATIO="1:1"
136+
137+
# Default resolution for generated images
138+
# Valid values: "1K", "2K", "4K"
139+
# Default: "2K"
140+
GOOGLE_IMAGE_GENERATION_RESOLUTION="2K"
141+
131142
# Enable Gemini thoughts outputs globally
132143
# Default: true
133144
GOOGLE_INCLUDE_THOUGHTS=true
@@ -199,6 +210,100 @@ VERTEX_AI_RAG_STORE="projects/your-project/locations/global/collections/default_
199210
>
200211
> Future versions may extend these settings to also optimize generated images before upload/display.
201212
213+
## Image Generation Configuration
214+
215+
The Google Gemini pipeline supports configurable aspect ratios and resolutions for image generation with image-capable models (e.g., `gemini-2.5-flash-image-preview`).
216+
217+
### Aspect Ratio
218+
219+
Control the shape and proportions of generated images using the aspect ratio setting:
220+
221+
**Valid Values:**
222+
- `1:1` - Square (default)
223+
- `2:3`, `3:2` - Classic photo ratios
224+
- `3:4`, `4:3` - Standard display ratios
225+
- `4:5`, `5:4` - Portrait/landscape variants
226+
- `9:16`, `16:9` - Mobile and widescreen ratios
227+
- `21:9` - Ultra-wide format
228+
229+
**Configuration:**
230+
```bash
231+
# Set via environment variable (global default)
232+
GOOGLE_IMAGE_GENERATION_ASPECT_RATIO="16:9"
233+
```
234+
235+
Or configure through the pipeline valves in Open WebUI's Admin panel.
236+
237+
### Resolution
238+
239+
Control the quality and size of generated images:
240+
241+
**Valid Values:**
242+
- `1K` - Lower resolution, faster generation
243+
- `2K` - Balanced quality and speed (default)
244+
- `4K` - Highest quality, slower generation
245+
246+
**Configuration:**
247+
```bash
248+
# Set via environment variable (global default)
249+
GOOGLE_IMAGE_GENERATION_RESOLUTION="4K"
250+
```
251+
252+
Or configure through the pipeline valves in Open WebUI's Admin panel.
253+
254+
### Per-Request Override
255+
256+
You can override the default settings on a per-request basis by including these parameters in the request body:
257+
258+
**Example API Usage:**
259+
260+
```python
261+
from google import genai
262+
from google.genai import types
263+
264+
client = genai.Client(api_key="your-api-key")
265+
266+
# Generate a 4K widescreen image
267+
response = client.models.generate_content(
268+
model="gemini-2.5-flash-image-preview",
269+
contents="A serene mountain landscape at sunset",
270+
config=types.GenerateContentConfig(
271+
response_modalities=["TEXT", "IMAGE"],
272+
image_config=types.ImageConfig(
273+
aspect_ratio="16:9",
274+
image_size="4K"
275+
),
276+
)
277+
)
278+
279+
for part in response.parts:
280+
if part.text:
281+
print(part.text)
282+
elif image := part.as_image():
283+
image.save("landscape.png")
284+
```
285+
286+
### Use Cases
287+
288+
**Portrait Photography (`3:4` or `4:5`)**
289+
- Social media profile images
290+
- Portrait-oriented artwork
291+
292+
**Widescreen Content (`16:9` or `21:9`)**
293+
- Desktop wallpapers
294+
- YouTube thumbnails
295+
- Presentation slides
296+
297+
**Square Images (`1:1`)**
298+
- Instagram posts
299+
- Icons and logos
300+
- Product photos
301+
302+
**Mobile-First (`9:16`)**
303+
- Instagram Stories
304+
- TikTok content
305+
- Mobile app screens
306+
202307
## Web search and access
203308

204309
[Grounding with Google search](https://ai.google.dev/gemini-api/docs/google-search) together with the [URL context tool](https://ai.google.dev/gemini-api/docs/url-context) are enabled/disabled together via the `google_search_tool` feature, which can be switched on/off in a Filter.

pipelines/google/google_gemini.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
author_url: https://github.com/owndev/
55
project_url: https://github.com/owndev/Open-WebUI-Functions
66
funding_url: https://github.com/sponsors/owndev
7-
version: 1.9.2
7+
version: 1.10.0
88
required_open_webui_version: 0.6.26
99
license: Apache License 2.0
1010
description: Highly optimized Google Gemini pipeline with advanced image generation capabilities, intelligent compression, and streamlined processing workflows.
@@ -35,6 +35,7 @@
3535
- Flexible upload fallback options and optimization controls
3636
- Configurable thinking levels (low/high) for Gemini 3 models
3737
- Configurable thinking budgets (0-32768 tokens) for Gemini 2.5 models
38+
- Configurable image generation aspect ratio (1:1, 16:9, etc.) and resolution (1K, 2K, 4K)
3839
"""
3940

4041
import os
@@ -259,6 +260,14 @@ class Valves(BaseModel):
259260
default=os.getenv("GOOGLE_IMAGE_HISTORY_FIRST", "true").lower() == "true",
260261
description="If true (default), history images precede current message images; if false, current images first.",
261262
)
263+
IMAGE_GENERATION_ASPECT_RATIO: str = Field(
264+
default=os.getenv("GOOGLE_IMAGE_GENERATION_ASPECT_RATIO", "1:1"),
265+
description="Default aspect ratio for image generation. Valid values: '1:1', '2:3', '3:2', '3:4', '4:3', '4:5', '5:4', '9:16', '16:9', '21:9'",
266+
)
267+
IMAGE_GENERATION_RESOLUTION: str = Field(
268+
default=os.getenv("GOOGLE_IMAGE_GENERATION_RESOLUTION", "2K"),
269+
description="Default resolution for image generation. Valid values: '1K', '2K', '4K'",
270+
)
262271

263272
# ---------------- Internal Helpers ---------------- #
264273
async def _gather_history_images(
@@ -863,6 +872,69 @@ def _validate_thinking_budget(self, budget: int) -> int:
863872
)
864873
return -1
865874

875+
def _validate_aspect_ratio(self, aspect_ratio: str) -> Optional[str]:
876+
"""
877+
Validate and normalize the aspect ratio value.
878+
879+
Args:
880+
aspect_ratio: The aspect ratio string to validate
881+
882+
Returns:
883+
Validated aspect ratio string or None if invalid
884+
"""
885+
if not aspect_ratio:
886+
return None
887+
888+
# Valid aspect ratios according to Google's API
889+
valid_ratios = [
890+
"1:1",
891+
"2:3",
892+
"3:2",
893+
"3:4",
894+
"4:3",
895+
"4:5",
896+
"5:4",
897+
"9:16",
898+
"16:9",
899+
"21:9",
900+
]
901+
902+
normalized = aspect_ratio.strip()
903+
if normalized in valid_ratios:
904+
return normalized
905+
906+
self.log.warning(
907+
f"Invalid aspect ratio '{aspect_ratio}'. Valid values are: {', '.join(valid_ratios)}. "
908+
"Using default '1:1'."
909+
)
910+
return "1:1"
911+
912+
def _validate_resolution(self, resolution: str) -> Optional[str]:
913+
"""
914+
Validate and normalize the resolution value.
915+
916+
Args:
917+
resolution: The resolution string to validate
918+
919+
Returns:
920+
Validated resolution string or None if invalid
921+
"""
922+
if not resolution:
923+
return None
924+
925+
# Valid resolutions according to Google's API
926+
valid_resolutions = ["1K", "2K", "4K"]
927+
928+
normalized = resolution.strip().upper()
929+
if normalized in valid_resolutions:
930+
return normalized
931+
932+
self.log.warning(
933+
f"Invalid resolution '{resolution}'. Valid values are: {', '.join(valid_resolutions)}. "
934+
"Using default '2K'."
935+
)
936+
return "2K"
937+
866938
def pipes(self) -> List[Dict[str, str]]:
867939
"""
868940
Returns a list of available Google Gemini models for the UI.
@@ -1569,6 +1641,36 @@ def _configure_generation(
15691641
if enable_image_generation:
15701642
gen_config_params["response_modalities"] = ["TEXT", "IMAGE"]
15711643

1644+
# Configure image generation parameters (aspect ratio and resolution)
1645+
# Body parameters override valve defaults for per-request customization
1646+
aspect_ratio = body.get(
1647+
"aspect_ratio", self.valves.IMAGE_GENERATION_ASPECT_RATIO
1648+
)
1649+
resolution = body.get("image_size", self.valves.IMAGE_GENERATION_RESOLUTION)
1650+
1651+
# Validate and normalize the values
1652+
validated_aspect_ratio = self._validate_aspect_ratio(aspect_ratio)
1653+
validated_resolution = self._validate_resolution(resolution)
1654+
1655+
# Create image config if we have valid values
1656+
if validated_aspect_ratio and validated_resolution:
1657+
try:
1658+
gen_config_params["image_config"] = types.ImageConfig(
1659+
aspect_ratio=validated_aspect_ratio,
1660+
image_size=validated_resolution,
1661+
)
1662+
self.log.debug(
1663+
f"Image generation config: aspect_ratio={validated_aspect_ratio}, resolution={validated_resolution}"
1664+
)
1665+
except (AttributeError, TypeError) as e:
1666+
# Fall back if SDK does not support ImageConfig
1667+
self.log.warning(
1668+
f"ImageConfig not supported by SDK version: {e}. Image generation will use default settings."
1669+
)
1670+
except Exception as e:
1671+
# Log unexpected errors but continue without image config
1672+
self.log.warning(f"Unexpected error configuring ImageConfig: {e}")
1673+
15721674
# Configure Gemini thinking/reasoning for models that support it
15731675
# This is independent of include_thoughts - thinking config controls HOW the model reasons,
15741676
# while include_thoughts controls whether the reasoning is shown in the output

0 commit comments

Comments
 (0)