Skip to content

feat(semantic-search): add a minScore relevance floor on the semantic kNN path - #19270

Merged
alexjst merged 1 commit into
datahub-project:masterfrom
alexjst:feat-semantic-min-score-floor
Aug 20, 2026
Merged

feat(semantic-search): add a minScore relevance floor on the semantic kNN path#19270
alexjst merged 1 commit into
datahub-project:masterfrom
alexjst:feat-semantic-min-score-floor

Conversation

@alexjst

@alexjst alexjst commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Adds an optional minScore to SearchFlags and honors it on the semantic (kNN) search path. Hits scoring below the floor are dropped after the kNN returns, so a caller such as an agent can abstain ("nothing is relevant enough") instead of surfacing weak matches. An off-topic query that currently returns every result at a low score can now be given a floor so it returns nothing.

Post-kNN filtering keeps this engine-agnostic across the ES8 and OpenSearch shims. Wired end to end: model SearchFlags.pdl, the GraphQL SearchFlags input, and SearchFlagsInputMapper. When unset, no floor is applied and behavior is unchanged.


Summary by cubic

Adds an optional minScore relevance floor on the semantic (kNN) search path to drop low-scoring hits. Previously the semantic path returned weak, off-topic hits; now callers can set a floor so results below it are removed and empty results are possible. When unset, behavior is unchanged.

Details

  • Adds minScore to GraphQL SearchFlags and Pegasus SearchFlags; maps through SearchFlagsInputMapper.
  • Filters kNN hits with score < minScore in SemanticEntitySearchService before pagination; engine-agnostic across ES8 and OpenSearch.
  • Optional and limited to the semantic path; exact/keyword paths unchanged. Clients may set searchFlags: { minScore: <float> }. Tests cover mapping and filtering.

Written for commit 2e41db6. Summary will update on new commits.

Review in cubic

@github-actions

Copy link
Copy Markdown
Contributor

Linear: CAT-2970

Thanks for your contribution! We have created an internal ticket to track this PR. A member of the core DataHub team will be assigned to review it within the next few business days - you will get a follow-up comment once a reviewer is assigned.

@github-actions github-actions Bot added product PR or Issue related to the DataHub UI/UX community-contribution PR or Issue raised by member(s) of DataHub Community labels Aug 18, 2026

@cubic-dev-ai cubic-dev-ai Bot 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.

1 issue found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="metadata-io/src/test/java/com/linkedin/metadata/search/semantic/SemanticEntitySearchServiceTest.java">

<violation number="1" location="metadata-io/src/test/java/com/linkedin/metadata/search/semantic/SemanticEntitySearchServiceTest.java:227">
P2: Custom agent: **Enforce Pragmatic Test Coverage**

testSearchAppliesMinScoreFloor only covers the partial-drop path (0.95/0.80 kept, 0.50 dropped). The PR's core claim — an off-topic query with a floor returns nothing — is untested: no test drops all hits and asserts an empty result. Also, the test asserts only that retained scores are >= 0.75, not the exact values, and never covers a hit exactly at the floor even though the implementation keeps scores >= minScore. Add a case where every hit falls below the floor and assert numEntities 0 / empty entities, and cover the exact-value and equal-to-floor boundaries.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@@ -224,6 +224,27 @@ public void testSearchPagination() throws IOException {
assertEquals(result.getEntities().size(), 2); // Page size
}

@Test

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.

P2: Custom agent: Enforce Pragmatic Test Coverage

testSearchAppliesMinScoreFloor only covers the partial-drop path (0.95/0.80 kept, 0.50 dropped). The PR's core claim — an off-topic query with a floor returns nothing — is untested: no test drops all hits and asserts an empty result. Also, the test asserts only that retained scores are >= 0.75, not the exact values, and never covers a hit exactly at the floor even though the implementation keeps scores >= minScore. Add a case where every hit falls below the floor and assert numEntities 0 / empty entities, and cover the exact-value and equal-to-floor boundaries.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At metadata-io/src/test/java/com/linkedin/metadata/search/semantic/SemanticEntitySearchServiceTest.java, line 227:

<comment>testSearchAppliesMinScoreFloor only covers the partial-drop path (0.95/0.80 kept, 0.50 dropped). The PR's core claim — an off-topic query with a floor returns nothing — is untested: no test drops all hits and asserts an empty result. Also, the test asserts only that retained scores are >= 0.75, not the exact values, and never covers a hit exactly at the floor even though the implementation keeps scores >= minScore. Add a case where every hit falls below the floor and assert numEntities 0 / empty entities, and cover the exact-value and equal-to-floor boundaries.</comment>

<file context>
@@ -224,6 +224,27 @@ public void testSearchPagination() throws IOException {
     assertEquals(result.getEntities().size(), 2); // Page size
   }
 
+  @Test
+  public void testSearchAppliesMinScoreFloor() throws IOException {
+    setupMockKnnResponse(
</file context>

@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

@maggiehays maggiehays added the needs-review Label for PRs that need review from a maintainer. label Aug 18, 2026
… kNN path

Adds an optional minScore to SearchFlags and honors it on the semantic (kNN) path. Hits scoring below the floor are dropped after the kNN returns, so a caller such as an agent can abstain (nothing is relevant enough) instead of surfacing weak matches. Post-kNN filtering keeps it engine-agnostic across the ES8 and OpenSearch shims. Wired end to end: model SearchFlags.pdl, the GraphQL SearchFlags input, and SearchFlagsInputMapper. When unset, behavior is unchanged.
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@alexsku alexsku left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice — clean, well-scoped addition. Traced it end to end (GraphQL input → SearchFlagsInputMapper → opContext searchFlagsSemanticSearchServiceSemanticEntitySearchService) and the wiring, the type plumbing, and the inclusive >= floor all check out. Optional and inert when unset, so it's a safe additive change. The doc note that the score is a raw, non-normalized engine value needing per-deployment calibration is exactly the right caveat to call out.

Approving. One thing I'd still like, non-blocking:

Test the empty path. testSearchAppliesMinScoreFloor only covers a partial drop (0.95/0.80 kept, 0.50 dropped). The whole point of the floor is the abstain case — an off-topic query returning nothing — and that's currently untested. Worth adding a case where every hit is below the floor asserting numEntities == 0 / empty entities, plus a hit exactly at the floor to pin the inclusive >= boundary. (Same thing the cubic bot flagged.)

Two minor notes, no action needed:

  • minScore lives on the shared SearchFlags input, so a client that sets it on a keyword searchAcrossEntities gets a silent no-op. It's documented, but a bit of a footgun on a shared type — might be worth a warn, or a semantic-specific input, down the line.
  • The floor runs on the oversampled candidate window before slicing, so from > 0 pages with a floor set can come back short / under-count numEntities. Fine for the page-0 abstain use case, just flagging the interaction.

@alexjst
alexjst merged commit 2678076 into datahub-project:master Aug 20, 2026
135 of 139 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution PR or Issue raised by member(s) of DataHub Community needs-review Label for PRs that need review from a maintainer. product PR or Issue related to the DataHub UI/UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants