Skip to content

Blender Reranker

rankify.models.blender_reranker

BaseRanking

Bases: ABC

An abstract base class for implementing different ranking models.

This class defines the interface for all ranking models, ensuring that all subclasses implement the required methods.

Attributes:

Name Type Description
method str

The name of the ranking method.

model_name str

The name of the model being used for ranking.

api_key str

An optional API key for accessing remote models or services.

Source code in rankify/models/base.py
class BaseRanking(ABC):
    """
    An abstract base class for implementing different ranking models.

    This class defines the interface for all ranking models, ensuring that all subclasses implement the required methods.

    Attributes:
        method (str): The name of the ranking method.
        model_name (str): The name of the model being used for ranking.
        api_key (str, optional): An optional API key for accessing remote models or services.
    """

    @abstractmethod
    def __init__(self, method: str= None, model_name: str= None, api_key: str= None, **kwargs) ->None:
        """
        Initializes the base ranking model.

        Args:
            method (str, optional): The name of the ranking method. Defaults to None.
            model_name (str, optional): The name of the model being used for ranking. Defaults to None.
            api_key (str, optional): An optional API key for accessing remote models or services. Defaults to None.

        Example:
            ```python
            class MyRanking(BaseRanking):
                def __init__(self, method, model_name):
                    super().__init__(method, model_name)
            ```
        """
        pass

    @abstractmethod
    def rank(self, documents: list[Document] ):
        """
        Abstract method to rank a list of documents.

        Args:
            documents (list[Document]): A list of Document instances that need to be ranked.

        Raises:
            NotImplementedError: This method must be implemented by subclasses.

        Example:
            ```python
            class MyRanking(BaseRanking):
                def __init__(self, method, model_name):
                    super().__init__(method, model_name)

                def rank(self, documents):
                    # Ranking implementation here
                    pass
            ```
        """
        pass

__init__(method=None, model_name=None, api_key=None, **kwargs) abstractmethod

Initializes the base ranking model.

Parameters:

Name Type Description Default
method str

The name of the ranking method. Defaults to None.

None
model_name str

The name of the model being used for ranking. Defaults to None.

None
api_key str

An optional API key for accessing remote models or services. Defaults to None.

None
Example
class MyRanking(BaseRanking):
    def __init__(self, method, model_name):
        super().__init__(method, model_name)
Source code in rankify/models/base.py
@abstractmethod
def __init__(self, method: str= None, model_name: str= None, api_key: str= None, **kwargs) ->None:
    """
    Initializes the base ranking model.

    Args:
        method (str, optional): The name of the ranking method. Defaults to None.
        model_name (str, optional): The name of the model being used for ranking. Defaults to None.
        api_key (str, optional): An optional API key for accessing remote models or services. Defaults to None.

    Example:
        ```python
        class MyRanking(BaseRanking):
            def __init__(self, method, model_name):
                super().__init__(method, model_name)
        ```
    """
    pass

rank(documents) abstractmethod

Abstract method to rank a list of documents.

Parameters:

Name Type Description Default
documents list[Document]

A list of Document instances that need to be ranked.

required

Raises:

Type Description
NotImplementedError

This method must be implemented by subclasses.

Example
class MyRanking(BaseRanking):
    def __init__(self, method, model_name):
        super().__init__(method, model_name)

    def rank(self, documents):
        # Ranking implementation here
        pass
Source code in rankify/models/base.py
@abstractmethod
def rank(self, documents: list[Document] ):
    """
    Abstract method to rank a list of documents.

    Args:
        documents (list[Document]): A list of Document instances that need to be ranked.

    Raises:
        NotImplementedError: This method must be implemented by subclasses.

    Example:
        ```python
        class MyRanking(BaseRanking):
            def __init__(self, method, model_name):
                super().__init__(method, model_name)

            def rank(self, documents):
                # Ranking implementation here
                pass
        ```
    """
    pass

Document

Represents a document consisting of a question, answers, and contexts.

Attributes:

Name Type Description
question Question

The question associated with the document.

answers Answer

The answers to the question.

contexts list[Context]

A list of related contexts.

reorder_contexts list[Context] or None

A reordered list of contexts based on relevance.

