RecomNext

Logic & algorithms

Recommendation logics and algorithm deep dives.

05 - Logic types & algorithms

Related: ML models · Worked examples

Search algorithms are omitted from this pack.

Matrix

LogicIntentRequired inputsDefault algorithmAlso available
user-to-itemPersonalized “for you”userIdweighted-historyelsa-cf, realm-sequential
item-to-itemRelated to one productitemIdco-occurrenceelsa-cf
items-to-itemsRelated to a set (cart)itemIds[]multi-seed-co-occurrencemulti-seed-hybrid
similar-productsContent/vector similarityitemIdvector-similaritybeeformer-multimodal
recently-viewedRecency of viewsuserIdrecency-

1. user-to-item → weighted-history (default)

Idea

Rank items the user already engaged with by weighted interaction strength, then fill with popular items if needed.

Score

total_weight(item) = Σ event.weight × type_multiplier(type)
window = last 30 days
type_multiplier: purchase=4, rating=3, cart=2, else 1

Over-fetch count × 4. If still short, append 7-day popular items with score 0.5 when no personal weight.

Option B (geo, v1): when the request has a country and the personal list is short, the 7d popular fill is a shrinkage blend of country / cluster / global counts (k = 500):

α_c = n_c / (n_c + 500)
α_r = n_r / (n_r + 500) * (1 - α_c)
α_g = 1 - α_c - α_r
blended_count(item) = α_c·count_c + α_r·count_r + α_g·count_g

Personal 30d scores are not geo-sliced and not lifted. Fill scores stay 0.5. Geo only changes which IDs are appended and fill order (blended_count desc). If the personal list is already full, skip geo popular queries. Unclustered country (no clusterFor) blends country+global only.

Blend-miss limitation: each grain query is top-N by its own count, then blend in-app. An item that is mediocre on every grain list but would win only after blending can miss all three cuts. Rare; the engine does not re-rank the global list only.

Constraints can still clip fill: diversity, segments, purchase cap, and filters run after append and can drop or reorder geo-popular IDs. Geo fill does not guarantee those IDs appear in the final list.

Flow

Tweaks

  • Scenario filter/boosters/constraints as usual.
  • Event quality & identity merge dominate accuracy.
  • Type multipliers are code constants (not Admin fields).

2. item-to-item → co-occurrence (default)

Idea

“Users who interacted with seed also interacted with …”

Score

co_count = number of user co-interactions between seed and candidate in 30 days (self-join on user_id).

Fallback: same category catalog items with score 0.5.

Flow

Example

If 40 users touched both seed S and item R in 30d, R scores 40 (before boosters).

Geo lift: when country is set, applyGeoLift multiplies co_count (and category-fill 0.5) before filters/boosters. Lift can be below 1 when the item’s 7d regional rate lags global — that is intended, not a bug.

Tweaks

  • Needs enough overlapping users; sparse catalogs rely on category fallback.
  • Pass userId to enable purchase cap.

3. items-to-items → multi-seed-co-occurrence (default)

Idea

Aggregate co-occurrence across multiple seeds (cart). Candidates matching a seed category get a ×2 category boost (legacy hardcoded).

Score (simplified)

base = aggregated co_count across seeds
score = base × (2 if category matches any seed else 1)

Fallback: same-category catalog fill.

Geo lift: same applyGeoLift as item-to-item (including the hybrid empty-union fallback that returns this path).

Tweaks

  • Prefer this for classic cart rails.
  • For vector+co fusion, switch algorithm to multi-seed-hybrid.

4. items-to-items → multi-seed-hybrid

Idea

Fuse collaborative (multi-seed co-occurrence) and vector (Qdrant) ranked lists with RRF, with strategies:

StrategyBehavior
rrfPer-seed fan-out + RRF fuse
centroidAverage seed vectors → one Qdrant query (good when cart is homogeneous)
adaptiveHomogeneity ratio unique(seed categories)/seedCount; ≤0.5 → centroid, else RRF fan-out

RRF contribution per list:

score(id) += 1 / (rrfK + rank_index + 1)

Typical rrfK ≈ 60 (configurable). Missing legs degrade gracefully (union of available lists).

Key hybridSettings

KnobRole
enabledIf false → fall back to multi-seed-co-occurrence
strategyrrf / centroid / adaptive
rrfK, coTopK, vectorTopKFusion / fan-out sizes
minCoSupportMin distinct seeds that must support a candidate
categoryBoostMultiplier for category match (hybrid path)
qdrantSettingsVector engine tuning (threshold, ef, …)

V1 fusion mode is RRF (weighted fusion reserved).

Geo lift: applied on the fused list before applyScenario. Do not double-lift if the request already fell back to multi-seed-co-occurrence.


5. similar-products → vector-similarity (default)

Idea

Nearest neighbors of the seed’s embedding in Qdrant.

Score

Qdrant similarity score (higher = closer). Settings from tenant defaults + scenario qdrantSettings:

KnobRole
score_thresholdDrop weak neighbors
hnsw_efSearch quality vs latency
filter_categoriesRestrict neighbor categories
quantization_rescore / oversamplingQuantized index behavior

Flow

Geo lift: applyGeoLift on Qdrant scores before scenario (same formula as i2i). Lift can be < 1.

Tweaks

  • Embedding template / reindex quality dominates.
  • Raise threshold → fewer but “stronger” neighbors; may trigger minItems auto-relax.

6. recently-viewed → recency

Idea

Items the user viewed in 30d, ordered by most recent view time.

Notes

  • Uses type = 'view' only for ordering source.
  • Still runs through scenario post-process when a scenario is attached.
  • Accepts request country but ignores it for rank and cache (not geo-ranked).

7. ML algorithms (summary - details in ch.06)

AlgorithmLogicsOnline scoring
elsa-cfuser-to-item, item-to-itemDot product of user↔item or item↔item factors; fallback to weighted-history / co-occurrence if factors missing
realm-sequentialuser-to-itemSession/sequence-aware next-item from GRU factors; fallback weighted-history
beeformer-multimodalsimilar-productsNN in Qdrant using beeFormer embeddings

Geo lift on ML factors: when factors exist, lift runs on factor scores before scenario (same formula as i2i / similar). Fallbacks inherit that path’s geo rules (weighted-history = Option B fill only; co-occurrence = lift). Lift can be < 1.


Choosing logic for a placement

Driffle PDP similar rail uses similar-products + scenario pdp-similar-products (vector path).