Repository: deepset-ai/haystack

Issue:
Remove deprecated `debug` parameter from `Pipeline.run`
See #8015.

Discussion:
coveralls: ## Pull Request Test Coverage Report for [Build 10560112094](https://coveralls.io/builds/69427939)


### Details

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* **13** unchanged lines in **1** file lost coverage.
* Overall coverage decreased (**-0.002%**) to **90.208%**

---


|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [core/pipeline/pipeline.py](https://coveralls.io/builds/69427939/source?filename=core%2Fpipeline%2Fpipeline.py#L220) | 13 | 79.55% |
<!-- | **Total:** | **13** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/69427939/badge)](https://coveralls.io/builds/69427939) |
| :-- | --: |
| Change from base [Build 10528666835](https://coveralls.io/builds/69397373): |  -0.002% |
| Covered Lines: | 6974 |
| Relevant Lines: | 7731 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/haystack/components/retrievers/sentence_window_retriever.py b/haystack/components/retrievers/sentence_window_retriever.py
index a96b4adb..7ec000f7 100644
--- a/haystack/components/retrievers/sentence_window_retriever.py
+++ b/haystack/components/retrievers/sentence_window_retriever.py
@@ -54,7 +54,20 @@ class SentenceWindowRetriever:
 
     >> {'sentence_window_retriever': {'context_windows': ['some words. There is a second sentence.
     >> And there is also a third sentence. It also contains a fourth sentence. And a fifth sentence. And a sixth
-    >> sentence. And a']}}
+    >> sentence. And a'], 'context_documents': [[Document(id=..., content: 'some words. There is a second sentence.
+    >> And there is ', meta: {'source_id': '...', 'page_number': 1, 'split_id': 1, 'split_idx_start': 20,
+    >> '_split_overlap': [{'doc_id': '...', 'range': (20, 43)}, {'doc_id': '...', 'range': (0, 30)}]}),
+    >> Document(id=..., content: 'second sentence. And there is also a third sentence. It ',
+    >> meta: {'source_id': '74ea87deb38012873cf8c07e...f19d01a26a098447113e1d7b83efd30c02987114', 'page_number': 1,
+    >> 'split_id': 2, 'split_idx_start': 43, '_split_overlap': [{'doc_id': '...', 'range': (23, 53)}, {'doc_id': '...',
+    >> 'range': (0, 26)}]}), Document(id=..., content: 'also a third sentence. It also contains a fourth sentence. ',
+    >> meta: {'source_id': '...', 'page_number': 1, 'split_id': 3, 'split_idx_start': 73, '_split_overlap':
+    >> [{'doc_id': '...', 'range': (30, 56)}, {'doc_id': '...', 'range': (0, 33)}]}), Document(id=..., content:
+    >> 'also contains a fourth sentence. And a fifth sentence. And ', meta: {'source_id': '...', 'page_number': 1,
+    >> 'split_id': 4, 'split_idx_start': 99, '_split_overlap': [{'doc_id': '...', 'range': (26, 59)},
+    >> {'doc_id': '...', 'range': (0, 26)}]}), Document(id=..., content: 'And a fifth sentence. And a sixth sentence.
+    >> And a ', meta: {'source_id': '...', 'page_number': 1, 'split_id': 5, 'split_idx_start': 132,
+    >> '_split_overlap': [{'doc_id': '...', 'range': (33, 59)}, {'doc_id': '...', 'range': (0, 24)}]})]]}}}}
     ```
     """
 
@@ -123,7 +136,7 @@ class SentenceWindowRetriever:
         # deserialize the component
         return default_from_dict(cls, data)
 
-    @component.output_types(context_windows=List[str])
+    @component.output_types(context_windows=List[str], context_documents=List[List[Document]])
     def run(self, retrieved_documents: List[Document]):
         """
         Based on the `source_id` and on the `doc.meta['split_id']` get surrounding documents from the document store.
@@ -134,7 +147,12 @@ class SentenceWindowRetriever:
         :param retrieved_documents: List of retrieved documents from the previous retriever.
         :returns:
             A dictionary with the following keys:
-            - `context_windows`:  List of strings representing the context windows of the retrieved documents.
+                - `context_windows`: A list of strings, where each string represents the concatenated text from the
+                                     context window of the corresponding document in `retrieved_documents`.
+                - `context_documents`: A list of lists of `Document` objects, where each inner list contains the
+                                     documents that form the context window for the corresponding document in
+                                     `retrieved_documents`.
+
         """
 
         if not all("split_id" in doc.meta for doc in retrieved_documents):
@@ -143,7 +161,8 @@ class SentenceWindowRetriever:
         if not all("source_id" in doc.meta for doc in retrieved_documents):
             raise ValueError("The retrieved documents must have 'source_id' in the metadata.")
 
-        context_windows = []
+        context_text = []
+        context_documents = []
         for doc in retrieved_documents:
             source_id = doc.meta["source_id"]
             split_id = doc.meta["split_id"]
@@ -159,6 +178,7 @@ class SentenceWindowRetriever:
                     ],
                 }
             )
-            context_windows.append(self.merge_documents_text(context_docs))
+            context_text.append(self.merge_documents_text(context_docs))
+            context_documents.append(context_docs)
 
-        return {"context_windows": context_windows}
+        return {"context_windows": context_text, "context_documents": context_documents}
diff --git a/haystack/core/pipeline/pipeline.py b/haystack/core/pipeline/pipeline.py
index 6ae9df49..1f5732d3 100644
--- a/haystack/core/pipeline/pipeline.py
+++ b/haystack/core/pipeline/pipeline.py
@@ -85,7 +85,7 @@ class Pipeline(PipelineBase):
             return res
 
     def run(  # noqa: PLR0915
-        self, data: Dict[str, Any], debug: bool = False, include_outputs_from: Optional[Set[str]] = None
+        self, data: Dict[str, Any], include_outputs_from: Optional[Set[str]] = None
     ) -> Dict[str, Any]:
         """
         Runs the pipeline with given input data.
@@ -105,8 +105,6 @@ class Pipeline(PipelineBase):
             }
             ```
 
