Home· Features· AI Search & Semantic
🧠 AI Search & Semantic

Four search modes. One smart router.

Skryx picks the right backend per query — keyword for SKUs, semantic for questions, hybrid for the messy middle — and merges results with Reciprocal Rank Fusion so you never pay for AI you don't need.

Growth Scale Enterprise
SearchModeRouter::decide($q)
"WH-1000XM5"keyword // SKU pattern
"sony"keyword // single word
"iphone 15"keyword // brand+model
"wireless headphones"hybrid // 2 words
"laptop for editing"hybrid // 3 words
"how do I fix charging"semantic // question
"headphones for travel"semantic // 4+ desc.
The router

A heuristic that knows when not to use AI.

Every search through Skryx hits SearchModeRouter. It runs ten cheap checks (in order) and picks the cheapest mode that can answer the query. Most importantly: it knows when keyword is enough, so you don't pay for an embedding call on "iPhone 15 Pro 256GB".

// SearchModeRouter::decide() — actual order of checks
1.  plan quota exhausted              → keyword
2.  caller passed search_mode=…        → respect it
3.  q is empty or "*"keyword
4.  q is "quoted"keyword  (cost saver)
5.  q matches SKU regex                → keyword  /^[A-Za-z]{2,5}[\-_]?\d{3,9}…/
6.  q is one word                      → keyword
7.  q is brand+model (2–3 words,
       last token has 2+ digits)        → keyword
8.  q is two words                     → hybrid
9.  q ends with "?" or contains
       how/why/cum/care nu/best …      → semantic
10. q is 6+ words                      → semantic
default (3–5 words)                    → hybrid

// AFTER keyword leg of a hybrid query:
// if keyword returned 5–30 hits, skip the vector call → keyword only
                
The four modes

Each one is overridable per query.

🔤 keyword

The classic engine path, tuned for precision.

Pure full-text search through the Skryx engine. Typo tolerance is on (per-index num_typos, default 2 with a length floor), prefix matching is on by default, stop-words are stripped per index, and ranking rules + custom-ranking tiebreakers all apply.

  • Cheapest mode — no embeddings, no LLM calls
  • Wins on SKUs, brand names, exact titles
  • Default for free / Starter tenants and any tenant without a semantic quota
// Request
POST /v1/indexes/products/query
{ "q": "WH-1000XM5",
"search_mode": "keyword" }
🧠 semantic

Vector-only search for natural-language queries.

Skryx embeds the query (cached 3 ways), runs an HNSW nearest-neighbour lookup against per-document vectors, and returns the closest matches by cosine distance. Results below the per-index confidence threshold are dropped (default 0.65 for main hits, 0.50 for related).

  • Used for questions, problem queries, and any 6+ word phrase
  • Document text = title × 3 + brand + category + description (capped)
  • Embedding field is always stripped from API responses (~14 KB / hit saved)
{
  "q": "phone won't charge",
  "search_mode": "semantic",
  // engine returns
  "hits": [
    { "vector_distance": 0.42,
      "document": "USB-C charging cable" },
    { "vector_distance": 0.48,
      "document": "Wireless charger" }
  ]
}
🪡 hybrid

Keyword + vector, merged via Reciprocal Rank Fusion.

Runs both legs (keyword first, then vector if needed), then merges the two rank lists with the standard RRF formula score = 1/(60 + rankk) + 1/(60 + rankv). Documents that appear in both lists are boosted (sum of contributions); pure-semantic matches that pass the confidence threshold ride along.

  • RRF constant k = 60 — equal weight, no per-leg tuning required
  • Confidence-tier split: main hits + a separate related_hits array (similarity 0.50–0.65)
  • Smart skip: if the keyword leg already returns 5–30 hits, the vector call is skipped (saves an embedding)
{
  "hits": [
    { "match_type": "hybrid",    // in both lists
      "document": { "id": "sku-001" } },
    { "match_type": "keyword",
      "document": { "id": "sku-002" } },
    { "match_type": "semantic",
      "document": { "id": "sku-003" } }
  ],
  "related_hits": [ /* similarity 0.50–0.65 */ ]
}
⚙️ auto

The router picks for you, per query.

The default mode for every index. You can override per query by passing search_mode, or change the index default in Search Settings. Tenants who don't think about it get the right behaviour automatically; tenants who want control have full control.

  • Set per-index in search_mode_default
  • Override per query via ?search_mode= or POST body
  • Override always wins (rule #2 in the router)
// Search Settings · per index
search_mode_default: auto
semantic_config:
threshold: 0.65
related_threshold: 0.50
max_results: 30
Query understanding

An optional rewrite step for vague queries.

Before the engine runs, queries that look uncertain get rewritten by Skryx AI into a tighter, in-language form. The rewrite is conservative, cached, and gated by your monthly AI quota — so it doesn't fire on queries that don't need it.

When it fires

4+ words, a question marker, or a buying-intent phrase.

Skips empty, SKU, single- and two-word queries (unless they contain ?, how, why, best, recommend, care, pentru, cum). Triple cache: per-request memo → DB cache table → fresh call. Triple gate: heuristic check → cache check → monthly quota slot.

  • Language detected by quick heuristic (RO markers: ă â ț ș î)
  • Rewrite returned in user's language (≤ 6 words)
  • Optional user_message for "Showing results for X" banners
{
  "intent":    "buy_part",
  "rewritten_query": "usb-c charger 65w",
  "alternative_queries": [
    "fast charger usb c",
    "laptop charger 65w"
  ],
  "detected_problem": null,
  "use_case":   "laptop charging",
  "confidence": "high",
  "user_message": "Showing 65W USB-C chargers"
}
Embedding pipeline

Three caches, one quota, live progress.

1

Pick your model

At enable time. Four Skryx embedding models are available, ranging from 512-dim (fast, cheap) to 1024-dim (highest recall). Cost per million tokens is shown in the dashboard before you commit.

2

Index the catalog

GenerateEmbeddingsJob walks every document, builds the text-rep (title × 3 + brand + category + description capped), batches embedding calls, persists vectors to the engine. Per-batch retry with backoff; live progress updates after every batch.

3

Stay in sync

Every document POST/PATCH queues an EmbedDocumentsJob for just that doc. Title or description edits trigger a re-embed; price / stock edits don't. The engine field stays consistent without full re-indexes.

3 ×
Query embedding cache: per-request memo · 24 h Redis · persistent table
RRF k=60
Reciprocal Rank Fusion · the standard hybrid blend, no per-leg knobs
0.65 / 0.50
Default main / related similarity thresholds · per-index configurable
Multi-lingual today

The embedding model is multi-lingual by design.

A French query against an English catalog still works — the underlying Skryx embedding model maps both into the same vector space. Query understanding detects Romanian vs English and keeps the rewritten query in the original language. Per-language synonyms and per-language Romanian morphology layer on top via the Synonyms & Typo module.

Keep exploring

Other things Skryx does

Try it on your own catalog.

Free tier, no credit card. EU-hosted from day one.