Skip to content

Commit 27f4121

Browse files
committed
feature #787 [Platform][Mistral] Add ImageUrlNormalizer (franzwilding)
This PR was squashed before being merged into the main branch. Discussion ---------- [Platform][Mistral] Add `ImageUrlNormalizer` | Q | A | ------------- | --- | Bug fix? | yes | New feature? | yes | Docs? | no | License | MIT The mistral platform factory gets a contract per default as an argument, so all the internal normalizers will not be used. This PR changes this by adding a custom MistralContract that will be used (like in the openAI birdge). This PR also adds an imageUrl normalizer, since the mistral chat api supports image_urls as well. Commits ------- c1227e4 [Platform][Mistral] Add `ImageUrlNormalizer`
2 parents 8226b5e + c1227e4 commit 27f4121

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\Mistral\Contract;
13+
14+
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
15+
use Symfony\AI\Platform\Contract\Normalizer\ModelContractNormalizer;
16+
use Symfony\AI\Platform\Message\Content\ImageUrl;
17+
use Symfony\AI\Platform\Model;
18+
19+
/**
20+
* @author Franz Mayr-Wilding
21+
*/
22+
class ImageUrlNormalizer extends ModelContractNormalizer
23+
{
24+
/**
25+
* @param ImageUrl $data
26+
*
27+
* @return array{type: 'image_url', image_url: string}
28+
*/
29+
public function normalize(mixed $data, ?string $format = null, array $context = []): array
30+
{
31+
return [
32+
'type' => 'image_url',
33+
'image_url' => $data->getUrl(),
34+
];
35+
}
36+
37+
protected function supportedDataClass(): string
38+
{
39+
return ImageUrl::class;
40+
}
41+
42+
protected function supportsModel(Model $model): bool
43+
{
44+
return $model instanceof Mistral;
45+
}
46+
}

src/platform/src/Bridge/Mistral/PlatformFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\AI\Platform\Bridge\Mistral\Contract\DocumentNormalizer;
1515
use Symfony\AI\Platform\Bridge\Mistral\Contract\DocumentUrlNormalizer;
16+
use Symfony\AI\Platform\Bridge\Mistral\Contract\ImageUrlNormalizer;
1617
use Symfony\AI\Platform\Bridge\Mistral\Contract\ToolNormalizer;
1718
use Symfony\AI\Platform\Contract;
1819
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
@@ -41,6 +42,7 @@ public static function create(
4142
new ToolNormalizer(),
4243
new DocumentNormalizer(),
4344
new DocumentUrlNormalizer(),
45+
new ImageUrlNormalizer(),
4446
),
4547
);
4648
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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 Bridge\Mistral\Contract;
13+
14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Platform\Bridge\Mistral\Contract\ImageUrlNormalizer;
17+
use Symfony\AI\Platform\Bridge\Mistral\Mistral;
18+
use Symfony\AI\Platform\Contract;
19+
use Symfony\AI\Platform\Message\Content\ImageUrl;
20+
21+
final class ImageUrlNormalizerTest extends TestCase
22+
{
23+
public function testSupportsNormalization()
24+
{
25+
$normalizer = new ImageUrlNormalizer();
26+
27+
$this->assertTrue($normalizer->supportsNormalization(new ImageUrl('https://example.com/image.png'), context: [
28+
Contract::CONTEXT_MODEL => new Mistral('mistral-large-latest'),
29+
]));
30+
$this->assertFalse($normalizer->supportsNormalization('not a image url'));
31+
}
32+
33+
public function testGetSupportedTypes()
34+
{
35+
$normalizer = new ImageUrlNormalizer();
36+
37+
$expected = [
38+
ImageUrl::class => true,
39+
];
40+
41+
$this->assertSame($expected, $normalizer->getSupportedTypes(null));
42+
}
43+
44+
#[DataProvider('normalizeDataProvider')]
45+
public function testNormalize(ImageUrl $file, array $expected)
46+
{
47+
$normalizer = new ImageUrlNormalizer();
48+
49+
$normalized = $normalizer->normalize($file);
50+
51+
$this->assertEquals($expected, $normalized);
52+
}
53+
54+
public static function normalizeDataProvider(): iterable
55+
{
56+
yield 'image with url' => [
57+
new ImageUrl('https://example.com/image.png'),
58+
[
59+
'type' => 'image_url',
60+
'image_url' => 'https://example.com/image.png',
61+
],
62+
];
63+
}
64+
}

0 commit comments

Comments
 (0)