> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/sdgm/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/sdgm/_mcp/server.

# Item-to-Item Recommendation

Recommend products to show beside an item a shopper is viewing. This example ranks candidate products by whether they will appear in an order with the viewed item during the next 30 days. The target is a future pair of products, not whether this particular shopper will buy either one.

## Data and relationships

The example assumes a Kumo Engine `graph` and matching `snapshot` with these tables:

| Table             | Required data and role                                                                                               |
| ----------------- | -------------------------------------------------------------------------------------------------------------------- |
| `anchor_items`    | `item_id` primary key. Products to recommend beside.                                                                 |
| `candidate_items` | `item_id` primary key. Products to recommend. This can use the same catalog extract.                                 |
| `item_pairs`      | `pair_id` primary key; `anchor_item_id`, `related_item_id`, and `timestamp`. Products observed together in an order. |

For each distinct product pair in an order, record a row in each direction. Connect `item_pairs.anchor_item_id` to `anchor_items.item_id` and `item_pairs.related_item_id` to `candidate_items.item_id`. Mark `item_pairs.timestamp` as the time column. Keep the two item roles separate in the graph so each pair column has one unambiguous relationship. Do not create pairs from products that merely share a category or description: those would change the prediction target.

## Rank future product pairs

The query asks Kumo Engine to rank candidate products for each anchor product using pair events in a 30 day future window. `LIST_DISTINCT` counts a candidate once as a target even when it appears in several orders in that window.

```python
from datetime import datetime
from kumo.engine import PredictiveQuery

query_text = (
    "PREDICT LIST_DISTINCT(item_pairs.related_item_id, 0, 30, days) "
    "RANK TOP 20 FOR EACH anchor_items.item_id"
)
query = PredictiveQuery(graph, query_text)
query.validate()
print(query.get_task_type())  # temporal_link_prediction

prediction_time = datetime(2024, 4, 30, 12)  # Replace with your chosen UTC time.
prediction_table = query.generate_prediction_table(
    snapshot, prediction_time=prediction_time
)
ranked = trainer.predict(
    prediction_table, snapshot=snapshot, num_classes_to_return=20
).frame
display = ranked.loc[ranked["ENTITY"] != ranked["CLASS"]]
```

Here `trainer` is a fitted model for this query. Choose a prediction time after the latest pair event in the snapshot. The prediction table selects anchor products and a time; it does not train the model. In the ranked output, `ENTITY` is an anchor item, `CLASS` is a candidate item, and `SCORE` orders candidates for that anchor. A score does not guarantee that the products will share an order.

The `display` rows omit any candidate that is the same product as the anchor. You can use the remaining ranked candidates for a product detail page. This query learns from observed order pairs; it does not establish that products are visually or semantically similar, or that a specific shopper prefers them. The request for 20 output classes is applied before the display filter, so fewer than 20 candidates may remain.