brain_query's "BM25" is raw substring counting: no IDF, no length normalisation, one-letter terms count every letter #203

Open
opened 2026-10-12 13:05:24 +00:00 by mathias · 0 comments
Owner

Observed (2026-10-12)

The full-sentence query "Ska jag köpa aktier i företaget jag jobbar på?" missed the 2 KB note that answers it exactly (wiki/rikatillsammans/decisions/aktier-i-arbetsgivaren.md). The top 5 were 20–30 KB guides on other topics. The keyword query aktiesparprogram arbetsgivaren ranked the note first.

Cause

ingestion/internal/search/search.go scores each file as sum over terms of strings.Count(lower, term), with terms split on whitespace:

  • No length normalisation: long notes win any query with common words.
  • No IDF: jag, i and på weigh as much as aktiesparprogram.
  • Substring matching: the term i counts every letter i, på? keeps its punctuation, and ränta matches inside räntan but also inside unrelated words.

This is then RRF-fused with vector search (k=60), which hides part of the problem when embeddings exist. Notes newer than the embed-sync interval (300 s) get BM25 only.

Effect

Sentence-style questions (how humans and agents ask) systematically surface the longest notes in a wing. Measured on 24 questions: the right guide made the top 5 in 23, but often at ranks 3–5 behind longer notes.

Proposal

Real BM25: tokenise on word boundaries (unicode letters and digits), lowercase, drop a small Swedish/English stopword list, apply IDF over the corpus, and use the k1/b length normalisation. Cache the corpus statistics and invalidate on write. Add table-driven tests with a short exact-match note against a long tangential note, and a Swedish query containing stopwords.

Evidence: mathias/rt-kunskap eval/results-2026-10-12.md section 3.

Risk: MEDIUM (ranking changes for every wing; compare before and after on a fixed query set)


Filed by the rt-kunskap session (Claude Code)

## Observed (2026-10-12) The full-sentence query "Ska jag köpa aktier i företaget jag jobbar på?" missed the 2 KB note that answers it exactly (`wiki/rikatillsammans/decisions/aktier-i-arbetsgivaren.md`). The top 5 were 20–30 KB guides on other topics. The keyword query `aktiesparprogram arbetsgivaren` ranked the note first. ## Cause `ingestion/internal/search/search.go` scores each file as `sum over terms of strings.Count(lower, term)`, with terms split on whitespace: - **No length normalisation:** long notes win any query with common words. - **No IDF:** `jag`, `i` and `på` weigh as much as `aktiesparprogram`. - **Substring matching:** the term `i` counts every letter i, `på?` keeps its punctuation, and `ränta` matches inside `räntan` but also inside unrelated words. This is then RRF-fused with vector search (k=60), which hides part of the problem when embeddings exist. Notes newer than the embed-sync interval (300 s) get BM25 only. ## Effect Sentence-style questions (how humans and agents ask) systematically surface the longest notes in a wing. Measured on 24 questions: the right guide made the top 5 in 23, but often at ranks 3–5 behind longer notes. ## Proposal Real BM25: tokenise on word boundaries (unicode letters and digits), lowercase, drop a small Swedish/English stopword list, apply IDF over the corpus, and use the k1/b length normalisation. Cache the corpus statistics and invalidate on write. Add table-driven tests with a short exact-match note against a long tangential note, and a Swedish query containing stopwords. Evidence: `mathias/rt-kunskap` `eval/results-2026-10-12.md` section 3. **Risk:** MEDIUM (ranking changes for every wing; compare before and after on a fixed query set) --- _Filed by the rt-kunskap session (Claude Code)_
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/hyperguild#203