|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: Vector search |
| 4 | +nav_order: 22 |
| 5 | +has_children: false |
| 6 | +has_toc: false |
| 7 | +--- |
| 8 | + |
| 9 | +# Vector search |
| 10 | + |
| 11 | +OpenSearch is a comprehensive search platform that supports a variety of data types, including vectors. OpenSearch vector database functionality is seamlessly integrated with its generic database function. |
| 12 | + |
| 13 | +In OpenSearch, you can generate vector embeddings, store those embeddings in an index, and use them for vector search. Choose one of the following options: |
| 14 | + |
| 15 | +- Generate embeddings using a library of your choice before ingesting them into OpenSearch. Once you ingest vectors into an index, you can perform a vector similarity search on the vector space. For more information, see [Working with embeddings generated outside of OpenSearch](#working-with-embeddings-generated-outside-of-opensearch). |
| 16 | +- Automatically generate embeddings within OpenSearch. To use embeddings for semantic search, the ingested text (the corpus) and the query need to be embedded using the same model. [Neural search]({{site.url}}{{site.baseurl}}/search-plugins/neural-search/) packages this functionality, eliminating the need to manage the internal details. For more information, see [Generating vector embeddings within OpenSearch](#generating-vector-embeddings-in-opensearch). |
| 17 | + |
| 18 | +## Working with embeddings generated outside of OpenSearch |
| 19 | + |
| 20 | +After you generate vector embeddings, upload them to an OpenSearch index and search the index using vector search. For a complete example, see [Example](#example). |
| 21 | + |
| 22 | +### k-NN index |
| 23 | + |
| 24 | +To build a vector database and use vector search, you must specify your index as a [k-NN index]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index/) when creating it by setting `index.knn` to `true`: |
| 25 | + |
| 26 | +```json |
| 27 | +PUT test-index |
| 28 | +{ |
| 29 | + "settings": { |
| 30 | + "index": { |
| 31 | + "knn": true, |
| 32 | + "knn.algo_param.ef_search": 100 |
| 33 | + } |
| 34 | + }, |
| 35 | + "mappings": { |
| 36 | + "properties": { |
| 37 | + "my_vector1": { |
| 38 | + "type": "knn_vector", |
| 39 | + "dimension": 1024, |
| 40 | + "method": { |
| 41 | + "name": "hnsw", |
| 42 | + "space_type": "l2", |
| 43 | + "engine": "nmslib", |
| 44 | + "parameters": { |
| 45 | + "ef_construction": 128, |
| 46 | + "m": 24 |
| 47 | + } |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | +} |
| 53 | +``` |
| 54 | +{% include copy-curl.html %} |
| 55 | + |
| 56 | +### k-NN vector |
| 57 | + |
| 58 | +You must designate the field that will store vectors as a [`knn_vector`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/knn-vector/) field type. OpenSearch supports vectors of up to 16,000 dimensions, each of which is represented as a 32-bit or 16-bit float. |
| 59 | + |
| 60 | +To save storage space, you can use `byte` vectors. For more information, see [Lucene byte vector]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/knn-vector#lucene-byte-vector). |
| 61 | + |
| 62 | +### k-NN vector search |
| 63 | + |
| 64 | +Vector search finds the vectors in your database that are most similar to the query vector. OpenSearch supports the following search methods: |
| 65 | + |
| 66 | +- [Approximate search](#approximate-search) (approximate k-NN, or ANN): Returns approximate nearest neighbors to the query vector. Usually, approximate search algorithms sacrifice indexing speed and search accuracy in exchange for performance benefits such as lower latency, smaller memory footprints, and more scalable search. For most use cases, approximate search is the best option. |
| 67 | + |
| 68 | +- Exact search (exact k-NN): A brute-force, exact k-NN search of vector fields. OpenSearch supports the following types of exact search: |
| 69 | + - [Exact k-NN with scoring script]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-score-script/): Using the k-NN scoring script, you can apply a filter to an index before executing the nearest neighbor search. |
| 70 | + - [Painless extensions]({{site.url}}{{site.baseurl}}/search-plugins/knn/painless-functions/): Adds the distance functions as Painless extensions that you can use in more complex combinations. You can use this method to perform a brute-force, exact k-NN search of an index, which also supports pre-filtering. |
| 71 | + |
| 72 | +### Approximate search |
| 73 | + |
| 74 | +OpenSearch supports several algorithms for approximate vector search, each with its own advantages. For complete documentation, see [Approximate search]({{site.url}}{{site.baseurl}}/search-plugins/knn/approximate-knn/). For more information about the search methods and engines, see [Method definitions]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index/#method-definitions). For method recommendations, see [Choosing the right method]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index/#choosing-the-right-method). |
| 75 | + |
| 76 | +To use approximate vector search, specify one of the following search methods (algorithms) in the `method` parameter: |
| 77 | + |
| 78 | +- Hierarchical Navigable Small World (HNSW) |
| 79 | +- Inverted File System (IVF) |
| 80 | + |
| 81 | +Additionally, specify the engine (library) that implements this method in the `engine` parameter: |
| 82 | + |
| 83 | +- [Non-Metric Space Library (NMSLIB)](https://github.com/nmslib/nmslib) |
| 84 | +- [Facebook AI Similarity Search (Faiss)](https://github.com/facebookresearch/faiss) |
| 85 | +- Lucene |
| 86 | + |
| 87 | +The following table lists the combinations of search methods and libraries supported by the k-NN engine for approximate vector search. |
| 88 | + |
| 89 | +Method | Engine |
| 90 | +:--- | :--- |
| 91 | +HNSW | NMSLIB, Faiss, Lucene |
| 92 | +IVF | Faiss |
| 93 | + |
| 94 | +### Engine recommendations |
| 95 | + |
| 96 | +In general, select NMSLIB or Faiss for large-scale use cases. Lucene is a good option for smaller deployments and offers benefits like smart filtering, where the optimal filtering strategy—pre-filtering, post-filtering, or exact k-NN—is automatically applied depending on the situation. The following table summarizes the differences between each option. |
| 97 | + |
| 98 | +| | NMSLIB/HNSW | Faiss/HNSW | Faiss/IVF | Lucene/HNSW | |
| 99 | +|:---|:---|:---|:---|:---| |
| 100 | +| Max dimensions | 16,000 | 16,000 | 16,000 | 1,024 | |
| 101 | +| Filter | Post-filter | Post-filter | Post-filter | Filter during search | |
| 102 | +| Training required | No | No | Yes | No | |
| 103 | +| Similarity metrics | `l2`, `innerproduct`, `cosinesimil`, `l1`, `linf` | `l2`, `innerproduct` | `l2`, `innerproduct` | `l2`, `cosinesimil` | |
| 104 | +| Number of vectors | Tens of billions | Tens of billions | Tens of billions | Less than 10 million | |
| 105 | +| Indexing latency | Low | Low | Lowest | Low | |
| 106 | +| Query latency and quality | Low latency and high quality | Low latency and high quality | Low latency and low quality | High latency and high quality | |
| 107 | +| Vector compression | Flat | Flat <br>Product quantization | Flat <br>Product quantization | Flat | |
| 108 | +| Memory consumption | High | High <br> Low with PQ | Medium <br> Low with PQ | High | |
| 109 | + |
| 110 | +### Example |
| 111 | + |
| 112 | +In this example, you'll create a k-NN index, add data to the index, and search the data. |
| 113 | + |
| 114 | +#### Step 1: Create a k-NN index |
| 115 | + |
| 116 | +First, create an index that will store sample hotel data. Set `index.knn` to `true` and specify the `location` field as a `knn_vector`: |
| 117 | + |
| 118 | +```json |
| 119 | +PUT /hotels-index |
| 120 | +{ |
| 121 | + "settings": { |
| 122 | + "index": { |
| 123 | + "knn": true, |
| 124 | + "knn.algo_param.ef_search": 100, |
| 125 | + "number_of_shards": 1, |
| 126 | + "number_of_replicas": 0 |
| 127 | + } |
| 128 | + }, |
| 129 | + "mappings": { |
| 130 | + "properties": { |
| 131 | + "location": { |
| 132 | + "type": "knn_vector", |
| 133 | + "dimension": 2, |
| 134 | + "method": { |
| 135 | + "name": "hnsw", |
| 136 | + "space_type": "l2", |
| 137 | + "engine": "lucene", |
| 138 | + "parameters": { |
| 139 | + "ef_construction": 100, |
| 140 | + "m": 16 |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | +} |
| 147 | +``` |
| 148 | +{% include copy-curl.html %} |
| 149 | + |
| 150 | +#### Step 2: Add data to your index |
| 151 | + |
| 152 | +Next, add data to your index. Each document represents a hotel. The `location` field in each document contains a vector specifying the hotel's location: |
| 153 | + |
| 154 | +```json |
| 155 | +POST /_bulk |
| 156 | +{ "index": { "_index": "hotels-index", "_id": "1" } } |
| 157 | +{ "location": [5.2, 4.4] } |
| 158 | +{ "index": { "_index": "hotels-index", "_id": "2" } } |
| 159 | +{ "location": [5.2, 3.9] } |
| 160 | +{ "index": { "_index": "hotels-index", "_id": "3" } } |
| 161 | +{ "location": [4.9, 3.4] } |
| 162 | +{ "index": { "_index": "hotels-index", "_id": "4" } } |
| 163 | +{ "location": [4.2, 4.6] } |
| 164 | +{ "index": { "_index": "hotels-index", "_id": "5" } } |
| 165 | +{ "location": [3.3, 4.5] } |
| 166 | +``` |
| 167 | +{% include copy-curl.html %} |
| 168 | + |
| 169 | +#### Step 3: Search your data |
| 170 | + |
| 171 | +Now search for hotels closest to the pin location `[5, 4]`. This location is labeled `Pin` in the following image. Each hotel is labeled with its document number. |
| 172 | + |
| 173 | + |
| 174 | + |
| 175 | +To search for the top three closest hotels, set `k` to `3`: |
| 176 | + |
| 177 | +```json |
| 178 | +POST /hotels-index/_search |
| 179 | +{ |
| 180 | + "size": 3, |
| 181 | + "query": { |
| 182 | + "knn": { |
| 183 | + "location": { |
| 184 | + "vector": [ |
| 185 | + 5, |
| 186 | + 4 |
| 187 | + ], |
| 188 | + "k": 3 |
| 189 | + } |
| 190 | + } |
| 191 | + } |
| 192 | +} |
| 193 | +``` |
| 194 | +{% include copy-curl.html %} |
| 195 | + |
| 196 | +The response contains the hotels closest to the specified pin location: |
| 197 | + |
| 198 | +```json |
| 199 | +{ |
| 200 | + "took": 1093, |
| 201 | + "timed_out": false, |
| 202 | + "_shards": { |
| 203 | + "total": 1, |
| 204 | + "successful": 1, |
| 205 | + "skipped": 0, |
| 206 | + "failed": 0 |
| 207 | + }, |
| 208 | + "hits": { |
| 209 | + "total": { |
| 210 | + "value": 3, |
| 211 | + "relation": "eq" |
| 212 | + }, |
| 213 | + "max_score": 0.952381, |
| 214 | + "hits": [ |
| 215 | + { |
| 216 | + "_index": "hotels-index", |
| 217 | + "_id": "2", |
| 218 | + "_score": 0.952381, |
| 219 | + "_source": { |
| 220 | + "location": [ |
| 221 | + 5.2, |
| 222 | + 3.9 |
| 223 | + ] |
| 224 | + } |
| 225 | + }, |
| 226 | + { |
| 227 | + "_index": "hotels-index", |
| 228 | + "_id": "1", |
| 229 | + "_score": 0.8333333, |
| 230 | + "_source": { |
| 231 | + "location": [ |
| 232 | + 5.2, |
| 233 | + 4.4 |
| 234 | + ] |
| 235 | + } |
| 236 | + }, |
| 237 | + { |
| 238 | + "_index": "hotels-index", |
| 239 | + "_id": "3", |
| 240 | + "_score": 0.72992706, |
| 241 | + "_source": { |
| 242 | + "location": [ |
| 243 | + 4.9, |
| 244 | + 3.4 |
| 245 | + ] |
| 246 | + } |
| 247 | + } |
| 248 | + ] |
| 249 | + } |
| 250 | +} |
| 251 | +``` |
| 252 | + |
| 253 | +### Vector search with filtering |
| 254 | + |
| 255 | +For information about vector search with filtering, see [k-NN search with filters]({{site.url}}{{site.baseurl}}/search-plugins/knn/filter-search-knn/). |
| 256 | + |
| 257 | +## Generating vector embeddings in OpenSearch |
| 258 | + |
| 259 | +[Neural search]({{site.url}}{{site.baseurl}}/search-plugins/neural-search/) encapsulates the infrastructure needed to perform semantic vector searches. After you integrate an inference (embedding) service, neural search functions like lexical search, accepting a textual query and returning relevant documents. |
| 260 | + |
| 261 | +When you index your data, neural search transforms text into vector embeddings and indexes both the text and its vector embeddings in a vector index. When you use a neural query during search, neural search converts the query text into vector embeddings and uses vector search to return the results. |
| 262 | + |
| 263 | +### Choosing a model |
| 264 | + |
| 265 | +The first step in setting up neural search is choosing a model. You can upload a model to your OpenSearch cluster, use one of the pretrained models provided by OpenSearch, or connect to an externally hosted model. For more information, see [Integrating ML models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/integrating-ml-models/). |
| 266 | + |
| 267 | +### Neural search tutorial |
| 268 | + |
| 269 | +For a step-by-step tutorial, see [Neural search tutorial]({{site.url}}{{site.baseurl}}/search-plugins/neural-search-tutorial/). |
| 270 | + |
| 271 | +### Search methods |
| 272 | + |
| 273 | +Choose one of the following search methods to use your model for neural search: |
| 274 | + |
| 275 | +- [Semantic search]({{site.url}}{{site.baseurl}}/search-plugins/semantic-search/): Uses dense retrieval based on text embedding models to search text data. |
| 276 | + |
| 277 | +- [Hybrid search]({{site.url}}{{site.baseurl}}/search-plugins/hybrid-search/): Combines lexical and neural search to improve search relevance. |
| 278 | + |
| 279 | +- [Multimodal search]({{site.url}}{{site.baseurl}}/search-plugins/multimodal-search/): Uses neural search with multimodal embedding models to search text and image data. |
| 280 | + |
| 281 | +- [Neural sparse search]({{site.url}}{{site.baseurl}}/search-plugins/neural-sparse-search/): Uses neural search with sparse retrieval based on sparse embedding models to search text data. |
| 282 | + |
| 283 | +- [Conversational search]({{site.url}}{{site.baseurl}}/search-plugins/conversational-search/): With conversational search, you can ask questions in natural language, receive a text response, and ask additional clarifying questions. |
0 commit comments