Skip to content

Commit b371e8c

Browse files
Merge branch 'main' into EXP-247-chats-review
2 parents d73bc25 + 09f6519 commit b371e8c

File tree

17 files changed

+713
-53
lines changed

17 files changed

+713
-53
lines changed

.code-samples.meilisearch.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,11 @@ geosearch_guide_filter_usage_3: |-
685685
-X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
686686
-H 'Content-type:application/json' \
687687
--data-binary '{ "filter": "_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])" }'
688+
geosearch_guide_filter_usage_4: |-
689+
curl \
690+
-X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
691+
-H 'Content-type:application/json' \
692+
--data-binary '{ "filter": "_geoPolygon([45.494181, 9.214024], [45.449484, 9.179175], [45.449486, 9.179177])" }'
688693
geosearch_guide_sort_settings_1: |-
689694
curl \
690695
-X PUT 'MEILISEARCH_URL/indexes/restaurants/settings/sortable-attributes' \
@@ -1596,3 +1601,14 @@ search_parameter_reference_media_1: |-
15961601
}
15971602
}
15981603
}'
1604+
get_vector_store_settings_1: |-
1605+
curl \
1606+
-X GET 'MEILISEARCH_URL/indexes/INDEX_UID/settings/vector-store'
1607+
update_vector_store_settings_1: |-
1608+
curl \
1609+
-X PATCH 'MEILISEARCH_URL/indexes/INDEX_UID/settings/vector-store' \
1610+
-H 'Content-Type: application/json' \
1611+
--data-binary '"experimental"'
1612+
reset_vector_store_settings_1: |-
1613+
curl \
1614+
-X DELETE 'MEILISEARCH_URL/indexes/INDEX_UID/settings/vector-store'
-9.36 KB
Loading
25.5 KB
Loading

