Skip to main content
Semantic (vector) search captures meaning; keyword (BM25) search captures exact terms. Hybrid search blends both with one parameter, alpha, set on QueryOptions. As with all queries, load the index first with load_index() (or open a session).

The alpha parameter

alphaBehavior
1.0Pure semantic (embeddings only)
0.0Pure keyword (BM25 only)
betweenBlends the two; default is semantic-heavy at 0.8

Example

import asyncio
from moss import MossClient, QueryOptions

async def main():
    client = MossClient(MOSS_PROJECT_ID, MOSS_PROJECT_KEY)
    await client.load_index("faqs")   # required before querying

    # Blend semantic and keyword scoring (60/40).
    hybrid = await client.query("faqs", "return policy", QueryOptions(top_k=3, alpha=0.6))

    # Pure keyword.
    keyword_only = await client.query("faqs", "return policy", QueryOptions(top_k=3, alpha=0.0))

    # Pure semantic (the default leans here at 0.8).
    semantic_only = await client.query("faqs", "return policy", QueryOptions(top_k=3, alpha=1.0))

    for doc in hybrid.docs:
        print(f"{doc.id} score={doc.score:.3f} {doc.text}")

asyncio.run(main())
alpha also applies inside a session query and composes with metadata filtering:
session = await client.session(index_name="call-123")
await session.query("billing dispute", QueryOptions(top_k=3, alpha=0.6))

Choosing alpha

  • Lower alpha (toward keyword) when queries contain exact identifiers, SKUs, names, or jargon.
  • Higher alpha (toward semantic) when queries are natural-language paraphrases.
  • Tune per index and per intent (returns, billing, onboarding, and so on).

Behavior notes

  • If you omit alpha, it defaults to 0.8.
  • alpha is ignored for multi-index search, which is embedding-only.

Metadata filtering

Constrain results by document metadata.

Custom embeddings

Bring your own vectors.