Skip to content

Commit a5c6fe3

Browse files
authored
Merge pull request #1167 from awais786/enable-multi-modal
Add support for multi-modal search
2 parents 3747b2e + f4984a9 commit a5c6fe3

File tree

8 files changed

+386
-0
lines changed

8 files changed

+386
-0
lines changed

.code-samples.meilisearch.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,25 @@ get_batch_1: |-
767767
client.get_batch(BATCH_UID)
768768
get_similar_post_1: |-
769769
client.index("INDEX_NAME").get_similar_documents({"id": "TARGET_DOCUMENT_ID", "embedder": "default"})
770+
search_parameter_reference_media_1: |-
771+
client.index('movies_fragments').search(
772+
"a futuristic space movie",
773+
{
774+
"media": {
775+
"textAndPoster": {
776+
"text": "a futuristic space movie",
777+
"image": {
778+
"mime": "image/jpeg",
779+
"data": "BASE64_ENCODED_IMAGE_DATA"
780+
}
781+
}
782+
},
783+
"hybrid": {
784+
"embedder": "multimodal",
785+
"semanticRatio": 1.0
786+
},
787+
}
788+
)
770789
webhooks_get_1: |-
771790
client.get_webhooks()
772791
webhooks_get_single_1: |-

datasets/multimodal_movies.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[
2+
{"id":"287947","title":"Shazam!","poster":"https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview":"A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date":1553299200},
3+
{"id":"299537","title":"Captain Marvel","poster":"https://image.tmdb.org/t/p/w1280/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg","overview":"The story follows Carol Danvers as she becomes one of the universe’s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.","release_date":1551830400},
4+
{"id":"522681","title":"Escape Room","poster":"https://image.tmdb.org/t/p/w1280/8yZAx7tlKRZIg7pJfaPhl00yHIQ.jpg","overview":"Six strangers find themselves in circumstances beyond their control, and must use their wits to survive.","release_date":1546473600},
5+
{"id":"166428","title":"How to Train Your Dragon: The Hidden World","poster":"https://image.tmdb.org/t/p/w1280/xvx4Yhf0DVH8G4LzNISpMfFBDy2.jpg","overview":"As Hiccup fulfills his dream of creating a peaceful dragon utopia, Toothless’ discovery of an untamed, elusive mate draws the Night Fury away. When danger mounts at home and Hiccup’s reign as village chief is tested, both dragon and rider must make impossible decisions to save their kind.","release_date":1546473600},
6+
{"id":"450465","title":"Glass","poster":"https://image.tmdb.org/t/p/w1280/svIDTNUoajS8dLEo7EosxvyAsgJ.jpg","overview":"In a series of escalating encounters, security guard David Dunn uses his supernatural abilities to track Kevin Wendell Crumb, a disturbed man who has twenty-four personalities. Meanwhile, the shadowy presence of Elijah Price emerges as an orchestrator who holds secrets critical to both men.","release_date":1547596800},
7+
{"id":"495925","title":"Doraemon the Movie: Nobita's Treasure Island","poster":"https://image.tmdb.org/t/p/w1280/cmJ71gdZxCqkMUvGwWgSg3MK7pC.jpg","overview":"The story is based on Robert Louis Stevenson's Treasure Island novel.","release_date":1520035200},
8+
{"id":"329996","title":"Dumbo","poster":"https://image.tmdb.org/t/p/w1280/279PwJAcelI4VuBtdzrZASqDPQr.jpg","overview":"A young elephant, whose oversized ears enable him to fly, helps save a struggling circus, but when the circus plans a new venture, Dumbo and his friends discover dark secrets beneath its shiny veneer.","release_date":1553644800},
9+
{"id":"299536","title":"Avengers: Infinity War","poster":"https://image.tmdb.org/t/p/w1280/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg","overview":"As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.","release_date":1524618000}]

meilisearch/client.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,3 +1117,41 @@ def _valid_uuid(uuid: str) -> bool:
11171117
)
11181118
match = uuid4hex.match(uuid)
11191119
return bool(match)
1120+
1121+
def get_experimental_features(self) -> Dict[str, Any]:
1122+
"""Retrieve the current settings for all experimental features.
1123+
1124+
Returns
1125+
-------
1126+
features:
1127+
A dictionary mapping feature names to their enabled/disabled state.
1128+
For example: {"multimodal": True, "vectorStore": False}
1129+
1130+
Raises
1131+
------
1132+
MeilisearchApiError
1133+
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
1134+
"""
1135+
return self.http.get(self.config.paths.experimental_features)
1136+
1137+
def update_experimental_features(self, features: Dict[str, bool]) -> Dict[str, Any]:
1138+
"""Update one or more experimental features.
1139+
1140+
Parameters
1141+
----------
1142+
features:
1143+
A dictionary mapping feature names to booleans.
1144+
For example, {"multimodal": True} to enable multimodal,
1145+
or {"multimodal": True, "vectorStore": False} to update multiple features.
1146+
1147+
Returns
1148+
-------
1149+
features:
1150+
The updated experimental features settings as a dictionary.
1151+
1152+
Raises
1153+
------
1154+
MeilisearchApiError
1155+
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
1156+
"""
1157+
return self.http.patch(self.config.paths.experimental_features, body=features)

meilisearch/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class Paths:
4747
localized_attributes = "localized-attributes"
4848
edit = "edit"
4949
network = "network"
50+
experimental_features = "experimental-features"
5051
webhooks = "webhooks"
5152

5253
def __init__(

meilisearch/models/embedders.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ class RestEmbedder(CamelBase):
167167
Template defining the data Meilisearch sends to the embedder
168168
document_template_max_bytes: Optional[int]
169169
Maximum allowed size of rendered document template (defaults to 400)
170+
indexing_fragments: Optional[Dict[str, Dict[str, Any]]]
171+
Defines how to fragment documents for indexing (multi-modal search).
172+
Fragments can contain complex nested structures (e.g., lists of objects).
173+
search_fragments: Optional[Dict[str, Dict[str, Any]]]
174+
Defines how to fragment search queries (multi-modal search).
175+
Fragments can contain complex nested structures (e.g., lists of objects).
170176
request: Dict[str, Any]
171177
A JSON value representing the request Meilisearch makes to the remote embedder
172178
response: Dict[str, Any]
@@ -185,6 +191,8 @@ class RestEmbedder(CamelBase):
185191
dimensions: Optional[int] = None
186192
document_template: Optional[str] = None
187193
document_template_max_bytes: Optional[int] = None
194+
indexing_fragments: Optional[Dict[str, Dict[str, Any]]] = None
195+
search_fragments: Optional[Dict[str, Dict[str, Any]]] = None
188196
request: Dict[str, Any]
189197
response: Dict[str, Any]
190198
headers: Optional[Dict[str, str]] = None
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""Tests for experimental features API."""
2+
3+
4+
def test_get_experimental_features(client):
5+
"""Test getting experimental features."""
6+
response = client.get_experimental_features()
7+
assert isinstance(response, dict)
8+
# Check that at least one known experimental feature is present
9+
assert "multimodal" in response or "vectorStoreSetting" in response
10+
11+
12+
def test_update_experimental_features(client):
13+
"""Test updating experimental features."""
14+
# Enable multimodal
15+
response = client.update_experimental_features({"multimodal": True})
16+
assert isinstance(response, dict)
17+
assert response.get("multimodal") is True
18+
19+
# Disable multimodal
20+
response = client.update_experimental_features({"multimodal": False})
21+
assert isinstance(response, dict)
22+
assert response.get("multimodal") is False

0 commit comments

Comments
 (0)