Source code in rankify/dataset/dataset.py
class Document:
    """
    Represents a document consisting of a question, answers, and contexts.

    Attributes:
        question (Question): The question associated with the document.
        answers (Answer): The answers to the question.
        contexts (list[Context]): A list of related contexts.
        reorder_contexts (list[Context] or None): A reordered list of contexts based on relevance.
    """
    def __init__(self, question: Question, answers: Answer, contexts: list = None , id: int = None) -> None:
        """
        Initializes a Document instance.

        Args:
            question (Question): The question associated with the document.
            answers (Answer): The answers to the question.
            contexts (list[Context], optional): A list of contexts related to the question.

        Example:
            ```python
            q = Question("What is the capital of France?")
            a = Answer(["Paris"])
            c1 = Context(score=0.9, has_answer=True, id=1, title="Paris", text="The capital of France is Paris.")
            c2 = Context(score=0.5, has_answer=False, id=2, title="Berlin", text="Berlin is the capital of Germany.")
            d = Document(question=q, answers=a, contexts=[c1, c2])
            print(d)
            ```
        """
        self.question: Question = question
        self.answers: Answer = answers
        self.contexts: List[Context] = contexts
        self.reorder_contexts: List[Context] = None
        self.id = str(id) 

    @classmethod
    def from_dict(cls, data: dict,n_docs:int=100) -> 'Document':
        """
        Creates a Document instance from a dictionary.

        Args:
            data (dict): A dictionary containing the question, answers, and contexts.
            n_docs (int, optional): The number of contexts to include. Defaults to 100.

        Returns:
            Document: A new Document instance.

        Example:
            ```python
            data = {
                "question": "What is the capital of France?",
                "answers": ["Paris"],
                "ctxs": [
                    {"score": 0.9, "has_answer": True, "id": 1, "title": "Paris", "text": "The capital of France is Paris."},
                    {"score": 0.5, "has_answer": False, "id": 2, "title": "Berlin", "text": "Berlin is the capital of Germany."}
                ]
            }
            d = Document.from_dict(data)
            print(d.question)
            ```
        """
        question = Question(data["question"])
        if "answers" in data:
            answers = Answer(data["answers"])
        else:
            answers =Answer('')

        if "query_id" in data:
            id = data["query_id"]
        else:
            id = None
        contexts = [Context(**ctx) for ctx in data["ctxs"][:n_docs]]
        return cls(question, answers, contexts, id=id)

    def to_dict(self) -> Dict[str, Optional[object]]:
        """
        Converts the document into a dictionary representation.

        Returns:
            dict: A dictionary containing the question, answers, and contexts.
        """
        return {
            "question": self.question.question,
            "answers": self.answers.answers,
            "contexts": [ctx.to_dict() for ctx in self.contexts]
        }
    def to_dict_reoreder(self) -> Dict[str,Optional[object]]:
        return {
            "question" : self.question.question,
            "answers" : self.answers.answers,
            "contexts" : [ctx.to_dict() for ctx in self.reorder_contexts]
        }
    def __str__(self) -> str:
        """
        Returns a string representation of the Document instance.

        Returns:
            str: The formatted document information.

        Example:
            ```python
            d = Document(Question("What is the capital of France?"), Answer(["Paris"]))
            print(d)
            ```
        """
        contexts_str = "\n\n".join([str(ctx) for ctx in self.contexts])
        reorder_contexts_str= ''
        if self.reorder_contexts is not None:
            reorder_contexts_str = "\n\n".join([str(ctx) for ctx in self.reorder_contexts])
        return f"{self.question}\n\n{self.answers}\n\nContext: \n\n{contexts_str}\nReorder contexts: \n\n{reorder_contexts_str}"

__init__(question, answers, contexts=None, id=None)

Initializes a Document instance.

Parameters:

Name Type Description Default
question Question

The question associated with the document.

required
answers Answer

The answers to the question.

required
contexts list[Context]

A list of contexts related to the question.

