Repository: deepset-ai/haystack

Issue:
Pipeline eval breaks when node has empty answers list in Tutorial 15 TableQA
**Describe the bug**
We encounter an index out of range error when running the evaluation at the end of tutorial 15.
This is because of having an empty answer list in a node.

```python
eval_results = text_table_qa_pipeline.eval(table_labels + passage_labels, params={"top_k": 10})
```

**Error message**

![Tutorial15_TableQA-error](https://user-images.githubusercontent.com/4636315/188448700-77663b44-1f03-460a-90f5-f1559d9287e5.png)

The pipeline is as follows:

![pipeline](https://user-images.githubusercontent.com/4636315/188448943-b3711939-2c26-4b40-8a0d-ccdaf6fcdc05.png)

![Tutorial15_TableQA-error-debug](https://user-images.githubusercontent.com/4636315/188449111-3be21f62-caca-470a-9cde-360c5408ddfa.png)

What is happening is `output_1` from `RouteDocuments` is an empty list. So the `answers` from `TextReader` is also an empty list (but not `None`).

As such, [this check](https://github.com/deepset-ai/haystack/blob/b07fcb718541c9764b4400970f97c96a48f3254f/haystack/pipelines/base.py#L1471) fails. 

Note: I guess this is not a Tutorial 15 issue. More so on the pipeline eval.

**Expected behavior**
I'm not exactly sure if `_build_eval_dataframe` should handle it better or a node like `TextReader` shouldn't have an empty list as `answers` (only have `None`). 

cc: @tstadel @vblagoje 

**Additional context**
#2942 was a recent relevant change. 

**To Reproduce**
Run Tutorial 15.

**FAQ Check**
- [x ] Have you had a look at [our new FAQ page](https://haystack.deepset.ai/overview/faq)?

**System:**
 - OS: 
 - GPU/CPU:
 - Haystack version (commit or version number): `b07fcb718541c9764b4400970f97c96a48f3254f`
 - DocumentStore:
 - Reader:
 - Retriever:



Discussion:
Note: this issue might be a bit more general in that even with a simple Retriever-Reader pipeline for instance passing an empty list of docs (if the user forgot to add docs to the document-store) also ends up hitting this issue. 

cc: @mkkuemmel 

```
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Input In [36], in <cell line: 1>()
----> 1 old_eval_result = pipeline.eval(labels = labels)
      2 new_eval_result = pipeline_new.eval(labels = labels)
      3 old_metrics = old_eval_result.calculate_metrics()

File /opt/conda/lib/python3.10/site-packages/haystack/telemetry.py:128, in send_event.<locals>.wrapper(*args, **kwargs)
    125 @wraps(func)
    126 def wrapper(*args, **kwargs):
    127     send_custom_event(event=f"{type(args[0]).__name__}.{func.__name__} executed", payload=kwargs)
--> 128     return func(*args, **kwargs)

File /opt/conda/lib/python3.10/site-packages/haystack/pipelines/base.py:1159, in Pipeline.eval(self, labels, documents, params, sas_model_name_or_path, sas_batch_size, sas_use_gpu, add_isolated_node_eval, custom_document_id_field, context_matching_min_length, context_matching_boost_split_overlaps, context_matching_threshold, use_auth_token)
   1157     for node_name in predictions["_debug"].keys():
   1158         node_output = predictions["_debug"][node_name]["output"]
-> 1159         df = self._build_eval_dataframe(
   1160             queries=[label.query],
   1161             query_labels_per_query=[label],
   1162             node_name=node_name,
   1163             node_output=node_output,
   1164             custom_document_id_field=custom_document_id_field,
   1165             context_matching_threshold=context_matching_threshold,
   1166             context_matching_boost_split_overlaps=context_matching_boost_split_overlaps,
   1167             context_matching_min_length=context_matching_min_length,
   1168         )
   1169         eval_result.append(node_name, df)
   1171 eval_result = self._add_sas_to_eval_result(
   1172     sas_model_name_or_path=sas_model_name_or_path,
   1173     sas_batch_size=sas_batch_size,
   (...)
   1177     use_auth_token=use_auth_token,
   1178 )

File /opt/conda/lib/python3.10/site-packages/haystack/pipelines/base.py:1608, in Pipeline._build_eval_dataframe(self, queries, query_labels_per_query, node_name, node_output, custom_document_id_field, context_matching_min_length, context_matching_boost_split_overlaps, context_matching_threshold)
   1606 documents = node_output.get(field_name, None)
   1607 if documents is not None:
-> 1608     if isinstance(documents[i], list):
   1609         documents = documents[i]
   1610     if len(documents) == 0:
   1611         # add dummy document if there was no document retrieved, so query does not get lost in dataframe

IndexError: list index out of range
```

Perhaps a check for it could be added somewhere earlier in the pipeline to check for empty list of docs flowing through a node. Note: could also need distinguishing between cases where it might be okay (like the multiple routes above) vs where it may not be okay (when it's a single path in the pipeline).

Resolving patch:
diff --git a/haystack/pipelines/base.py b/haystack/pipelines/base.py
--- a/haystack/pipelines/base.py
+++ b/haystack/pipelines/base.py
@@ -1470,7 +1470,7 @@ def _build_eval_dataframe(
                 df_answers = pd.DataFrame()
                 answers = node_output.get(field_name, None)
                 if answers is not None:
-                    if isinstance(answers[i], list):
+                    if i < len(answers) and isinstance(answers[i], list):
                         # answers_isolated refers to only one relevant document and thus only a list of answers
                         # answers refers to multiple relevant documents and thus multiple lists of lists of answers
                         answers = answers[i]
@@ -1607,7 +1607,7 @@ def _build_eval_dataframe(
                 df_docs = pd.DataFrame()
                 documents = node_output.get(field_name, None)
                 if documents is not None:
-                    if isinstance(documents[i], list):
+                    if i < len(documents) and isinstance(documents[i], list):
                         documents = documents[i]
                     if len(documents) == 0:
                         # add dummy document if there was no document retrieved, so query does not get lost in dataframe


Test patch: