Skip to content

Commit ce1ef15

Browse files
authored
Merge pull request #3 from miroslaws8/develop
Add image creation
2 parents 1414024 + 694fa42 commit ce1ef15

17 files changed

+252
-12
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ OPENAI_API_KEY=sk-*
4343
* Models
4444
* [List models](https://platform.openai.com/docs/api-reference/models/list)
4545
* [Retrieve model](https://platform.openai.com/docs/api-reference/models/retrieve)
46-
46+
* Images
47+
* [Create image](https://platform.openai.com/docs/api-reference/images/create)
4748

4849
#### Coming soon:
4950
* Images
50-
* Create image
5151
* Create image edit
5252
* Audio
5353
* Create transcription
@@ -79,6 +79,21 @@ $result->getChoices(); // Choices from OpenAI.
7979

8080
```
8181

82+
#### Create image:
83+
84+
```php
85+
$openAI = $this->container->make(\Itsimiro\OpenAI\Services\OpenAI::class);
86+
87+
88+
$result = $openAI->getDalle()->createImage(new CreateImageParameters(
89+
'dog with a bone',
90+
2,
91+
responseFormat: ImageResponseFormatEnum::URL
92+
));
93+
94+
$result->getImages(); // Generated images
95+
```
96+
8297
#### See the [documentation](https://platform.openai.com/docs/api-reference) for more details on using OpenAI.
8398

8499
## Testing

composer.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
"phpstan/extension-installer": true
4747
}
4848
},
49-
"minimum-stability": "dev",
49+
"extra": {
50+
"laravel": {
51+
"providers": [
52+
"Itsimiro\\OpenAI\\Providers\\OpenaiServiceProvider"
53+
]
54+
}
55+
},
56+
"minimum-stability": "stable",
5057
"prefer-stable": true
5158
}

src/Enum/ImageResponseFormatEnum.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Enum;
4+
5+
enum ImageResponseFormatEnum: string
6+
{
7+
case URL = 'url';
8+
case BASE64 = 'b64_json';
9+
}

src/Enum/ImageSizeEnum.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Enum;
4+
5+
enum ImageSizeEnum: string
6+
{
7+
case SMALL = '256x256';
8+
case MEDIUM = '512x512';
9+
case LARGE = '1024x1024';
10+
}

src/Services/AIModels/Dalle.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@
22

33
namespace Itsimiro\OpenAI\Services\AIModels;
44

5+
use Itsimiro\OpenAI\Services\API\ApiService;
6+
use Itsimiro\OpenAI\Services\API\Results\CreateImageResult;
7+
use Itsimiro\OpenAI\Services\API\UrlService;
8+
use Itsimiro\OpenAI\Services\DataTransferObjects\CreateImageParameters;
9+
510
class Dalle
611
{
12+
public function __construct(private readonly ApiService $apiService, private readonly UrlService $urlService)
13+
{}
714

15+
public function createImage(CreateImageParameters $parameters): CreateImageResult
16+
{
17+
return $this->apiService->getResult(
18+
$this->apiService->sendRequest('POST', $this->urlService->createImage(), $parameters->toArray()),
19+
CreateImageResult::class
20+
);
21+
}
822
}

src/Services/API/Results/BodyParameters.php renamed to src/Services/API/Constants/BodyParameters.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Itsimiro\OpenAI\Services\API\Results;
3+
namespace Itsimiro\OpenAI\Services\API\Constants;
44

55
class BodyParameters
66
{
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Services\API\Constants;
4+
5+
class ImageBodyParameters
6+
{
7+
public const CREATED = 'created';
8+
public const DATA = 'data';
9+
public const URL = 'url';
10+
public const BASE64 = 'b64_json';
11+
}

src/Services/API/Results/ChatResult.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
namespace Itsimiro\OpenAI\Services\API\Results;
44

5-
use Spatie\LaravelData\Data;
6-
75
class ChatResult extends CompletionResult implements ResultInterface
86
{
97

src/Services/API/Results/CompletionResult.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22

33
namespace Itsimiro\OpenAI\Services\API\Results;
44

5+
use Itsimiro\OpenAI\Services\API\Constants\BodyParameters;
56
use Spatie\LaravelData\Data;
7+
use Spatie\LaravelData\Attributes\Validation\ArrayType;
68

79
class CompletionResult extends Data implements ResultInterface
810
{
9-
public function __construct(public array $result)
11+
public function __construct(
12+
#[ArrayType([
13+
BodyParameters::ID,
14+
BodyParameters::OBJECT,
15+
BodyParameters::CREATED_AT,
16+
BodyParameters::MODEL,
17+
BodyParameters::CHOICES,
18+
BodyParameters::USAGE
19+
])]
20+
public array $result
21+
)
1022
{}
1123

1224
public function getId(): string
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Services\API\Results;
4+
5+
use Illuminate\Support\Arr;
6+
use Itsimiro\OpenAI\Services\API\Constants\ImageBodyParameters;
7+
use Itsimiro\OpenAI\Services\DataTransferObjects\Image;
8+
use Spatie\LaravelData\Attributes\Validation\ArrayType;
9+
use Spatie\LaravelData\Data;
10+
11+
class CreateImageResult extends Data implements ResultInterface
12+
{
13+
public function __construct(
14+
#[ArrayType([
15+
ImageBodyParameters::CREATED,
16+
ImageBodyParameters::DATA,
17+
])]
18+
public array $result
19+
)
20+
{}
21+
22+
public function getImages(): array
23+
{
24+
return array_map(
25+
fn (array $image) => new Image($image),
26+
Arr::get($this->result, ImageBodyParameters::DATA, [])
27+
);
28+
}
29+
30+
public function getCreatedDate()
31+
{
32+
return Arr::get($this->result, ImageBodyParameters::CREATED);
33+
}
34+
}

src/Services/API/Results/EditsResult.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@
22

33
namespace Itsimiro\OpenAI\Services\API\Results;
44

5+
use Itsimiro\OpenAI\Services\API\Constants\BodyParameters;
6+
use Spatie\LaravelData\Attributes\Validation\ArrayType;
57
use Spatie\LaravelData\Data;
68

79
class EditsResult extends Data implements ResultInterface
810
{
9-
public function __construct(public array $result)
11+
public function __construct(
12+
#[ArrayType([
13+
BodyParameters::CREATED_AT,
14+
BodyParameters::CHOICES,
15+
BodyParameters::USAGE
16+
])]
17+
public array $result
18+
)
1019
{}
1120

1221
public function getCreateAt(): int

src/Services/API/Results/ModelResult.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,20 @@
33
namespace Itsimiro\OpenAI\Services\API\Results;
44

55
use Illuminate\Support\Arr;
6+
use Itsimiro\OpenAI\Services\API\Constants\BodyParameters;
7+
use Spatie\LaravelData\Attributes\Validation\ArrayType;
68
use Spatie\LaravelData\Data;
79

810
class ModelResult extends Data implements ResultInterface
911
{
10-
public function __construct(public array $result)
12+
public function __construct(
13+
#[ArrayType([
14+
BodyParameters::ID,
15+
BodyParameters::OBJECT,
16+
BodyParameters::OWNER_BY
17+
])]
18+
public array $result
19+
)
1120
{}
1221

1322
public function getId(): string

src/Services/API/UrlService.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ public function answers(): string
4444
return $this->buildUrl('/answers');
4545
}
4646

47-
public function images(): string
47+
public function createImage(): string
4848
{
49-
return $this->buildUrl('/images');
49+
return $this->buildUrl('/images/generations');
5050
}
5151

5252
public function embeddings(): string
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Services\DataTransferObjects;
4+
5+
use Itsimiro\OpenAI\Enum\ImageResponseFormatEnum;
6+
use Itsimiro\OpenAI\Enum\ImageSizeEnum;
7+
use Spatie\LaravelData\Data;
8+
9+
class CreateImageParameters extends Data
10+
{
11+
public function __construct(
12+
public string $prompt,
13+
public int $imageCount = 1,
14+
public ImageSizeEnum $size = ImageSizeEnum::LARGE,
15+
public ImageResponseFormatEnum $responseFormat = ImageResponseFormatEnum::URL,
16+
public string $user = ''
17+
)
18+
{}
19+
20+
public function toArray(): array
21+
{
22+
return [
23+
'prompt' => $this->prompt,
24+
'n' => $this->imageCount,
25+
'size' => $this->size->value,
26+
'response_format' => $this->responseFormat->value,
27+
'user' => $this->user
28+
];
29+
}
30+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Services\DataTransferObjects;
4+
5+
use Illuminate\Support\Arr;
6+
use Itsimiro\OpenAI\Services\API\Constants\ImageBodyParameters;
7+
use Spatie\LaravelData\Data;
8+
9+
class Image extends Data
10+
{
11+
public function __construct(
12+
public array $data
13+
)
14+
{}
15+
16+
public function getUrl(): ?string
17+
{
18+
return Arr::get($this->data, ImageBodyParameters::URL);
19+
}
20+
21+
public function getBase64(): ?string
22+
{
23+
return Arr::get($this->data, ImageBodyParameters::BASE64);
24+
}
25+
}

tests/Unit/AIModels/DalleTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Itsimiro\OpenAI\Tests\Unit\AIModels;
4+
5+
use Illuminate\Contracts\Container\BindingResolutionException;
6+
use Illuminate\Contracts\Container\Container;
7+
use Itsimiro\OpenAI\Services\AIModels\Dalle;
8+
use Itsimiro\OpenAI\Services\API\ApiService;
9+
use Itsimiro\OpenAI\Services\API\Constants\ImageBodyParameters;
10+
use Itsimiro\OpenAI\Services\API\Results\CreateImageResult;
11+
use Itsimiro\OpenAI\Services\API\UrlService;
12+
use Itsimiro\OpenAI\Services\DataTransferObjects\CreateImageParameters;
13+
use Itsimiro\OpenAI\Services\DataTransferObjects\Image;
14+
use PHPUnit\Framework\MockObject\Exception;
15+
use PHPUnit\Framework\TestCase;
16+
17+
class DalleTest extends TestCase
18+
{
19+
private Container $app;
20+
21+
protected function setUp(): void
22+
{
23+
parent::setUp();
24+
$this->app = app();
25+
}
26+
27+
/**
28+
* @throws Exception
29+
* @throws BindingResolutionException
30+
*/
31+
public function testCreateImage(): void
32+
{
33+
$expectedImage = new Image([
34+
ImageBodyParameters::URL => 'test url',
35+
ImageBodyParameters::BASE64 => '{"base64": "test"}',
36+
]);
37+
38+
$resultObject = $this->createMock(CreateImageResult::class);
39+
$resultObject->method('getImages')->willReturn([
40+
$expectedImage
41+
]);
42+
43+
$apiService = $this->createMock(ApiService::class);
44+
$this->app->bind(ApiService::class, fn() => $apiService);
45+
$apiService->expects($this->once())->method('getResult')->willReturn($resultObject);
46+
47+
$this->app->bind(UrlService::class, fn() => $this->createMock(UrlService::class));
48+
49+
$params = $this->createMock(CreateImageParameters::class);
50+
51+
$model = $this->app->make(Dalle::class);
52+
53+
$result = $model->createImage($params);
54+
55+
$this->assertCount(1, $result->getImages());
56+
$this->assertEquals($expectedImage->getUrl(), $result->getImages()[0]->getUrl());
57+
}
58+
}

tests/Unit/AIModels/GeneralTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use Itsimiro\OpenAI\Services\API\UrlService;
1212
use PHPUnit\Framework\MockObject\Exception;
1313
use PHPUnit\Framework\TestCase;
14-
use Spatie\LaravelData\DataCollection;
1514

1615
class GeneralTest extends TestCase
1716
{

0 commit comments

Comments
 (0)