None
Example
q = Question("What is the capital of France?")
a = Answer(["Paris"])
c1 = Context(score=0.9, has_answer=True, id=1, title="Paris", text="The capital of France is Paris.")
c2 = Context(score=0.5, has_answer=False, id=2, title="Berlin", text="Berlin is the capital of Germany.")
d = Document(question=q, answers=a, contexts=[c1, c2])
print(d)
Source code in rankify/dataset/dataset.py
def __init__(self, question: Question, answers: Answer, contexts: list = None , id: int = None) -> None:
    """
    Initializes a Document instance.

    Args:
        question (Question): The question associated with the document.
        answers (Answer): The answers to the question.
        contexts (list[Context], optional): A list of contexts related to the question.

    Example:
        ```python
        q = Question("What is the capital of France?")
        a = Answer(["Paris"])
        c1 = Context(score=0.9, has_answer=True, id=1, title="Paris", text="The capital of France is Paris.")
        c2 = Context(score=0.5, has_answer=False, id=2, title="Berlin", text="Berlin is the capital of Germany.")
        d = Document(question=q, answers=a, contexts=[c1, c2])
        print(d)
        ```
    """
    self.question: Question = question
    self.answers: Answer = answers
    self.contexts: List[Context] = contexts
    self.reorder_contexts: List[Context] = None
    self.id = str(id) 

from_dict(data, n_docs=100) classmethod

Creates a Document instance from a dictionary.

Parameters:

Name Type Description Default
data dict

A dictionary containing the question, answers, and contexts.

required
n_docs int

The number of contexts to include. Defaults to 100.

100

Returns:

Name Type Description
Document Document

A new Document instance.

Example
data = {
    "question": "What is the capital of France?",
    "answers": ["Paris"],
    "ctxs": [
        {"score": 0.9, "has_answer": True, "id": 1, "title": "Paris", "text": "The capital of France is Paris."},
        {"score": 0.5, "has_answer": False, "id": 2, "title": "Berlin", "text": "Berlin is the capital of Germany."}
    ]
}
d = Document.from_dict(data)
print(d.question)
Source code in rankify/dataset/dataset.py
@classmethod
def from_dict(cls, data: dict,n_docs:int=100) -> 'Document':
    """
    Creates a Document instance from a dictionary.

    Args:
        data (dict): A dictionary containing the question, answers, and contexts.
        n_docs (int, optional): The number of contexts to include. Defaults to 100.

    Returns:
        Document: A new Document instance.

    Example:
        ```python
        data = {
            "question": "What is the capital of France?",
            "answers": ["Paris"],
            "ctxs": [
                {"score": 0.9, "has_answer": True, "id": 1, "title": "Paris", "text": "The capital of France is Paris."},
                {"score": 0.5, "has_answer": False, "id": 2, "title": "Berlin", "text": "Berlin is the capital of Germany."}
            ]
        }
        d = Document.from_dict(data)
        print(d.question)
        ```
    """
    question = Question(data["question"])
    if "answers" in data:
        answers = Answer(data["answers"])
    else:
        answers =Answer('')

    if "query_id" in data:
        id = data["query_id"]
    else:
        id = None
    contexts = [Context(**ctx) for ctx in data["ctxs"][:n_docs]]
    return cls(question, answers, contexts, id=id)

to_dict()

Converts the document into a dictionary representation.

Returns:

Name Type Description
dict Dict[str, Optional[object]]

A dictionary containing the question, answers, and contexts.

Source code in rankify/dataset/dataset.py
def to_dict(self) -> Dict[str, Optional[object]]:
    """
    Converts the document into a dictionary representation.

    Returns:
        dict: A dictionary containing the question, answers, and contexts.
    """
    return {
        "question": self.question.question,
        "answers": self.answers.answers,
        "contexts": [ctx.to_dict() for ctx in self.contexts]
    }

__str__()

Returns a string representation of the Document instance.

Returns:

Name Type Description
str str

The formatted document information.

Example
d = Document(Question("What is the capital of France?"), Answer(["Paris"]))
print(d)
Source code in rankify/dataset/dataset.py
def __str__(self) -> str:
    """
    Returns a string representation of the Document instance.

    Returns:
        str: The formatted document information.

    Example:
        ```python
        d = Document(Question("What is the capital of France?"), Answer(["Paris"]))
        print(d)
        ```
    """
    contexts_str = "\n\n".join([str(ctx) for ctx in self.contexts])
    reorder_contexts_str= ''
    if self.reorder_contexts is not None:
        reorder_contexts_str = "\n\n".join([str(ctx) for ctx in self.reorder_contexts])
    return f"{self.question}\n\n{self.answers}\n\nContext: \n\n{contexts_str}\nReorder contexts: \n\n{reorder_contexts_str}"

BlenderReranker

Bases: BaseRanking

A reranking model that utilizes LLM-Blender's PairRanker to reorder document contexts based on relevance.

