SHARE
Teams building generative recommenders and designing item codes should read this. It leaves the generator alone and changes how item codes are made. Current practice merges category, title, and description into one vector and slices it into codes, so no code position has a clear meaning. CoFiRec makes the first positions correspond to category, title, and description, reserves the last for collaborative-filtering signals, and generates from coarse to fine. This work from the University of Illinois Urbana-Champaign and Meta ranks first on Recall@10 and NDCG@10 across three public datasets; on Instruments, Recall@10 rises from TIGER's 0.1035 to 0.1118; on rarely seen cold-start items, Recall@10 rises from 0.0801 to 0.0943, a larger gain than on popular items.
What problem is it actually solving?
Generative recommendation gives each item a string of discrete codes (Semantic IDs), and the model generates the next item's code position by position from the user history. In TIGER and similar methods, category, title, and description are concatenated, encoded into one vector, and sliced by residual quantization: the first code roughly approximates the vector, the second approximates what is left, and so on.
These codes have an order, but what each position means is unclear. An illustrative example: a user recently bought guitar strings and picks and wants a beginner electric guitar next.
| Position | Meaning in TIGER-style codes | Meaning in CoFiRec codes |
|---|---|---|
| 1 | Coarse approximation, mixing category and brand | Category: guitars |
| 2 | Residual left by position 1 | Title: beginner electric guitar |
| 3 | Residual again | Description: Yamaha Pacifica series |
| 4 | Residual again | Collaborative filtering: what it is bought with |
(Items and meanings are illustrative; the code structure follows Figure 2 of the paper.)
The authors start from how people shop: category first, then type, then series, then the exact item. If codes follow that order, the model's first step only decides "is the next item a guitar?", and each later step refines within the range already fixed. When each position has a clear meaning, each step is an easier decision and less likely to send the rest astray.
The pipeline: layered codes, then coarse-to-fine generation

- Tokenizer: each item gets four codes, three from the text fields and one from a collaborative-filtering vector.
- Generator: T5 reads the history's code sequence and generates the next item's codes in order, with beam search (keeping the 20 best partial paths per step) producing the list.
The key split: text narrows the range from category down to the exact style, and collaborative signals separate items that look almost identical.
Tokenizer: one code per text layer
Why not merge the text? Merged, category and description share one vector, every code carries both, and the first codes no longer correspond to the coarse category. CoFiRec encodes each field with LLaMA-7B, projects it with a small network shared across the three layers, and picks the nearest entry in that layer's own codebook; the entry's index is the code. Items missing a category get one extracted from the title or description. Training uses a reconstruction loss and a commitment loss that keeps projected vectors close to their chosen entries.
Why put collaborative filtering last?
Two items with nearly identical text, such as two colors of the same guitar, cannot be told apart by text. A collaborative-filtering vector records who bought an item and what it is bought with. CoFiRec takes each item's vector from a pretrained SASRec and quantizes it with its own encoder and codebook as code 4. It is most useful once category and style are fixed. Replacing code 4 with another text code drops Recall@10 from 0.1118 to 0.1082.
How does the generator know each code's role?
Each input embedding gets two learnable additions: one for the layer and one for the item's position in the history. Training uses a per-layer softmax that ranks the correct code above other codes in that layer.
Why coarse to fine? A worked example
The authors treat all items as leaves of a four-level tree. The gap between two items is set by where they branch: branching at level 3 means category and type match and the gap is 2; branching at level 1 gives a gap of 4. Suppose each level is guessed correctly with probability 0.5 (illustrative). Coarse to fine, the chance of matching the first one, two, three, and four levels is 0.5, 0.25, 0.125, and 0.0625; the expected gap is 4 minus their sum, about 3.06. For codes without hierarchy, the paper approximates prediction as picking a leaf at random, so matching level 1 by chance is 1/V (V is codes per layer; with an illustrative 256 that is about 0.004) and the expected gap is nearly 4. The authors' reasoning is that without hierarchy a correct code does not mean the same category. In my view the point is that with hierarchy, partial correctness counts, but the two settings are not strictly comparable, so the real evidence is the experiments.
Results: is it actually better?
Data are Amazon Instruments and Beauty plus Yelp, with each user's last interaction held out. From Table 1 of the paper:
| Dataset | Metric | SASRec | TIGER | IDGenRec | CoFiRec |
|---|---|---|---|---|---|
| Instruments | Recall@10 | 0.0947 | 0.1035 | 0.0999 | 0.1118 |
| Instruments | NDCG@10 | 0.0690 | 0.0782 | 0.0785 | 0.0820 |
| Beauty | Recall@10 | 0.0588 | 0.0353 | 0.0550 | 0.0679 |
| Beauty | NDCG@10 | 0.0313 | 0.0283 | 0.0311 | 0.0370 |
| Yelp | Recall@10 | 0.0296 | 0.0270 | 0.0323 | 0.0395 |
| Yelp | NDCG@10 | 0.0152 | 0.0173 | 0.0195 | 0.0208 |
CoFiRec is best on both metrics everywhere, showing that changing only the codes beats existing generative methods. Order matters too: reversing the four codes drops Instruments Recall@10 to 0.1047, and shuffling them to 0.0991, so the gain is not only from layering.
For cold start, the authors count how often each item appears as the next item to predict and test the 2% least frequent separately. Recall@10 rises from 0.1038 to 0.1101 on popular items and from 0.0801 to 0.0943 on cold items. Rare items have few interactions but do have a category and title, so layered codes place them under the same prefix as similar popular items.

Limitations as I see them
First, it does not win every metric: Yelp NDCG@5 is 0.0162, slightly below IDGenRec's 0.0165; business listings are less cleanly layered than products.
Second, the larger-backbone test is small. On sampled Instruments data, CoFiRec under LLaMA-3B has Recall@5 and Recall@10 both at 0.0403, so the test set is too small to separate top 5 from top 10.
Third, it relies on tidy metadata. The GPT-4o auto-hierarchy experiment used only 1% of users and 2,258 items.
How a recommendation team could try it
- Check metadata coverage for category, title, and description; if gaps are large, try LLM-generated layers first.
- Swap only the tokenizer, keep the generator, and compare Recall@10 and NDCG@10.
- Evaluate cold start separately by item age or interaction count; that is where gains are most likely.
- Start from the paper's codebook sizes: 512 entries for codes 3 and 4 beat 256 everywhere, while 1024 was worse.
Verdict
The key lesson: every code position should have a clear meaning, ordered the way users make decisions.
| Dimension | Assessment |
|---|---|
| Problem importance | High. Code quality caps generative recommendation, and cold start is a key hope for it |
| Novelty | Medium. Layered codes are intuitive; the contribution is combining text layers, collaborative filtering, and generation order |
| Evidence | Medium. Three datasets, ablations, cold-start analysis, but small data and a tiny backbone test |
| Engineering cost | Medium. Three text encodings plus a separate collaborative encoding |
| Worth trying | Yes, for product recommendation with tidy metadata and many new items |
How did this read for you?
Hoot made a note. Thanks for the feedback.
One tap, no sign-in; tap again to undo. Only anonymous counts are kept, never who you are.
Discussion
Add experiment details, reproduction notes or a different take. Requires a GitHub sign-in.
Loading the discussion…