Skip to content

Commit 82ec95b

Browse files
paulinevoschr-hertel
authored andcommitted
[Platform] Migrate OpenAI to Responses API
1 parent d8a3938 commit 82ec95b

29 files changed

+1330
-185
lines changed

examples/openai/audio-input.php

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,19 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
13-
use Symfony\AI\Platform\Message\Content\Audio;
14-
use Symfony\AI\Platform\Message\Message;
15-
use Symfony\AI\Platform\Message\MessageBag;
12+
use Symfony\AI\Platform\Exception\RuntimeException;
1613

1714
require_once dirname(__DIR__).'/bootstrap.php';
1815

19-
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
20-
21-
$messages = new MessageBag(
22-
Message::ofUser(
23-
'What is this recording about?',
24-
Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3'),
25-
),
26-
);
27-
$result = $platform->invoke('gpt-4o-audio-preview', $messages);
28-
29-
echo $result->asText().\PHP_EOL;
16+
throw new RuntimeException('This example is temporarily unavailable due to migration to Responses API (which does not support audio yet).');
17+
// $platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
18+
//
19+
// $messages = new MessageBag(
20+
// Message::ofUser(
21+
// 'What is this recording about?',
22+
// Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3'),
23+
// ),
24+
// );
25+
// $result = $platform->invoke('gpt-4o-audio-preview', $messages);
26+
//
27+
// echo $result->asText().\PHP_EOL;

examples/openai/chat-with-string-options.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
Message::forSystem('You are a pirate and you write funny.'),
2222
Message::ofUser('What is the Symfony framework?'),
2323
);
24-
$result = $platform->invoke('gpt-4o-mini?max_tokens=7', $messages);
24+
$result = $platform->invoke('gpt-4o-mini?max_output_tokens=16', $messages);
2525

2626
echo $result->asText().\PHP_EOL;

examples/openai/chat.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
Message::ofUser('What is the Symfony framework?'),
2323
);
2424
$result = $platform->invoke('gpt-4o-mini', $messages, [
25-
'max_tokens' => 500, // specific options just for this call
25+
'max_output_tokens' => 500, // specific options just for this call
2626
]);
2727

2828
echo $result->asText().\PHP_EOL;

examples/openai/token-metadata.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
Message::ofUser('What is the Symfony framework?'),
2626
);
2727
$result = $agent->call($messages, [
28-
'max_tokens' => 500, // specific options just for this call
28+
'max_output_tokens' => 500, // specific options just for this call
2929
]);
3030

