We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
feat: Add embed_meta_fields support to rankers like in Haystack v1
**Is your feature request related to a problem? Please describe.**
We have found that `embed_meta_fields` greatly improves ranking when metadata is relevant while searching. This is a feature that we use a lot from v1 that would be great to also have in v2.

**Describe the solution you'd like**
Add support for `embed_meta_fields` as an init parameter to rankers like `TransformersSimilarityRanker`.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `haystack/components/rankers/transformers_similarity.py`
Content:
```
1 import logging
2 from pathlib import Path
3 from typing import List, Union, Dict, Any, Optional
4 
5 from haystack import ComponentError, Document, component, default_to_dict
6 from haystack.lazy_imports import LazyImport
7 
8 logger = logging.getLogger(__name__)
9 
10 
11 with LazyImport(message="Run 'pip install transformers[torch,sentencepiece]'") as torch_and_transformers_import:
12     import torch
13     from transformers import AutoModelForSequenceClassification, AutoTokenizer
14 
15 
16 @component
17 class TransformersSimilarityRanker:
18     """
19     Ranks Documents based on their similarity to the query.
20     It uses a pre-trained cross-encoder model (from the Hugging Face Hub) to embed the query and the Documents.
21 
22     Usage example:
23     ```
24     from haystack import Document
25     from haystack.components.rankers import TransformersSimilarityRanker
26 
27     ranker = TransformersSimilarityRanker()
28     docs = [Document(content="Paris"), Document(content="Berlin")]
29     query = "City in Germany"
30     output = ranker.run(query=query, documents=docs)
31     docs = output["documents"]
32     assert len(docs) == 2
33     assert docs[0].content == "Berlin"
34     ```
35     """
36 
37     def __init__(
38         self,
39         model_name_or_path: Union[str, Path] = "cross-encoder/ms-marco-MiniLM-L-6-v2",
40         device: str = "cpu",
41         token: Union[bool, str, None] = None,
42         top_k: int = 10,
43     ):
44         """
45         Creates an instance of TransformersSimilarityRanker.
46 
47         :param model_name_or_path: The name or path of a pre-trained cross-encoder model
48             from the Hugging Face Hub.
49         :param device: The torch device (for example, cuda:0, cpu, mps) to which you want to limit model inference.
50         :param token: The API token used to download private models from Hugging Face.
51             If this parameter is set to `True`, the token generated when running
52             `transformers-cli login` (stored in ~/.huggingface) is used.
53         :param top_k: The maximum number of Documents to return per query.
54         """
55         torch_and_transformers_import.check()
56 
57         self.model_name_or_path = model_name_or_path
58         if top_k <= 0:
59             raise ValueError(f"top_k must be > 0, but got {top_k}")
60         self.top_k = top_k
61         self.device = device
62         self.token = token
63         self.model = None
64         self.tokenizer = None
65 
66     def _get_telemetry_data(self) -> Dict[str, Any]:
67         """
68         Data that is sent to Posthog for usage analytics.
69         """
70         return {"model": str(self.model_name_or_path)}
71 
72     def warm_up(self):
73         """
74         Warm up the model and tokenizer used for scoring the Documents.
75         """
76         if self.model_name_or_path and not self.model:
77             self.model = AutoModelForSequenceClassification.from_pretrained(self.model_name_or_path, token=self.token)
78             self.model = self.model.to(self.device)
79             self.model.eval()
80             self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, token=self.token)
81 
82     def to_dict(self) -> Dict[str, Any]:
83         """
84         Serialize this component to a dictionary.
85         """
86         return default_to_dict(
87             self,
88             device=self.device,
89             model_name_or_path=self.model_name_or_path,
90             token=self.token if not isinstance(self.token, str) else None,  # don't serialize valid tokens
91             top_k=self.top_k,
92         )
93 
94     @component.output_types(documents=List[Document])
95     def run(self, query: str, documents: List[Document], top_k: Optional[int] = None):
96         """
97         Returns a list of Documents ranked by their similarity to the given query.
98 
99         :param query: Query string.
100         :param documents: List of Documents.
101         :param top_k: The maximum number of Documents you want the Ranker to return.
102         :return: List of Documents sorted by their similarity to the query with the most similar Documents appearing first.
103         """
104         if not documents:
105             return {"documents": []}
106 
107         if top_k is None:
108             top_k = self.top_k
109 
110         elif top_k <= 0:
111             raise ValueError(f"top_k must be > 0, but got {top_k}")
112 
113         # If a model path is provided but the model isn't loaded
114         if self.model_name_or_path and not self.model:
115             raise ComponentError(
116                 f"The component {self.__class__.__name__} wasn't warmed up. Run 'warm_up()' before calling 'run()'."
117             )
118 
119         query_doc_pairs = [[query, doc.content] for doc in documents]
120         features = self.tokenizer(
121             query_doc_pairs, padding=True, truncation=True, return_tensors="pt"
122         ).to(  # type: ignore
123             self.device
124         )
125         with torch.inference_mode():
126             similarity_scores = self.model(**features).logits.squeeze(dim=1)  # type: ignore
127 
128         _, sorted_indices = torch.sort(similarity_scores, descending=True)
129         ranked_docs = []
130         for sorted_index_tensor in sorted_indices:
131             i = sorted_index_tensor.item()
132             documents[i].score = similarity_scores[i].item()
133             ranked_docs.append(documents[i])
134         return {"documents": ranked_docs[:top_k]}
135
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/haystack/components/rankers/transformers_similarity.py b/haystack/components/rankers/transformers_similarity.py
--- a/haystack/components/rankers/transformers_similarity.py
+++ b/haystack/components/rankers/transformers_similarity.py
@@ -40,6 +40,8 @@
         device: str = "cpu",
         token: Union[bool, str, None] = None,
         top_k: int = 10,
+        meta_fields_to_embed: Optional[List[str]] = None,
+        embedding_separator: str = "\n",
     ):
         """
         Creates an instance of TransformersSimilarityRanker.
@@ -51,6 +53,8 @@
             If this parameter is set to `True`, the token generated when running
             `transformers-cli login` (stored in ~/.huggingface) is used.
         :param top_k: The maximum number of Documents to return per query.
+        :param meta_fields_to_embed: List of meta fields that should be embedded along with the Document content.
+        :param embedding_separator: Separator used to concatenate the meta fields to the Document content.
         """
         torch_and_transformers_import.check()
 
@@ -62,6 +66,8 @@
         self.token = token
         self.model = None
         self.tokenizer = None
+        self.meta_fields_to_embed = meta_fields_to_embed or []
+        self.embedding_separator = embedding_separator
 
     def _get_telemetry_data(self) -> Dict[str, Any]:
         """
@@ -89,6 +95,8 @@
             model_name_or_path=self.model_name_or_path,
             token=self.token if not isinstance(self.token, str) else None,  # don't serialize valid tokens
             top_k=self.top_k,
+            meta_fields_to_embed=self.meta_fields_to_embed,
+            embedding_separator=self.embedding_separator,
         )
 
     @component.output_types(documents=List[Document])
@@ -116,7 +124,14 @@
                 f"The component {self.__class__.__name__} wasn't warmed up. Run 'warm_up()' before calling 'run()'."
             )
 
-        query_doc_pairs = [[query, doc.content] for doc in documents]
+        query_doc_pairs = []
+        for doc in documents:
+            meta_values_to_embed = [
+                str(doc.meta[key]) for key in self.meta_fields_to_embed if key in doc.meta and doc.meta[key]
+            ]
+            text_to_embed = self.embedding_separator.join(meta_values_to_embed + [doc.content or ""])
+            query_doc_pairs.append([query, text_to_embed])
+
         features = self.tokenizer(
             query_doc_pairs, padding=True, truncation=True, return_tensors="pt"
         ).to(  # type: ignore

{"golden_diff": "diff --git a/haystack/components/rankers/transformers_similarity.py b/haystack/components/rankers/transformers_similarity.py\n--- a/haystack/components/rankers/transformers_similarity.py\n+++ b/haystack/components/rankers/transformers_similarity.py\n@@ -40,6 +40,8 @@\n         device: str = \"cpu\",\n         token: Union[bool, str, None] = None,\n         top_k: int = 10,\n+        meta_fields_to_embed: Optional[List[str]] = None,\n+        embedding_separator: str = \"\\n\",\n     ):\n         \"\"\"\n         Creates an instance of TransformersSimilarityRanker.\n@@ -51,6 +53,8 @@\n             If this parameter is set to `True`, the token generated when running\n             `transformers-cli login` (stored in ~/.huggingface) is used.\n         :param top_k: The maximum number of Documents to return per query.\n+        :param meta_fields_to_embed: List of meta fields that should be embedded along with the Document content.\n+        :param embedding_separator: Separator used to concatenate the meta fields to the Document content.\n         \"\"\"\n         torch_and_transformers_import.check()\n \n@@ -62,6 +66,8 @@\n         self.token = token\n         self.model = None\n         self.tokenizer = None\n+        self.meta_fields_to_embed = meta_fields_to_embed or []\n+        self.embedding_separator = embedding_separator\n \n     def _get_telemetry_data(self) -> Dict[str, Any]:\n         \"\"\"\n@@ -89,6 +95,8 @@\n             model_name_or_path=self.model_name_or_path,\n             token=self.token if not isinstance(self.token, str) else None,  # don't serialize valid tokens\n             top_k=self.top_k,\n+            meta_fields_to_embed=self.meta_fields_to_embed,\n+            embedding_separator=self.embedding_separator,\n         )\n \n     @component.output_types(documents=List[Document])\n@@ -116,7 +124,14 @@\n                 f\"The component {self.__class__.__name__} wasn't warmed up. Run 'warm_up()' before calling 'run()'.\"\n             )\n \n-        query_doc_pairs = [[query, doc.content] for doc in documents]\n+        query_doc_pairs = []\n+        for doc in documents:\n+            meta_values_to_embed = [\n+                str(doc.meta[key]) for key in self.meta_fields_to_embed if key in doc.meta and doc.meta[key]\n+            ]\n+            text_to_embed = self.embedding_separator.join(meta_values_to_embed + [doc.content or \"\"])\n+            query_doc_pairs.append([query, text_to_embed])\n+\n         features = self.tokenizer(\n             query_doc_pairs, padding=True, truncation=True, return_tensors=\"pt\"\n         ).to(  # type: ignore\n", "issue": "feat: Add embed_meta_fields support to rankers like in Haystack v1\n**Is your feature request related to a problem? Please describe.**\r\nWe have found that `embed_meta_fields` greatly improves ranking when metadata is relevant while searching. This is a feature that we use a lot from v1 that would be great to also have in v2.\r\n\r\n**Describe the solution you'd like**\r\nAdd support for `embed_meta_fields` as an init parameter to rankers like `TransformersSimilarityRanker`.\r\n\n", "before_files": [{"content": "import logging\nfrom pathlib import Path\nfrom typing import List, Union, Dict, Any, Optional\n\nfrom haystack import ComponentError, Document, component, default_to_dict\nfrom haystack.lazy_imports import LazyImport\n\nlogger = logging.getLogger(__name__)\n\n\nwith LazyImport(message=\"Run 'pip install transformers[torch,sentencepiece]'\") as torch_and_transformers_import:\n    import torch\n    from transformers import AutoModelForSequenceClassification, AutoTokenizer\n\n\n@component\nclass TransformersSimilarityRanker:\n    \"\"\"\n    Ranks Documents based on their similarity to the query.\n    It uses a pre-trained cross-encoder model (from the Hugging Face Hub) to embed the query and the Documents.\n\n    Usage example:\n    ```\n    from haystack import Document\n    from haystack.components.rankers import TransformersSimilarityRanker\n\n    ranker = TransformersSimilarityRanker()\n    docs = [Document(content=\"Paris\"), Document(content=\"Berlin\")]\n    query = \"City in Germany\"\n    output = ranker.run(query=query, documents=docs)\n    docs = output[\"documents\"]\n    assert len(docs) == 2\n    assert docs[0].content == \"Berlin\"\n    ```\n    \"\"\"\n\n    def __init__(\n        self,\n        model_name_or_path: Union[str, Path] = \"cross-encoder/ms-marco-MiniLM-L-6-v2\",\n        device: str = \"cpu\",\n        token: Union[bool, str, None] = None,\n        top_k: int = 10,\n    ):\n        \"\"\"\n        Creates an instance of TransformersSimilarityRanker.\n\n        :param model_name_or_path: The name or path of a pre-trained cross-encoder model\n            from the Hugging Face Hub.\n        :param device: The torch device (for example, cuda:0, cpu, mps) to which you want to limit model inference.\n        :param token: The API token used to download private models from Hugging Face.\n            If this parameter is set to `True`, the token generated when running\n            `transformers-cli login` (stored in ~/.huggingface) is used.\n        :param top_k: The maximum number of Documents to return per query.\n        \"\"\"\n        torch_and_transformers_import.check()\n\n        self.model_name_or_path = model_name_or_path\n        if top_k <= 0:\n            raise ValueError(f\"top_k must be > 0, but got {top_k}\")\n        self.top_k = top_k\n        self.device = device\n        self.token = token\n        self.model = None\n        self.tokenizer = None\n\n    def _get_telemetry_data(self) -> Dict[str, Any]:\n        \"\"\"\n        Data that is sent to Posthog for usage analytics.\n        \"\"\"\n        return {\"model\": str(self.model_name_or_path)}\n\n    def warm_up(self):\n        \"\"\"\n        Warm up the model and tokenizer used for scoring the Documents.\n        \"\"\"\n        if self.model_name_or_path and not self.model:\n            self.model = AutoModelForSequenceClassification.from_pretrained(self.model_name_or_path, token=self.token)\n            self.model = self.model.to(self.device)\n            self.model.eval()\n            self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, token=self.token)\n\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"\n        Serialize this component to a dictionary.\n        \"\"\"\n        return default_to_dict(\n            self,\n            device=self.device,\n            model_name_or_path=self.model_name_or_path,\n            token=self.token if not isinstance(self.token, str) else None,  # don't serialize valid tokens\n            top_k=self.top_k,\n        )\n\n    @component.output_types(documents=List[Document])\n    def run(self, query: str, documents: List[Document], top_k: Optional[int] = None):\n        \"\"\"\n        Returns a list of Documents ranked by their similarity to the given query.\n\n        :param query: Query string.\n        :param documents: List of Documents.\n        :param top_k: The maximum number of Documents you want the Ranker to return.\n        :return: List of Documents sorted by their similarity to the query with the most similar Documents appearing first.\n        \"\"\"\n        if not documents:\n            return {\"documents\": []}\n\n        if top_k is None:\n            top_k = self.top_k\n\n        elif top_k <= 0:\n            raise ValueError(f\"top_k must be > 0, but got {top_k}\")\n\n        # If a model path is provided but the model isn't loaded\n        if self.model_name_or_path and not self.model:\n            raise ComponentError(\n                f\"The component {self.__class__.__name__} wasn't warmed up. Run 'warm_up()' before calling 'run()'.\"\n            )\n\n        query_doc_pairs = [[query, doc.content] for doc in documents]\n        features = self.tokenizer(\n            query_doc_pairs, padding=True, truncation=True, return_tensors=\"pt\"\n        ).to(  # type: ignore\n            self.device\n        )\n        with torch.inference_mode():\n            similarity_scores = self.model(**features).logits.squeeze(dim=1)  # type: ignore\n\n        _, sorted_indices = torch.sort(similarity_scores, descending=True)\n        ranked_docs = []\n        for sorted_index_tensor in sorted_indices:\n            i = sorted_index_tensor.item()\n            documents[i].score = similarity_scores[i].item()\n            ranked_docs.append(documents[i])\n        return {\"documents\": ranked_docs[:top_k]}\n", "path": "haystack/components/rankers/transformers_similarity.py"}], "after_files": [{"content": "import logging\nfrom pathlib import Path\nfrom typing import List, Union, Dict, Any, Optional\n\nfrom haystack import ComponentError, Document, component, default_to_dict\nfrom haystack.lazy_imports import LazyImport\n\nlogger = logging.getLogger(__name__)\n\n\nwith LazyImport(message=\"Run 'pip install transformers[torch,sentencepiece]'\") as torch_and_transformers_import:\n    import torch\n    from transformers import AutoModelForSequenceClassification, AutoTokenizer\n\n\n@component\nclass TransformersSimilarityRanker:\n    \"\"\"\n    Ranks Documents based on their similarity to the query.\n    It uses a pre-trained cross-encoder model (from the Hugging Face Hub) to embed the query and the Documents.\n\n    Usage example:\n    ```\n    from haystack import Document\n    from haystack.components.rankers import TransformersSimilarityRanker\n\n    ranker = TransformersSimilarityRanker()\n    docs = [Document(content=\"Paris\"), Document(content=\"Berlin\")]\n    query = \"City in Germany\"\n    output = ranker.run(query=query, documents=docs)\n    docs = output[\"documents\"]\n    assert len(docs) == 2\n    assert docs[0].content == \"Berlin\"\n    ```\n    \"\"\"\n\n    def __init__(\n        self,\n        model_name_or_path: Union[str, Path] = \"cross-encoder/ms-marco-MiniLM-L-6-v2\",\n        device: str = \"cpu\",\n        token: Union[bool, str, None] = None,\n        top_k: int = 10,\n        meta_fields_to_embed: Optional[List[str]] = None,\n        embedding_separator: str = \"\\n\",\n    ):\n        \"\"\"\n        Creates an instance of TransformersSimilarityRanker.\n\n        :param model_name_or_path: The name or path of a pre-trained cross-encoder model\n            from the Hugging Face Hub.\n        :param device: The torch device (for example, cuda:0, cpu, mps) to which you want to limit model inference.\n        :param token: The API token used to download private models from Hugging Face.\n            If this parameter is set to `True`, the token generated when running\n            `transformers-cli login` (stored in ~/.huggingface) is used.\n        :param top_k: The maximum number of Documents to return per query.\n        :param meta_fields_to_embed: List of meta fields that should be embedded along with the Document content.\n        :param embedding_separator: Separator used to concatenate the meta fields to the Document content.\n        \"\"\"\n        torch_and_transformers_import.check()\n\n        self.model_name_or_path = model_name_or_path\n        if top_k <= 0:\n            raise ValueError(f\"top_k must be > 0, but got {top_k}\")\n        self.top_k = top_k\n        self.device = device\n        self.token = token\n        self.model = None\n        self.tokenizer = None\n        self.meta_fields_to_embed = meta_fields_to_embed or []\n        self.embedding_separator = embedding_separator\n\n    def _get_telemetry_data(self) -> Dict[str, Any]:\n        \"\"\"\n        Data that is sent to Posthog for usage analytics.\n        \"\"\"\n        return {\"model\": str(self.model_name_or_path)}\n\n    def warm_up(self):\n        \"\"\"\n        Warm up the model and tokenizer used for scoring the Documents.\n        \"\"\"\n        if self.model_name_or_path and not self.model:\n            self.model = AutoModelForSequenceClassification.from_pretrained(self.model_name_or_path, token=self.token)\n            self.model = self.model.to(self.device)\n            self.model.eval()\n            self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, token=self.token)\n\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"\n        Serialize this component to a dictionary.\n        \"\"\"\n        return default_to_dict(\n            self,\n            device=self.device,\n            model_name_or_path=self.model_name_or_path,\n            token=self.token if not isinstance(self.token, str) else None,  # don't serialize valid tokens\n            top_k=self.top_k,\n            meta_fields_to_embed=self.meta_fields_to_embed,\n            embedding_separator=self.embedding_separator,\n        )\n\n    @component.output_types(documents=List[Document])\n    def run(self, query: str, documents: List[Document], top_k: Optional[int] = None):\n        \"\"\"\n        Returns a list of Documents ranked by their similarity to the given query.\n\n        :param query: Query string.\n        :param documents: List of Documents.\n        :param top_k: The maximum number of Documents you want the Ranker to return.\n        :return: List of Documents sorted by their similarity to the query with the most similar Documents appearing first.\n        \"\"\"\n        if not documents:\n            return {\"documents\": []}\n\n        if top_k is None:\n            top_k = self.top_k\n\n        elif top_k <= 0:\n            raise ValueError(f\"top_k must be > 0, but got {top_k}\")\n\n        # If a model path is provided but the model isn't loaded\n        if self.model_name_or_path and not self.model:\n            raise ComponentError(\n                f\"The component {self.__class__.__name__} wasn't warmed up. Run 'warm_up()' before calling 'run()'.\"\n            )\n\n        query_doc_pairs = []\n        for doc in documents:\n            meta_values_to_embed = [\n                str(doc.meta[key]) for key in self.meta_fields_to_embed if key in doc.meta and doc.meta[key]\n            ]\n            text_to_embed = self.embedding_separator.join(meta_values_to_embed + [doc.content or \"\"])\n            query_doc_pairs.append([query, text_to_embed])\n\n        features = self.tokenizer(\n            query_doc_pairs, padding=True, truncation=True, return_tensors=\"pt\"\n        ).to(  # type: ignore\n            self.device\n        )\n        with torch.inference_mode():\n            similarity_scores = self.model(**features).logits.squeeze(dim=1)  # type: ignore\n\n        _, sorted_indices = torch.sort(similarity_scores, descending=True)\n        ranked_docs = []\n        for sorted_index_tensor in sorted_indices:\n            i = sorted_index_tensor.item()\n            documents[i].score = similarity_scores[i].item()\n            ranked_docs.append(documents[i])\n        return {\"documents\": ranked_docs[:top_k]}\n", "path": "haystack/components/rankers/transformers_similarity.py"}]}