MemorySyncMemorySync
Retrieval

Semantic Ranking

Recall's ranker fuses seven factors into a single hybrid score, then applies a small set of additive boosts. Every weight, half-life, and tiebreak in this page comes from the recall engine source.

The default formula

TEXT
hybrid_score = 0.40 * semantic_norm
              + 0.20 * cluster_norm
              + 0.15 * recency_norm
              + 0.15 * importance_norm
              + 0.10 * usage_norm

Weights are normalised to sum to 1 even if a caller overrides them. Quality, decay, and graph factors are also computed, but their default weights are 0 — they are kept available for explainability and for callers who want to opt them in.

Semantic factor (weight 0.40)

Cosine similarity from the vector search, mapped to 1 - clamp(distance, 0, 1). This is the only factor that takes the query string into account directly.

Recency factor (weight 0.15) — half-life by intent

Detected query intentHalf-life
HIGH (recency-sensitive)24 hours
MEDIUM (default)72 hours
LOW (background knowledge)168 hours (7 days)

Score formula: recency_score = exp(-hours_since_created * ln(2) / half_life). Older memories decay logarithmically rather than dropping off a cliff.

Importance factor (weight 0.15)

The importance column is in [0, 1] and feeds in directly. It defaults to 0.5 when the caller did not provide one. The ranker does not use the platform-computed importance_score here — that field drives the cost gate, not recall.

Usage factor (weight 0.10) — log-scale

usage_score = min(1.0, log(1 + usage_count) / 5.0). The log keeps a memory recalled a thousand times from drowning out a memory recalled five times.

Cluster factor (weight 0.20)

When the cluster weight is non-zero, each memory's score includes the cosine similarity between the query vector and the centroid of the memory's cluster. Mapped from [-1, 1] to [0, 1] for normalisation parity. Centroids are bulk-loaded in a single round trip per query batch.

Per-batch normalisation

Every factor is min-max normalised using only the memories in the current result batch — not global stats. Two consequences worth remembering:

  • Adding a high-scoring outlier to the batch suppresses everyone else proportionally.
  • The same memory can score differently between batches because the normalisation reference set has changed. This is intentional.

The variance floor tiebreak (σ < 0.02)

If the per-batch standard deviation of hybrid_score falls below 0.02, the ranking is essentially flat. The engine then applies a deterministic tiebreak chain: (semantic_score desc, importance desc, recency desc, id desc). The response carries tiebreak_applied=true so callers can tell when this fired.

Additive boosts on top of the hybrid score

BoostMagnitudeWhen it fires
supports edge+0.08Multi-hop traversal lands on this memory through a supports edge.
extends edge+0.07Reached via an extends edge.
continuation+0.06Reached via a continuation edge.
detail_of+0.05Detail-of edge.
summary_of+0.04Summary-of edge.
similar / references+0.03 eachSimilar / references edges.
derived_from / caused_by+0.02 eachDerivation or causal edges.
contradiction+0.01A contradicting memory is surfaced for explainability.
Personalisationup to +0.10 (capped)Memory matches an entity or topic the user has shown affinity for.
Session continuity+0.03The memory was returned earlier in the same session_id.

Adaptive weights when the caller skips them

If the request omits weights, the engine inspects the query features and picks an intent-aware weight profile — factual queries get more semantic, recent-news queries get more recency, analytical queries get more graph. This is a soft tweak; the floor is always the default profile above.