Implementing OpenSearch AI Search with a Search Foundation Model
By integrating the embedding capabilities of a search foundation model, OpenSearch can automatically generate embeddings when documents are indexed and perform semantic or hybrid search at query time, combining exact matching with semantic retrieval.
Application Scenarios
Traditional keyword search (BM25) relies on term matching. It cannot understand synonyms, related terms, or semantic relationships. As a result, it may fail to retrieve relevant documents when users phrase queries differently. For example, a user may ask "What should I do if I don't have permission to update a file?", while the relevant document may describe the issue as "the operation is restricted" or "the modification was rejected." Keyword search may fail to match these different expressions.
By integrating the embedding capabilities of a search foundation model, OpenSearch can automatically convert text into vector embeddings when documents are indexed. At query time, it uses semantic search (the neural query) to convert the query text into an embedding and retrieve semantically similar documents, enabling intent-aware search and improving precision and recall. Furthermore, hybrid search combines keyword search with semantic search, delivering more comprehensive search results by combining exact matching with semantic understanding.
OpenSearch AI Search is useful for semantic search use cases such as Retrieval-Augmented Generation (RAG), enterprise document search, e-commerce search, and intelligent question answering.
Solution Architecture
The core components of OpenSearch AI search are as follows:
- Search foundation model: Provides embedding and rerank model services. Three sources are supported: a CSS dedicated search foundation model cluster (under Search Model > Exclusive Clusters, restricted availability), a MaaS service, or an external model service. The model can be accessed through either a private or public network address.
- ML Commons plugin: The built-in machine learning plugin in OpenSearch. It can be used to register external models, create connectors, and manage model groups.
- Connector: Defines how OpenSearch connects to an external model service, including the access protocol, input/output formats, and authentication.
- Ingest pipeline: Automatically invokes the embedding model when documents are indexed and converts text fields into vector embeddings.
- Semantic search (neural search): Automatically invokes the embedding model at query time to convert the query text into a vector embedding and performs k-NN (k-Nearest Neighbors) semantic search.
- Hybrid search: Combines keyword search and semantic search, using a search pipeline to normalize and combine scores and leverage the strengths of both retrieval methods.
The overall procedure is as follows:
- Prepare the search foundation model and obtain the model service endpoint.
- Prepare the OpenSearch cluster and complete the initial configuration.
- Register a model group, create a connector, and register and deploy an embedding model.
- Create an ingest pipeline and associate it with the embedding model to automatically generate embeddings.
- Create an index containing text and vector fields and associate it with the ingest pipeline.
- Index documents. The ingest pipeline automatically generates embeddings.
- Perform semantic search (neural query) and hybrid search (hybrid query).
If the search model is deployed on a private network, we recommend deploying it in the same VPC as the OpenSearch cluster and accessing it through a private address without exposing it to the public network. If the model service is accessed through a public network, use HTTPS and an authentication key to secure communications. Configure the authentication key in the connector's credential field so that only authorized OpenSearch clusters can invoke the model service.
Advantages
- Semantic understanding: Traditional keyword search cannot understand synonyms or semantic relationships. An embedding model converts text into embeddings, enabling intent-aware search and overcoming the limitations of keyword matching.
- Automatic embedding generation: Traditional vector search requires embeddings to be generated and stored in advance. By associating an ingest pipeline with an embedding model, OpenSearch can automatically generate embeddings when documents are indexed, simplifying data processing.
- Dual-path retrieval: Pure semantic search may miss documents containing exact keywords, while pure keyword search lacks semantic understanding. Hybrid search combines both retrieval methods to cover more relevant documents and improve recall.
- Flexible weighting: The weights parameter adjusts the relative contribution of keyword and semantic search to meet different search requirements.
- End-to-end integration: Traditional solutions often require middleware to connect different components and coordinate the model invocation and search processes. This solution uses OpenSearch's native capabilities throughout the process, from model registration and data ingestion to retrieval, reducing integration complexity.
Constraints
- The OpenSearch cluster version must be 3.4.0.
- Each query clause in a hybrid query is executed independently. We recommend using no more than five query clauses to avoid additional performance overhead.
- The dimension of the vector field must match the output dimension of the embedding model.
- The connector's pre_process_function and post_process_function must be correctly set. Otherwise, the connector cannot be integrated with the ingest or search pipeline. These functions do not affect calls to the _predict API.
- Invoking an embedding model when indexing documents increases write latency. Depending on the model response time, the additional latency is approximately 50–200 ms per document. For batch indexing, control the batch size to prevent a backlog in the ingest pipeline.
- Subqueries in a hybrid query are executed independently. Adding more subqueries increases latency. Determine the appropriate value of k and number of subqueries through testing in your production environment.
Resource and Cost Planning
| Resource | Description | Quantity | Billing |
|---|---|---|---|
| Search foundation model | Provides embedding and rerank model services. An exclusive CSS cluster can be accessed through a private network. MaaS or an external model service can be accessed through a private or public network, depending on the deployment. | 1 | Pay-per-use |
| OpenSearch cluster | OpenSearch 3.4.0 cluster running ML Commons and ingest/search pipelines for data indexing and search. | 1 | Pay-per-use |
Operation Procedure
| Step | Description |
|---|---|
| Creates a logical group for the search foundation model. This step is required only when fine-grained access control is required for models in a cluster with security mode enabled. | |
| Defines how OpenSearch connects to an external model service. | |
| Registers a remote model through the connector and deploys it. | |
| Uses _predict to verify that the model is available. | |
| Creates an ingest pipeline and configures it to automatically invoke the embedding model to generate embeddings when documents are indexed. | |
| Creates an index that contains a vector field named knn_vector and a text field. | |
| The ingest pipeline automatically generates embeddings when documents are indexed. | |
| Uses the neural query to verify semantic search. | |
| Creates a search pipeline to normalize, weight, and combine scores from different query clauses. This step is required only for hybrid search. | |
| Uses the hybrid query to combine keyword and semantic search. |
Prerequisites
- You have prepared a search foundation model. The following three sources are supported:
- An exclusive cluster under Search Model on the CSS management console: Set Model Version to text-embedding-rank. The exclusive cluster provides both embedding and rerank models.
Access to exclusive clusters for search foundation models is controlled. To use it, submit a service ticket.
- MaaS: Subscribe to an embedding model and rerank model through the MaaS service and obtain the API endpoint and authentication information.
- External model service: Deploy an embedding model and rerank model yourself. For example, you can deploy an open-source model using vLLM. The model service must provide an OpenAI-compatible /v1/embeddings API.
Regardless of the deployment method, you must record the model service address, port number, model ID (or name), and authentication key. They will be needed when you configure the connector.
- An exclusive cluster under Search Model on the CSS management console: Set Model Version to text-embedding-rank. The exclusive cluster provides both embedding and rerank models.
- An OpenSearch 3.4.0 cluster has been created, and the cluster status is Available.
- If the model service is accessed through a private network, deploy the model service and OpenSearch cluster in the same VPC. Configure inbound security group rules to allow traffic to the model service port and port 9200. The default model service port is 18088 for an exclusive search model cluster. For MaaS or an external model service, use the actual service port. Port 9200 is used for OpenSearch cluster communication. If the model service is accessed through a public network, make sure the OpenSearch cluster have access to the public network.
Logging In to OpenSearch Dashboards
Log in to OpenSearch Dashboards and go to the command execution page. OpenSearch clusters support multiple access methods. This topic uses OpenSearch Dashboards as an example to describe the operation procedures.
- Log in to the CSS management console.
- In the navigation pane on the left, choose Clusters > OpenSearch.
- In the cluster list, find the target cluster, and click Dashboards in the Operation column to log in to OpenSearch Dashboards.
- In the left navigation pane, choose Dev Tools.
The left part of the console is the command input box, and the triangle icon in its upper-right corner is the execution button. The right part shows the execution result.
Step 1: Create a Model Group
A model group usually contains multiple models of the same type, or multiple versions of the same model. Backend roles can be granted access to a model group using the Security plugin for fine-grained permission control.
- For a non-security mode cluster (Security Mode is Disabled), no access control is required. You can skip this step.
- For a security-mode cluster (Security Mode is Enabled), creating a model group is optional. If no model group is created, model access is controlled using the default permissions defined by the ML Commons plugin. If a model group is specified, backend roles can be used to implement fine-grained access control.
Run the following command to create an embedding model group:
POST /_plugins/_ml/model_groups/_register
{
"name": "embedding_model_group",
"description": "A model group for external embedding models"
} | Parameter | Description | Example Value |
|---|---|---|
| name | Custom name of the model group. | embedding_model_group |
| description | Description of the model group. | A model group for external embedding models |
Example response:
{
"model_group_id": "DHCWnZgBEIau0nVrgXDm",
"status": "CREATED"
} Record the returned model_group_id. It will be needed for model registration later.
Step 2: Create a Model Connector
A connector defines how OpenSearch connects to an external model service, including the communication protocol, input/output format, and authentication.
- Run the following command to create an embedding connector:
POST /_plugins/_ml/connectors/_create { "name": "embedding connector", "description": "The connector to public embedding models", "version": 1, "protocol": "http", "parameters": { "endpoint": "<search model address>:<port>, "model": "query2doc" }, "credential": { "api_key": "abc" }, "actions": [ { "action_type": "predict", "method": "POST", "url": "http://${parameters.endpoint}/v1/embeddings", "headers": { "Content-Type": "application/json" }, "request_body": "{ \"input\": ${parameters.input}, \"model\": \"${parameters.model}\" }", "pre_process_function": "connector.pre_process.openai.embedding", "post_process_function": "connector.post_process.openai.embedding" } ] } - Run the following command to create a rerank connector:
POST /_plugins/_ml/connectors/_create { "name": "pangu rerank connector", "description": "The connector to public rerank models", "version": 1, "protocol": "http", "parameters": { "endpoint": "<search model address>:<port>, "model": "rerank", "response_filter": "$.results" }, "credential": { "api_key": "abc" }, "actions": [ { "action_type": "predict", "method": "POST", "url": "http://${parameters.endpoint}/v1/rerank", "headers": { "Content-Type": "application/json" }, "request_body": "{ \"documents\":${parameters.documents}, \"query\": \"${parameters.query}\", \"model\": \"${parameters.model}\", \"top_n\": ${parameters.top_n}}", "pre_process_function": "connector.pre_process.default.rerank", "post_process_function": "connector.post_process.default.rerank" } ] }
| Parameter | Description | Example Value (Embedding) |
|---|---|---|
| name | Custom name of the connector. | pangu embedding connector |
| description | Description of the connector. | The connector to public embedding models |
| protocol | Communication protocol used by the connector to access the model service. The value can be http or https, depending on the protocol supported by the model service. | http |
| parameters.endpoint | Address and port number for accessing the model service, which are obtained from the model service. For an exclusive search model cluster, the default port is 18088. For MaaS or an external model service, the port varies. | 10.10.1.117:18088 |
| parameters.model | Model identifier. For an exclusive search model cluster, use the model version selected during cluster creation. For a MaaS service, use the name of the subscribed model. For an external model service, use the name specified during deployment. | query2doc |
| credential.api_key | Authentication key for connecting to the model service. Required when the model service requires authentication, such as MaaS. Omit this parameter if authentication is not required, for example, an exclusive search model cluster connected via a private network. | abc |
| actions[0].url | Request URL of the model service. The URL references the endpoint defined in parameters.endpoint. | http://${parameters.endpoint}/v1/embeddings |
| actions[0].pre_process_function | Preprocessing function, which converts input data into the format required by the model. | connector.pre_process.openai.embedding |
| actions[0].post_process_function | Postprocessing function, which converts model responses into the format required by OpenSearch. | connector.post_process.openai.embedding |
- pre_process_function and post_process_function must be configured correctly. Otherwise, mismatched input and output formats may cause errors when the connector is integrated with the ingest or search pipeline. For configuration details, see Connector blueprints - OpenSearch Documentation.
- OpenSearch provides built-in OpenAI-compatible preprocessing and postprocessing functions when connecting to embedding and rerank models. If the model service uses a different API format, you can use Painless scripts to customize the processing functions.
Example response:
{
"connector_id": "23CmnZgBEIau0nVrGHCp"
} Record the returned connector_id. It will be needed for model registration later.
Step 3: Register and Deploy a Model
Use the connector to register a remote model and deploy it immediately so that it can be invoked by the ingest and search pipelines.
- Run the following command to register and deploy an embedding model:
POST /_plugins/_ml/models/_register?deploy=true { "name": "embedding model", "function_name": "remote", "model_group_id": "<model group ID>", "description": "embedding model", "connector_id": "<connector ID>" } - Run the following command to register and deploy a rerank model:
POST /_plugins/_ml/models/_register?deploy=true { "name": "rerank model", "function_name": "remote", "model_group_id": "<model group ID>", "description": "rerank model", "connector_id": "<connector ID>" }
| Parameter | Description | Example Value (Embedding) |
|---|---|---|
| deploy | URL parameter, which specifies whether to deploy the model immediately after registration. | true |
| name | Custom display name of the model in OpenSearch. | embedding model |
| function_name | Fixed to remote when accessing an external model service through a connector. | remote |
| model_group_id | Model group ID, that is, model_group_id returned in Step 1: Create a Model Group. This parameter is optional depending on the cluster's security mode setting. For a security-mode cluster, this parameter allows fine-grained model access control. Skip this parameter if security mode is disabled or if no model group is created. | DHCWnZgBEIau0nVrgXDm |
| description | Description of the registered model. | embedding model |
| connector_id | Connector ID, that is, connector_id returned in Step 2: Create a Model Connector. | 23CmnZgBEIau0nVrGHCp |
Example response:
{
"task_id": "cHCxnZgBEIau0nVrb3G_",
"status": "CREATED",
"model_id": "aEJ7P58BSQOU_3XGorlP"
}
Model deployment is an asynchronous operation. After task_id is returned, wait for approximately 1–10 seconds. Then, run GET /_plugins/_ml/tasks/<task_id> to check the deployment task status. If the value of state is COMPLETED, the deployment is complete.
Record the returned model_id. It will be needed when creating an ingest pipeline and performing searches later.
Step 4: Test Model Availability
Use the _predict API to verify that the model is correctly configured, that is, whether it can be reached and whether the output format is as expected.
- Run the following command to test the availability of the embedding model:
POST /_plugins/_ml/models/<model_id>/_predict { "parameters": { "input": ["sun", "sunny"] } }Table 6 Model test parameters Parameter
Description
Example Value
model_id
Model ID, that is, model_id of the embedding model returned in Step 3: Register and Deploy a Model.
aEJ7P58BSQOU_3XGorlP
Example response (partial):
{ "inference_results": [ { "output": [ { "name": "response", "dataAsMap": { "embeddings": [ { "values": [0.0123, -0.0456, 0.0789, ...] } ] } } ] } ] }Result verification: If embeddings in the form of a floating-point number array are returned, the model is correctly configured. You can proceed to the next step. If an error occurs, check the model service endpoint in the connector configuration, and whether inbound security group rules allows the model service port as well as port 9200.
- Run the following command to test the availability of the rerank model:
POST /_plugins/_ml/models/<model_id>/_predict { "parameters": { "query": "Is elementary school math difficult?", "top_n": 4, "documents": [ "Elementary school math mainly covers addition, subtraction, multiplication, and division. It is generally not very difficult and provides a foundation for later study.", "Middle school math introduces algebra and geometry, and becomes gradually more difficult.", "University-level math covers subjects such as calculus and linear algebra and is considerably more difficult.", "Elementary school Chinese mainly covers Pinyin and basic Chinese characters." ] } }Example response:
{ "inference_results": [ { "output": [ { "name": "similarity", "data_type": "FLOAT32", "shape": [ 1 ], "data": [ 0.9980276 ] }, { "name": "similarity", "data_type": "FLOAT32", "shape": [ 1 ], "data": [ 0.5402266 ] }, { "name": "similarity", "data_type": "FLOAT32", "shape": [ 1 ], "data": [ 0.03015741 ] }, { "name": "similarity", "data_type": "FLOAT32", "shape": [ 1 ], "data": [ 0.01433703 ] } ], "status_code": 200 } ] }Result verification: A successful response indicates that the rerank model is correctly configured and you can proceed to the next step.
Step 5: Create an Ingest Pipeline
Create an ingest pipeline that automatically invokes the embedding model when documents are indexed.
Run the following command to create an ingest pipeline named nlp-ingest-pipeline for the embedding model:
PUT /_ingest/pipeline/nlp-ingest-pipeline
{
"description": "A text embedding pipeline",
"processors": [
{
"text_embedding": {
"model_id": "<Embedding model ID>"
"field_map": {
"passage_text": "passage_embedding"
}
}
}
]
} | Parameter | Description | Example Value |
|---|---|---|
| nlp-ingest-pipeline | Custom name of the ingest pipeline. | nlp-ingest-pipeline |
| description | Description of the ingest pipeline. | A text embedding pipeline |
| text_embedding | Fixed processor name of the OpenSearch ingest pipeline. At index time, the pipeline automatically runs the text_embedding processor to convert the text in the passage_text field into an embedding and stores the result in the passage_embedding field. | - |
| model_id | Embedding model ID, that is, model_id of the embedding model returned in Step 3: Register and Deploy a Model. | aEJ7P58BSQOU_3XGorlP |
| field_map | Maps the input text field to the output vector field. In this example, passage_text is converted into an embedding stored in passage_embedding. | {"passage_text": "passage_embedding"} |
Result verification: If the result contains "acknowledged": true, the execution is successful.
Step 6: Create a Vector Index
Create an index containing both vector and text fields, and associate the created ingest pipeline with it as the default pipeline.
Run the following command to create a vector index named my-nlp-index:
PUT /my-nlp-index
{
"settings": {
"index.knn": true,
"default_pipeline": "nlp-ingest-pipeline"
},
"mappings": {
"properties": {
"passage_embedding": {
"type": "knn_vector",
"dimension": 768,
"method": {
"engine": "faiss",
"space_type": "innerproduct",
"name": "hnsw"
}
},
"passage_text": {
"type": "text"
}
}
}
} | Parameter | Description | Example Value |
|---|---|---|
| my-nlp-index | Custom index name. | my-nlp-index |
| index.knn | Whether to enable k-NN search. The value is fixed to true. | true |
| default_pipeline | Associates the index with the ingest pipeline created in Step 5: Create an Ingest Pipeline. At index time, the ingest pipeline automatically invokes the embedding model to convert text into embeddings. | nlp-ingest-pipeline |
| passage_embedding.type | Vector field type. The value is fixed to knn_vector. | knn_vector |
| passage_embedding.dimension | Vector dimension. This value must match the output dimension of the embedding model. | 768 |
| passage_embedding.method.engine | Vector search engine. Select faiss or lucene based on the model and service requirements. | faiss |
| passage_embedding.method.space_type | Distance measurement method. Select l2 (Euclidean distance) or innerproduct (inner product) based on the model and service requirements. When innerproduct is used, the vectors must be normalized first. | innerproduct |
| passage_embedding.method.name | Index algorithm name. The value is fixed to hnsw. | hnsw |
| passage_text.type | Text field type. The value is fixed to text. | text |
Result verification: If the result contains "acknowledged": true, the execution is successful.
Step 7: Index Documents
Write documents to the vector index. Because the index has been associated with the ingest pipeline, you only need to provide the passage_text field. The ingest pipeline will automatically convert text into embeddings.
- Index a single document:
POST /my-nlp-index/_doc/1 { "passage_text": "The system returned error 403: The user does not have administrator privileges. Check the policy permissions configured for the IAM role." } - Index multiple documents in a single batch:
POST /my-nlp-index/_bulk {"index": {"_id": 2}} {"passage_text": "If you cannot save a file or your changes are rejected, check whether you have permission to edit and modify the content."} {"index": {"_id": 3}} {"passage_text": "The Finance Department officially released its financial report for the previous quarter. The report details the company's spending on policy subsidies and tax compliance."} {"index": {"_id": 4}} {"passage_text": "If the system indicates that an update could not be performed due to restrictions, contact the team leader to request permission to modify the content."}
After the documents are indexed, the ingest pipeline automatically invokes the text_embedding processor to generate an embedding for each passage_text field and stores the embedding in passage_embedding. The indexed documents contain both the original passage_text field and the generated passage_embedding vector.
Result verification:
- Run the following command. If the number of returned documents matches the number of indexed documents, indexing was successful.
GET /my-nlp-index/_count - Run the following command to view the indexed documents and vector embeddings and check whether the ingest pipeline has taken effect.
GET /my-nlp-index/_searchExample response (partial):
"hits": { "total": { "value": 4, "relation": "eq" }, "max_score": 1, "hits": [ { "_index": "my-nlp-index-2", "_id": "4", "_score": 1, "_source": { "passage_embedding": [ -0.10803223, -0.31982422, 0.023406982, ...... ], "passage_text": "If the system indicates that an update could not be performed due to restrictions, contact the team leader to request permission to modify the content." } }, ...... ] }passage_text indicates original text, and passage_embedding indicates the generated embeddings.
Step 8: Perform Semantic Search
Use the neural query to perform semantic search. The neural query automatically invokes the embedding model to convert the query text into an embedding and then performs k-NN search.
Run the following command to perform a semantic search:
GET /my-nlp-index/_search
{
"_source": {
"excludes": ["passage_embedding"]
},
"query": {
"neural": {
"passage_embedding": {
"query_text": "What should I do if I don't have permission to update a file?",
"model_id": "<Embedding model ID>",
"k": 1
}
}
}
} | Parameter | Description | Example Value |
|---|---|---|
| _source.excludes | Excludes the vector field from the response to make the search results easier to read. | ["passage_embedding"] |
| neural | Performs semantic search based on vector similarity (nearest neighbor search). passage_embedding indicates the vector field name in the index. | - |
| neural.query_text | Natural-language query text. The embedding model converts the query text into a vector embedding. | What should I do if I don't have permission to update a file |
| neural.model_id | Embedding model ID, that is, model_id of the embedding model returned in Step 3: Register and Deploy a Model. | aEJ7P58BSQOU_3XGorlP |
| neural.k | The number of most relevant documents to retrieve. | 1 |
Example response:
{
"took": 21,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 104.77277,
"hits": [
{
"_index": "my-nlp-index",
"_id": "4",
"_score": 104.77277,
"_source": {
"passage_text": "If the system indicates that an update could not be performed due to restrictions, contact the team leader to request permission to modify the content."
}
},
{
"_index": "my-nlp-index",
"_id": "2",
"_score": 103.32463,
"_source": {
"passage_text": "If you cannot save a file or your changes are rejected, check whether you have permission to edit and modify the content."
}
}
]
}
} Result verification: If semantically relevant results are returned, the semantic search is successful.
Result analysis: As shown in the example response, documents 2 and 4 that are most relevant to the query intent are successfully retrieved. Although these documents do not use exactly the same wording as the query, semantic search can identify them based on their semantic similarity. This is something that traditional keyword search cannot do.
Step 9: Create a Search Pipeline
A search pipeline can be used to process and combine the results of multiple query clauses in a hybrid query.
Two types of processors are available for hybrid search:
- Normalization processor: Normalizes and combines scores from multiple query clauses.
- Score ranker processor: Combines and re-ranks hybrid search results using rank fusion.
For hybrid search, you can add the rerank processor to the search pipeline to process search results in two phases. The normalization processor in phase_results_processors combines the scores of multiple subqueries; and then the rerank processor in response_processors performs second-phase reranking on the combined results.
- Run the following command to create the search pipeline my-search-pipeline using the normalization processor:
PUT /_search/pipeline/my-search-pipeline { "description": "Post processor for hybrid search", "phase_results_processors": [ { "normalization-processor": { "normalization": { "technique": "min_max" }, "combination": { "technique": "arithmetic_mean", "parameters": { "weights": [ 0.3, 0.7 ] } } } } ] } - Run the following command to create the search pipeline my-search-pipeline using the normalization processor and rerank processor:
PUT /_search/pipeline/my-search-pipeline { "description": "Post processor for hybrid search", "phase_results_processors": [ { "normalization-processor": { "normalization": { "technique": "min_max" }, "combination": { "technique": "arithmetic_mean", "parameters": { "weights": [ 0.3, 0.7 ] } } } } ], "response_processors": [ { "rerank": { "ml_opensearch": { "model_id": "<Rerank model ID>" }, "context": { "document_fields": [ "passage_text" ] } } } ] }
| Parameter | Description | Example Value |
|---|---|---|
| my-search-pipeline | Custom name of the search pipeline. | my-search-pipeline |
| description | Description of the search pipeline. | Post processor for hybrid search |
| normalization-processor | Fixed processor name for score normalization and combination. | - |
| normalization.technique | Normalizes the scores of each subquery to the range [0, 1]. Value range:
| min_max |
| combination.technique | Method for combining normalized scores. The value can be:
| arithmetic_mean |
| combination.parameters.weights | Weights assigned to each query clause, expressed as decimal values. The number of weights must match the number of query clauses in the hybrid query, and the order must be the same. For details about how to configure this parameter, see Q1: How do I adjust the weights in a hybrid search when creating a search pipeline?. | [0.3, 0.7] |
| rerank | Fixed processor name used for second-phase reranking. Configured in response_processors, the rerank processor runs after score normalization and combination. | - |
| rerank.ml_opensearch | Fixed configuration block for the rerank processor. | - |
| rerank.ml_opensearch.model_id | Rerank model ID, that is, model_id of the rerank model returned in Step 3: Register and Deploy a Model. | bFJ7P58BSQOU_3XGorlR |
| rerank.context | Rerank context configuration block, which specifies the data source sent to the rerank model. | - |
| rerank.context.document_fields | List of document fields involved in reranking. The rerank model reads text from these fields and scores their semantic relevance with the query. | ["passage_text"] |
Step 10: Perform Hybrid Search
Hybrid search normalizes and combines document scores from different query clauses with configurable weights through a search pipeline, delivering more comprehensive search results. This section introduces several hybrid search options:
- Option 1: Combine keyword search with semantic vector search (search pipeline without a rerank processor) Run the following command to perform a hybrid query that combines keyword search (match) and semantic vector search (neural), and specify the newly created search pipeline using the search_pipeline parameter:
GET /my-nlp-index/_search?search_pipeline=my-search-pipeline { "_source": { "excludes": ["passage_embedding"] }, "query": { "hybrid": { "queries": [ { "match": { "passage_text": "What should I do if I don't have permission to update a file?" } }, { "neural": { "passage_embedding": { "query_text": "What should I do if I don't have permission to update a file?", "model_id": "<Embedding model ID>", "k": 5 } } } ] } } }
Table 11 Hybrid search parameters (match + neural) Parameter
Description
Example Value
search_pipeline
URL parameter that specifies the name of the search pipeline. The value must be the same as the name of the search pipeline specified in Step 9: Create a Search Pipeline. The search pipeline is used to normalize and combine hybrid search results with configurable weights.
You can set a default search pipeline so that you don't have to specify this parameter for every query. For details, see Q2: How do I set a default search pipeline?.
my-search-pipeline
_source.excludes
Excludes the vector field from the response to make the search results easier to read.
["passage_embedding"]
hybrid.queries
An array of one or more query clauses. The scores of these clauses are normalized and combined according to the configured weights. The order of the array corresponds to the order of the weights array in the search pipeline.
-
match
A keyword search clause that performs full-text search based on the BM25 algorithm.
-
match.passage_text
Text field (passage_text) to search.
What should I do if I don't have permission to update a file
neural
Performs semantic search based on vector similarity (nearest neighbor search). passage_embedding indicates the vector field name in the index.
-
neural.passage_embedding.query_text
Natural-language query text. The embedding model converts the query text into a vector embedding.
What should I do if I don't have permission to update a file
neural.passage_embedding.model_id
Embedding model ID, that is, the value of model_id returned in Step 3: Register and Deploy a Model.
aEJ7P58BSQOU_3XGorlP
neural.passage_embedding.k
The number of most relevant documents to retrieve.
5
Example response:
{ "took": 24, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": 1, "hits": [ { "_index": "my-nlp-index", "_id": "4", "_score": 1, "_source": { "passage_text": "If the system indicates that an update could not be performed due to restrictions, contact the team leader to request permission to modify the content." } }, { "_index": "my-nlp-index", "_id": "2", "_score": 0.7050488, "_source": { "passage_text": "If you cannot save a file or your changes are rejected, check whether you have permission to edit and modify the content." } }, { "_index": "my-nlp-index", "_id": "3", "_score": 0.083689965, "_source": { "passage_text": "The Finance Department officially released its financial report for the previous quarter. The report details the company's spending on policy subsidies and tax compliance." } }, { "_index": "my-nlp-index", "_id": "1", "_score": 0.001, "_source": { "passage_text": "The system returned error 403: The user does not have administrator privileges. Check the policy permissions configured for the IAM role." } } ] } }Verification: If the query successfully returns results ranked by normalized combined scores and max_score is 1.0 (the maximum value after min_max normalization), the hybrid search configuration is successful.
Result analysis: When the query is What should I do if I don't have permission to update a file, hybrid search returns four results, as shown in Table 12.
Table 12 Hybrid search ranking (match + neural) Rank
Document ID
Normalized Score
Content Summary
Matching Analysis
1
4
1.0
Document update disallowed. You should request for change and operation permissions.
Strong semantic match with the query, with some keywords matched.
2
2
0.705
Request to save or change the file rejected. Confirm your permission.
Some degree of semantic match with the query, with some keywords matched.
3
3
0.084
The financial report mentions policy subsidies.
Weak keyword matching only; not semantically relevant.
4
1
0.001
System error 403 is returned. Check the policy permissions configured for the IAM role.
Weak keyword matching only; not semantically relevant.
Compared with pure semantic search (Step 8: Perform Semantic Search), hybrid search has the following advantages:
- Retains the advantage of semantic matching: Documents 4 and 2 rank among the top two based on semantic similarity, consistent with the results of pure semantic search.
- Provides complementary recall through keyword matching: Documents 3 and 1 are retrieved because they contain the keyword policy. Although their semantic relevance is low, they broaden the search coverage.
- Ranks results effectively using normalized scores: Semantically irrelevant documents (Documents 3 and 1) receive lower scores and rank at the bottom, balancing recall and precision.
- Option 2: Combine keyword search and exact matching (search pipeline without a rerank processor)
This option only uses the search pipeline to normalize and combine the scores of two text query clauses. Use it if you need to combine multiple text matching strategies without relying on semantic search.
Run the following command to perform a hybrid query that combines keyword search (match) and exact matching (term), and specify the newly created search pipeline using the search_pipeline parameter.GET /my-nlp-index/_search?search_pipeline=my-search-pipeline { "_source": { "excludes": ["passage_embedding"] }, "query": { "hybrid": { "queries": [ { "match": { "passage_text": "Permission" } }, { "term": { "passage_text": { "value": "policy" } } } ] } } }
Table 13 Hybrid query parameters (match + term) Parameter
Description
Example Value
search_pipeline
URL parameter that specifies the name of the search pipeline. The value must be the same as the name of the search pipeline specified in Step 9: Create a Search Pipeline. The search pipeline is used to normalize and combine hybrid search results with configurable weights.
You can set a default search pipeline so that you don't have to specify this parameter for every query. For details, see Q2: How do I set a default search pipeline?.
my-search-pipeline
_source.excludes
Excludes the vector field from the response to make the search results easier to read.
["passage_embedding"]
hybrid.queries
An array of one or more query clauses. The scores of these clauses are normalized and combined according to the configured weights. The order of the array corresponds to the order of the weights array in the search pipeline.
-
match
A keyword search clause that performs full-text search based on the BM25 algorithm.
-
match.passage_text
Text field (passage_text) to search.
Permission
term
An exact matching clause that performs exact term matching on the specified field.
-
term.passage_text.value
passage_text is the name of the text field in the index, and value is the term for exact matching.
policy
Example response:
{ "took": 10, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 3, "relation": "eq" }, "max_score": 1, "hits": [ { "_index": "my-nlp-index", "_id": "1", "_score": 1, "_source": { "passage_text": "The system returned error 403: The user does not have administrator privileges. Check the policy permissions configured for the IAM role." } }, { "_index": "my-nlp-index", "_id": "3", "_score": 0.5, "_source": { "passage_text": "The Finance Department officially released its financial report for the previous quarter. The report details the company's spending on policy subsidies and tax compliance." } }, { "_index": "my-nlp-index", "_id": "4", "_score": 0.3, "_source": { "If the system indicates that an update could not be performed due to restrictions, contact the team leader to request permission to modify the content." } } ] } }Verification: If the query successfully returns results ranked by normalized combined scores and max_score is 1.0, the hybrid search configuration is successful.
Result analysis: When permission (match) and policy (term) are queried, hybrid search returns three results, as shown in the table below.
Table 14 Hybrid search ranking (match + term) Rank
Document ID
Normalized Score
Content Summary
Matching Analysis
1
1
1.0
System error 403 is returned. Check the policy permissions configured for the IAM role.
permission is matched using the match query, and policy is matched using the term query.
2
3
0.5
The financial report mentions policy subsidies.
The term query matches policy, but the match query fails to match permission.
3
4
0.3
Document update disallowed. You should request for change and operation permissions.
The match query matches permission (or authorization which has similar semantics), but the term query fails to match policy.
- Option 3: Combine keyword search with semantic vector search (search pipeline with a rerank processor)
Run the following command to perform a hybrid query that combines keyword search (match) and semantic vector search (neural), and specify the search pipeline with a rerank processor using the search_pipeline parameter:
GET /my-nlp-index/_search?search_pipeline=my-search-pipeline { "_source": { "excludes": ["passage_embedding"] }, "query": { "hybrid": { "queries": [ { "match": { "passage_text": "What should I do if I don't have permission to update a file?" } }, { "neural": { "passage_embedding": { "query_text": "What should I do if I don't have permission to update a file?", "model_id": "<Embedding model ID>", "k": 5 } } } ] } }, "ext": { "rerank": { "query_context": { "query_text": "What should I do if I don't have permission to update a file?" } } } }
Table 15 Description of the rerank parameter in a hybrid query Parameter
Description
Example Value
query_context.query_text
Query value received by the rerank model. It should be the same as the value in query.
What should I do if I don't have permission to update a file
Verification and result analysis: Result ranking is different from when there is no rerank processor, and the _score values also change (the rerank scores have replaced the normalized combined scores).
FAQ
- Q1: How do I adjust the weights in a hybrid search when creating a search pipeline?
Adjust the weights parameter according to the desired balance between semantic and keyword search.
- Prioritize semantic matching: Increase the weight of vector search, for example, [0.2, 0.8]. Use this setting in scenarios with rich synonyms where semantic understanding is prioritized.
- Prioritize keyword matching: Increase the weight of keyword search, for example, [0.7, 0.3]. Use this setting in scenarios where precise term matching is prioritized.
- Balance the two: Set the weights to [0.5, 0.5] to give equal weight to both search methods.
- Q2: How do I set a default search pipeline?
You can set a default search pipeline for an index to avoid specifying the search_pipeline parameter for every query.
Run the following command to set my-search-pipeline as the default search pipeline for the my-nlp-index index:
PUT /my-nlp-index/_settings { "index.search.default_pipeline": "my-search-pipeline" }
After the default search pipeline is set, queries on the index automatically use this search pipeline.
- Q3: What should I do if the "vector dimension mismatch" error is returned during indexing?
Cause: The dimension parameter of the knn_vector field in the index does not match the actual output dimension of the embedding model.
Solution: Use the _predict API to obtain the embedding output and determine its dimension. Then recreate the index and set the dimension parameter to the value that matches the model output dimension.
- Q4: What should I do if the "input/output format mismatch" error is returned for the ingest or search pipeline?
Cause: The connector does not have a pre_process_function or post_process_function, resulting in a mismatch between the input/output format and the format required by the pipeline.
Solution: Add preprocessing and postprocessing functions (connector.pre_process.openai.embedding and connector.post_process.openai.embedding) compatible with the OpenAI format to the connector configuration. If the model service uses a different API format, customize the preprocessing and postprocessing functions using Painless scripts.
Related Documents
- OpenSearch AI Search: Official OpenSearch community documentation for semantic search, including detailed syntax for neural and hybrid queries.
- OpenSearch Machine Learning: Official OpenSearch community documentation for the ML Commons plugin, including the APIs for connectors, model registration, and model deployment.
- CSS Vector Database: Learn about the vector index algorithms and parameter settings supported by CSS.
What is your overall rating for this page?
Thank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot