Skip to content

perf: query the Document Store once in SentenceWindowRetriever - #12997

Merged
julian-risch merged 1 commit into
mainfrom
fix/sentence-window-single-filter-call
Sep 28, 2026
Merged

julian-risch merged 1 commit into
mainfrom
fix/sentence-window-single-filter-call

Conversation

@julian-risch

@julian-risch julian-risch commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Related Issues

SentenceWindowRetriever called document_store.filter_documents() (or filter_documents_async()) once for every retrieved document. With a top_k of 10 upstream, one pipeline run sent 10 separate queries to the Document Store, which puts unnecessary load on backends like OpenSearch.

Proposed Changes:

Now run() and run_async() send one query:

  • Build the existing per-document window condition (source_id fields ==, split_id between split_id ± window_size) for each retrieved document, drop duplicate conditions, and combine them into one {"operator": "OR", "conditions": [...]} filter.
  • Call the Document Store once with that filter. Skip the call if no retrieved document has the required metadata.
  • In memory, assign the returned documents to each retrieved document's window with the same source-ID and split-ID range check. Then build context_windows / context_documents exactly as before.

The output contract is unchanged.

The two private helpers _retrieve_context_for_document and _retrieve_context_for_document_async are replaced by shared sync/async helpers (_get_windows, _build_filters, _assemble_context), so the only sync/async difference left is the store call.

How did you test it?

  • New unit tests (sync and async)
  • I ran tests locally. Timing on a local opensearch, window_size=3, averaged over 20 runs:
top_k main PR
10 16.3 ms 4.0 ms
50 67.3 ms 6.6 ms

Load on the cluster now stays flat as top_k grows instead of rising with it.

Notes for the reviewer

  • Result-size limits: a single query now returns up to len(retrieved_documents) * (2 * window_size + 1) documents (70 for top_k=10, window_size=3). This is well under the stores' filter_documents caps (OpenSearch/Elasticsearch size=10_000; Pinecone's 1000 top_k limit is the tightest). It could matter only with very large top_k × window_size on Pinecone.
  • Filter size: the OR filter grows linearly with the number of retrieved documents. That is a few bool clauses per document, far from OpenSearch's default max_clause_count.
  • Overlap with fix: sort SentenceWindowRetriever context before merging text #12976: that PR changes the same lines (sorting by split_id before merge_documents_text). Whichever merges second needs a trivial rebase. With this PR the change becomes self.merge_documents_text(sorted_context_docs) inside _assemble_context.

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes. — n/a, internal issue
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

🤖 Generated with Claude Code

SentenceWindowRetriever called filter_documents once per retrieved
document. It now combines all windows into a single OR filter and
assigns the returned documents to each window in memory.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
haystack-docs Ignored Ignored Preview Sep 28, 2026 7:04am UTC

Request Review

@github-actions github-actions Bot added topic:tests type:documentation Improvements on the docs labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/components/retrievers
  sentence_window_retriever.py
Project Total  

This report was generated by python-coverage-comment-action

@julian-risch julian-risch added this to the 3.3.0 milestone Sep 28, 2026
@julian-risch
julian-risch marked this pull request as ready for review September 28, 2026 09:49
@julian-risch
julian-risch requested a review from a team as a code owner September 28, 2026 09:49
@julian-risch
julian-risch requested review from sjrl and removed request for a team September 28, 2026 09:49

@sjrl sjrl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@julian-risch
julian-risch merged commit 43b12cc into main Sep 28, 2026
30 checks passed
@julian-risch
julian-risch deleted the fix/sentence-window-single-filter-call branch September 28, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants