# es-search-relevance

Part of **ES**

<!-- intent-backlink:auto -->

> 💡 **Path Selection**: This skill is one implementation path for the following routing skills. If you're unsure which path to take, check the corresponding routing skill:

> - [Run A/B tests for search algorithms](../../intent/es-run-search/SKILL.md)
> - [Optimize search result relevance](../../intent/es-optimize-results/SKILL.md)

# Elasticsearch Relevance Optimization

## Capabilities Overview

| Sub-capability | Models | Calling Mode | Description |
|----------------|--------|--------------|-------------|
| Rerank Documents | ops-bge-reranker-larger, ops-text-reranker-001, ops-qwen3-reranker-0.6b | Synchronous | Reorder search results based on contextual relevance using neural models. |
| Score Multimodal Relevance | ops-mm-reranker-001 | Synchronous | Assess relevance between multimodal queries and documents. |
| Retrieve AB Test Configuration | — | Synchronous | Get configuration details for A/B test experiments. |
| Create AB Test Group | — | Synchronous | Create groups for A/B testing scenarios. |
| Create AB Test Scene | — | Synchronous | Define scenes or scenarios for A/B testing experiments. |
| Create Intervention Dictionary | — | Synchronous | Create dictionaries for search result intervention and optimization. |
| Manage Intervention Dictionary Entry | — | Synchronous | Add, modify, or remove entries in intervention dictionaries. |
| Configure Fine Sort | — | Synchronous | Set up second-level ranking and fine sorting parameters for search results. |
| Configure Algorithm Parameters | — | Synchronous | Configure parameters for search algorithm modules. |
| Create Query Analysis Rule | — | Synchronous | Define rules for interpreting and transforming user queries. |
| Manage Query Processors | — | Synchronous | Create, list, describe, modify, and remove query processors for advanced query analysis. |
| Get Entity Priority Settings | — | Synchronous | Retrieve named entity recognition priority settings from query processors. |
| Manage Search Strategy | — | Synchronous | Create, update, delete, and retrieve search strategy configurations. |

## API Calling Patterns

### Authentication
Use **Bearer Token** authentication as the primary method.

- Include the header: `Authorization: Bearer <your-api-key>`
- Store your API key in the environment variable: `DASHSCOPE_API_KEY`
- Some endpoints may use `OPENSEARCH_API_KEY` or `YOUR_API_KEY`—check the specific service documentation, but `DASHSCOPE_API_KEY` is the most common.

### Service Endpoint
Endpoints follow region-specific patterns:

- **China regions**: `https://opensearch.{region}.aliyuncs.com`  
  Common regions: `cn-hangzhou`, `cn-shanghai`, `cn-beijing`
- **International regions**: `https://opensearch.{region}.aliyuncs.com`  
  Example: `cn-shanghai`
- **AI Search Open Platform**: `http://{workspace}-{id}.platform-{env}-{region}.opensearch.aliyuncs.com`  
  Example: `http://default-0fm.platform-pre-shanghai.opensearch.aliyuncs.com`

Always remove the `http://` or `https://` prefix when configuring SDK endpoints.

### Synchronous API Calls
All functions in this domain use **synchronous** calling patterns:

1. Send a POST/GET/PUT/DELETE request to the appropriate endpoint with required headers (`Authorization`, `Content-Type`)
2. Include parameters in the request body (for POST/PUT) or query string (for GET)
3. Receive a JSON response immediately
4. Parse the `result` field for success data or check error codes if status is not 2xx

No polling or streaming is required—responses are returned in a single round trip.

## Parameter Reference

### Rerank Documents

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|--------|--------|------------|-------------|
| host | string | Yes | — | — | The service endpoint (e.g., `****-hangzhou.opensearch.aliyuncs.com`) |
| workspace_name | string | Yes | — | Example: `default` | The name of the workspace |
| service_id | string | Yes | — | Must be one of: `ops-bge-reranker-larger`, `ops-text-reranker-001`, `ops-qwen3-reranker-0.6b` | The ID of the reranking model to use |
| Content-Type | string | Yes | — | Must be `application/json` | Request content type |
| Authorization | string | Yes | — | Format: `Bearer <your-api-key>` | API key for authentication |
| query | string | Yes | — | — | The search query to score documents against |
| docs | list<string> | Yes | — | Max request body size: 8 MB | List of candidate documents to rerank |

