How to Build Hybrid Search With Weaviate and OpenAI Embeddings

October 12, 2026

Pure vector search is great at meaning and terrible at exact strings. Ask for “SKU-4471B” and an embedding may return something merely similar. Keyword search has the opposite problem. Weaviate ships hybrid search that runs both and merges the results.

Quick answer: Use col.query.hybrid(query="...", alpha=0.5, vector=vec). The alpha parameter sets the blend: 0 is pure keyword, 1 is pure vector, 0.5 splits them evenly.

Getting the blend right matters more than most teams think. The default 0.5 is rarely the best value for real data.

How does the alpha parameter work?

Alpha controls the rank fusion between BM25 keyword scores and vector distance. Low alpha leans keyword, high leans semantic.

alpha Behavior Good for
0.0 Keyword only (BM25) Codes, names, IDs
0.25 Keyword-leaning Product catalogs, legal
0.5 Balanced General docs
0.75 Semantic-leaning Support questions
1.0 Vector only Paraphrase-heavy text

How do you generate and store embeddings?

from openai import OpenAI
import weaviate

oc = OpenAI()
client = weaviate.connect_to_local()
col = client.collections.get("Product")

resp = oc.embeddings.create(
    model="text-embedding-3-small",
    input="Wireless noise-cancelling earbuds")
vec = resp.data[0].embedding  # 1536 dims

col.data.insert(properties={"title": "Earbuds", "sku": "SKU-4471B"}, vector=vec)

text-embedding-3-small costs $0.02 per million tokens, which makes embedding a 100,000-document catalog a few dollars. Big models are not always better here; small is often enough for search.

How do you run a hybrid query?

q = "waterproof earbuds SKU-4471B"
qv = oc.embeddings.create(model="text-embedding-3-small",
                          input=q).data[0].embedding

res = col.query.hybrid(query=q, vector=qv, alpha=0.4, limit=10)
for o in res.objects:
    print(round(o.metadata.score, 3), o.properties["title"])

Scores are normalized to 0-1, which makes thresholds easy to reason about. Anything under about 0.6 is usually noise.

How do you tune alpha without guessing?

Build a set of 20-30 real queries with known good answers. Run them across alpha values from 0 to 1 in steps of 0.2 and measure how often the right document lands in the top 3. Pick the winner. This takes an afternoon and usually beats gut feel by a wide margin.

What are the practical limits?

  • Hybrid needs both a vector and the text indexed; storing vectors only disables the keyword half.
  • BM25 tokenization matters — compound SKUs need the right analyzer or they split wrongly.
  • Two searches per query means slightly higher latency than vector-only.
  • Embedding costs scale with document count and any re-indexing you trigger.

Who this suits: catalogs, documentation sites, and support systems where users mix natural language with exact identifiers. Who should skip it: if all your queries are fuzzy and long, a pure vector search is simpler and only slightly worse.

Quick Summary

  • Hybrid search fuses BM25 keyword scores with vector similarity.
  • Control the mix with alpha: 0 keyword, 1 vector, 0.5 balanced.
  • Start at alpha 0.4 for catalogs, then tune against real queries.
  • text-embedding-3-small is cheap enough for large catalogs.
  • Scores are normalized 0-1; treat sub-0.6 results as weak.