Skip to content

Commit dd45f30

Browse files
committed
feat: add new models, mark deprecated ones
Add gpt-image-1.5, gpt-image-1-mini, gemini-2.5-flash-image, gemini-3-pro-image-preview, and Imagen 4 variants to model registry. Mark dall-e-2, dall-e-3, and gemini-2.0-flash as deprecated with shutdown dates. Widen quality param to str, add 2:3/3:2 aspect ratios, update default fallbacks from deprecated to current models.
1 parent 665a719 commit dd45f30

16 files changed

Lines changed: 279 additions & 41 deletions

CONFIGURATION.md

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Complete configuration reference for the Image Generation API.
5353

5454
**`DEFAULT_MODEL`**
5555
- Default model for generation/editing when not specified in request
56-
- Example: `gpt-image-1`, `dall-e-3`
56+
- Example: `gpt-image-1`, `gpt-image-1.5`
5757
- Optional - if not set, first available model is used
5858

5959
### Response Configuration
@@ -109,27 +109,51 @@ Complete configuration reference for the Image Generation API.
109109

110110
### OpenAI Models
111111

112-
**dall-e-2**
113-
- Aspect Ratios: `1:1` only
112+
**gpt-image-1.5** (latest)
113+
- Aspect Ratios: `1:1`, `2:3`, `3:2`
114+
- Quality: `auto`, `high`, `medium`, `low`
115+
- Max Images (n): 4
116+
- Editing: Yes (mask-based)
117+
118+
**gpt-image-1**
119+
- Aspect Ratios: `1:1`, `16:9`, `9:16`
114120
- Quality: Not supported
115121
- Max Images (n): 4
116122
- Editing: Yes (mask-based)
117123

118-
**dall-e-3**
124+
**gpt-image-1-mini**
125+
- Aspect Ratios: `1:1`, `16:9`, `9:16`
126+
- Quality: `low`, `medium`, `high`
127+
- Max Images (n): 4
128+
- Editing: Yes (mask-based)
129+
130+
**dall-e-3** *(deprecated — shutting down May 12, 2026)*
119131
- Aspect Ratios: `1:1`, `16:9`, `9:16`
120132
- Quality: `standard`, `hd`
121133
- Max Images (n): 1
122134
- Editing: No
123135

124-
**gpt-image-1**
125-
- Aspect Ratios: `1:1`, `16:9`, `9:16`
136+
**dall-e-2** *(deprecated — shutting down May 12, 2026)*
137+
- Aspect Ratios: `1:1` only
126138
- Quality: Not supported
127139
- Max Images (n): 4
128140
- Editing: Yes (mask-based)
129141

130142
### Google Gemini Models
131143

132-
**gemini-2.0-flash-preview-image-generation**
144+
**gemini-2.5-flash-image** (recommended)
145+
- Aspect Ratios: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `2:3`, `3:2`
146+
- Quality: Not supported
147+
- Max Images (n): 4
148+
- Editing: Yes (prompt-based)
149+
150+
**gemini-3-pro-image-preview** (preview)
151+
- Aspect Ratios: `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`
152+
- Quality: Not supported
153+
- Max Images (n): 4
154+
- Editing: Yes (prompt-based)
155+
156+
**gemini-2.0-flash-preview-image-generation** *(deprecated — shutting down March 31, 2026)*
133157
- Aspect Ratios: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`
134158
- Quality: Not supported
135159
- Max Images (n): 4
@@ -187,7 +211,7 @@ Set `provider="openai"` or `provider="gemini"` in requests.
187211

188212
```json
189213
{
190-
"model": "dall-e-3" // or null for auto-select
214+
"model": "gpt-image-1" // or null for auto-select
191215
}
192216
```
193217

@@ -201,13 +225,15 @@ Leave `null` to use first available model for provider.
201225
}
202226
```
203227

204-
Options: `1:1`, `16:9` (landscape), `9:16` (portrait), `4:3`, `3:4`
228+
Options: `1:1`, `16:9` (landscape), `9:16` (portrait), `4:3`, `3:4`, `2:3` (tall portrait), `3:2` (wide landscape)
205229

206230
Model compatibility:
207-
- dall-e-2: `1:1` only
208-
- dall-e-3: `1:1`, `16:9`, `9:16`
209-
- gpt-image-1: `1:1`, `16:9`, `9:16`
210-
- Gemini models: All ratios
231+
- gpt-image-1.5: `1:1`, `2:3`, `3:2`
232+
- gpt-image-1 / gpt-image-1-mini: `1:1`, `16:9`, `9:16`
233+
- gemini-2.5-flash-image: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `2:3`, `3:2`
234+
- gemini-3-pro-image-preview: All 10 ratios including `4:5`, `5:4`, `21:9`
235+
- dall-e-3 (deprecated): `1:1`, `16:9`, `9:16`
236+
- dall-e-2 (deprecated): `1:1` only
211237

212238
### Quality
213239

