---
title: "Rankers"
id: rankers-api
description: "Reorders a set of Documents based on their relevance to the query."
slug: "/rankers-api"
---
## llm_ranker
### LLMRanker
Ranks documents for a query using a Large Language Model.
The LLM is expected to return a JSON object containing ranked document indices.
Usage example:
```python
from haystack import Document
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.rankers import LLMRanker
chat_generator = OpenAIChatGenerator(
model="gpt-4.1-mini",
generation_kwargs={
"temperature": 0.0,
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "document_ranking",
"schema": {
"type": "object",
"properties": {
"documents": {
"type": "array",
"items": {
"type": "object",
"properties": {"index": {"type": "integer"}},
"required": ["index"],
"additionalProperties": False,
},
}
},
"required": ["documents"],
"additionalProperties": False,
},
},
},
},
)
ranker = LLMRanker(chat_generator=chat_generator)
documents = [
Document(id="paris", content="Paris is the capital of France."),
Document(id="berlin", content="Berlin is the capital of Germany."),
]
result = ranker.run(query="capital of Germany", documents=documents)
print(result["documents"][0].id)
```
#### __init__
```python
__init__(
*,
chat_generator: ChatGenerator | None = None,
prompt: str = DEFAULT_PROMPT_TEMPLATE,
top_k: int = 10,
raise_on_failure: bool = False
) -> None
```
Initialize the LLMRanker component.
**Parameters:**
- **chat_generator** (ChatGenerator | None) – The chat generator to use for reranking. If `None`, a default `OpenAIChatGenerator` configured for JSON
output is used.
- **prompt** (str) – Custom prompt template for reranking. The prompt must include exactly the variables `query` and
`documents` and instruct the LLM to return ranked 1-based document indices as JSON.
- **top_k** (int) – The maximum number of documents to return.
- **raise_on_failure** (bool) – If `True`, raise when generation or response parsing fails. If `False`, log the failure and return the
input documents in fallback order.
#### warm_up
```python
warm_up() -> None
```
Warm up the underlying chat generator.
#### warm_up_async
```python
warm_up_async() -> None
```
Warm up the underlying chat generator on the serving event loop.
#### close
```python
close() -> None
```
Release the underlying chat generator's resources.
#### close_async
```python
close_async() -> None
```
Release the underlying chat generator's async resources.
#### to_dict
```python
to_dict() -> dict[str, Any]
```
Serialize this component to a dictionary.
**Returns:**
- dict\[str, Any\] – Dictionary with serialized data.
#### from_dict
```python
from_dict(data: dict[str, Any]) -> LLMRanker
```
Deserialize this component from a dictionary.
**Parameters:**
- **data** (dict\[str, Any\]) – The dictionary representation of the component.
**Returns:**
- LLMRanker – The deserialized component instance.
#### run
```python
run(
query: str, documents: list[Document], top_k: int | None = None
) -> dict[str, list[Document]]
```
Rank documents for a query using an LLM.
Before ranking, duplicate documents are removed.
**Parameters:**
- **query** (str) – The query used for reranking.
- **documents** (list\[Document\]) – Candidate documents to rerank.
- **top_k** (int | None) – The maximum number of documents to return. Overrides the instance's `top_k` if provided.
**Returns:**
- dict\[str, list\[Document\]\] – A dictionary with the ranked documents under the `documents` key.
#### run_async
```python
run_async(
query: str, documents: list[Document], top_k: int | None = None
) -> dict[str, list[Document]]
```
Asynchronously rank documents for a query using an LLM.
Before ranking, duplicate documents are removed.
This is the asynchronous version of the `run` method. It has the same parameters and return values
but can be used with `await` in an async code. If the chat generator only implements a synchronous
`run` method, it is executed in a thread to avoid blocking the event loop.
**Parameters:**
- **query** (str) – The query used for reranking.
- **documents** (list\[Document\]) – Candidate documents to rerank.
- **top_k** (int | None) – The maximum number of documents to return. Overrides the instance's `top_k` if provided.
**Returns:**
- dict\[str, list\[Document\]\] – A dictionary with the ranked documents under the `documents` key.
## lost_in_the_middle
### LostInTheMiddleRanker
A LostInTheMiddle Ranker.
Ranks documents based on the 'lost in the middle' order so that the most relevant documents are either at the
beginning or end, while the least relevant are in the middle.
LostInTheMiddleRanker assumes that some prior component in the pipeline has already ranked documents by relevance
and requires no query as input but only documents. It is typically used as the last component before building a
prompt for an LLM to prepare the input context for the LLM.
Lost in the Middle ranking lays out document contents into LLM context so that the most relevant contents are at
the beginning or end of the input context, while the least relevant is in the middle of the context. See the
paper ["Lost in the Middle: How Language Models Use Long Contexts"](https://arxiv.org/abs/2307.03172) for more
details.
Usage example:
```python
from haystack.components.rankers import LostInTheMiddleRanker
from haystack import Document
ranker = LostInTheMiddleRanker()
docs = [Document(content="Paris"), Document(content="Berlin"), Document(content="Madrid")]
result = ranker.run(documents=docs)
for doc in result["documents"]:
print(doc.content)
```
#### __init__
```python
__init__(
word_count_threshold: int | None = None, top_k: int | None = None
) -> None
```
Initialize the LostInTheMiddleRanker.
If 'word_count_threshold' is specified, this ranker includes all documents up until the point where adding
another document would exceed the 'word_count_threshold'. The last document that causes the threshold to
be breached will be included in the resulting list of documents, but all subsequent documents will be
discarded.
**Parameters:**
- **word_count_threshold** (int | None) – The maximum total number of words across all documents selected by the ranker.
- **top_k** (int | None) – The maximum number of documents to return.
#### run
```python
run(
documents: list[Document],
top_k: int | None = None,
word_count_threshold: int | None = None,
) -> dict[str, list[Document]]
```
Reranks documents based on the "lost in the middle" order.
Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
if a score is present.
**Parameters:**
- **documents** (list\[Document\]) – List of Documents to reorder.
- **top_k** (int | None) – The maximum number of documents to return.
- **word_count_threshold** (int | None) – The maximum total number of words across all documents selected by the ranker.
**Returns:**
- dict\[str, list\[Document\]\] – A dictionary with the following keys:
- `documents`: Reranked list of Documents
**Raises:**
- ValueError – If any of the documents is not textual.
## meta_field
### MetaFieldRanker
Ranks Documents based on the value of their specific meta field.
The ranking can be performed in descending order or ascending order.
Usage example:
```python
from haystack import Document
from haystack.components.rankers import MetaFieldRanker
ranker = MetaFieldRanker(meta_field="rating")
docs = [
Document(content="Paris", meta={"rating": 1.3}),
Document(content="Berlin", meta={"rating": 0.7}),
Document(content="Barcelona", meta={"rating": 2.1}),
]
output = ranker.run(documents=docs)
docs = output["documents"]
assert docs[0].content == "Barcelona"
```
#### __init__
```python
__init__(
meta_field: str,
weight: float = 1.0,
top_k: int | None = None,
ranking_mode: Literal[
"reciprocal_rank_fusion", "linear_score"
] = "reciprocal_rank_fusion",
sort_order: Literal["ascending", "descending"] = "descending",
missing_meta: Literal["drop", "top", "bottom"] = "bottom",
meta_value_type: Literal["float", "int", "date"] | None = None,
) -> None
```
Creates an instance of MetaFieldRanker.
**Parameters:**
- **meta_field** (str) – The name of the meta field to rank by.
- **weight** (float) – In range [0,1].
0 disables ranking by a meta field.
0.5 ranking from previous component and based on meta field have the same weight.
1 ranking by a meta field only.
- **top_k** (int | None) – The maximum number of Documents to return per query.
If not provided, the Ranker returns all documents it receives in the new ranking order.
- **ranking_mode** (Literal['reciprocal_rank_fusion', 'linear_score']) – The mode used to combine the Retriever's and Ranker's scores.
Possible values are 'reciprocal_rank_fusion' (default) and 'linear_score'.
Use the 'linear_score' mode only with Retrievers or Rankers that return a score in range [0,1].
- **sort_order** (Literal['ascending', 'descending']) – Whether to sort the meta field by ascending or descending order.
Possible values are `descending` (default) and `ascending`.
- **missing_meta** (Literal['drop', 'top', 'bottom']) – What to do with documents that are missing the sorting metadata field.
Possible values are:
- 'drop' will drop the documents entirely.
- 'top' will place the documents at the top of the metadata-sorted list
(regardless of 'ascending' or 'descending').
- 'bottom' will place the documents at the bottom of metadata-sorted list
(regardless of 'ascending' or 'descending').
- **meta_value_type** (Literal['float', 'int', 'date'] | None) – Parse the meta value into the data type specified before sorting.
This will only work if all meta values stored under `meta_field` in the provided documents are strings.
For example, if we specified `meta_value_type="date"` then for the meta value `"date": "2015-02-01"`
we would parse the string into a datetime object and then sort the documents by date.
The available options are:
- 'float' will parse the meta values into floats.
- 'int' will parse the meta values into integers.
- 'date' will parse the meta values into datetime objects.
- 'None' (default) will do no parsing.
#### run
```python
run(
documents: list[Document],
top_k: int | None = None,
weight: float | None = None,
ranking_mode: (
Literal["reciprocal_rank_fusion", "linear_score"] | None
) = None,
sort_order: Literal["ascending", "descending"] | None = None,
missing_meta: Literal["drop", "top", "bottom"] | None = None,
meta_value_type: Literal["float", "int", "date"] | None = None,
) -> dict[str, Any]
```
Ranks a list of Documents based on the selected meta field by:
1. Sorting the Documents by the meta field in descending or ascending order.
1. Merging the rankings from the previous component and based on the meta field according to ranking mode and
weight.
1. Returning the top-k documents.
Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
if a score is present.
**Parameters:**
- **documents** (list\[Document\]) – Documents to be ranked.
- **top_k** (int | None) – The maximum number of Documents to return per query.
If not provided, the top_k provided at initialization time is used.
- **weight** (float | None) – In range [0,1].
0 disables ranking by a meta field.
0.5 ranking from previous component and based on meta field have the same weight.
1 ranking by a meta field only.
If not provided, the weight provided at initialization time is used.
- **ranking_mode** (Literal['reciprocal_rank_fusion', 'linear_score'] | None) – (optional) The mode used to combine the Retriever's and Ranker's scores.
Possible values are 'reciprocal_rank_fusion' (default) and 'linear_score'.
Use the 'score' mode only with Retrievers or Rankers that return a score in range [0,1].
If not provided, the ranking_mode provided at initialization time is used.
- **sort_order** (Literal['ascending', 'descending'] | None) – Whether to sort the meta field by ascending or descending order.
Possible values are `descending` (default) and `ascending`.
If not provided, the sort_order provided at initialization time is used.
- **missing_meta** (Literal['drop', 'top', 'bottom'] | None) – What to do with documents that are missing the sorting metadata field.
Possible values are:
- 'drop' will drop the documents entirely.
- 'top' will place the documents at the top of the metadata-sorted list
(regardless of 'ascending' or 'descending').
- 'bottom' will place the documents at the bottom of metadata-sorted list
(regardless of 'ascending' or 'descending').
If not provided, the missing_meta provided at initialization time is used.
- **meta_value_type** (Literal['float', 'int', 'date'] | None) – Parse the meta value into the data type specified before sorting.
This will only work if all meta values stored under `meta_field` in the provided documents are strings.
For example, if we specified `meta_value_type="date"` then for the meta value `"date": "2015-02-01"`
we would parse the string into a datetime object and then sort the documents by date.
The available options are:
-'float' will parse the meta values into floats.
-'int' will parse the meta values into integers.
-'date' will parse the meta values into datetime objects.
-'None' (default) will do no parsing.
**Returns:**
- dict\[str, Any\] – A dictionary with the following keys:
- `documents`: List of Documents sorted by the specified meta field.
**Raises:**
- ValueError – If `top_k` is not > 0.
If `weight` is not in range [0,1].
If `ranking_mode` is not 'reciprocal_rank_fusion' or 'linear_score'.
If `sort_order` is not 'ascending' or 'descending'.
If `meta_value_type` is not 'float', 'int', 'date' or `None`.
## meta_field_grouping_ranker
### MetaFieldGroupingRanker
Reorders the documents by grouping them based on metadata keys.
The MetaFieldGroupingRanker can group documents by a primary metadata key `group_by`, and subgroup them with an optional
secondary key, `subgroup_by`.
Within each group or subgroup, it can also sort documents by a metadata key `sort_docs_by`.
The output is a flat list of documents ordered by `group_by` and `subgroup_by` values.
Any documents without a group are placed at the end of the list.
The proper organization of documents helps improve the efficiency and performance of subsequent processing by an LLM.
### Usage example
```python
from haystack.components.rankers import MetaFieldGroupingRanker
from haystack.dataclasses import Document
docs = [
Document(content="Javascript is a popular programming language", meta={"group": "42", "split_id": 7, "subgroup": "subB"}),
Document(content="Python is a popular programming language",meta={"group": "42", "split_id": 4, "subgroup": "subB"}),
Document(content="A chromosome is a package of DNA", meta={"group": "314", "split_id": 2, "subgroup": "subC"}),
Document(content="An octopus has three hearts", meta={"group": "11", "split_id": 2, "subgroup": "subD"}),
Document(content="Java is a popular programming language", meta={"group": "42", "split_id": 3, "subgroup": "subB"})
]
ranker = MetaFieldGroupingRanker(group_by="group",subgroup_by="subgroup", sort_docs_by="split_id")
result = ranker.run(documents=docs)
print(result["documents"])
# >>
# >> Document(id=d665bbc83e52c08c3d8275bccf4f22bf2bfee21c6e77d78794627637355b8ebc,
# >> content: 'Java is a popular programming language', meta: {'group': '42', 'split_id': 3, 'subgroup': 'subB'}),
# >> Document(id=a20b326f07382b3cbf2ce156092f7c93e8788df5d48f2986957dce2adb5fe3c2,
# >> content: 'Python is a popular programming language', meta: {'group': '42', 'split_id': 4, 'subgroup': 'subB'}),
# >> Document(id=ce12919795d22f6ca214d0f161cf870993889dcb146f3bb1b3e1ffdc95be960f,
# >> content: 'Javascript is a popular programming language', meta: {'group': '42', 'split_id': 7, 'subgroup': 'subB'}),
# >> Document(id=d9fc857046c904e5cf790b3969b971b1bbdb1b3037d50a20728fdbf82991aa94,
# >> content: 'A chromosome is a package of DNA', meta: {'group': '314', 'split_id': 2, 'subgroup': 'subC'}),
# >> Document(id=6d3b7bdc13d09aa01216471eb5fb0bfdc53c5f2f3e98ad125ff6b85d3106c9a3,
# >> content: 'An octopus has three hearts', meta: {'group': '11', 'split_id': 2, 'subgroup': 'subD'})
```
#### __init__
```python
__init__(
group_by: str,
subgroup_by: str | None = None,
sort_docs_by: str | None = None,
) -> None
```
Creates an instance of MetaFieldGroupingRanker.
**Parameters:**
- **group_by** ([str) – The metadata key to aggregate the documents by.
- **subgroup_by** (str | None) – The metadata key to aggregate the documents within a group that was created by the
`group_by` key.
- **sort_docs_by** (str | None) – Determines which metadata key is used to sort the documents. If not provided, the
documents within the groups or subgroups are not sorted and are kept in the same order as
they were inserted in the subgroups.
#### run
```python
run(documents: list[Document]) -> dict[str, list[Document]]
```
Groups the provided list of documents based on the `group_by` parameter and optionally the `subgroup_by`.
Before grouping, documents are deduplicated by their id, retaining only the document with the highest score
if a score is present.
The output is a list of documents reordered based on how they were grouped.
**Parameters:**
- **documents** (list\[Document\]) – The list of documents to group.
**Returns:**
- dict\[str, list\[Document\]\] – A dictionary with the following keys:
- documents: The list of documents ordered by the `group_by` and `subgroup_by` metadata values.