diff --git a/src/platform/src/Bridge/Mistral/Contract/ImageUrlNormalizer.php b/src/platform/src/Bridge/Mistral/Contract/ImageUrlNormalizer.php new file mode 100644 index 000000000..348e7e996 --- /dev/null +++ b/src/platform/src/Bridge/Mistral/Contract/ImageUrlNormalizer.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\AI\Platform\Bridge\Mistral\Contract; + +use Symfony\AI\Platform\Bridge\Mistral\Mistral; +use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer; +use Symfony\AI\Platform\Message\Content\ImageUrl; +use Symfony\AI\Platform\Model; + +/** + * @author Franz Mayr-Wilding + */ +class ImageUrlNormalizer extends ModelContractNormalizer +{ + /** + * @param ImageUrl $data + * + * @return array{type: 'image_url', image_url: string} + */ + public function normalize(mixed $data, ?string $format = null, array $context = []): array + { + return [ + 'type' => 'image_url', + 'image_url' => $data->getUrl(), + ]; + } + + protected function supportedDataClass(): string + { + return ImageUrl::class; + } + + protected function supportsModel(Model $model): bool + { + return $model instanceof Mistral; + } +} diff --git a/src/platform/src/Bridge/Mistral/PlatformFactory.php b/src/platform/src/Bridge/Mistral/PlatformFactory.php index 325247a29..87bfd9d87 100644 --- a/src/platform/src/Bridge/Mistral/PlatformFactory.php +++ b/src/platform/src/Bridge/Mistral/PlatformFactory.php @@ -13,6 +13,7 @@ use Symfony\AI\Platform\Bridge\Mistral\Contract\DocumentNormalizer; use Symfony\AI\Platform\Bridge\Mistral\Contract\DocumentUrlNormalizer; +use Symfony\AI\Platform\Bridge\Mistral\Contract\ImageUrlNormalizer; use Symfony\AI\Platform\Bridge\Mistral\Contract\ToolNormalizer; use Symfony\AI\Platform\Contract; use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface; @@ -41,6 +42,7 @@ public static function create( new ToolNormalizer(), new DocumentNormalizer(), new DocumentUrlNormalizer(), + new ImageUrlNormalizer(), ), ); } diff --git a/src/platform/tests/Bridge/Mistral/Contract/ImageUrlNormalizerTest.php b/src/platform/tests/Bridge/Mistral/Contract/ImageUrlNormalizerTest.php new file mode 100644 index 000000000..86b9334b9 --- /dev/null +++ b/src/platform/tests/Bridge/Mistral/Contract/ImageUrlNormalizerTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Bridge\Mistral\Contract; + +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; +use Symfony\AI\Platform\Bridge\Mistral\Contract\ImageUrlNormalizer; +use Symfony\AI\Platform\Bridge\Mistral\Mistral; +use Symfony\AI\Platform\Contract; +use Symfony\AI\Platform\Message\Content\ImageUrl; + +final class ImageUrlNormalizerTest extends TestCase +{ + public function testSupportsNormalization() + { + $normalizer = new ImageUrlNormalizer(); + + $this->assertTrue($normalizer->supportsNormalization(new ImageUrl('https://example.com/image.png'), context: [ + Contract::CONTEXT_MODEL => new Mistral('mistral-large-latest'), + ])); + $this->assertFalse($normalizer->supportsNormalization('not a image url')); + } + + public function testGetSupportedTypes() + { + $normalizer = new ImageUrlNormalizer(); + + $expected = [ + ImageUrl::class => true, + ]; + + $this->assertSame($expected, $normalizer->getSupportedTypes(null)); + } + + #[DataProvider('normalizeDataProvider')] + public function testNormalize(ImageUrl $file, array $expected) + { + $normalizer = new ImageUrlNormalizer(); + + $normalized = $normalizer->normalize($file); + + $this->assertEquals($expected, $normalized); + } + + public static function normalizeDataProvider(): iterable + { + yield 'image with url' => [ + new ImageUrl('https://example.com/image.png'), + [ + 'type' => 'image_url', + 'image_url' => 'https://example.com/image.png', + ], + ]; + } +}