diff --git a/haystack/components/builders/answer_builder.py b/haystack/components/builders/answer_builder.py index a25d3f25cc..aff0535bf2 100644 --- a/haystack/components/builders/answer_builder.py +++ b/haystack/components/builders/answer_builder.py @@ -222,7 +222,7 @@ def run( else set(range(len(documents))) ) - for idx in doc_idxs: + for idx in sorted(doc_idxs): # An explicit bounds check is needed because references are 1-based: a reference like [0] # yields idx = -1, which Python would otherwise silently resolve to the last document. if not 0 <= idx < len(documents): diff --git a/releasenotes/notes/fix-answer-builder-doc-order-f63c572cd6560bf4.yaml b/releasenotes/notes/fix-answer-builder-doc-order-f63c572cd6560bf4.yaml new file mode 100644 index 0000000000..cb6d48b434 --- /dev/null +++ b/releasenotes/notes/fix-answer-builder-doc-order-f63c572cd6560bf4.yaml @@ -0,0 +1,10 @@ +--- +fixes: + - | + Fixed ``AnswerBuilder`` returning referenced documents in a scrambled order + instead of ascending source-index order. The referenced document indices + were collected in a ``set`` and iterated directly, so documents were emitted + in the set's internal hash-table order (e.g. citations [3] [10] [50] + yielded documents ordered 10, 3, 50). This order was deterministic but did + not match the intuitive source order. The referenced documents are now + returned sorted by their source index. diff --git a/test/components/builders/test_answer_builder.py b/test/components/builders/test_answer_builder.py index dfe847b530..5310751882 100644 --- a/test/components/builders/test_answer_builder.py +++ b/test/components/builders/test_answer_builder.py @@ -146,6 +146,16 @@ def test_run_with_documents_with_reference_pattern(self): assert answers[0].documents[0].meta["referenced"] is True assert answers[0].documents[0].meta["source_index"] == 2 + def test_run_returns_referenced_documents_in_source_order(self): + component = AnswerBuilder(reference_pattern="\\[(\\d+)\\]", return_only_referenced_documents=True) + output = component.run( + query="test query", + replies=["First [3], then [10], and finally [50]."], + documents=[Document(content=f"doc{i}") for i in range(1, 51)], + ) + source_indices = [doc.meta["source_index"] for doc in output["answers"][0].documents] + assert source_indices == [3, 10, 50] + def test_run_with_documents_with_reference_pattern_return_all_documents(self): component = AnswerBuilder(reference_pattern="\\[(\\d+)\\]", return_only_referenced_documents=False) output = component.run(