@@ -217,8 +243,11 @@ Model compatibility:
217243
}
218244
```
219245

220-
- `standard`: Faster generation
221-
- `hd`: Higher detail (dall-e-3 only)
246+
Values depend on model:
247+
- dall-e-3: `standard`, `hd`
248+
- gpt-image-1.5: `auto`, `high`, `medium`, `low`
249+
- gpt-image-1-mini: `low`, `medium`, `high`
250+
- Other models: quality parameter ignored
222251

223252
### Number of Images
224253

@@ -230,6 +259,7 @@ Model compatibility:
230259

231260
Constraints:
232261
- dall-e-3: max 1
262+
- imagen-4.0-ultra: max 1
233263
- Others: max 4
234264

235265
## Image Editing
@@ -238,7 +268,7 @@ The `/edit` endpoint supports two editing modes:
238268

239269
### Mask-based Editing (OpenAI)
240270

241-
Used with `dall-e-2` and `gpt-image-1`. Requires:
271+
Used with `gpt-image-1`, `gpt-image-1.5`, `gpt-image-1-mini`, and `dall-e-2`. Requires:
242272
- `image`: Source image (upload or URL)
243273
- `mask`: PNG with transparent areas marking regions to edit
244274
- `prompt`: Description of what to generate in masked area
@@ -247,7 +277,7 @@ The mask should have transparent (alpha=0) pixels where editing should occur.
247277

248278
### Prompt-based Editing (Gemini)
249279

250-
Used with `gemini-2.0-flash-preview-image-generation`. Requires:
280+
Used with `gemini-2.5-flash-image`, `gemini-3-pro-image-preview`, and other Gemini models. Requires:
251281
- `image`: Source image (upload or URL)
252282
- `prompt`: Natural language description of the edit
253283

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ OpenAPI server for AI image generation and editing. Supports LiteLLM proxy (for
66

77
- **Image Generation**: Create images from text prompts
88
- **Image Editing**: Edit existing images with mask-based inpainting (OpenAI) or prompt-based editing (Gemini)
9-
- **Multi-Provider**: OpenAI (DALL-E 3, GPT-Image-1) and Google Gemini
9+
- **Multi-Provider**: OpenAI (GPT-Image-1.5, GPT-Image-1) and Google Gemini
1010
- **LiteLLM Integration**: Unified API with cost tracking
1111
- **Open WebUI Integration**: Auto-upload images to Open WebUI's file storage
1212
- **Dynamic Models**: Auto-discovers available models from LiteLLM
@@ -67,7 +67,7 @@ curl -X POST "http://localhost:8000/generate" \
6767
-H "Content-Type: application/json" \
6868
-d '{
6969
"prompt": "A mountain landscape at sunset",
70-
"model": "dall-e-3",
70+
"model": "gpt-image-1",
7171
"aspect_ratio": "16:9"
7272
}'
7373
```
@@ -145,15 +145,19 @@ Currently applies to:
145145
146146
| Model | Generation | Editing | Notes |
147147
|-------|------------|---------|-------|
148-
| dall-e-3 | Yes | No | HD quality, multiple aspect ratios |
148+
| gpt-image-1.5 | Yes | Yes (mask) | Latest, quality: auto/high/medium/low |
149149
| gpt-image-1 | Yes | Yes (mask) | Fast, supports inpainting |
150-
| dall-e-2 | Yes | Yes (mask) | Square only |
150+
| gpt-image-1-mini | Yes | Yes (mask) | Cost-efficient variant |
151+
| ~~dall-e-3~~ | Yes | No | **Deprecated** — shutting down May 12, 2026 |
152+
| ~~dall-e-2~~ | Yes | Yes (mask) | **Deprecated** — shutting down May 12, 2026 |
151153
152154
### Google Gemini
153155
154156
| Model | Generation | Editing | Notes |
155157
|-------|------------|---------|-------|
156-
| gemini-2.0-flash-preview-image-generation | Yes | Yes (prompt) | Fast, prompt-based editing |
158+
| gemini-2.5-flash-image | Yes | Yes (prompt) | Fast, wide aspect ratio support |
159+
| gemini-3-pro-image-preview | Yes | Yes (prompt) | Preview, up to 4K resolution |
160+
| ~~gemini-2.0-flash-preview-image-generation~~ | Yes | Yes (prompt) | **Deprecated** — shutting down March 31, 2026 |
157161
158162
See [CONFIGURATION.md](CONFIGURATION.md) for details.
159163