-        :param debug:
-            Set to True to collect and return debug information.
         :param include_outputs_from:
             Set of component names whose individual outputs are to be
             included in the pipeline's output. For components that are
@@ -155,8 +153,6 @@ class Pipeline(PipelineBase):
         The pipeline resolves inputs to the correct components, returning
         {'hello2': {'output': 'Hello, Hello, world!!'}}.
         """
-        warn("The 'debug' parameter is deprecated and will be removed in Haystack 2.5.0.", DeprecationWarning)
-
         pipeline_running(self)
 
         # Reset the visits count for each component
@@ -208,7 +204,6 @@ class Pipeline(PipelineBase):
             tags={
                 "haystack.pipeline.input_data": data,
                 "haystack.pipeline.output_data": final_outputs,
-                "haystack.pipeline.debug": debug,
                 "haystack.pipeline.metadata": self.metadata,
                 "haystack.pipeline.max_loops_allowed": self.max_loops_allowed,
             },
diff --git a/releasenotes/notes/remove-deprecated-pipeline-run-debug-eab0c31ea0ce513d.yaml b/releasenotes/notes/remove-deprecated-pipeline-run-debug-eab0c31ea0ce513d.yaml
new file mode 100644
index 00000000..45704def
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-pipeline-run-debug-eab0c31ea0ce513d.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+  - |
+    Remove unused `debug` parameter from `Pipeline.run` method.
diff --git a/releasenotes/notes/sentence-window-retriever-output-docs-d3de2ac4328488f1.yaml b/releasenotes/notes/sentence-window-retriever-output-docs-d3de2ac4328488f1.yaml
new file mode 100644
index 00000000..7e86f75e
--- /dev/null
+++ b/releasenotes/notes/sentence-window-retriever-output-docs-d3de2ac4328488f1.yaml
@@ -0,0 +1,4 @@
+---
+enhancements:
+  - |
+    The SentenceWindowRetriever has now an extra output key containing all the documents belonging to the context window.


Test patch:
diff --git a/test/components/retrievers/test_sentence_window_retriever.py b/test/components/retrievers/test_sentence_window_retriever.py
index 6d6e8478..d05f4780 100644
--- a/test/components/retrievers/test_sentence_window_retriever.py
+++ b/test/components/retrievers/test_sentence_window_retriever.py
@@ -130,19 +130,31 @@ class TestSentenceWindowRetriever:
         doc_store = InMemoryDocumentStore()
         doc_store.write_documents(docs["documents"])
 
-        rag = Pipeline()
-        rag.add_component("bm25_retriever", InMemoryBM25Retriever(doc_store, top_k=1))
-        rag.add_component("sentence_window_retriever", SentenceWindowRetriever(document_store=doc_store, window_size=2))
-        rag.connect("bm25_retriever", "sentence_window_retriever")
-        result = rag.run({"bm25_retriever": {"query": "third"}})
-
-        expected = {
-            "sentence_window_retriever": {
-                "context_windows": [
-                    "some words. There is a second sentence. And there is also a third sentence. It also "
-                    "contains a fourth sentence. And a fifth sentence. And a sixth sentence. And a "
-                ]
-            }
-        }
+        pipe = Pipeline()
+        pipe.add_component("bm25_retriever", InMemoryBM25Retriever(doc_store, top_k=1))
+        pipe.add_component(
+            "sentence_window_retriever", SentenceWindowRetriever(document_store=doc_store, window_size=2)
+        )
+        pipe.connect("bm25_retriever", "sentence_window_retriever")
+        result = pipe.run({"bm25_retriever": {"query": "third"}})
+
+        assert result["sentence_window_retriever"]["context_windows"] == [
+            "some words. There is a second sentence. And there is also a third sentence. It also "
+            "contains a fourth sentence. And a fifth sentence. And a sixth sentence. And a "
+        ]
+        assert len(result["sentence_window_retriever"]["context_documents"][0]) == 5
+
+    @pytest.mark.integration
+    def test_serialization_deserialization_in_pipeline(self):
+        doc_store = InMemoryDocumentStore()
+        pipe = Pipeline()
+        pipe.add_component("bm25_retriever", InMemoryBM25Retriever(doc_store, top_k=1))
+        pipe.add_component(
+            "sentence_window_retriever", SentenceWindowRetriever(document_store=doc_store, window_size=2)
+        )
+        pipe.connect("bm25_retriever", "sentence_window_retriever")
+
+        serialized = pipe.to_dict()
+        deserialized = Pipeline.from_dict(serialized)
 
-        assert result == expected
+        assert deserialized == pipe
diff --git a/test/core/pipeline/test_tracing.py b/test/core/pipeline/test_tracing.py
index 3c19d14d..ef6bec17 100644
--- a/test/core/pipeline/test_tracing.py
+++ b/test/core/pipeline/test_tracing.py
@@ -44,7 +44,6 @@ class TestTracing:
                 tags={
                     "haystack.pipeline.input_data": {"hello": {"word": "world"}},
                     "haystack.pipeline.output_data": {"hello2": {"output": "Hello, Hello, world!!"}},
-                    "haystack.pipeline.debug": False,
                     "haystack.pipeline.metadata": {},
                     "haystack.pipeline.max_loops_allowed": 100,
                 },
@@ -99,7 +98,6 @@ class TestTracing:
             SpyingSpan(
                 operation_name="haystack.pipeline.run",
                 tags={
-                    "haystack.pipeline.debug": False,
                     "haystack.pipeline.metadata": {},
                     "haystack.pipeline.max_loops_allowed": 100,
                     "haystack.pipeline.input_data": {"hello": {"word": "world"}},