### Score Multimodal Relevance

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|--------|--------|------------|-------------|
| host | string | Yes | — | Example: `****-hangzhou.opensearch.aliyuncs.com` | The service endpoint |
| workspace_name | string | Yes | — | Example: `default` | The name of the workspace |
| service_id | string | Yes | — | Must be `ops-mm-reranker-001` | The built-in service ID |
| query | ContentObject | Yes | — | Provide either `text` or `image` | The query content |
| docs | List[ContentObject] | Yes | — | Max 100 documents | Candidate documents to rank |
| options.resize_method | string | No | `default` | One of: `default`, `crop`, `stretch`, `pad` | Method to resize images before processing |

### Manage Query Processors

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|--------|--------|------------|-------------|
| appGroupIdentity | String | Yes | — | — | The name of the application |
| appId | Integer | Yes | — | — | The ID of the version |
| name | String | Yes (for modify/delete) | — | — | The name of the query analysis rule |
| dryRun | Boolean | No | `false` | — | Specifies whether the request is a dry run |
| domain | String | No | `GENERAL` | One of: `GENERAL`, `ECOMMERCE`, `IT_CONTENT` | The type of the industry |
| indexes | Array | No | `["default"]` | Max length: 100 items | Indexes to which the rule applies |
| processors[] | Object | Yes (for create/modify) | — | — | Features used in the query analysis rule |
| active | Boolean | No | `true` | — | Whether the rule is enabled |

### Manage Intervention Dictionary Entry

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|--------|--------|------------|-------------|
| cmd | string | Yes | — | One of: `add`, `delete` | The operation to perform |
| word | string | Yes | — | — | The intervention entry (query term to match) |
| stopword | boolean | Conditional | — | Required for stopword type | Adds/removes term as stop word |
| alias | array | Conditional | — | Required for synonym type | Synonyms to add |
| correction | string | Conditional | — | Required for correction type | Corrected query to use |
| tokens[].token | string | Conditional | — | Required for NER/term weighting | The term |
| tokens[].weight | integer | Conditional | — | Range: 1–7 | Weight: 7=high, 4=medium, 1=low |
| tokens[].tag | string | Conditional | — | Valid entity tags (e.g., `brand`, `category`) | Internal name of entity type |
| rank | integer | Conditional | — | Range: 1–10 | Position in top search results |
| expirationTime | integer | No | — | Unix timestamp | When the entry expires |

## Code Examples

### Rerank Documents - Bash - All Regions

```bash
curl -X POST \
  "http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/ranker/ops-bge-reranker-larger" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-api-key>" \
  -d '{
    "query": "opensearch documentation",
    "docs": [
      "what is opensearch",
      "what is LLM-based conversational search edition",
      "What is the advantage of LLM-based conversational search edition"
    ]
  }'
```

### Rerank Documents - Python - All Regions

```python
from alibabacloud_tea_openapi.models import Config
from alibabacloud_searchplat20240529.client import Client
from alibabacloud_searchplat20240529.models import GetDocumentRankRequest

config = Config(
    bearer_token="<your-api-key>",
    endpoint="<your-api-endpoint>",
    protocol="http"
)
client = Client(config=config)

request = GetDocumentRankRequest(
    query="When is the Apple earnings call scheduled?",
    docs=[
        "The Mediterranean diet emphasizes fish, olive oil, and fresh vegetables.",
        "Apple's earnings call is scheduled for Thursday, November 2 at 2:00 p.m. PT.",
        "Recent advances in battery technology have extended EV range significantly.",
    ]
)

response = client.get_document_rank("default", "ops-bge-reranker-larger", request)
for item in response.body.result.items:
    print(f"Index: {item.index}  Score: {item.score:.4f}  Document: {request.docs[item.index]}")
```

### Multimodal Reranking - Python - All Regions