3131
print_token_usage($result->getMetadata());
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract\Gpt\Message;
13+
14+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
15+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
16+
use Symfony\AI\Platform\Message\AssistantMessage;
17+
use Symfony\AI\Platform\Model;
18+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
19+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
20+
21+
/**
22+
* @author Guillermo Lengemann <guillermo.lengemann@gmail.com>
23+
*/
24+
final class AssistantMessageNormalizer extends ModelContractNormalizer implements NormalizerAwareInterface
25+
{
26+
use NormalizerAwareTrait;
27+
28+
/**
29+
* @param AssistantMessage $data
30+
*
31+
* @return array{
32+
* role: 'assistant',
33+
* type: 'message',
34+
* content: ?string
35+
* }
36+
*/
37+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
38+
{
39+
if ($data->hasToolCalls()) {
40+
return $this->normalizer->normalize($data->getToolCalls(), $format, $context);
41+
}
42+
43+
return [
44+
'role' => $data->getRole()->value,
45+
'type' => 'message',
46+
'content' => $data->getContent(),
47+
];
48+
}
49+
50+
protected function supportedDataClass(): string
51+
{
52+
return AssistantMessage::class;
53+
}
54+
55+
protected function supportsModel(Model $model): bool
56+
{
57+
return $model instanceof Gpt;
58+
}
59+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract\Gpt\Message\Content;
13+
14+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
15+
use Symfony\AI\Platform\Capability;
16+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
17+
use Symfony\AI\Platform\Message\Content\Document;
18+
use Symfony\AI\Platform\Message\Content\File;
19+
use Symfony\AI\Platform\Model;
20+
21+
/**
22+
* @author Guillermo Lengemann <guillermo.lengemann@gmail.com>
23+
*/
24+
class DocumentNormalizer extends ModelContractNormalizer
25+
{
26+
/**
27+
* @param File $data
28+
*
29+
* @return array{type: 'input_file', filename: string, file_data: string}
30+
*/
31+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
32+
{
33+
return [
34+
'type' => 'input_file',
35+
'filename' => $data->getFilename(),
36+
'file_data' => $data->asDataUrl(),
37+
];
38+
}
39+
40+
protected function supportedDataClass(): string
41+
{
42+
return Document::class;
43+
}
44+
45+
protected function supportsModel(Model $model): bool
46+
{
47+
return $model instanceof Gpt && $model->supports(Capability::INPUT_PDF);
48+
}
49+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract\Gpt\Message\Content;
13+
14+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
15+
use Symfony\AI\Platform\Capability;
16+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
17+
use Symfony\AI\Platform\Message\Content\Image;
18+
use Symfony\AI\Platform\Model;
19+
20+
/**
21+
* See: https://platform.openai.com/docs/guides/images-vision#giving-a-model-images-as-input.
22+
*/
23+
final class ImageNormalizer extends ModelContractNormalizer
24+
{
25+
/**
26+
* @param Image $data
27+
*
28+
* @return array{
29+
* type: 'input_image',
30+
* image_url: string
31+
* }
32+
*/
33+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
34+
{
35+
return [
36+
'type' => 'input_image',
37+
'image_url' => $data->asDataUrl(),
38+
];
39+
}
40+
41+
protected function supportedDataClass(): string
42+
{
43+
return Image::class;
44+
}
45+
46+
protected function supportsModel(Model $model): bool
47+
{
48+
return $model instanceof Gpt && $model->supports(Capability::INPUT_IMAGE);
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract\Gpt\Message\Content;
13+
14+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
15+
use Symfony\AI\Platform\Capability;
16+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
17+
use Symfony\AI\Platform\Message\Content\ImageUrl;
18+
use Symfony\AI\Platform\Model;
19+
20+
/**
21+
* See: https://platform.openai.com/docs/guides/images-vision#giving-a-model-images-as-input.
22+
*/
23+
final class ImageUrlNormalizer extends ModelContractNormalizer
24+
{
25+
/**
26+
* @param ImageUrl $data
27+
*
28+
* @return array{
29+
* type: 'input_image',
30+
* image_url: string
31+
* }
32+
*/
33+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
34+
{
35+
return [
36+
'type' => 'input_image',
37+
'image_url' => $data->getUrl(),
38+
];
39+
}
40+
41+
protected function supportedDataClass(): string
42+
{
43+
return ImageUrl::class;
44+
}
45+
46+
protected function supportsModel(Model $model): bool
47+
{
48+
return $model instanceof Gpt && $model->supports(Capability::INPUT_IMAGE);
49+
}
50+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract\Gpt\Message\Content;
13+
14+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
15+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
16+
use Symfony\AI\Platform\Message\Content\Text;
17+
use Symfony\AI\Platform\Model;
18+
19+
/**
20+
* See: https://platform.openai.com/docs/guides/images-vision#giving-a-model-images-as-input.
21+
*/
22+
final class TextNormalizer extends ModelContractNormalizer
23+
{
24+
/**
25+
* @param Text $data
26+
*
27+
* @return array{
28+
* type: 'input_text',
29+
* text: string
30+
* }
31+
*/
32+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
33+
{
34+
return [
35+
'type' => 'input_text',
36+
'text' => $data->getText(),
37+
];
38+
}
39+
40+
protected function supportedDataClass(): string
41+
{
42+
return Text::class;
43+
}
44+
45+
protected function supportsModel(Model $model): bool
46+
{
47+
return $model instanceof Gpt;
48+
}
49+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Bridge\OpenAi\Contract\Gpt\Message;
13+
14+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
15+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
16+
use Symfony\AI\Platform\Message\AssistantMessage;
17+
use Symfony\AI\Platform\Message\MessageBag;
18+
use Symfony\AI\Platform\Model;
19+
use Symfony\Component\Serializer\Exception\ExceptionInterface;
20+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
21+
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
22+
23+
/**
24+
* @author Pauline Vos <pauline.vos@mongodb.com>
25+
*/
26+
final class MessageBagNormalizer extends ModelContractNormalizer implements NormalizerAwareInterface
27+
{
28+
use NormalizerAwareTrait;
29+
30+
/**
31+
* @param MessageBag $data
32+
*
33+
* @return array{
34+
* input: array<string, mixed>,
35+
* model?: string,
36+
* system?: string,
37+
* }
38+
*
39+
* @throws ExceptionInterface
40+
*/
41+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
42+
{
43+
$messages['input'] = [];
44+
45+
foreach ($data->withoutSystemMessage()->getMessages() as $message) {
46+
$normalized = $this->normalizer->normalize($message, $format, $context);
47+
48+
if ($message instanceof AssistantMessage && $message->hasToolCalls()) {
49+
$messages['input'] = array_merge($messages['input'], $normalized);
50+
continue;
51+
}
52+
53+
$messages['input'][] = $normalized;
54+
}
55+
56+
if ($data->getSystemMessage()) {
57+
$messages['instructions'] = $data->getSystemMessage()->getContent();
58+
}
59+
60+
return $messages;
61+
}
62+
63+
protected function supportedDataClass(): string
64+
{
65+
return MessageBag::class;
66+
}
67+
68+
protected function supportsModel(Model $model): bool
69+
{
70+
return $model instanceof Gpt;
71+
}
72+
}

0 commit comments

Comments
 (0)