Skip to content

phoenix/

A two-stage Grok-style recsys.

Retrieval narrows millions of posts to thousands. Ranking scores those thousands with a transformer that is not allowed to let candidates look at each other.

STAGE 1

Retrieval

Two-tower. Your history embedding against a semantic-ID index.

millions → thousands

→
STAGE 2

Ranking

Transformer with candidate isolation. Score(A) does not depend on B.

thousands → ordered

corpusretrievedranked
Production training lives in phoenix/xrex. A nano config trains on one GPU with synthetic data.

Retrieval — two towers

No learned user-ID embedding. You are what you interacted with. Candidates are semantic IDs — 6 × 256 residual-quantized codes from multimodal embeddings — plus hashed author IDs.

USER TOWER

History transformer

  • Engagement sequence
  • Profile token · no user ID
  • Normalized embedding [B, D]
dot·top-K
CANDIDATE TOWER

Semantic-ID index

  • 6 × 256 residual codes
  • Hashed author IDs
  • Stored in the checkpoint
Serving loads post_embeddings from the checkpoint and retrieves by dot product. Same-topic posts share SID prefixes, so unseen posts still compose.

Ranking — candidate isolation

The ranker sees user tokens, history, and candidates. History can attend normally. Candidates may attend to the user and the history — never to other candidates. The score for post A does not depend on whether post B is in the batch, so scores are cacheable.

Rows attend to columns. Filled cells are allowed. Empty cells between candidates are the isolation rule.

Query ↓ / Key →UserHistoryABC
Userallowedallowedblockedblockedblocked
Historyallowedallowedblockedblockedblocked
Cand Aallowedallowedallowedblockedblocked
Cand Ballowedallowedblockedallowedblocked
Cand Callowedallowedblockedblockedallowed
Allowed Blocked
Candidates may attend to the viewer and to history — never to each other. That is why scores are cacheable.

What the ranker actually outputs

Logits for each action (like, reply, report, dwell, …) plus a dwell regression. Combining those into one number is Home Mixer's job, not the model's. Hash embeddings mean a brand-new post is representable immediately — there is no vocabulary to rebuild.

Phoenix

Ara

A short briefing for this page — not the whole text.