```python
from alibabacloud_tea_openapi.models import Config
from alibabacloud_searchplat20240529.client import Client
from alibabacloud_searchplat20240529.models import GetMultiModalRerankerRequest, GetMultiModalRerankerResponse
if __name__ == '__main__': 
    config = Config(bearer_token="OS-****",
                    endpoint="default-0fm.platform-pre-shanghai.opensearch.aliyuncs.com",
                    protocol="http")
    client = Client(config=config)
    
    request = GetMultiModalRerankerRequest()
    request.from_map({"query":{"text":"Does it support data sync through an SDK?"}, "docs":[{"image":"https://img.alicdn.com/imgextra/i1/O1CN01WksnF41hlhBFsXDNB_!!6000000004318-0-tps-1000-1400.jpg"},{"image":"https://img.alicdn.com/imgextra/i1/O1CN01n1sLsF1DoV8KACrpr_!!6000000000263-2-tps-691-547.png"}], "options":{"resize_method":"default"}})
    
    response : GetMultiModalRerankerResponse = client.get_multi_modal_reranker("default", "ops-mm-reranker-001", request)
    print (response.body.request_id)
    print (response.body.result)
    print (response.body.usage)
```

### Create Query Processor - Bash - All Regions

```bash
curl -X POST https://your-endpoint/v4/openapi/app-groups/os_function_test_v1/apps/110157886/query-processors \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
    "name": "query_filter",
    "domain": "GENERAL",
    "indexes": ["default"],
    "processors": [
        {
            "name": "synonym",
            "useSystemDictionary": true
        },
        {
            "name": "stop_word",
            "useSystemDictionary": true,
            "interventionDictionary": "helo"
        }
    ]
}'
```

### List Query Processors - Bash - All Regions

```bash
curl -X GET 'https://your-endpoint/v4/openapi/app-groups/os_function_test_v1/apps/110157886/query-processors' \ 
-H 'Authorization: Bearer $DASHSCOPE_API_KEY'
```

### Delete Search Strategy - Bash - China Region

```bash
curl -X DELETE \
  'https://opensearch.cn-hangzhou.aliyuncs.com/v4/openapi/app-groups/my_app_group_name/apps/110157886/search-strategies/default' \
  -H 'Authorization: Bearer $DASHSCOPE_API_KEY' \
  -H 'Content-Type: application/json'
```

### Get Entity Priority Settings - Python - All Regions

```python
import requests

def list_query_processor_ners(domain='ECOMMERCE'):
    url = f'https://openapi.aliyun.com/v4/openapi/query-processor/ner/default-priorities'
    params = {'domain': domain}
    headers = {
        'Authorization': 'Bearer $DASHSCOPE_API_KEY',
        'Content-Type': 'application/json'
    }
    response = requests.get(url, params=params, headers=headers)
    return response.json()

# Example usage
result = list_query_processor_ners()
print(result)
```

### Rerank Documents - Java - All Regions

