Skip to content

Commit c44c665

Browse files
authored
Merge branch 'main' into feature/sort-documents
2 parents 7770c9e + 04f7e54 commit c44c665

File tree

5 files changed

+345
-1
lines changed

5 files changed

+345
-1
lines changed

.code-samples.meilisearch.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,3 +808,18 @@ update_embedders_1: |-
808808
'documentTemplate' => 'A document titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}'
809809
]
810810
]);
811+
search_parameter_reference_media_1: |-
812+
$client->index('INDEX_NAME')->search('a futuristic movie', [
813+
'hybrid' => [
814+
'embedder' => 'EMBEDDER_NAME'
815+
],
816+
'media' => [
817+
'textAndPoster' => [
818+
'text' => 'a futuristic movie',
819+
'image' => [
820+
'mime' => 'image/jpeg',
821+
'data' => 'base64EncodedImageData'
822+
]
823+
]
824+
]
825+
]);

src/Meilisearch.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class Meilisearch
88
{
9-
public const VERSION = '1.15.0';
9+
public const VERSION = '1.16.0';
1010

1111
/**
1212
* @return non-empty-string
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Endpoints;
6+
7+
use Meilisearch\Endpoints\Indexes;
8+
use Meilisearch\Http\Client;
9+
use Tests\TestCase;
10+
11+
final class MultiModalSearchTest extends TestCase
12+
{
13+
private Indexes $index;
14+
private array $documents;
15+
16+
protected function setUp(): void
17+
{
18+
parent::setUp();
19+
20+
$http = new Client($this->host, getenv('MEILISEARCH_API_KEY'));
21+
$http->patch('/experimental-features', ['multimodal' => true]);
22+
23+
$voyageApiKey = getenv('VOYAGE_API_KEY');
24+
if (false === $voyageApiKey || '' === $voyageApiKey) {
25+
self::markTestSkipped('Missing `VOYAGE_API_KEY` environment variable');
26+
}
27+
28+
$this->index = $this->createEmptyIndex($this->safeIndexName());
29+
$updateSettingsPromise = $this->index->updateSettings([
30+
'searchableAttributes' => ['title', 'overview'],
31+
'embedders' => [
32+
'multimodal' => self::getVoyageEmbedderConfig($voyageApiKey),
33+
],
34+
]);
35+
$this->index->waitForTask($updateSettingsPromise['taskUid']);
36+
37+
// Load the movies.json dataset
38+
$documentsJson = file_get_contents('./tests/datasets/movies.json');
39+
$this->documents = json_decode($documentsJson, true, 512, JSON_THROW_ON_ERROR);
40+
$addDocumentsPromise = $this->index->addDocuments($this->documents);
41+
$this->index->waitForTask($addDocumentsPromise['taskUid']);
42+
}
43+
44+
public function testTextOnlySearch(): void
45+
{
46+
$query = 'A movie with lightsabers in space';
47+
$response = $this->index->search($query, [
48+
'media' => [
49+
'text' => ['text' => $query],
50+
],
51+
'hybrid' => [
52+
'embedder' => 'multimodal',
53+
'semanticRatio' => 1,
54+
],
55+
]);
56+
self::assertSame('Star Wars', $response->getHits()[0]['title']);
57+
}
58+
59+
public function testImageOnlySearch(): void
60+
{
61+
$theFifthElementPoster = $this->documents[3]['poster'];
62+
$response = $this->index->search(null, [
63+
'media' => [
64+
'poster' => [
65+
'poster' => $theFifthElementPoster,
66+
],
67+
],
68+
'hybrid' => [
69+
'embedder' => 'multimodal',
70+
'semanticRatio' => 1,
71+
],
72+
]);
73+
self::assertSame('The Fifth Element', $response->getHits()[0]['title']);
74+
}
75+
76+
public function testTextAndImageSearch(): void
77+
{
78+
$query = 'a futuristic movie';
79+
$masterYodaBase64 = base64_encode(file_get_contents('./tests/assets/master-yoda.jpeg'));
80+
$response = $this->index->search(null, [
81+
'media' => [
82+
'textAndPoster' => [
83+
'text' => $query,
84+
'image' => [
85+
'mime' => 'image/jpeg',
86+
'data' => $masterYodaBase64,
87+
],
88+
],
89+
],
90+
'hybrid' => [
91+
'embedder' => 'multimodal',
92+
'semanticRatio' => 1,
93+
],
94+
]);
95+
self::assertSame('Star Wars', $response->getHits()[0]['title']);
96+
}
97+
98+
private static function getVoyageEmbedderConfig(string $voyageApiKey): array
99+
{
100+
return [
101+
'source' => 'rest',
102+
'url' => 'https://api.voyageai.com/v1/multimodalembeddings',
103+
'apiKey' => $voyageApiKey,
104+
'dimensions' => 1024,
105+
'indexingFragments' => [
106+
'textAndPoster' => [
107+
// the shape of the data here depends on the model used
108+
'value' => [
109+
'content' => [
110+
[
111+
'type' => 'text',
112+
'text' => 'A movie titled {{doc.title}} whose description starts with {{doc.overview|truncatewords:20}}.',
113+
],
114+
[
115+
'type' => 'image_url',
116+
'image_url' => '{{doc.poster}}',
117+
],
118+
],
119+
],
120+
],
121+
'text' => [
122+
'value' => [
123+
// The shape of the data here depends on the model used
124+
'content' => [
125+
[
126+
'type' => 'text',
127+
'text' => 'A movie titled {{doc.title}} whose description starts with {{doc.overview|truncatewords:20}}.',
128+
],
129+
],
130+
],
131+
],
132+
'poster' => [
133+
'value' => [
134+
// The shape of the data here depends on the model used
135+
'content' => [
136+
[
137+
'type' => 'image_url',
138+
'image_url' => '{{doc.poster}}',
139+
],
140+
],
141+
],
142+
],
143+
],
144+
'searchFragments' => [
145+
'textAndPoster' => [
146+
'value' => [
147+
'content' => [
148+
[
149+
'type' => 'text',
150+
'text' => '{{media.textAndPoster.text}}',
151+
],
152+
[
153+
'type' => 'image_base64',
154+
'image_base64' => 'data:{{media.textAndPoster.image.mime}};base64,{{media.textAndPoster.image.data}}',
155+
],
156+
],
157+
],
158+
],
159+
'text' => [
160+
'value' => [
161+
'content' => [
162+
[
163+
'type' => 'text',
164+
'text' => '{{media.text.text}}',
165+
],
166+
],
167+
],
168+
],
169+
'poster' => [
170+
'value' => [
171+
'content' => [
172+
[
173+
'type' => 'image_url',
174+
'image_url' => '{{media.poster.poster}}',
175+
],
176+
],
177+
],
178+
],
179+
],
180+
'request' => [
181+
// This request object matches the Voyage API request object
182+
'inputs' => ['{{fragment}}', '{{..}}'],
183+
'model' => 'voyage-multimodal-3',
184+
],
185+
'response' => [
186+
// This response object matches the Voyage API response object
187+
'data' => [
188+
[
189+
'embedding' => '{{embedding}}',
190+
],
191+
'{{..}}',
192+
],
193+
],
194+
];
195+
}
196+
}

tests/assets/master-yoda.jpeg

178 KB
Loading

tests/datasets/movies.json

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
[
2+
{
3+
"id": 11,
4+
"title": "Star Wars",
5+
"overview": "Princess Leia is captured and held hostage by the evil Imperial forces in their effort to take over the galactic Empire. Venturesome Luke Skywalker and dashing captain Han Solo team together with the loveable robot duo R2-D2 and C-3PO to rescue the beautiful princess and restore peace and justice in the Empire.",
6+
"genres": [
7+
"Adventure",
8+
"Action",
9+
"Science Fiction"
10+
],
11+
"poster": "https://image.tmdb.org/t/p/w500/6FfCtAuVAW8XJjZ7eWeLibRLWTw.jpg",
12+
"release_date": 233366400
13+
},
14+
{
15+
"id": 12,
16+
"title": "Finding Nemo",
17+
"overview": "Nemo, an adventurous young clownfish, is unexpectedly taken from his Great Barrier Reef home to a dentist's office aquarium. It's up to his worrisome father Marlin and a friendly but forgetful fish Dory to bring Nemo home -- meeting vegetarian sharks, surfer dude turtles, hypnotic jellyfish, hungry seagulls, and more along the way.",
18+
"genres": [
19+
"Animation",
20+
"Family"
21+
],
22+
"poster": "https://image.tmdb.org/t/p/w500/eHuGQ10FUzK1mdOY69wF5pGgEf5.jpg",
23+
"release_date": 1054252800
24+
},
25+
{
26+
"id": 13,
27+
"title": "Forrest Gump",
28+
"overview": "A man with a low IQ has accomplished great things in his life and been present during significant historic events—in each case, far exceeding what anyone imagined he could do. But despite all he has achieved, his one true love eludes him.",
29+
"genres": [
30+
"Comedy",
31+
"Drama",
32+
"Romance"
33+
],
34+
"poster": "https://image.tmdb.org/t/p/w500/h5J4W4veyxMXDMjeNxZI46TsHOb.jpg",
35+
"release_date": 773452800
36+
},
37+
{
38+
"id": 18,
39+
"title": "The Fifth Element",
40+
"overview": "In 2257, a taxi driver is unintentionally given the task of saving a young girl who is part of the key that will ensure the survival of humanity.",
41+
"genres": [
42+
"Adventure",
43+
"Fantasy",
44+
"Action",
45+
"Thriller",
46+
"Science Fiction"
47+
],
48+
"poster": "https://image.tmdb.org/t/p/w500/fPtlCO1yQtnoLHOwKtWz7db6RGU.jpg",
49+
"release_date": 862531200
50+
},
51+
{
52+
"id": 22,
53+
"title": "Pirates of the Caribbean: The Curse of the Black Pearl",
54+
"overview": "Jack Sparrow, a freewheeling 18th-century pirate, quarrels with a rival pirate bent on pillaging Port Royal. When the governor's daughter is kidnapped, Sparrow decides to help the girl's love save her.",
55+
"genres": [
56+
"Adventure",
57+
"Fantasy",
58+
"Action"
59+
],
60+
"poster": "https://image.tmdb.org/t/p/w500/z8onk7LV9Mmw6zKz4hT6pzzvmvl.jpg",
61+
"release_date": 1057708800
62+
},
63+
{
64+
"id": 24,
65+
"title": "Kill Bill: Vol. 1",
66+
"overview": "An assassin is shot by her ruthless employer, Bill, and other members of their assassination circle – but she lives to plot her vengeance.",
67+
"genres": [
68+
"Action",
69+
"Crime"
70+
],
71+
"poster": "https://image.tmdb.org/t/p/w500/v7TaX8kXMXs5yFFGR41guUDNcnB.jpg",
72+
"release_date": 1065744000
73+
},
74+
{
75+
"id": 35,
76+
"title": "The Simpsons Movie",
77+
"overview": "After Homer accidentally pollutes the town's water supply, Springfield is encased in a gigantic dome by the EPA and the Simpsons are declared fugitives.",
78+
"genres": [
79+
"Animation",
80+
"Comedy",
81+
"Family"
82+
],
83+
"poster": "https://image.tmdb.org/t/p/w500/s3b8TZWwmkYc2KoJ5zk77qB6PzY.jpg",
84+
"release_date": 1185321600
85+
},
86+
{
87+
"id": 62,
88+
"title": "2001: A Space Odyssey",
89+
"overview": "Humanity finds a mysterious object buried beneath the lunar surface and sets off to find its origins with the help of HAL 9000, the world's most advanced super computer.",
90+
"genres": [
91+
"Science Fiction",
92+
"Mystery",
93+
"Adventure"
94+
],
95+
"poster": "https://image.tmdb.org/t/p/w500/ve72VxNqjGM69Uky4WTo2bK6rfq.jpg",
96+
"release_date": -55209600
97+
},
98+
{
99+
"id": 65,
100+
"title": "8 Mile",
101+
"overview": "The setting is Detroit in 1995. The city is divided by 8 Mile, a road that splits the town in half along racial lines. A young white rapper, Jimmy \"B-Rabbit\" Smith Jr. summons strength within himself to cross over these arbitrary boundaries to fulfill his dream of success in hip hop. With his pal Future and the three one third in place, all he has to do is not choke.",
102+
"genres": [
103+
"Music",
104+
"Drama"
105+
],
106+
"poster": "https://image.tmdb.org/t/p/w500/7BmQj8qE1FLuLTf7Xjf9sdIHzoa.jpg",
107+
"release_date": 1036713600
108+
},
109+
{
110+
"id": 81,
111+
"title": "Nausicaä of the Valley of the Wind",
112+
"overview": "After a global war, the seaside kingdom known as the Valley of the Wind remains one of the last strongholds on Earth untouched by a poisonous jungle and the powerful insects that guard it. Led by the courageous Princess Nausicaä, the people of the Valley engage in an epic struggle to restore the bond between humanity and Earth.",
113+
"genres": [
114+
"Adventure",
115+
"Animation",
116+
"Fantasy"
117+
],
118+
"poster": "https://image.tmdb.org/t/p/w500/sIpcATxMrKHRRUJAGI5UIUT7XMG.jpg",
119+
"release_date": 447811200
120+
},
121+
{
122+
"id": 98,
123+
"title": "Gladiator",
124+
"overview": "In the year 180, the death of emperor Marcus Aurelius throws the Roman Empire into chaos. Maximus is one of the Roman army's most capable and trusted generals and a key advisor to the emperor. As Marcus' devious son Commodus ascends to the throne, Maximus is set to be executed. He escapes, but is captured by slave traders. Renamed Spaniard and forced to become a gladiator, Maximus must battle to the death with other men for the amusement of paying audiences.",
125+
"genres": [
126+
"Action",
127+
"Drama",
128+
"Adventure"
129+
],
130+
"poster": "https://image.tmdb.org/t/p/w500/ehGpN04mLJIrSnxcZBMvHeG0eDc.jpg",
131+
"release_date": 957139200
132+
}
133+
]

0 commit comments

Comments
 (0)