Skip to content

bug fix for non-normalized dot product vectors returning no matches and causing assertion to fail if using hierarchy - #714

Open
MarkWolters wants to merge 1 commit into
mainfrom
fix_hierarchy_bug
Open

bug fix for non-normalized dot product vectors returning no matches and causing assertion to fail if using hierarchy#714
MarkWolters wants to merge 1 commit into
mainfrom
fix_hierarchy_bug

Conversation

@MarkWolters

@MarkWolters MarkWolters commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

This PR resolves issue #713.

When dot product vsf is used for graph search in conjunction with enabling hierarchy this can result in a failed Assertion when no candidate is found to be sufficiently close to the search vector at the level being searched, in this case where level > 0.

Any candidate whose score is < 0 is silently dropped, never added to approximateResults. If every candidate reachable from the entry point within that hierarchy layer happens to score negative for a given query, approximateResults stays empty and the size() == 1 assert fires.

0.0f is only a valid "accept everything" sentinel for similarity functions that are mathematically bounded to (0, 1] — COSINE and EUCLIDEAN are. DOT_PRODUCT is not bounded unless callers pre-normalize vectors to unit length. VectorDotProductWithLengthTest.testTrueDotproduct (the failing Cassandra unit test that surfaced this issue) deliberately uses non-unit 2D vectors with components in [-100, 100].

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Before you submit for review:

  • Does your PR follow guidelines from CONTRIBUTIONS.md?
  • Did you summarize what this PR does clearly and concisely?
  • Did you include performance data for changes which may be performance impacting?
  • Did you include useful docs for any user-facing changes or features?
  • Did you include useful javadocs for developer oriented changes, explaining new concepts or key changes?
  • Did you rebase your branch onto the latest main for regression testing and PR submission?
  • Did you trigger regression testing via Run Bench Main and review results?
  • Did you adhere to the code formatting guidelines (TBD)
  • Did you group your changes for easy review, providing meaningful descriptions for each commit?
  • Did you ensure that all files contain the correct copyright header?
  • Did you add documentation for this feature to the release notes directory?

If you did not complete any of these, then please explain below.

@MarkWolters
MarkWolters marked this pull request as ready for review August 24, 2026 16:25
* @param topK the number of results to look for. With threshold=0, the search will continue until at least
* `topK` results have been found, or until the entire graph has been searched.
* @param rerankK the number of (approximately-scored) results to rerank before returning the best `topK`.
* @param threshold the minimum similarity (0..1) to accept; 0 will accept everything. May be used

@ashkrisk ashkrisk Aug 27, 2026

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.

Most of the Javadocs for the *search* functions in this file either imply or explicitly state that threshold = 0 will accept everything. We should probably update all of the affected lines to make it clear that this isn't true, and that users should use Float.NEGATIVE_INFINITY if they really want to accept everything.

int topK,
float threshold,
Bits acceptOrds) {
return search(scoreProvider, topK, topK, threshold, 0.0f, acceptOrds);

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.

Should we set the rerankFloor parameter here to Float.NEGATIVE_INFINITY instead of 0.0f?

int topK,
Bits acceptOrds)
{
return search(scoreProvider, topK, 0.0f, acceptOrds);

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.

Similarly, here we might want to change the hard-coded threshold parameter from 0.0f to Float.NEGATIVE_INFINITY

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GraphSearcher Assertion can fail for dot product when all candidates score negative

2 participants