```java
package com.aliyun.sample;

import com.aliyun.searchplat20240529.Client;
import com.aliyun.searchplat20240529.models.GetDocumentRankRequest;
import com.aliyun.searchplat20240529.models.GetDocumentRankResponse;
import com.aliyun.teaopenapi.models.Config;

import java.util.Arrays;

public class RankerDemo {
    public static void main(String[] args) throws Exception {
        Config config = new Config();
        config.setBearerToken("your-api-key: OS-****");
        config.setEndpoint("Replace with the API endpoint: ****.opensearch.aliyuncs.com");
        config.setProtocol("http");
        Client client = new Client(config);
        GetDocumentRankRequest request = new GetDocumentRankRequest();
        request.setQuery("");
        String[] docs = {"Application: An application is a user's data configuration set. It includes the data source structure, index schema, and other data property configurations. An application functions as a search service. Document: A document is a searchable unit of structured data. A document contains one or more fields but must have a primary key field. OpenSearch uses the primary key value to identify a unique document. If a primary key is duplicated, the document is overwritten. Field: A field is a component of a document. It contains a field name and field content.","Index: An index is a data structure that speeds up document retrieval. A user can create multiple indexes. Compound index: Lets a user index multiple source fields of text types, such as TEXT and SHORT_TEXT, into a single field. For example, for a forum search that requires searches based on title and comprehensive searches based on both title and body, you can create `title_search` and `default` indexes for the `title` field, and a `default` index for the `body` field. Querying `title_search` then searches by title, while querying `default` searches by both title and body. Default display field: Used to display results. You can also use the `fetch_fields` API parameter to control which fields are returned. Note that setting `fetch_fields` in your program overwrites the application's default display field configuration. If `fetch_fields` is not set, the application's default configuration is used. Tokenization: The process of splitting pushed documents into word groups. The TEXT type is split by retrieval unit. The SHORT_TEXT type is split by single character. For example, for the Chinese phrase for 'Zhejiang University', the TEXT type is split into two terms: 'Zhejiang' and 'University'. The SHORT_TEXT type is split into the four individual characters that form the phrase. Term: A word group after tokenization is called a term.","Index building: After tokenization, an index is built to quickly locate specific documents based on user queries. Search engines typically build two types of linked lists: inverted and forward. Inverted list: A linked list of term-to-document mappings. The `query` clause uses this method for high query efficiency. For example: term1->doc1, doc2, doc3. term2->doc1, doc2. Forward list: A linked list of document-to-field mappings. The `filter` clause uses this method. Its performance is slightly slower than that of inverted lists. For example: doc1->id, type, create_time... Retrieval: The user's query keywords are tokenized. The resulting terms are used to quickly locate documents by searching the inverted list. This process is called retrieval. Retrieval count: The number of documents obtained through retrieval.","Sort expression: A mathematical expression used to control the sorting of documents in search results. It supports basic mathematical operations, mathematical functions, and built-in functions. Rough sort expression: Performs the first round of selection on search results. Because all documents must be traversed (up to a current limit of 1 million), the rough sort expression should be as simple as possible. It should use the most important document attributes, such as text relevance and timeliness for news. A score is calculated for each document based on the expression, and the documents are sorted by score. Fine sort expression: The top N results from the first round are selected for a second, more detailed scoring using the fine sort expression. The final results are sorted based on these scores and returned to the user. Search result summary: Text content is often long. When displaying search results, you can show only a portion of the matching content to help users quickly understand the document's main points. Query analysis: You can configure several analysis rules. Features such as spell check, stop words, and term weights are supported. This lets users better influence search behavior and get a better search experience. "};
        request.setDocs(Arrays.asList(docs));
        GetDocumentRankResponse response = client.getDocumentRank("default","ops-bge-reranker-larger",request);
        System.out.println(response.getStatusCode());
    }
}
```

## Response Format

```json
{
  "request_id": "24B004E0-ADEF-****-879B-F28359BFAD1D",
  "latency": 19,
  "usage": {
    "doc_count": 3
  },
  "result": {
    "scores": [
      { "index": 0, "score": 0.45026873385713345 },
      { "index": 1, "score": 1.1412238544346029E-4 },
      { "index": 2, "score": 8.029784284533197E-5 }
    ]
  }
}
```

**Key Fields**:
- `request_id` — Unique identifier for the API request
- `latency` — Processing time in milliseconds
- `usage.doc_count` — Number of documents processed
- `result.scores[].index` — Original index of the document in the input list
- `result.scores[].score` — Relevance score (higher = more relevant)

### Streaming Chunk Format
Not applicable (all APIs are synchronous).

## Error Handling

| Error Code | Description | Recommended Action |
|------------|-------------|-------------------|
| InvalidParameter | The request contains invalid parameters. Check the request body format and ensure all required fields are present. | Validate request body structure and required fields |
| 400 | Bad Request – The request body is malformed or exceeds 8 MB limit. | Check JSON syntax and ensure request size ≤ 8 MB |
| 401 | Unauthorized – Invalid or missing bearer token in the configuration. | Verify API key and `Authorization` header format |
| 404 | Not Found – The specified model or endpoint does not exist. | Confirm `service_id`, `workspace_name`, and endpoint URL |
| 500 | Internal Server Error – An unexpected error occurred on the server side. | Retry after a short delay; contact support if persistent |
| 429 | Too many requests. Rate limit exceeded. The QPS limit is 20 shared across all Alibaba Cloud accounts and RAM users. | Implement exponential backoff; reduce request frequency |

