Repository: deepset-ai/haystack

Issue:
`TransformersSimilarityRanker` breaks when `documents` list consists of a single document
**Describe the bug**
`TransformersSimilarityRanker` throws an error if its input for `documents` consists of a list containing only a single Document.

**Error message**
```
Traceback (most recent call last):
  File "/Users/bogdan/Repositories/haystack/haystack/core/pipeline/pipeline.py", line 634, in _run_component
    outputs = instance.run(**inputs)
              ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bogdan/Repositories/haystack/haystack/components/rankers/transformers_similarity.py", line 130, in run
    for sorted_index_tensor in sorted_indices:
  File "/Users/bogdan/miniconda3/envs/haystack/lib/python3.11/site-packages/torch/_tensor.py", line 990, in __iter__
    raise TypeError("iteration over a 0-d tensor")
TypeError: iteration over a 0-d tensor

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/bogdan/Repositories/haystack/bogdan_scripts/advent2.py", line 39, in <module>
    result = pipeline.run({
             ^^^^^^^^^^^^^^
  File "/Users/bogdan/Repositories/haystack/haystack/pipeline.py", line 85, in run
    return self._run_internal(data=data, debug=debug)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bogdan/Repositories/haystack/haystack/pipeline.py", line 111, in _run_internal
    return super().run(data=data, debug=debug)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bogdan/Repositories/haystack/haystack/core/pipeline/pipeline.py", line 491, in run
    outputs = self._run_component(name=component_name, inputs=dict(inputs))
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bogdan/Repositories/haystack/haystack/core/pipeline/pipeline.py", line 647, in _run_component
    raise PipelineRuntimeError(
haystack.core.errors.PipelineRuntimeError: ranker raised 'TypeError: iteration over a 0-d tensor' 
Inputs: {'query': 'What is our favorite animal?', 'documents': [Document(id=763a01ff13b87fd4f8bcb0a2cd0903f3aa6522002ac4e1f2fe1590fb96b48d16, content: 'Try out Haystack 2.0-Beta to discover what’s coming in the next major release
with 10 challenges in ...', meta: {'content_type': 'text/html', 'url': 'https://haystack.deepset.ai/advent-of-haystack/day-1#challenge', 'source_id': '1754c44adcb6ab95cd02b13c6b7c5b265d9de856f381e5717d6abfd4bc1ffc8e'})]}

See the stacktrace above for more information.
```

**Expected behavior**
The pipeline should run fine if the ranker gets only a single document. 

**Additional context**
I noticed this error while trying to solve day 2 of the advent of Haystack. 
I'll create a PR to fix this :) 

**To Reproduce**
```python
from haystack.components.fetchers.link_content import LinkContentFetcher
from haystack.components.converters import HTMLToDocument
from haystack.components.preprocessors import DocumentSplitter
from haystack.components.rankers import TransformersSimilarityRanker
from haystack.components.generators import GPTGenerator
from haystack.components.builders.prompt_builder import PromptBuilder
from haystack import Pipeline


openai_api_key = <API_KEY>
prompt_template = """
According to these documents:

{% for doc in documents %}
  {{ doc.content }}
{% endfor %}

Answer the given question: {{question}}
Answer:
"""
prompt_builder = PromptBuilder(template=prompt_template)

pipeline = Pipeline()
pipeline.add_component("fetcher", instance=LinkContentFetcher())
pipeline.add_component("converter", instance=HTMLToDocument())
pipeline.add_component("splitter", instance=DocumentSplitter())
pipeline.add_component("ranker", instance=TransformersSimilarityRanker())
pipeline.add_component("prompt_builder", instance=prompt_builder)
pipeline.add_component("generator", instance=GPTGenerator(api_key=openai_api_key))

pipeline.connect("fetcher", "converter")
pipeline.connect("converter", "splitter")
pipeline.connect("splitter.documents", "ranker.documents")
pipeline.connect("ranker.documents", "prompt_builder.documents")
pipeline.connect("prompt_builder", "generator")


question = "What is our favorite animal?"
result = pipeline.run({
    "prompt_builder": {"question": question},
    "ranker": {"query": question},
    "fetcher": {"urls": ["https://haystack.deepset.ai/advent-of-haystack/day-1#challenge"]}
})

print(result['generator']['replies'][0])
```

**FAQ Check**
- [x] Have you had a look at [our new FAQ page](https://docs.haystack.deepset.ai/docs/faq)?

**System:**
 - OS: Google Colab 
 - Haystack version (commit or version number): 2.0-beta



Discussion:

Resolving patch:
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
@@ -123,7 +123,7 @@ def run(self, query: str, documents: List[Document], top_k: Optional[int] = None
             self.device
         )
         with torch.inference_mode():
-            similarity_scores = self.model(**features).logits.squeeze()  # type: ignore
+            similarity_scores = self.model(**features).logits.squeeze(dim=1)  # type: ignore
 
         _, sorted_indices = torch.sort(similarity_scores, descending=True)
         ranked_docs = []


Test patch:
diff --git a/test/components/rankers/test_transformers_similarity.py b/test/components/rankers/test_transformers_similarity.py
--- a/test/components/rankers/test_transformers_similarity.py
+++ b/test/components/rankers/test_transformers_similarity.py
@@ -98,3 +98,16 @@ def test_run_top_k(self, query, docs_before_texts, expected_first_text):
 
         sorted_scores = sorted([doc.score for doc in docs_after], reverse=True)
         assert [doc.score for doc in docs_after] == sorted_scores
+
+    @pytest.mark.integration
+    def test_run_single_document(self):
+        """
+        Test if the component runs with a single document.
+        """
+        ranker = TransformersSimilarityRanker(model_name_or_path="cross-encoder/ms-marco-MiniLM-L-6-v2")
+        ranker.warm_up()
+        docs_before = [Document(content="Berlin")]
+        output = ranker.run(query="City in Germany", documents=docs_before)
+        docs_after = output["documents"]
+
+        assert len(docs_after) == 1