Skip to content

Commit 6de5b78

Browse files
authored
feat: image generation (#428)
1 parent 96c384f commit 6de5b78

File tree

25 files changed

+1004
-6
lines changed

25 files changed

+1004
-6
lines changed

docs/.vitepress/config.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ export default defineConfig({
114114
text: "Embeddings",
115115
link: "/core-concepts/embeddings",
116116
},
117+
{
118+
text: "Image Generation",
119+
link: "/core-concepts/image-generation",
120+
},
117121
{
118122
text: "Schemas",
119123
link: "/core-concepts/schemas",
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Image Generation
2+
3+
Generate stunning images from text prompts using AI-powered models. Prism provides a clean, consistent API for image generation across different providers, starting with comprehensive OpenAI support.
4+
5+
## Getting Started
6+
7+
Creating images with Prism is as simple as describing what you want:
8+
9+
```php
10+
use Prism\Prism\Prism;
11+
12+
$response = Prism::image()
13+
->using('openai', 'dall-e-3')
14+
->withPrompt('A cute baby sea otter floating on its back in calm blue water')
15+
->generate();
16+
17+
$image = $response->firstImage();
18+
echo $image->url; // https://oaidalleapiprodscus.blob.core.windows.net/...
19+
```
20+
21+
## Provider Support
22+
23+
Currently, Prism supports image generation through:
24+
25+
- **OpenAI**: DALL-E 2, DALL-E 3, and GPT-Image-1 models
26+
27+
Additional providers will be added in future releases as the ecosystem evolves.
28+
29+
## Basic Usage
30+
31+
### Simple Generation
32+
33+
The most straightforward way to generate an image:
34+
35+
```php
36+
$response = Prism::image()
37+
->using('openai', 'dall-e-3')
38+
->withPrompt('A serene mountain landscape at sunset')
39+
->generate();
40+
41+
// Access the generated image
42+
$image = $response->firstImage();
43+
if ($image->hasUrl()) {
44+
echo "Image URL: " . $image->url;
45+
}
46+
```
47+
48+
### Working with Responses
49+
50+
The response object provides helpful methods for accessing generated content:
51+
52+
```php
53+
$response = Prism::image()
54+
->using('openai', 'dall-e-2')
55+
->withPrompt('Abstract geometric patterns in vibrant colors')
56+
->generate();
57+
58+
// Check if images were generated
59+
if ($response->hasImages()) {
60+
echo "Generated {$response->imageCount()} image(s)";
61+
62+
// Access all images
63+
foreach ($response->images as $image) {
64+
if ($image->hasUrl()) {
65+
echo "Image: {$image->url}\n";
66+
}
67+
68+
if ($image->hasRevisedwithPrompt()) {
69+
echo "Revised prompt: {$image->revisedPrompt}\n";
70+
}
71+
}
72+
73+
// Or just get the first one
74+
$firstImage = $response->firstImage();
75+
}
76+
77+
// Check usage information
78+
echo "Prompt tokens: {$response->usage->promptTokens}";
79+
echo "Model used: {$response->meta->model}";
80+
```
81+
82+
## Provider-Specific Options
83+
84+
While Prism provides a consistent API, you can access provider-specific features using the `withProviderOptions()` method.
85+
86+
### OpenAI Options
87+
88+
OpenAI offers various customization options depending on the model:
89+
90+
#### DALL-E 3 Options
91+
92+
```php
93+
$response = Prism::image()
94+
->using('openai', 'dall-e-3')
95+
->withPrompt('A beautiful sunset over mountains')
96+
->withProviderOptions([
97+
'size' => '1792x1024', // 1024x1024, 1024x1792, 1792x1024
98+
'quality' => 'hd', // standard, hd
99+
'style' => 'vivid', // vivid, natural
100+
'response_format' => 'url', // url, b64_json
101+
])
102+
->generate();
103+
```
104+
105+
## Testing
106+
107+
Prism provides convenient fakes for testing image generation:
108+
109+
```php
110+
use Prism\Prism\Prism;
111+
use Prism\Prism\Testing\PrismFake;
112+
113+
test('can generate images', function () {
114+
$fake = PrismFake::create()->image();
115+
Prism::fake($fake);
116+
117+
$response = Prism::image()
118+
->using('openai', 'dall-e-3')
119+
->withPrompt('Test image')
120+
->generate();
121+
122+
expect($response->hasImages())->toBeTrue();
123+
expect($response->firstImage()->url)->toContain('fake-image-url');
124+
});
125+
```
126+
127+
Need help with a specific provider or use case? Check the [provider documentation](/providers/openai) for detailed configuration options and examples.

docs/providers/openai.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,127 @@ Prism::text()
9797
])
9898
->asText()
9999
```
100+
101+
## Image Generation
102+
103+
OpenAI provides powerful image generation capabilities through multiple models. Prism supports all of OpenAI's image generation models with their full feature sets.
104+
105+
### Supported Models
106+
107+
| Model | Description |
108+
|-------|-------------|
109+
| `dall-e-3` | Latest DALL-E model |
110+
| `dall-e-2` | Previous generation |
111+
| `gpt-image-1` | GPT-based image model |
112+
113+
### Basic Usage
114+
115+
```php
116+
$response = Prism::image()
117+
->using('openai', 'dall-e-3')
118+
->withPrompt('A serene mountain landscape at sunset')
119+
->generate();
120+
121+
$image = $response->firstImage();
122+
echo $image->url; // Generated image URL
123+
```
124+
125+
### DALL-E 3 Options
126+
127+
DALL-E 3 is the most advanced model with the highest quality output:
128+
129+
```php
130+
$response = Prism::image()
131+
->using('openai', 'dall-e-3')
132+
->withPrompt('A futuristic cityscape with flying cars')
133+
->withProviderOptions([
134+
'size' => '1792x1024', // 1024x1024, 1024x1792, 1792x1024
135+
'quality' => 'hd', // standard, hd
136+
'style' => 'vivid', // vivid, natural
137+
])
138+
->generate();
139+
140+
// DALL-E 3 automatically revises prompts for better results
141+
if ($response->firstImage()->hasRevisedPrompt()) {
142+
echo "Revised prompt: " . $response->firstImage()->revisedPrompt;
143+
}
144+
```
145+
146+
### DALL-E 2 Options
147+
148+
DALL-E 2 supports generating multiple images and is more cost-effective:
149+
150+
```php
151+
$response = Prism::image()
152+
->using('openai', 'dall-e-2')
153+
->withPrompt('Abstract geometric patterns')
154+
->withProviderOptions([
155+
'n' => 4, // Number of images (1-10)
156+
'size' => '1024x1024', // 256x256, 512x512, 1024x1024
157+
'response_format' => 'url', // url only
158+
'user' => 'user-123', // Optional user identifier
159+
])
160+
->generate();
161+
162+
// Process multiple images
163+
foreach ($response->images as $image) {
164+
echo "Image: {$image->url}\n";
165+
}
166+
```
167+
168+
### GPT-Image-1 Options
169+
170+
GPT-Image-1 offers advanced features including image editing and format control:
171+
172+
```php
173+
$response = Prism::image()
174+
->using('openai', 'gpt-image-1')
175+
->withPrompt('A detailed architectural rendering of a modern house')
176+
->withProviderOptions([
177+
'size' => '1536x1024', // Various sizes supported
178+
'quality' => 'high', // standard, high
179+
'output_format' => 'webp', // png, webp, jpeg
180+
'output_compression' => 85, // Compression level (0-100)
181+
'background' => 'transparent', // transparent, white, black
182+
'moderation' => true, // Enable content moderation
183+
])
184+
->generate();
185+
```
186+
187+
### Image Editing with GPT-Image-1
188+
189+
GPT-Image-1 supports sophisticated image editing operations:
190+
191+
```php
192+
// Load your source image and mask
193+
$originalImage = base64_encode(file_get_contents('/path/to/photo.jpg'));
194+
$maskImage = base64_encode(file_get_contents('/path/to/mask.png'));
195+
196+
$response = Prism::image()
197+
->using('openai', 'gpt-image-1')
198+
->withPrompt('Replace the sky with a dramatic sunset')
199+
->withProviderOptions([
200+
'image' => $originalImage, // Base64 encoded original image
201+
'mask' => $maskImage, // Base64 encoded mask (optional)
202+
'size' => '1024x1024',
203+
'output_format' => 'png',
204+
'quality' => 'high',
205+
])
206+
->generate();
207+
```
208+
209+
### Response Format
210+
211+
Generated images are returned as URLs:
212+
213+
```php
214+
$response = Prism::image()
215+
->using('openai', 'dall-e-3')
216+
->withPrompt('Digital artwork')
217+
->generate();
218+
219+
$image = $response->firstImage();
220+
if ($image->hasUrl()) {
221+
echo "<img src='{$image->url}' alt='Generated image'>";
222+
}
223+
```

src/Contracts/Provider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use Generator;
88
use Prism\Prism\Embeddings\Request as EmbeddingsRequest;
99
use Prism\Prism\Embeddings\Response as EmbeddingsResponse;
10+
use Prism\Prism\Images\Request as ImagesRequest;
11+
use Prism\Prism\Images\Response as ImagesResponse;
1012
use Prism\Prism\Structured\Request as StructuredRequest;
1113
use Prism\Prism\Structured\Response as StructuredResponse;
1214
use Prism\Prism\Text\Chunk;
@@ -22,6 +24,8 @@ public function structured(StructuredRequest $request): StructuredResponse;
2224

2325
public function embeddings(EmbeddingsRequest $request): EmbeddingsResponse;
2426

27+
public function images(ImagesRequest $request): ImagesResponse;
28+
2529
/**
2630
* @return Generator<Chunk>
2731
*/

src/Images/PendingRequest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Prism\Prism\Images;
6+
7+
use Illuminate\Contracts\View\View;
8+
use Prism\Prism\Concerns\ConfiguresClient;
9+
use Prism\Prism\Concerns\ConfiguresModels;
10+
use Prism\Prism\Concerns\ConfiguresProviders;
11+
use Prism\Prism\Concerns\HasProviderOptions;
12+
13+
class PendingRequest
14+
{
15+
use ConfiguresClient;
16+
use ConfiguresModels;
17+
use ConfiguresProviders;
18+
use HasProviderOptions;
19+
20+
protected string $prompt = '';
21+
22+
public function withPrompt(string|View $prompt): self
23+
{
24+
$this->prompt = is_string($prompt) ? $prompt : $prompt->render();
25+
26+
return $this;
27+
}
28+
29+
public function generate(): Response
30+
{
31+
return $this->provider->images($this->toRequest());
32+
}
33+
34+
public function toRequest(): Request
35+
{
36+
return new Request(
37+
model: $this->model,
38+
prompt: $this->prompt,
39+
clientOptions: $this->clientOptions,
40+
clientRetry: $this->clientRetry,
41+
providerOptions: $this->providerOptions,
42+
);
43+
}
44+
}

src/Images/Request.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Prism\Prism\Images;
6+
7+
use Closure;
8+
use Prism\Prism\Concerns\ChecksSelf;
9+
use Prism\Prism\Concerns\HasProviderOptions;
10+
use Prism\Prism\Contracts\PrismRequest;
11+
12+
class Request implements PrismRequest
13+
{
14+
use ChecksSelf, HasProviderOptions;
15+
16+
/**
17+
* @param array<string, mixed> $clientOptions
18+
* @param array{0: array<int, int>|int, 1?: Closure|int, 2?: ?callable, 3?: bool} $clientRetry
19+
* @param array<string, mixed> $providerOptions
20+
*/
21+
public function __construct(
22+
protected string $model,
23+
protected string $prompt,
24+
protected array $clientOptions,
25+
protected array $clientRetry,
26+
array $providerOptions = [],
27+
) {
28+
$this->providerOptions = $providerOptions;
29+
}
30+
31+
/**
32+
* @return array{0: array<int, int>|int, 1?: Closure|int, 2?: ?callable, 3?: bool} $clientRetry
33+
*/
34+
public function clientRetry(): array
35+
{
36+
return $this->clientRetry;
37+
}
38+
39+
/**
40+
* @return array<string, mixed> $clientOptions
41+
*/
42+
public function clientOptions(): array
43+
{
44+
return $this->clientOptions;
45+
}
46+
47+
public function prompt(): string
48+
{
49+
return $this->prompt;
50+
}
51+
52+
#[\Override]
53+
public function model(): string
54+
{
55+
return $this->model;
56+
}
57+
}

0 commit comments

Comments
 (0)