Rankers
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:
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
__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. IfNone, a defaultOpenAIChatGeneratorconfigured for JSON output is used. - prompt (
str) – Custom prompt template for reranking. The prompt must include exactly the variablesqueryanddocumentsand 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) – IfTrue, raise when generation or response parsing fails. IfFalse, log the failure and return the input documents in fallback order.
warm_up
Warm up the underlying chat generator.
warm_up_async
Warm up the underlying chat generator on the serving event loop.
close
Release the underlying chat generator's resources.
close_async
Release the underlying chat generator's async resources.
to_dict
Serialize this component to a dictionary.
Returns:
dict[str, Any]– Dictionary with serialized data.
from_dict
Deserialize this component from a dictionary.
Parameters:
- data (
dict[str, Any]) – The dictionary representation of the component.
Returns:
LLMRanker– The deserialized component instance.
run
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'stop_kif provided.
Returns:
dict[str, list[Document]]– A dictionary with the ranked documents under thedocumentskey.
run_async
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'stop_kif provided.
Returns:
dict[str, list[Document]]– A dictionary with the ranked documents under thedocumentskey.
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" for more details.
Usage example:
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
__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
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:
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
__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 aredescending(default) andascending. - 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 undermeta_fieldin the provided documents are strings. For example, if we specifiedmeta_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
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:
- Sorting the Documents by the meta field in descending or ascending order.
- Merging the rankings from the previous component and based on the meta field according to ranking mode and weight.
- 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 aredescending(default) andascending. 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 undermeta_fieldin the provided documents are strings. For example, if we specifiedmeta_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– Iftop_kis not > 0. Ifweightis not in range [0,1]. Ifranking_modeis not 'reciprocal_rank_fusion' or 'linear_score'. Ifsort_orderis not 'ascending' or 'descending'. Ifmeta_value_typeis not 'float', 'int', 'date' orNone.
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
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
__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 thegroup_bykey. - 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
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_byandsubgroup_bymetadata values.