This reranker employs pairwise ranking techniques to compare context passages and determine the optimal ranking. The model is based on the LLM-Blender approach for reranking.

Attributes:

Name Type Description
method str

The reranking method name.

blender Blender

The LLM-Blender model used for reranking.

References
  • Jiang, Dongfu, Xiang Ren, and Bill Yuchen Lin. LLM-Blender: Ensembling large language models with pairwise ranking and generative fusion. arXiv preprint (2023).
See Also
  • Reranking: Main interface for reranking models, including BlenderReranker.
Example
from rankify.dataset.dataset import Document, Question, Answer, Context
from rankify.models.reranking import Reranking

question = Question("When did Thomas Edison invent the light bulb?")
answers = Answer(["1879"])
contexts = [
    Context(text="Lightning strike at Seoul National University", id=1),
    Context(text="Thomas Edison invented the light bulb in 1879", id=4),
]
document = Document(question=question, answers=answers, contexts=contexts)

model = Reranking(method="blender_reranker", model_name="PairRM")
model.rank([document])
Notes
  • LLM-Blender’s PairRanker uses pairwise ranking to compare contexts and determine the best order.
  • The model supports flexible reranking across multiple contexts.
  • It is integrated into the Reranking class, meaning users should call Reranking instead of directly instantiating BlenderReranker.
Source code in rankify/models/blender_reranker.py
class BlenderReranker(BaseRanking):
    """
    A reranking model that utilizes LLM-Blender's PairRanker to reorder document contexts based on relevance.

    This reranker employs **pairwise ranking techniques** to compare context passages and determine the optimal ranking.
    The model is based on the **LLM-Blender approach for reranking**.

    Attributes:
        method (str, optional): The reranking method name.
        blender (llm_blender.Blender): The LLM-Blender model used for reranking.

    References:
        - Jiang, Dongfu, Xiang Ren, and Bill Yuchen Lin. *LLM-Blender: Ensembling large language models with pairwise ranking and generative fusion*.
          [arXiv preprint](https://arxiv.org/abs/2306.02561) (2023).

    See Also:
        - `Reranking`: Main interface for reranking models, including `BlenderReranker`.

    Example:
        ```python
        from rankify.dataset.dataset import Document, Question, Answer, Context
        from rankify.models.reranking import Reranking

        question = Question("When did Thomas Edison invent the light bulb?")
        answers = Answer(["1879"])
        contexts = [
            Context(text="Lightning strike at Seoul National University", id=1),
            Context(text="Thomas Edison invented the light bulb in 1879", id=4),
        ]
        document = Document(question=question, answers=answers, contexts=contexts)

        model = Reranking(method="blender_reranker", model_name="PairRM")
        model.rank([document])
        ```

    Notes:
        - LLM-Blender’s PairRanker uses **pairwise ranking** to compare contexts and determine the best order.
        - The model supports **flexible reranking** across multiple contexts.
        - It is **integrated into the `Reranking` class**, meaning users should call `Reranking` instead of directly instantiating `BlenderReranker`.
    """

    def __init__(self, method: str = None, model_name: str = "llm-blender/PairRM", **kwargs):
        """
        Initializes the BlenderReranker for document reranking using LLM-Blender's PairRanker.

        Args:
            method (str, optional): The reranking method name. Defaults to `None`.
            model_name (str, optional): The model name for LLM-Blender's PairRanker. Defaults to `"llm-blender/PairRM"`.
            **kwargs: Additional keyword arguments for configuration.

        Example:
            ```python
            model = BlenderReranker(method="blender_reranker", model_name="PairRM")
            ```
        """
        ranker_config = RankerConfig(
            device="cuda",
            fp16=True,
        )
        self.device = kwargs.get("device", "cuda") 
        self.method = method
        self.blender = llm_blender.Blender() #ranker_config=ranker_config
        self.blender.loadranker(model_name , fp16=True, device=self.device)  # Load the ranker model

    def rank(self, documents: List[Document]) -> List[Document]:
        """
        Reranks the contexts within each document using LLM-Blender's PairRanker.

        Args:
            documents (List[Document]): A list of documents containing contexts to be reranked.

        Returns:
            List[Document]: The documents with reordered contexts.

        Raises:
            ValueError: If no contexts are provided in a document.
            ValueError: If the model returns an invalid ranking result.

        Example:
            ```python
            model = BlenderReranker(method="blender_reranker", model_name="PairRM")
            reranked_documents = model.rank(documents)
            ```
        """
        for document in tqdm(documents, desc="Reranking Documents"):
                document = self._rerank_document(document)
        return documents

    def _rerank_document(self, document: Document) -> Document:
        """
        Reranks a single document's contexts using LLM-Blender's PairRanker.

        Args:
            document (Document): The document instance whose contexts need to be reranked.

        Returns:
            Document: The reranked document with updated `reorder_contexts`.

        Raises:
            ValueError: If no contexts are provided.
            ValueError: If the API returns an invalid ranking.

        Example:
            ```python
            ranked_doc = model._rerank_document(document)
            ```
        """
        # Prepare inputs for LLM-Blender
        input_text = document.question.question  # The query text
        candidate_texts = [ctx.text for ctx in document.contexts]  # Candidate contexts

        # Ensure candidates are provided
        if not candidate_texts:
            raise ValueError("No Context Provide!!!!")

        # Perform reranking
        scores = self.blender.rank([input_text], [candidate_texts], return_scores=True, disable_tqdm=True)
        ranks =get_ranks_from_scores(scores)

        if ranks.size == 0 or len(ranks[0]) != len(candidate_texts):
            raise ValueError("Invalid ranks returned from LLM-Blender.")

        # Map ranks to contexts
        contexts = copy.deepcopy(document.contexts)
        ranked_contexts = []
        for score, idx in zip(scores[0], ranks[0]):
            ctx= contexts[idx-1]
            ctx.score= score
            ranked_contexts.append(ctx)


        # Update the document's reordered contexts
        document.reorder_contexts = ranked_contexts
        return document

