deepset-ai / deepset-ai/haystack-core-integrations

Filter document from score_threshold after search in QdrantDocumentStore

Open
#1,055 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

integration:qdrant P3
Dominant language
Python
Stars
203
Forks
332
Avg merge
2d 4h
Merged PRs (30d)
80

Description

Is your feature request related to a problem? Please describe.
While working with the QdrantHybridRetriever I found out that the score_threshold parameter can be a little tricky to understand and seems like that it is used only during the search of the sparse vectors as shown here in the QdrantDocumentStore module:


       ...
        sparse_request = rest.SearchRequest(
            vector=rest.NamedSparseVector(
                name=SPARSE_VECTORS_NAME,
                vector=rest.SparseVector(
                    indices=query_sparse_embedding.indices,
                    values=query_sparse_embedding.values,
                ),
            ),
            filter=qdrant_filters,
            limit=top_k,
            with_payload=True,
            with_vector=return_embedding,
            score_threshold=score_threshold,
        )

        dense_request = rest.SearchRequest(
            vector=rest.NamedVector(
                name=DENSE_VECTORS_NAME,
                vector=query_embedding,
            ),
            filter=qdrant_filters,
            limit=top_k,
            with_payload=True,
            with_vector=return_embedding,
        )
       ...

The score that is returned from the requests is not normalized, so that make more difficult to set a threshold score.

Describe the solution you'd like
A simple solution to this problem can be implemented in one of these ways:

  • Solution A:
  1. Remove the score_threshold from the sparse vector search
  2. Add an optional parameter to the reciprocal_rank_fusion function so that it can optionally filter all the points that have a score lower than the threshold
  • Solution B:
  1. Remove the score_threshold from the sparse vector search
  2. Add a condition on the point score to the following list comprehension:
results = [convert_qdrant_point_to_haystack_document(point, use_sparse_embeddings=True) for point in points if point.score >= score_threshold] 

Describe alternatives you've considered
Another alternative, is to implement a component that filters out the document based on the score given from the retriever like this:

@component
class RetrieverDocumentFilter:

    @component.output_types(documents=List[Document])
    def run(self, documents: List[Document], score_threshold: float):
        return {"documents": [d for d in documents if d.score >= score_threshold]}

Although is not a bad solution, I think it should be a cool thing to be able to perform the filtering directly on the retriever component

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Locate the QdrantDocumentStore module and the reciprocal_rank_fusion entry point, then trace how score_threshold reaches the sparse and dense SearchRequest calls. Choose one filtering point described in the issue, ensure the threshold consistently applies to returned documents, and verify the resulting behavior across hybrid retrieval.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
databases, machine-learning
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.