Lexical vs Hybrid Search

Last updated:

Lumo Cloud supports two search modes: pure lexical (BM25F) and hybrid (BM25F + semantic reranking). This page explains how they work and when to use each.

Lexical Search (Default)

Every collection uses BM25F lexical scoring by default. This is the same algorithm used by Elasticsearch and other production search engines. It works by:

  • Tokenizing documents and queries into terms
  • Computing term frequency (TF) and inverse document frequency (IDF)
  • Applying field weights so title matches rank higher than body matches
  • Using trigram matching for typo tolerance
  • Boosting exact matches (2x) and prefix matches (1.25x)

Lexical search is fast, predictable, and works well when users search with specific keywords that appear in the documents.

Hybrid Search (Semantic Reranking)

When semantic reranking is enabled, Lumo Cloud adds a second scoring pass:

  1. At index time, each document is embedded using Amazon Bedrock Titan Embed V2 (1024 dimensions)
  2. At search time, the query is embedded with the same model
  3. BM25F produces a ranked candidate list (lexical scores)
  4. Cosine similarity is computed between the query embedding and each candidate's embedding
  5. Final score = α × lexical + (1-α) × semantic, where α defaults to 0.7

This means lexical relevance still dominates (70% weight), but semantic similarity can promote results that are conceptually related even if they don't share exact keywords.

When to Use Each

ScenarioRecommended
Product catalog with SKUs and exact namesLexical
Documentation with technical termsHybrid
FAQ or knowledge baseHybrid
Autocomplete / search-as-you-typeLexical
Natural language questionsHybrid
Minimal latency requiredLexical

Tuning the Alpha Parameter

You can control the blend ratio per query by passing semanticAlpha in the search request:

const results = await search.search('how to find things', {
  semanticAlpha: 0.5  // 50% lexical, 50% semantic
})
  • 1.0 — pure lexical (semantic disabled)
  • 0.7 — default (lexical-dominant hybrid)
  • 0.5 — balanced blend
  • 0.3 — semantic-dominant

Checking the Response

The API response includes meta.semanticReranking to indicate whether reranking was applied:

{
  "results": [...],
  "meta": {
    "collection": "products",
    "queryTimeMs": 12.5,
    "semanticReranking": true
  }
}

If semanticReranking is false, the collection either doesn't have semantic enabled or the embedding provider wasn't available. Results fall back to pure lexical scoring — the search never fails.