TODO.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# TODO - openapi-image-gen
2+
3+
## 1. Investigation & General Improvements
4+
Status: DONE
5+
6+
Fix security and code quality issues found during review:
7+
- Use `secrets.compare_digest()` for bearer token comparison
8+
- Add basic SSRF guard to `storage_service.get_image()` (block metadata IPs, private ranges)
9+
- Fix CORS: don't combine `allow_origins=["*"]` with `allow_credentials=True`
10+
- Sanitize filenames extracted from URLs (even though UUIDs, harden the path)
11+
- Extract duplicated MIME type dict and OPENWEBUI_MODE response logic into helpers
12+
- Replace sync `open()` with `aiofiles` in async route handlers
13+
- Fix Dockerfile: add `COPY pyproject.toml .` so version reading works in container
14+
- Add async lock to model registry cache
15+
- Bump stale dependency versions where appropriate
16+
17+
## 2. Add New Models
18+
Status: DONE
19+
20+
Add models released since the last update:
21+
- OpenAI: gpt-image-1 variants, any new DALL-E models
22+
- Google: gemini-2.0-flash-preview-image-generation updates, newer Gemini image models, Imagen 3 updates
23+
- Update KNOWN_CAPABILITIES in model_registry.py
24+
- Update documentation tables
25+
- Test with LiteLLM model discovery
26+
27+
## 3. Improve OWUI Image Display
28+
Status: PENDING
29+
30+
Current approach returns HTMLResponse with base64-encoded `<img>` tag — a workaround
31+
that went through several iterations. OWUI has had updates since; investigate:
32+
- Check current OWUI tool response handling (artifact display, image rendering)
33+
- See if OWUI now natively supports image URLs or base64 in tool responses without HTML hack
34+
- Consider using OWUI's file upload API to store images there directly
35+
- Reduce unnecessary disk I/O (currently writes to disk then reads back for base64)
36+
- Test with latest OWUI version and document the recommended setup

app/api/routes/edit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,6 @@ def _get_default_edit_model(provider: str) -> str:
268268

269269
# Fallback defaults
270270
if provider == "gemini":
271-
return "gemini-2.0-flash-preview-image-generation"
271+
return "gemini-2.5-flash-image"
272272
else:
273273
return "gpt-image-1"

app/api/routes/generate.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,11 @@ def _get_default_model(provider: str) -> str:
314314
if not provider_models:
315315
# Fallback defaults
316316
if provider == "openai" or provider == "litellm":
317-
return "dall-e-3"
317+
return "gpt-image-1"
318318
elif provider == "gemini":
319-
return "gemini-2.0-flash-preview-image-generation"
319+
return "gemini-2.5-flash-image"
320320
else:
321-
return "dall-e-3"
321+
return "gpt-image-1"
322322

323323
# Return first available model
324324
return provider_models[0].id

app/schemas/requests.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,24 @@ class ImageRequest(BaseModel):
3434
examples=["openai/dall-e-3", "openai/gpt-image-1", "gemini/gemini-2.5-flash-image"],
3535
)
3636

37-
aspect_ratio: Literal["1:1", "16:9", "9:16", "4:3", "3:4"] = Field(
37+
aspect_ratio: Literal["1:1", "16:9", "9:16", "4:3", "3:4", "2:3", "3:2"] = Field(
3838
default="1:1",
3939
description=(
4040
"Image aspect ratio. "
4141
"1:1 = square, 16:9 = landscape, 9:16 = portrait, "
42-
"4:3 = classic landscape, 3:4 = classic portrait"
42+
"4:3 = classic landscape, 3:4 = classic portrait, "
43+
"2:3 = tall portrait, 3:2 = wide landscape"
4344
),
4445
)
4546

46-
quality: Literal["standard", "hd"] = Field(
47-
default="standard", description="Image quality. 'hd' available for dall-e-3 only"
47+
quality: str = Field(
48+
default="standard",
49+
description=(
50+
"Image quality. Values depend on model: "
51+
"'standard'/'hd' (dall-e-3), "
52+
"'auto'/'high'/'medium'/'low' (gpt-image-1.5). "
53+
"Ignored by models that don't support quality."
54+
),
4855
)
4956

5057
n: int = Field(

app/schemas/responses.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ class ModelCapabilities(BaseModel):
4545
default=False, description="Whether model supports quality parameter"
4646
)
4747

48+
quality_values: list[str] | None = Field(
49+
default=None,
50+
description="Accepted quality values (e.g., ['standard', 'hd'] or ['auto', 'high', 'medium', 'low'])",
51+
)
52+
4853
supports_aspect_ratios: list[str] = Field(
4954
default_factory=lambda: ["1:1"], description="Supported aspect ratios"
5055
)
@@ -60,6 +65,10 @@ class ModelCapabilities(BaseModel):
6065
description="Type of editing: 'mask' (OpenAI inpainting) or 'prompt' (Gemini natural language)",
6166
)
6267

68+
deprecated: str | None = Field(
69+
default=None, description="Deprecation notice with shutdown date, or None if active"
70+
)
71+
6372

6473
class ModelInfo(BaseModel):
6574
"""

app/services/gemini_service.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class GeminiService:
2020
"9:16": "9:16",
2121
"4:3": "4:3",
2222
"3:4": "3:4",
23+
"2:3": "2:3",
24+
"3:2": "3:2",
2325
}
2426

2527
def __init__(self):

app/services/litellm_service.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class LiteLLMService:
2525
"9:16": "1024x1792",
2626
"4:3": "1792x1024",
2727
"3:4": "1024x1792",
28+
"2:3": "1024x1536",
29+
"3:2": "1536x1024",
2830
}
2931

3032
def __init__(self):

0 commit comments

Comments
 (0)