Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ The table below lists the recommendation models/algorithms featured in Cornac. E

| Year | Model and Paper | Type | Environment | Example |
| :--: | --------------- | :--: | :---------: | :-----: |
| 2025 | [Generating Long Semantic IDs in Parallel for Recommendation (RPG)](cornac/models/rpg), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.rpg.recom_rpg), [paper](https://arxiv.org/abs/2506.05781) | Next-Item / Content-Based | [requirements](cornac/models/rpg/requirements.txt), CPU / GPU | [quick-start](examples/rpg_example.py)
| 2024 | [Comparative Aspects and Opinions Ranking for Recommendation Explanations (Companion)](cornac/models/companion), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.companion.recom_companion), [paper](https://lthoang.com/assets/publications/mlj24.pdf) | Hybrid / Sentiment / Explainable | CPU | [quick-start](examples/companion_example.py)
| | [Hypergraphs with Attention on Reviews (HypAR)](cornac/models/hypar), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.hypar.recom_hypar), [paper](https://doi.org/10.1007/978-3-031-56027-9_14)| Hybrid / Sentiment / Explainable | [requirements](cornac/models/hypar/requirements_cu118.txt), CPU / GPU | [quick-start](https://github.com/PreferredAI/HypAR)
| 2023 | [Recommender Systems with Generative Retrieval (TIGER)](cornac/models/tiger), [docs](https://cornac.readthedocs.io/en/stable/api_ref/models.html#module-cornac.models.tiger.recom_tiger), [paper](https://arxiv.org/pdf/2305.05065.pdf) | Next-Item / Content-Based | [requirements](cornac/models/tiger/requirements.txt), CPU / GPU | [quick-start](examples/tiger_example.py)
Expand Down
9 changes: 9 additions & 0 deletions cornac/eval_methods/next_item_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,14 @@ class NextItemEvaluation(BaseMethod):

Notes
-----
**Item content.** Modalities (e.g.,
``item_feature=FeatureModality(features=..., ids=...)``) can be passed as
keyword arguments to the constructor or any of the class-method builders
(:meth:`from_splits`, :meth:`from_timestamps`, :meth:`leave_last_out`).
They are built against the global item-ID map and attached to all splits,
so content-based next-item models (e.g., TIGER) can read
``train_set.item_feature.features`` with rows aligned to item indices.

**Data splitting.** Ratio-based splitting (inherited from
:obj:`BaseMethod`) and per-user leave-last-out both leak future
information into training: a random split trains on interactions that
Expand Down Expand Up @@ -277,6 +285,7 @@ def _build_datasets(self, train_data, test_data, val_data=None):
fmt=self.fmt,
global_uid_map=self.global_uid_map,
global_iid_map=self.global_iid_map,
global_sid_map=self.global_sid_map,
seed=self.seed,
exclude_unknowns=self.exclude_unknowns,
)
Expand Down
1 change: 1 addition & 0 deletions cornac/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
from .pcrl import PCRL
from .pmf import PMF
from .recvae import RecVAE
from .rpg import RPG
from .sansa import SANSA
from .sasrec import SASRec
from .sbpr import SBPR
Expand Down
142 changes: 142 additions & 0 deletions cornac/models/rpg/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# RPG

Cornac implementation of **RPG** (Generating Long Semantic IDs in Parallel for
Recommendation, Hou et al., KDD 2025,
[arXiv:2506.05781](https://arxiv.org/abs/2506.05781)). RPG represents each item
with a long, unordered Semantic ID produced by product quantization and predicts
all of the next item's Semantic-ID digits in parallel. This port follows the
[official implementation](https://github.com/facebookresearch/RPG_KDD2025) for
OPQ tokenization, causal-session training, the GPT-2 multi-token-prediction
(MTP) backbone, and similarity-graph-guided decoding.

## Requirements

RPG needs PyTorch, Transformers, FAISS, and scikit-learn:

```bash
pip install -r cornac/models/rpg/requirements.txt
```

The FAISS tokenizer uses 8-bit product quantization, so the supported
`codebook_size` is 256. Item content embeddings must cover every item known to
the train, validation, and test splits.

## Usage

Supply precomputed item content embeddings through a `FeatureModality`. Its
`features` rows must align with `ids` (see
[`examples/rpg_example.py`](../../../examples/rpg_example.py) for an end-to-end
example):

```python
from cornac.data import FeatureModality
from cornac.eval_methods import NextItemEvaluation
from cornac.models import RPG
from cornac.models.rpg import RPG_BEAUTY_CONFIG

eval_method = NextItemEvaluation.from_splits(
train_data=train,
val_data=val,
test_data=test,
mode="last",
item_feature=FeatureModality(features=item_embeddings, ids=item_ids),
)

model = RPG(**{**RPG_BEAUTY_CONFIG, "device": "auto", "seed": 2024})
```

The paper uses 3072-dimensional OpenAI `text-embedding-3-large` item
embeddings, followed by whitened PCA to 512 dimensions. Other content
embeddings are accepted, but Semantic-ID quality and recommendation results
depend on them.

Constructor defaults provide a lighter training setup. Use `RPG_CONFIG` for
the official repository defaults or a per-dataset configuration for the
paper-best Amazon recipe:

| Config | LR | Temperature | Codebooks | Beams | Graph edges | Propagation steps |
| ------------------- | -----: | ----------: | --------: | ----: | ----------: | ----------------: |
| `RPG_CONFIG` | 0.0003 | 0.07 | 32 | 50 | 50 | 3 |
| `RPG_BEAUTY_CONFIG` | 0.01 | 0.03 | 32 | 20 | 200 | 3 |
| `RPG_SPORTS_CONFIG` | 0.003 | 0.03 | 16 | 100 | 30 | 5 |
| `RPG_TOYS_CONFIG` | 0.003 | 0.03 | 16 | 200 | 20 | 3 |

All shipped configurations use a maximum history length of 50, batch size 256,
AdamW, cosine scheduling with 10,000 warmup steps, and at most 150 epochs. The
validation NDCG@10 is evaluated every epoch in batches of 32; training stops
after 20 consecutive non-improving epochs and restores the best checkpoint.

## Training iteration

RPG does **not** expand a short session into independent prefix-target rows as
TIGER, LETTER, and SASRec do. For a session `[a, b, c, d]`, RPG creates one
causal training row:

```text
input: [a, b, c, PAD, ...]
labels: [b, c, d, -100, ...]
```

The GPT-2 backbone produces a hidden state at every input position. Each valid
label contributes an MTP loss that predicts all Semantic-ID codebooks in
parallel; `-100` labels are ignored. Consequently, the three next-item targets
share one forward pass and one optimizer step.

For a session longer than `max_len + 1`, the first window supervises every
position. Later sliding windows supervise only their final position, ensuring
that every next-item target is counted exactly once. A session of length `T`
therefore produces `max(T - max_len, 1)` training rows, rather than `T - 1`
prefix rows.

## Scoring modes

- `scoring="graph"` follows the paper: it propagates a beam over a similarity
graph built from item Semantic IDs and assigns real scores only to the final
candidates. Set `n_beams` at least as large as the largest evaluation cutoff.
- `scoring="exact"` scores the full catalog by gathering and averaging the
parallel per-codebook logits. It is useful as a deterministic diagnostic and
for modest catalogs, but it is not the paper's retrieval path.

Both modes use the same trained model. On the Amazon experiments below, their
Recall/NDCG results differ by at most 0.0018 in absolute value.

## Results

Paper-style graph-decoding results on the three Amazon Reviews 2014 5-core
datasets:

| Dataset | R@5 ours/paper | N@5 ours/paper | R@10 ours/paper | N@10 ours/paper |
| ------- | --------------: | --------------: | --------------: | --------------: |
| Beauty | 0.0533 / 0.0550 | 0.0372 / 0.0381 | 0.0789 / 0.0809 | 0.0454 / 0.0464 |
| Sports | 0.0288 / 0.0314 | 0.0198 / 0.0216 | 0.0420 / 0.0463 | 0.0241 / 0.0263 |
| Toys | 0.0613 / 0.0592 | 0.0415 / 0.0401 | 0.0898 / 0.0869 | 0.0506 / 0.0490 |

**Setting:** per-user leave-last-out (`train = sequence[:-2]`, validation target
= second-to-last, test target = last), `mode="last"`, `max_len=50`, and
`seed=123`. Items use the official RPG `text-embedding-3-large` embeddings.
Each category uses its per-dataset configuration above. Beauty and Sports are
within 3.1% and 8.3% of the paper's R@5, respectively; Toys is 3.5% higher.

### Graph versus exact scoring

| Dataset | Scoring | R@5 | N@5 | R@10 | N@10 | R@20 | N@20 | MRR | Total (s) |
| ------- | ------- | -----: | -----: | -----: | -----: | -----: | -----: | -----: | --------: |
| Beauty | graph | 0.0533 | 0.0372 | 0.0789 | 0.0454 | 0.1113 | 0.0536 | 0.0380 | 2502 |
| Beauty | exact | 0.0534 | 0.0373 | 0.0798 | 0.0457 | 0.1125 | 0.0539 | 0.0412 | — |
| Sports | graph | 0.0288 | 0.0198 | 0.0420 | 0.0241 | 0.0619 | 0.0291 | 0.0219 | 4095 |
| Sports | exact | 0.0291 | 0.0201 | 0.0428 | 0.0245 | 0.0627 | 0.0295 | 0.0229 | — |
| Toys | graph | 0.0613 | 0.0415 | 0.0898 | 0.0506 | 0.1233 | 0.0591 | 0.0439 | 1682 |
| Toys | exact | 0.0611 | 0.0414 | 0.0903 | 0.0508 | 0.1251 | 0.0596 | 0.0444 | — |

## Practical notes

- `n_codebook` controls Semantic-ID length. The paper-best Sports and Toys
recipes use 16 codebooks, Beauty uses 32, and the paper's long-ID
CDs-and-Vinyl experiment uses 64.
- OPQ is trained only on items present in the training interactions, while the
resulting tokenizer assigns codes to all items with supplied features.
- Content embeddings are part of the model recipe. Random features are useful
for smoke tests but do not provide meaningful semantic IDs.
- Graph decoding is approximate and stochastic because its initial beam is
sampled. Set `seed` for repeatability, or use exact scoring when deterministic
full-catalog ranks are required.
22 changes: 22 additions & 0 deletions cornac/models/rpg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2026 The Cornac Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================

from .recom_rpg import RPG
from .rpg_config import (
RPG_CONFIG,
RPG_BEAUTY_CONFIG,
RPG_SPORTS_CONFIG,
RPG_TOYS_CONFIG,
)
Loading
Loading