Skip to content

fix(search): make equal-score ranking deterministic#46

Open
saagpatel wants to merge 1 commit into
devwhodevs:mainfrom
saagpatel:agent/deterministic-search
Open

fix(search): make equal-score ranking deterministic#46
saagpatel wants to merge 1 commit into
devwhodevs:mainfrom
saagpatel:agent/deterministic-search

Conversation

@saagpatel

Copy link
Copy Markdown

Refs #44 and #34.

What changed

  • Add stable tie-breakers to RRF fusion, graph expansion, reranker/temporal ordering, file deduplication, and merged search seeds.
  • Add chunks(file_id) indexing and an id tie-break for best-chunk selection.
  • Add a model-free golden search battery that repeats expected rankings ten times.

Why

Several result collections originate in HashMaps. Equal-score entries therefore inherited randomized map iteration order, which could change ranks, confidence, and graph-expansion truncation across otherwise identical searches. The graph lane also repeatedly looked up chunks by file_id without an index.

Impact

Searches with score ties now produce stable ordering, and graph best-chunk lookups avoid full chunk-table scans. Non-tied ranking semantics are unchanged.

Validation

  • cargo fmt --check
  • cargo clippy -- -D warnings
  • cargo test --lib — 468 passed
  • cargo test --test golden_search — passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f73f2972d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/search.rs
b.score
.partial_cmp(&a.score)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| a.file_path.cmp(&b.file_path))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve pass-one order for tied rerank scores

When the reranker assigns the same score to multiple candidates, including the existing unwrap_or(0.0) path when scoring fails, this tie-break turns the rerank lane into an alphabetical ranking. Because the rerank lane is fused with a nonzero weight, equal reranker scores can now promote alphabetically earlier files over candidates that were ranked higher by pass 1; the deterministic tie-break here should preserve the existing fused_pass1 candidate order instead of using file_path.

Useful? React with 👍 / 👎.

Comment thread src/search.rs
b.score
.partial_cmp(&a.score)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| a.file_path.cmp(&b.file_path))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve base relevance for equal temporal scores

For temporal queries where several candidates fall inside the requested date range, temporal_score gives them identical scores, so this tie-break makes the temporal lane rank those equally timed notes alphabetically. Since the temporal lane has a high RRF weight, that can push alphabetically earlier paths above more relevant base results even though the temporal signal did not distinguish them; tie scores should keep the base_fused order to preserve the existing relevance signal deterministically.

Useful? React with 👍 / 👎.

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.

1 participant