docs.json

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
"learn/ai_powered_search/getting_started_with_ai_search",
168168
"learn/ai_powered_search/configure_rest_embedder",
169169
"learn/ai_powered_search/document_template_best_practices",
170+
"learn/ai_powered_search/image_search_with_multimodal_embeddings",
170171
"learn/ai_powered_search/image_search_with_user_provided_embeddings",
171172
"learn/ai_powered_search/search_with_user_provided_embeddings",
172173
"learn/ai_powered_search/retrieve_related_search_results",
@@ -182,6 +183,12 @@
182183
"learn/chat/conversational_search"
183184
]
184185
},
186+
{
187+
"group": "Personalization",
188+
"pages": [
189+
"learn/personalization/search_personalization"
190+
]
191+
},
185192
{
186193
"group": "Self-hosted",
187194
"pages": [
@@ -280,7 +287,8 @@
280287
"learn/indexing/rename_an_index",
281288
"learn/indexing/indexing_best_practices",
282289
"learn/indexing/ram_multithreading_performance",
283-
"learn/indexing/tokenization"
290+
"learn/indexing/tokenization",
291+
"learn/indexing/multilingual-datasets"
284292
]
285293
},
286294
{
@@ -447,9 +455,6 @@
447455
"segment": {
448456
"key": "KIC0Lcb5C9ssRY79dUKPOK8Wq6wLHiUP"
449457
},
450-
"ga4": {
451-
"measurementId": "G-S0LFS24LR2"
452-
},
453458
"gtm": {
454459
"tagId": "GTM-TNSCGVBH"
455460
}
@@ -956,8 +961,44 @@
956961
"destination": "/learn/chat/getting_started_with_chat"
957962
},
958963
{
959-
"source": "learn/ai_powered_search/conversational_search_with_chat",
960-
"destination": "learn/chat/conversational_search"
964+
"source": "/learn/ai_powered_search/conversational_search_with_chat",
965+
"destination": "/learn/chat/conversational_search"
966+
},
967+
{
968+
"source": "/guides/ai/openai",
969+
"destination": "/guides/embedders/openai"
970+
},
971+
{
972+
"source": "/guides/ai/langchain",
973+
"destination": "/guides/langchain"
974+
},
975+
{
976+
"source": "/guides/ai/huggingface",
977+
"destination": "/guides/embedders/huggingface"
978+
},
979+
{
980+
"source": "/guides/ai/cloudflare",
981+
"destination": "/guides/embedders/cloudflare"
982+
},
983+
{
984+
"source": "/guides/ai/cohere",
985+
"destination": "/guides/embedders/cohere"
986+
},
987+
{
988+
"source": "/guides/ai/mistral",
989+
"destination": "/guides/embedders/mistral"
990+
},
991+
{
992+
"source": "/guides/ai/voyage",
993+
"destination": "/guides/embedders/voyage"
994+
},
995+
{
996+
"source": "/guides/integrations/vercel",
997+
"destination": "/guides/vercel"
998+
},
999+
{
1000+
"source": "/guides/back_end/laravel_scout",
1001+
"destination": "/guides/laravel_scout"
9611002
}
9621003
]
9631004
}
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
---
2+
title: Image search with multimodal embeddings
3+
description: This article shows you the main steps for performing multimodal text-to-image searches
4+
---
5+
6+
This guide shows the main steps to search through a database of images using Meilisearch's experimental multimodal embeddings.
7+
8+
## Requirements
9+
10+
- A database of images
11+
- A Meilisearch project
12+
- Access to a multimodal embedding provider (for example, [VoyageAI multimodal embeddings](https://docs.voyageai.com/reference/multimodal-embeddings-api))
13+
14+
## Enable multimodal embeddings
15+
16+
First, enable the `multimodal` experimental feature:
17+
18+
```sh
19+
curl \
20+
-X PATCH 'MEILISEARCH_URL/experimental-features/' \
21+
-H 'Content-Type: application/json' \
22+
--data-binary '{
23+
"multimodal": true
24+
}'
25+
```
26+
27+
You may also enable multimodal in your Meilisearch Cloud project's general settings, under "Experimental features".
28+
29+
## Configure a multimodal embedder
30+
31+
Much like other embedders, multimodal embedders must set their `source` to `rest` and explicitly declare their `url`. Depending on your chosen provider, you may also have to specify `apiKey`.
32+
33+
All multimodal embedders must contain an `indexingFragments` field and a `searchFragments` field. Fragments are sets of embeddings built out of specific parts of document data.
34+
35+
Fragments must follow the structure defined by the REST API of your chosen provider.
36+
37+
### `indexingFragments`
38+
39+
Use `indexingFragments` to tell Meilisearch how to send document data to the provider's API when generating document embeddings.
40+
41+
For example, when using VoyageAI's multimodal model, an indexing fragment might look like this:
42+
43+
```json
44+
"indexingFragments": {
45+
"TEXTUAL_FRAGMENT_NAME": {
46+
"value": {
47+
"content": [
48+
{
49+
"type": "text",
50+
"text": "A document named {{doc.title}} described as {{doc.description}}"
51+
}
52+
]
53+
}
54+
},
55+
"IMAGE_FRAGMENT_NAME": {
56+
"value": {
57+
"content": [
58+
{
59+
"type": "image_url",
60+
"image_url": "{{doc.poster_url}}"
61+
}
62+
]
63+
}
64+
}
65+
}
66+
```
67+
68+
The example above requests Meilisearch to create two sets of embeddings during indexing: one for the textual description of an image, and another for the actual image.
69+
70+
Any JSON string value appearing in a fragment is handled as a Liquid template, where you interpolate document data present in `doc`. In `IMAGE_FRAGMENT_NAME`, that's `image_url` which outputs the plain URL string in the document field `poster_url`. In `TEXT_FRAGMENT_NAME`, `text` contains a longer string contextualizing two document fields, `title` and `description`.
71+
72+
### `searchFragments`
73+
74+
Use `searchFragments` to tell Meilisearch how to send search query data to the chosen provider's REST API when converting them into embeddings:
75+
76+
```json
77+
"searchFragments": {
78+
"USER_TEXT_FRAGMENT": {
79+
"value": {
80+
"content": [
81+
{
82+
"type": "text",
83+
"text": "{{q}}"
84+
}
85+
]
86+
}
87+
},
88+
"USER_SUBMITTED_IMAGE_FRAGMENT": {
89+
"value": {
90+
"content": [
91+
{
92+
"type": "image_base64",
93+
"image_base64": "data:{{media.image.mime}};base64,{{media.image.data}}"
94+
}
95+
]
96+
}
97+
}
98+
}
99+
```
100+
101+
In this example, two modes of search are configured:
102+
103+
1. A textual search based on the `q` parameter, which will be embedded as text
104+
2. An image search based on [data url](https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data) rebuilt from the `image.mime` and `image.data` field in the `media` field of the query
105+
106+
Search fragments have access to data present in the query parameters `media` and `q`.
107+
108+
Each semantic search query for this embedder should match exactly one search fragment of this embedder, so the fragments should each have at least one disambiguating field
109+
110+
### Complete embedder configuration
111+
112+
Your embedder should look similar to this example with all fragments and embedding provider data:
113+
114+
```sh
115+
curl \
116+
-X PATCH 'MEILISEARCH_URL/indexes/INDEX_NAME/settings' \
117+
-H 'Content-Type: application/json' \
118+
--data-binary '{
119+
"embedders": {
120+
"MULTIMODAL_EMBEDDER_NAME": {
121+
"source": "rest",
122+
"url": "https://api.voyageai.com/v1/multimodal-embeddings",
123+
"apiKey": "VOYAGE_API_KEY",
124+
"indexingFragments": {
125+
"TEXTUAL_FRAGMENT_NAME": {
126+
"value": {
127+
"content": [
128+
{
129+
"type": "text",
130+
"text": "A document named {{doc.title}} described as {{doc.description}}"
131+
}
132+
]
133+
}
134+
},
135+
"IMAGE_FRAGMENT_NAME": {
136+
"value": {
137+
"content": [
138+
{
139+
"type": "image_url",
140+
"image_url": "{{doc.poster_url}}"
141+
}
142+
]
143+
}
144+
}
145+
},
146+
"searchFragments": {
147+
"USER_TEXT_FRAGMENT": {
148+
"value": {
149+
"content": [
150+
{
151+
"type": "text",
152+
"text": "{{q}}"
153+
}
154+
]
155+
}
156+
},
157+
"USER_SUBMITTED_IMAGE_FRAGMENT": {
158+
"value": {
159+
"content": [
160+
{
161+
"type": "image_base64",
162+
"image_base64": "data:{{media.image.mime}};base64,{{media.image.data}}"
163+
}
164+
]
165+
}
166+
}
167+
}
168+
}
169+
}
170+
}'
171+
```
172+
173+
## Add documents
174+
175+
Once your embedder is configured, you can [add documents to your index](/learn/getting_started/cloud_quick_start) with the [`/documents` endpoint](/reference/api/documents).
176+
177+
During indexing, Meilisearch will automatically generate multimodal embeddings for each document using the configured `indexingFragments`.
178+
179+
## Perform searches
180+
181+
The final step is to perform searches using different types of content.
182+
183+
### Use text to search for images
184+
185+
Use the following search query to retrieve a mix of documents with images matching the description, documents with and documents containing the specified keywords:
186+
187+
```sh
188+
curl -X POST 'http://localhost:7700/indexes/INDEX_NAME/search' \
189+
-H 'Content-Type: application/json' \
190+
--data-binary '{
191+
"q": "a mountain sunset with snow",
192+
"hybrid": {
193+
"embedder": "MULTIMODAL_EMBEDDER_NAME"
194+
}
195+
}'
196+
```
197+
198+
### Use an image to search for images
199+
200+
You can also use an image to search for other, similar images:
201+
202+
```sh
203+
curl -X POST 'http://localhost:7700/indexes/INDEX_NAME/search' \
204+
-H 'Content-Type: application/json' \
205+
--data-binary '{
206+
"media": {
207+
"image": {
208+
"mime": "image/jpeg",
209+
"data": "<BASE64_ENCODED_IMAGE>"
210+
}
211+
},
212+
"hybrid": {
213+
"embedder": "MULTIMODAL_EMBEDDER_NAME"
214+
}
215+
}'
216+
```
217+
218+
<Tip>
219+
In most cases you will need a GUI interface that allows users to submit their images and converts these images to Base64 format. Creating this is outside the scope of this guide.
220+
</Tip>
221+
222+
## Conclusion
223+
224+
With multimodal embedders you can:
225+
226+
1. Configure Meilisearch to embed both images and queries
227+
2. Add image documents — Meilisearch automatically generates embeddings
228+
3. Accept text or image input from users
229+
4. Run hybrid searches using a mix of textual and input from other types of media, or run pure semantic semantic searches using only non-textual input

learn/async/working_with_tasks.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,17 @@ Meilisearch processes tasks in the order they were added to the queue. You can c
4848

4949
### Monitoring task status in the Meilisearch Cloud interface
5050

51-
Log into your [Meilisearch Cloud](https://meilisearch.com/cloud?utm_campaign=oss&utm_source=docs&utm_medium=tasks-tutorial) account and navigate to your project. Click the "Tasks" link in the project menu:
51+
Log into your [Meilisearch Cloud](https://meilisearch.com/cloud) account and navigate to your project. Click the "Tasks" link in the project menu:
5252

5353
![Meilisearch Cloud menu with "Tasks" highlighted](/assets/images/cloud-tasks-tutorial/01-tasks-menu.png)
5454

55-
This will lead you to the task overview. Look for your request's `taskUid` in the "Uid" column:
55+
This will lead you to the task overview, which shows a list of all batches enqueued, processing, and completed in your project:
5656

5757
![A table listing multiple Meilisearch Cloud tasks](/assets/images/cloud-tasks-tutorial/02-tasks-table.png)
5858

59-
When the task `status` changes to `succeeded`, Meilisearch has finished processing your request.
59+
All Meilisearch tasks are processed in batches. When the batch containing your task changes its `status` to `succeeded`, Meilisearch has finished processing your request.
6060

61-
If the task `status` changes to `failed`, Meilisearch was not able to fulfill your request. Check the task object's `error` field for more information.
61+
If the `status` changes to `failed`, Meilisearch was not able to fulfill your request. Check the object's `error` field for more information.
6262

6363
### Monitoring task status with the Meilisearch API
6464

0 commit comments

Comments
 (0)