__init__(method=None, model_name='llm-blender/PairRM', **kwargs)

Initializes the BlenderReranker for document reranking using LLM-Blender's PairRanker.

Parameters:

Name Type Description Default
method str

The reranking method name. Defaults to None.

None
model_name str

The model name for LLM-Blender's PairRanker. Defaults to "llm-blender/PairRM".

'llm-blender/PairRM'
**kwargs

Additional keyword arguments for configuration.

{}
Example
model = BlenderReranker(method="blender_reranker", model_name="PairRM")
Source code in rankify/models/blender_reranker.py
def __init__(self, method: str = None, model_name: str = "llm-blender/PairRM", **kwargs):
    """
    Initializes the BlenderReranker for document reranking using LLM-Blender's PairRanker.

    Args:
        method (str, optional): The reranking method name. Defaults to `None`.
        model_name (str, optional): The model name for LLM-Blender's PairRanker. Defaults to `"llm-blender/PairRM"`.
        **kwargs: Additional keyword arguments for configuration.

    Example:
        ```python
        model = BlenderReranker(method="blender_reranker", model_name="PairRM")
        ```
    """
    ranker_config = RankerConfig(
        device="cuda",
        fp16=True,
    )
    self.device = kwargs.get("device", "cuda") 
    self.method = method
    self.blender = llm_blender.Blender() #ranker_config=ranker_config
    self.blender.loadranker(model_name , fp16=True, device=self.device)  # Load the ranker model

rank(documents)

Reranks the contexts within each document using LLM-Blender's PairRanker.

Parameters:

Name Type Description Default
documents List[Document]

A list of documents containing contexts to be reranked.

required

Returns:

Type Description
List[Document]

List[Document]: The documents with reordered contexts.

Raises:

Type Description
ValueError

If no contexts are provided in a document.

ValueError

If the model returns an invalid ranking result.

Example
model = BlenderReranker(method="blender_reranker", model_name="PairRM")
reranked_documents = model.rank(documents)
Source code in rankify/models/blender_reranker.py
def rank(self, documents: List[Document]) -> List[Document]:
    """
    Reranks the contexts within each document using LLM-Blender's PairRanker.

    Args:
        documents (List[Document]): A list of documents containing contexts to be reranked.

    Returns:
        List[Document]: The documents with reordered contexts.

    Raises:
        ValueError: If no contexts are provided in a document.
        ValueError: If the model returns an invalid ranking result.

    Example:
        ```python
        model = BlenderReranker(method="blender_reranker", model_name="PairRM")
        reranked_documents = model.rank(documents)
        ```
    """
    for document in tqdm(documents, desc="Reranking Documents"):
            document = self._rerank_document(document)
    return documents