Repository: deepset-ai/haystack

Issue:
 num_return_sequences should be less than num_beams, not top_k
**Describe the bug**
In the `invoke` method of the `HFLocalInvocationLayer` object, we can see the following code snippet:
```python
if top_k:
    model_input_kwargs["num_return_sequences"] = top_k
    if "num_beams" not in model_input_kwargs or model_input_kwargs["num_beams"] < top_k:
        if "num_beams" in model_input_kwargs:
            logger.warning("num_beams should not be less than top_k, hence setting it to %s", top_k)
        model_input_kwargs["num_beams"] = top_k
```
But there are 2 problems with this logic here:
1. `num_beams` and `top_k` are 2 parameters of 2 different decoding methods for language generation (for more information, pls refer to this [article](https://huggingface.co/blog/how-to-generate). There is no relationship between them. There does exist a relationship between  `num_beams` and `num_return_sequences` (num_return_sequences<=num_beams). So we should use `num_beams` instead of `top_k`.
2. `top_k` is used to control the generation behavior of Top-K Sample or Sampling decoding method. And it is the user's freedom whether or not to set the `num_return_sequences`. We should not hard-set model_input_kwargs["num_return_sequences"] to `top_k` or whatever parameter in the code.

**Error message**
N/A

**Expected behavior**
The correct logic should be like this:
```python
if "num_beams" in model_input_kwargs: 
      num_beams = model_input_kwargs['num_beams']
      if "num_return_sequences" in model_input_kwargs and model_input_kwargs["num_return_sequences"] > num_beams:
          logger.warning("num_return_sequences should not be larger than num_beams, hence setting it to %s", num_beams)
          model_input_kwargs["num_return_sequences"] = num_beams
```
the first line indicates that users want to use beam search as their preferred decoding method. Then we check whether they also passed the `num_return_sequences` and whether `num_return_sequences` is larger than num_beams. If so, we give a warning to the users and manually change `num_return_sequences` to `num_beams`. 

**To Reproduce**
Steps to reproduce the behavior

**FAQ Check**
- [ x ] Have you had a look at [our new FAQ page](https://docs.haystack.deepset.ai/docs/faq)?

**System:**
 - OS: Linux
 - GPU/CPU: CPU
 - Haystack version (commit or version number): 
 - DocumentStore:
 - Reader:
 - Retriever:



Discussion:

Resolving patch:
diff --git a/haystack/nodes/prompt/invocation_layer/hugging_face.py b/haystack/nodes/prompt/invocation_layer/hugging_face.py
--- a/haystack/nodes/prompt/invocation_layer/hugging_face.py
+++ b/haystack/nodes/prompt/invocation_layer/hugging_face.py
@@ -196,7 +196,6 @@ def invoke(self, *args, **kwargs):
         """
         output: List[Dict[str, str]] = []
         stop_words = kwargs.pop("stop_words", None)
-        top_k = kwargs.pop("top_k", None)
         # either stream is True (will use default handler) or stream_handler is provided for custom handler
         stream = kwargs.get("stream", self.stream)
         stream_handler = kwargs.get("stream_handler", self.stream_handler)
@@ -241,12 +240,21 @@ def invoke(self, *args, **kwargs):
             if stop_words:
                 sw = StopWordsCriteria(tokenizer=self.pipe.tokenizer, stop_words=stop_words, device=self.pipe.device)
                 model_input_kwargs["stopping_criteria"] = StoppingCriteriaList([sw])
-            if top_k:
-                model_input_kwargs["num_return_sequences"] = top_k
-                if "num_beams" not in model_input_kwargs or model_input_kwargs["num_beams"] < top_k:
-                    if "num_beams" in model_input_kwargs:
-                        logger.warning("num_beams should not be less than top_k, hence setting it to %s", top_k)
-                    model_input_kwargs["num_beams"] = top_k
+
+            if "num_beams" in model_input_kwargs:
+                num_beams = model_input_kwargs["num_beams"]
+                if (
+                    "num_return_sequences" in model_input_kwargs
+                    and model_input_kwargs["num_return_sequences"] > num_beams
+                ):
+                    num_return_sequences = model_input_kwargs["num_return_sequences"]
+                    logger.warning(
+                        "num_return_sequences %s should not be larger than num_beams %s, hence setting it equal to num_beams",
+                        num_return_sequences,
+                        num_beams,
+                    )
+                    model_input_kwargs["num_return_sequences"] = num_beams
+
             # max_new_tokens is used for text-generation and max_length for text2text-generation
             if is_text_generation:
                 model_input_kwargs["max_new_tokens"] = model_input_kwargs.pop("max_length", self.max_length)


Test patch:
diff --git a/test/prompt/invocation_layer/test_hugging_face.py b/test/prompt/invocation_layer/test_hugging_face.py
--- a/test/prompt/invocation_layer/test_hugging_face.py
+++ b/test/prompt/invocation_layer/test_hugging_face.py
@@ -204,6 +204,48 @@ def test_ensure_token_limit_negative(caplog):
     assert caplog.records[0].message == expected_message
 
 
+@pytest.mark.unit
+def test_num_return_sequences_no_larger_than_num_beams(mock_pipeline, mock_get_task, caplog):
+    """
+    Test that num_return_sequences cannot be larger than num_beams and that a warning is logged
+    """
+
+    layer = HFLocalInvocationLayer("google/flan-t5-base")
+
+    with patch.object(layer.pipe, "run_single", MagicMock()):
+        layer.invoke(prompt="What does 42 mean?", generation_kwargs={"num_beams": 5, "num_return_sequences": 8})
+
+    expected_message = (
+        "num_return_sequences 8 should not be larger than num_beams 5, hence setting it equal to num_beams"
+    )
+    # check that the warning is logged
+    assert caplog.records[0].message == expected_message
+
+    # check that num_return_sequences is set to num_beams
+    _, kwargs = layer.pipe.call_args
+    assert kwargs["num_beams"] == 5
+    assert kwargs["num_return_sequences"] == 5
+
+
+@pytest.mark.unit
+def test_num_beams_larger_than_num_return_sequences(mock_pipeline, mock_get_task, caplog):
+    """
+    Test that num_beams can be larger than num_return_sequences and that no warning is logged
+    """
+    layer = HFLocalInvocationLayer("google/flan-t5-base")
+
+    with patch.object(layer.pipe, "run_single", MagicMock()):
+        layer.invoke(prompt="What does 42 mean?", generation_kwargs={"num_beams": 8, "num_return_sequences": 5})
+
+    # check that no warning is logged
+    assert not caplog.records
+
+    # check that num_return_sequences remains unchanged
+    _, kwargs = layer.pipe.call_args
+    assert kwargs["num_beams"] == 8
+    assert kwargs["num_return_sequences"] == 5
+
+
 @pytest.mark.unit
 def test_constructor_with_custom_pretrained_model(mock_pipeline, mock_get_task):
     """