Help Center/ Cloud Search Service/ User Guide/ OpenSearch/ Search and Analytics/ Implementing OpenSearch AI Search with a Search Foundation Model
Updated on 2026-09-20 GMT+08:00

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.
Figure 1 Solution architecture

The overall procedure is as follows:

  1. Prepare the search foundation model and obtain the model service endpoint.
  2. Prepare the OpenSearch cluster and complete the initial configuration.
  3. Register a model group, create a connector, and register and deploy an embedding model.
  4. Create an ingest pipeline and associate it with the embedding model to automatically generate embeddings.
  5. Create an index containing text and vector fields and associate it with the ingest pipeline.
  6. Index documents. The ingest pipeline automatically generates embeddings.
  7. 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

Table 1 Resources and costs

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

Table 2 Procedure

Step

Description

Step 1: Create a Model Group

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.

Step 2: Create a Model Connector

Defines how OpenSearch connects to an external model service.

Step 3: Register and Deploy a Model

Registers a remote model through the connector and deploys it.

Step 4: Test Model Availability

Uses _predict to verify that the model is available.

Step 5: Create an Ingest Pipeline

Creates an ingest pipeline and configures it to automatically invoke the embedding model to generate embeddings when documents are indexed.

Step 6: Create a Vector Index

Creates an index that contains a vector field named knn_vector and a text field.

Step 7: Index Documents

The ingest pipeline automatically generates embeddings when documents are indexed.

Step 8: Perform Semantic Search

Uses the neural query to verify semantic search.

Step 9: Create a Search Pipeline

Creates a search pipeline to normalize, weight, and combine scores from different query clauses. This step is required only for hybrid search.

Step 10: Perform 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 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.

  1. Log in to the CSS management console.
  2. In the navigation pane on the left, choose Clusters > OpenSearch.
  3. In the cluster list, find the target cluster, and click Dashboards in the Operation column to log in to OpenSearch Dashboards.
  4. 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"
}
Table 3 Model group parameters

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"
        }
      ]
    }
Table 4 Connector parameters

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>"
    }
Table 5 Model registration parameters

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"
        }
      }
    }
  ]
}
Table 7 Ingest pipeline parameters

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"
      }
    }
  }
}
Table 8 Parameters for configuring a vector index

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/_search

    Example 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
      }
    }
  }
}
Table 9 Neural query parameters

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" ]
            }
          }
        }
      ]
    }
Table 10 Search pipeline parameters

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: linear mapping, which maps the maximum score to 1, and the minimum score to 0, with other scores scaled proportionally.
  • l2: L2 norm normalization, where each score is divided by the square root of the sum of squared scores.

min_max

combination.technique

Method for combining normalized scores.

The value can be:

  • arithmetic_mean: Weighted arithmetic mean.
  • geometric_mean: Weighted geometric mean.
  • harmonic_mean: Weighted harmonic mean.

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.