### Rate Limits & Retry
- **Rerank APIs**: 20 QPS (shared across Alibaba Cloud accounts and RAM users)
- **Query Processor APIs**: 100 QPS per account
- **Intervention Dictionary**: 100 QPS
- **Search Strategy**: 10–100 QPS depending on operation

**Retry Strategy**: Use exponential backoff with jitter. For 429 errors, respect the `Retry-After` header if present. Start with 1s delay, double on each retry (max 30s), up to 3–5 attempts.

## Requirements

- **Python SDK**: `pip install alibabacloud_searchplat20240529>=1.0.0 alibabacloud_tea_openapi>=0.3.0`
- **Java SDK**: `com.aliyun.searchplat20240529: >=1.0.0`
- **Environment Variable**: `export DASHSCOPE_API_KEY=your_api_key_here`
- **Endpoint Configuration**: Remove `http://` prefix when setting SDK endpoint

## FAQ

Q: How do I choose between BGE reranker and Qwen3 reranker?
A: Use `ops-bge-reranker-larger` for general-purpose English/Chinese text reranking with high accuracy. Use `ops-qwen3-reranker-0.6b` for longer context (up to 32k tokens) and multilingual support. Both cost the same (0.002 CNY per 1k tokens).

Q: What's the maximum number of documents I can rerank in one request?
A: There's no hard limit on document count, but the total request body must not exceed 8 MB. For multimodal reranking, you can process up to 100 documents per request.

Q: Why am I getting a 401 Unauthorized error even with a valid API key?
A: Ensure your `Authorization` header uses the exact format: `Bearer <your-api-key>` (with space after "Bearer"). Also verify that your API key has permissions for the OpenSearch AI services.

Q: Can I use these APIs with standard Elasticsearch instances?
A: No—these APIs require the **AI Search Open Platform** or **OpenSearch High-performance Edition** on Alibaba Cloud. Standard Elasticsearch doesn't support these relevance optimization features.

Q: How do I test a query processor without applying it to production?
A: Use the `dryRun=true` parameter when creating or modifying a query processor. This validates the configuration without persisting changes.

## Pricing & Billing

### Billing Model
Per-request billing for all operations. Each API call (including dry runs) counts as one request.

### Price Reference

| Model/Specification | Input Price | Output Price | Other Fees |
|---------------------|-------------|--------------|-----------|
| ops-bge-reranker-larger | 0.002 CNY/1k tokens | 0.002 CNY/1k tokens | — |
| ops-text-reranker-001 | 0.002 CNY/1k tokens | 0.002 CNY/1k tokens | — |
| ops-qwen3-reranker-0.6b | 0.002 CNY/1k tokens | 0.002 CNY/1k tokens | — |
| ops-mm-reranker-001 | 0.002 CNY/1k tokens | 0.002 CNY/1k tokens | 0.000001 CNY/token (image), 0.0000005 CNY/token (text) |
| Query Processor Operations | 0.0001 CNY/call | 0.0001 CNY/call | — |
| Search Strategy Operations | 0.001 CNY/call | 0.001 CNY/call | — |

### Free Tier
- **Rerank APIs**: 1,000 free requests per month (some models)
- **Query Processors**: 1,000 free calls per month
- **Search Strategies**: 1,000 free calls per month
- **Multimodal Reranking**: 1,000 free calls per month

### Usage Limits
- **Token Limits**: 
  - BGE/OpenSearch models: 512 tokens (query + document combined)
  - Qwen3 model: 32k tokens
  - Multimodal: 8 MB request size, 100 documents max
- **Rate Limits**: 10–100 QPS depending on API (see Error Handling section)

### Billing Notes
- Dry run operations are billed as regular requests
- Failed requests (4xx/5xx) still count toward quota and billing
- Image token count in multimodal APIs is calculated automatically based on resolution
- Free tier resets monthly; usage beyond free tier is billed per actual consumption