# Next Best Product (NBP) Recommendations

Recommend the right next product to every customer — personalized, at scale, with no custom ML pipeline required.

## Overview and Use Cases

The NBP workflow from Treasure AI's machine learning platform (AI Signal) generates a ranked list of products — or services, or content — most likely to resonate with each customer, based on their transaction history. It learns from who bought what and when, then predicts what each customer is most likely to want next. The recommendations feed directly into Treasure AI features like Journeys, Triggers, Personalization, Segment Builder, and Agent Console, giving marketing, CRM, and digital teams a ready-to-activate personalization signal without building a recommender from scratch. The solution offers three complementary recommendation algorithms under one workflow:

**Collaborative filtering (ALS)** learns latent preferences via matrix factorization across your entire user base. It discovers patterns like "users who bought X also tend to buy Y" without needing explicit item metadata. It is the highest-quality personalization option and works best for known users with rich transaction history.

**Item-similarity (similar_to_latest)** recommends items most similar to each user's most recent purchase. It works for any user with at least one transaction and is fast and resilient when new items appear often.

**Trending items (popular)** returns the most-purchased or most-viewed items across the whole user base. It handles cold-start users who have no history at all and serves as a reliable universal fallback.

Common use cases:

* Personalize product carousels on your website or app based on each user's predicted interests
* Power personalized email campaigns with per-customer product recommendations
* Build cross-sell and upsell journeys triggered by a customer's next-best-product list
* Recommend content (articles, videos, shows) to keep users engaged between purchases
* Solve the cold-start problem by combining `popular` for new users with `als` for known users


Who benefits most: Lifecycle marketers, personalization teams, and CRM managers who need per-customer recommendations across millions of profiles — without a dedicated ML platform or data science team.

## Model Configuration

### Training Inputs

NBP AI Signals requires a transaction-level table — one row per purchase (or view, click, or other interaction). Column names are configurable via parameters.

| **Field**  | **Type**  | **Required**  | **Description**  |
|  --- | --- | --- | --- |
| `userid` | VARCHAR | Yes | Unique customer identifier. Override the column name with `user_column`. |
| `itemid` | VARCHAR | Yes | Unique product, service, or content identifier. Override with `item_column`. |
| `tstamp` | LONG | Yes | Unix timestamp of the transaction. Override with `tstamp_column`. |
| `rating` | NUMERIC | No | Optional explicit rating or score. Override with `rating_column`. |


Data quality requirements
* NBP does not impute missing values. Pre-process your data to remove nulls before training.
* For content recommendations (e.g., videos watched), replace `itemid` with your content identifier and set `item_column` accordingly.


### Training Outputs

NBP AI Signals produces up to three output tables depending on your configuration: a per-customer recommendations table, an optional similar-items table, and an optional metrics table.

**User Recommendations Table** — one row per customer, with a ranked array of recommended items:

| **Field**  | **Type**  | **Description**  |
|  --- | --- | --- |
| `user_id` | VARCHAR | Customer identifier, carried forward from input. |
| `rec_items` | ARRAY | Recommended item IDs, sorted by predicted relevance (highest first). Length controlled by `topk`. |


**Similar Items Table** (optional, when `similar_items_table` is configured) — for each item, its most similar peers:

| **Field**  | **Type**  | **Description**  |
|  --- | --- | --- |
| `target_item_id` | VARCHAR | The reference item. |
| `item_id` | VARCHAR | A similar item. |
| `score` | FLOAT | Similarity score. Higher means more similar. |


**Training Metrics Table** (optional, when `metrics_table` is configured) — stores model performance per training run:

| **Field**  | **Type**  | **Description**  |
|  --- | --- | --- |
| `session_id` | INTEGER | Unique training session ID. |
| `model_params` | VARCHAR | JSON of parameters used for this run. |
| `map_{topk}` | FLOAT | Mean Average Precision at K. |
| `ndcg_{topk}` | FLOAT | Normalized Discounted Cumulative Gain at K. |
| `precision_{topk}` | FLOAT | Precision at K. |
| `recall_{topk}` | FLOAT | Recall at K. |
| `mrr_{topk}` | FLOAT | Mean Reciprocal Rank at K. |


### Example Output

A sample of the recommendations table after prediction with a six-item `topk`:

| **user_id**  | **rec_items**  |
|  --- | --- |
| `A1146YGPNU9EUL` | [B007FHX9OK, B008DJIIG8] |
| `44039871` | [79255, 82886, 93487, 48930, 30495, 34234, 45003, 495039, GSH89SD89, DF203245] |


A sample of the similar items table (from `als` or `similar_to_latest`):

| **target_item_id**  | **item_id**  | **score**  |
|  --- | --- | --- |
| `B005L3SZ4Y` | `B003OSEMBI` | 112.185631 |
| `B005L3SZ4Y` | `B0074U1D0U` | 108.197929 |
| `B005L3SZ4Y` | `B008CBH2H8` | 96.921562 |
| `B002VPU9DU` | `B0002LD1LM` | 125.564163 |
| `B002VPU9DU` | `B001MXQYMW` | 108.048904 |


Reading the output: `rec_items` is ordered by predicted relevance — the first ID is the top recommendation for that user. Array length matches the `topk` parameter (default 10, max 100). The similar items table is useful for "customers who bought this also liked…" style widgets and for fallback recommendations when a user is not in the trained model.

### Algorithms

NBP supports three algorithms, each with different strengths. You can run them separately and merge the outputs downstream.

| **Algorithm**  | **Best for**  | **Cold-start handling**  | **Performance**  |
|  --- | --- | --- | --- |
| `als` | Known users with rich transaction history. Learns latent preferences via matrix factorization. | No — requires the user to be in training data. | Slower on large datasets; highest-quality personalization. |
| `similar_to_latest` | Users who have at least one transaction. Recommends items similar to their most recent purchase. | Partial — works for any user with one transaction. | Fast; resilient when new items appear often. |
| `popular` | Brand-new users and fallback recommendations. Returns trending items. | Yes — works for anyone. | Fastest; lowest personalization. |


Recommended combination
Run `als` + `similar_to_latest` + `popular`, then merge outputs by priority (e.g., `als` → `similar_to_latest` → `popular`) so every customer gets a recommendation regardless of history.

### Parameters

The pipeline has two stages, training and prediction, and each accepts its own configuration. Parameters fall into two groups: common parameters that apply to all algorithms, and algorithm-specific parameters.

**Common parameters (all algorithms):**

| **Parameter**  | **Type**  | **Default**  | **Required**  | **Description**  |
|  --- | --- | --- | --- | --- |
| `input_table` | string | — | Yes | Transaction source table in `dbname.table_name` format. |
| `output_table` | string | — | Yes | Destination table for recommendations, in `dbname.table_name` format. |
| `model_name` | string | — | Yes | Unique name for the stored model. Same `model_name` overwrites the previous model. Include the algorithm in the name to avoid accidental overwrites. Unique per TD account. |
| `algorithm` | string | `als` | No | One of `als`, `popular`, or `similar_to_latest`. |
| `output_mode` | string | `overwrite` | No | `overwrite` replaces the output table; `append` adds new rows for incremental runs. |
| `user_column` | string | `userid` | No | Input column holding the customer ID. |
| `item_column` | string | `itemid` | No | Input column holding the product/content ID. |
| `tstamp_column` | string | `tstamp` | No | Input column holding the Unix timestamp. |
| `rating_column` | string | `None` | No | Optional input column with explicit ratings or scores. |
| `filter_num` | integer | `0` | No | Minimum number of users an item must have before being included in training. `0` disables filtering. Useful for removing long-tail noise at scale. |
| `topk` | integer | `10` | No | Number of items recommended per user. Max 100. |
| `filter_viewed` | boolean | `false` | No | When `true`, excludes items the user has already interacted with from their recommendations. |
| `similar_items_table` | string | `None` | No | When set (as `db.table`), writes a per-item similarity table. Supported by `als` and `similar_to_latest`. |
| `metrics_table` | string | `None` | No | When set, appends model performance metrics (MAP, nDCG, Precision, Recall, MRR at `topk`) per training run. |


**`als`-specific parameters:**

| **Parameter**  | **Type**  | **Default**  | **Description**  |
|  --- | --- | --- | --- |
| `factors` | integer | `10` | Number of latent factors in the factorization. Higher captures more nuance but costs memory. |
| `regularization` | float | `0.1` | Regularization strength. Increase to reduce overfitting on sparse data. |
| `iterations` | integer | `10` | Number of training iterations. |
| `alpha` | float | `50` | Confidence weight for observed interactions. Higher emphasizes frequent buyers. |
| `tunable` | boolean | `false` | When `true`, hyperparameters are auto-tuned via Optuna. Produces better quality but higher and less predictable resource use. |


**`popular`-specific parameters:**

| **Parameter**  | **Type**  | **Default**  | **Description**  |
|  --- | --- | --- | --- |
| `popularity` | string | `n_users` | How to rank popularity. See RecTools documentation for options. |
| `period` | string | `None` | Time window for popularity calculation (e.g., `30D`). Uses Pandas timedelta format. |
| `begin_from` | string | `None` | Start date for the popularity window. Uses dateutil parse format. |


**`similar_to_latest`-specific parameters:**

| **Parameter**  | **Type**  | **Default**  | **Description**  |
|  --- | --- | --- | --- |
| `k` | integer | `20` | Number of nearest neighbors to consider. |
| `distance` | string | `bm25` | Similarity metric: `bm25`, `tf-idf`, or `cosine`. |
| `lastk` (prediction only) | integer | `1` | Number of most-recent items to base recommendations on. Setting higher than 1 improves prediction quality but uses more time and memory — the model pulls `lastk * topk` similar items, re-ranks, and returns the top `topk`. |


**Tuning notes:**

* **`tunable: true` on `als`** — Enable when model quality matters more than predictable resource use.
* **`filter_num` above 0** — Use on datasets with very long-tail items (e.g., millions of SKUs) to cut training memory significantly.
* **`filter_viewed: true`** — Use for product recommendations where repeat purchases are rare; leave it `false` for consumables.
* **`lastk` on `similar_to_latest`** — Raise to 5 when users have multi-item baskets and the latest item alone doesn't represent intent well.


## Example Workflow Code

NBP AI Signals runs in two stages: a training workflow that fits and registers the model, and a prediction workflow that scores customers using the registered model. The two stages can run on different cadences. For example, train weekly and predict daily or hourly, which keeps compute costs down without letting your recommendations go stale.

The workflow structure is the same for all algorithms; the difference is in the `solution_arguments` block. Pick the tab that matches your chosen algorithm.

ALS
### ALS Training Workflow

```yaml
# nbp_train_als.dig
# Treasure Workflow: NBP AI Signals — ALS Training
# Fits the collaborative filtering (ALS) model on your transaction
# history and registers it under `model_name`.

_export:
  user_column: user_id
  item_column: item_id
  tstamp_column: timestamp
  input_dataset: purchases
  algorithm: als

# Step 1: Submit the training job
+train:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/
  method: POST
  headers:
    - authorization: ${secret:td.apikey}
    - X-TD-ML-SESSION-ID: ${session_id}
    - X-TD-ML-ATTEMPT-ID: ${attempt_id}
  store_content: true
  content:
    input_table: rec_ml_datasets.${input_dataset}
    output_table: rec_ml_datasets.${input_dataset}_${algorithm}_outputs
    solution_name: nbp_train
    solution_arguments:
      model_name: ${input_dataset}_${algorithm}
      algorithm: ${algorithm}
      user_column: ${user_column}
      item_column: ${item_column}
      tstamp_column: ${tstamp_column}
      tunable: true
      similar_items_table: rec_ml_datasets.${input_dataset}_${algorithm}_similar

+print_response:
  echo>: "Training job submitted. Response: ${http.last_content}"

# Step 2: Poll until training completes
+train_poll_status:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/${JSON.parse(http.last_content)['id']}/status
  method: GET
  headers:
    - authorization: ${secret:td.apikey}
```

### ALS Prediction Workflow

```yaml
# nbp_predict_als.dig
# Treasure Workflow: NBP AI Signals — ALS Prediction
# Loads the ALS model registered under `model_name` and scores
# customers with per-user product recommendations.

_export:
  user_column: user_id
  item_column: item_id
  tstamp_column: timestamp
  input_dataset: purchases
  algorithm: als

# Step 1: Submit the prediction job
+pred:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/
  method: POST
  headers:
    - authorization: ${secret:td.apikey}
    - X-TD-ML-SESSION-ID: ${session_id}
    - X-TD-ML-ATTEMPT-ID: ${attempt_id}
  store_content: true
  content:
    input_table: rec_ml_datasets.${input_dataset}
    output_table: rec_ml_datasets.${input_dataset}_${algorithm}_recommendations
    solution_name: nbp_predict
    solution_arguments:
      model_name: ${input_dataset}_${algorithm}
      algorithm: ${algorithm}
      user_column: ${user_column}
      item_column: ${item_column}
      tstamp_column: ${tstamp_column}
      topk: 10

+print_response:
  echo>: "Prediction job submitted. Response: ${http.last_content}"

# Step 2: Poll until prediction completes
+pred_poll_status:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/${JSON.parse(http.last_content)['id']}/status
  method: GET
  headers:
    - authorization: ${secret:td.apikey}
```

Similar-to-Latest
### Similar-to-Latest Training Workflow

```yaml
# nbp_train_similar.dig
# Treasure Workflow: NBP AI Signals — Similar-to-Latest Training
# Fits the item-similarity model and registers it under `model_name`.

_export:
  user_column: user_id
  item_column: item_id
  tstamp_column: timestamp
  input_dataset: purchases
  algorithm: similar_to_latest

# Step 1: Submit the training job
+train:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/
  method: POST
  headers:
    - authorization: ${secret:td.apikey}
    - X-TD-ML-SESSION-ID: ${session_id}
    - X-TD-ML-ATTEMPT-ID: ${attempt_id}
  store_content: true
  content:
    input_table: rec_ml_datasets.${input_dataset}
    output_table: rec_ml_datasets.${input_dataset}_${algorithm}_outputs
    solution_name: nbp_train
    solution_arguments:
      model_name: ${input_dataset}_${algorithm}
      algorithm: ${algorithm}
      user_column: ${user_column}
      item_column: ${item_column}
      tstamp_column: ${tstamp_column}
      similar_items_table: rec_ml_datasets.${input_dataset}_${algorithm}_similar

+print_response:
  echo>: "Training job submitted. Response: ${http.last_content}"

# Step 2: Poll until training completes
+train_poll_status:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/${JSON.parse(http.last_content)['id']}/status
  method: GET
  headers:
    - authorization: ${secret:td.apikey}
```

### Similar-to-Latest Prediction Workflow

```yaml
# nbp_predict_similar.dig
# Treasure Workflow: NBP AI Signals — Similar-to-Latest Prediction
# Loads the similar-to-latest model and generates per-user recommendations.

_export:
  user_column: user_id
  item_column: item_id
  tstamp_column: timestamp
  input_dataset: purchases
  algorithm: similar_to_latest

# Step 1: Submit the prediction job
+pred:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/
  method: POST
  headers:
    - authorization: ${secret:td.apikey}
    - X-TD-ML-SESSION-ID: ${session_id}
    - X-TD-ML-ATTEMPT-ID: ${attempt_id}
  store_content: true
  content:
    input_table: rec_ml_datasets.${input_dataset}
    output_table: rec_ml_datasets.${input_dataset}_${algorithm}_recommendations
    solution_name: nbp_predict
    solution_arguments:
      model_name: ${input_dataset}_${algorithm}
      algorithm: ${algorithm}
      user_column: ${user_column}
      item_column: ${item_column}
      tstamp_column: ${tstamp_column}
      topk: 10

+print_response:
  echo>: "Prediction job submitted. Response: ${http.last_content}"

# Step 2: Poll until prediction completes
+pred_poll_status:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/${JSON.parse(http.last_content)['id']}/status
  method: GET
  headers:
    - authorization: ${secret:td.apikey}
```

Popular
### Popular Training Workflow

```yaml
# nbp_train_popular.dig
# Treasure Workflow: NBP AI Signals — Popular Training
# Fits the trending-items model and registers it under `model_name`.

_export:
  user_column: user_id
  item_column: item_id
  tstamp_column: timestamp
  input_dataset: purchases
  algorithm: popular

# Step 1: Submit the training job
+train:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/
  method: POST
  headers:
    - authorization: ${secret:td.apikey}
    - X-TD-ML-SESSION-ID: ${session_id}
    - X-TD-ML-ATTEMPT-ID: ${attempt_id}
  store_content: true
  content:
    input_table: rec_ml_datasets.${input_dataset}
    output_table: rec_ml_datasets.${input_dataset}_${algorithm}_outputs
    solution_name: nbp_train
    solution_arguments:
      model_name: ${input_dataset}_${algorithm}
      algorithm: ${algorithm}
      user_column: ${user_column}
      item_column: ${item_column}
      tstamp_column: ${tstamp_column}

+print_response:
  echo>: "Training job submitted. Response: ${http.last_content}"

# Step 2: Poll until training completes
+train_poll_status:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/${JSON.parse(http.last_content)['id']}/status
  method: GET
  headers:
    - authorization: ${secret:td.apikey}
```

### Popular Prediction Workflow

```yaml
# nbp_predict_popular.dig
# Treasure Workflow: NBP AI Signals — Popular Prediction
# Loads the popular model and generates trending-item recommendations.

_export:
  user_column: user_id
  item_column: item_id
  tstamp_column: timestamp
  input_dataset: purchases
  algorithm: popular

# Step 1: Submit the prediction job
+pred:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/
  method: POST
  headers:
    - authorization: ${secret:td.apikey}
    - X-TD-ML-SESSION-ID: ${session_id}
    - X-TD-ML-ATTEMPT-ID: ${attempt_id}
  store_content: true
  content:
    input_table: rec_ml_datasets.${input_dataset}
    output_table: rec_ml_datasets.${input_dataset}_${algorithm}_recommendations
    solution_name: nbp_predict
    solution_arguments:
      model_name: ${input_dataset}_${algorithm}
      algorithm: ${algorithm}
      user_column: ${user_column}
      item_column: ${item_column}
      tstamp_column: ${tstamp_column}
      topk: 10

+print_response:
  echo>: "Prediction job submitted. Response: ${http.last_content}"

# Step 2: Poll until prediction completes
+pred_poll_status:
  http>: https://ml-batch-api.treasuredata.com/v1/runs/${JSON.parse(http.last_content)['id']}/status
  method: GET
  headers:
    - authorization: ${secret:td.apikey}
```

**What these workflows do:** The training workflow submits a job that fits the chosen algorithm, evaluates it on a holdout set, writes metrics to your output table (if configured), and registers the trained model under `model_name`. The model persists at the account level for 6 months. The prediction workflow loads that registered model and scores the customers in your input table, writing per-customer recommendations to a separate output table. The polling steps handle the ML Batch API's behavior of returning HTTP 408 while a job is still running — Treasure Workflow automatically retries until it receives HTTP 200.

**Why split training from prediction?** Training is expensive and only needs to run when your product catalog or customer base has changed materially — typically once a week. Prediction is cheap and benefits from running often, usually daily or hourly, so that recently active customers receive fresh recommendations. Splitting the two stages lets you tune each cadence independently.

**Combining algorithms:** To cover both known and cold-start users, run training and prediction separately for `als`, `similar_to_latest`, and `popular`, then merge the output tables in a downstream SQL step — prioritizing `als` first, falling back to `similar_to_latest`, then `popular`.

Security
Store your TD API key as a Workflow secret named `td.apikey`. Never hardcode API keys in a workflow definition or commit them to version control.

## Scalability

NBP is designed to handle enterprise-scale datasets. The table below shows measured runtimes across profile counts, without parallelization, to establish a baseline.

**Baseline performance (single task):**

| **Profiles**  | **Algorithm**  | **Training time**  | **Prediction time**  | **Peak memory (training / prediction)**  |
|  --- | --- | --- | --- | --- |
| 5M | `als` (tuned) | ~19 min | ~20 min | 8.1 / 10.2 GiB |
| 5M | `similar_to_latest` | ~6 min | ~7 min | 3.2 / 7.7 GiB |
| 5M | `popular` | ~1 min | ~6 min | 3.5 / 8.5 GiB |
| 10M | `als` (tuned) | ~42 min | ~51 min | 7.7 / 17.3 GiB |
| 10M | `similar_to_latest` | ~7 min | ~12 min | 5.8 / 15.9 GiB |
| 50M | `als` (tuned) | ~179 min | ~156 min | 65.9 / 103.3 GiB |
| 50M | `similar_to_latest` | ~29 min | ~41 min | 29.3 / 82.8 GiB |
| 100M | `als` (tuned) | ~230 min | ~283 min | 140.8 / 208.7 GiB |
| 100M | `similar_to_latest` | ~41 min | ~90 min | 54.2 / 164.6 GiB |


**With 8-way parallel prediction:**

| **Profiles**  | **Algorithm**  | **Training**  | **Prediction**  |
|  --- | --- | --- | --- |
| 50M | `als` | 123 min | 59 min |
| 100M | `als` | 378 min | 95 min |
| 500M (trained on 50M) | `similar_to_latest` | 48 min | 49 min |
| 1B (trained on 100M) | `similar_to_latest` | 90 min | 82 min |
| 1B (trained on 100M) | `popular` | 75 min | 79 min |


**Guidelines:**

* **Under 10M profiles:** No parallelization needed. A single 64 GiB instance handles all three algorithms.
* **10M–100M profiles:** Parallelize prediction across 8 tasks (max concurrency per account). ALS still needs 128 GiB instances at this range.
* **Over 100M profiles:** ALS cannot recommend for all profiles without training on the full set. Use `similar_to_latest` or `popular` as the primary algorithm, optionally training on a 10% sample. Apply `filter_num` to trim long-tail items.


Contact your Treasure AI account team if your dataset exceeds 500 million profiles to discuss infrastructure and pricing options.

## Limitations and Known Issues

* **ALS cannot recommend for users not in the training data.** Pair it with `similar_to_latest` or `popular` to cover new customers.
* **Models expire after 6 months.** Re-train before the expiration window to avoid prediction failures.
* **`similar_to_latest` cannot handle cold items.** Items must appear at least once in the training data to be recommended. In most real deployments, cold items aren't a significant problem.
* **Training is infrequent by design.** NBP assumes weekly (or similar) full retraining, with more frequent prediction runs on the saved model. Partial or online training is not supported.
* **Parallelization has overhead.** Below 10M profiles, parallelizing prediction is slower than a single task due to data-splitting cost. Only parallelize at larger scales.
* **ALS resource usage is less predictable with `tunable: true`.** Optuna-driven tuning can shift memory and time per run. Set `tunable: false` for stable, reproducible resource use.
* **Pre-aggregated data is not used.** NBP needs raw transactions, not customer-level aggregates. For aggregate-based segmentation, use RFM AI Signals instead.


## Glossary

| **Term**  | **Definition**  |
|  --- | --- |
| Cold start | The problem of recommending for users or items with little or no history. `popular` handles cold users; `similar_to_latest` handles users with any history; `als` handles neither without help. |
| Collaborative filtering | Recommending items based on patterns of many users' behavior. `als` is a collaborative filtering algorithm. |
| ALS | Alternating Least Squares — a matrix factorization technique that learns latent user and item preferences from interaction data. |
| Matrix factorization | Representing the user-item interaction matrix as the product of two smaller matrices (user factors × item factors) to uncover hidden patterns. |
| Popularity model | Recommends the most-purchased or most-viewed items across the whole user base. Simple, fast, and a reliable fallback. |
| `similar_to_latest` | Recommends items most similar to a user's most recent transaction, using item-to-item similarity. |
| topk | The number of items returned per user in the recommendations. Default 10, max 100. |
| lastk | For `similar_to_latest`, the number of most-recent transactions to base recommendations on. Default 1. |
| MAP, nDCG, Precision, Recall, MRR @ K | Standard ranking metrics. Higher is better. See the metrics table output for per-training-run values. |
| RecTools | The open-source recommendation library powering NBP. |
| PrecisionML | The production ML infrastructure that powers NBP. |
| Cold item | An item with no or very few interactions in training data. Hard to recommend without supplementary data. |


## FAQs

| **Question**  | **Answer**  |
|  --- | --- |
| How often should I re-train the model? | Weekly is a reasonable default for most businesses — it captures shifting preferences without excessive compute cost. Re-run prediction more often (daily or hourly) against the saved model to pick up new users and recent transactions. Stored models expire after 6 months, so re-train at least that often. |
| Which algorithm should I use? | Start with all three. Run `als` for your known, active users (best personalization), `similar_to_latest` for anyone with at least one transaction, and `popular` as a universal fallback. Merge the outputs downstream with `als` → `similar_to_latest` → `popular` priority so every customer gets a recommendation. |
| How do I handle new customers with no transaction history? | Use the `popular` algorithm as a fallback — it works for everyone, including users who have never bought anything. In practice, most teams run all three algorithms and merge outputs so `popular` fills gaps left by `als` and `similar_to_latest`. |
| Can I recommend content instead of products? | Yes. NBP doesn't care what `itemid` represents — it can be a product ID, article URL, video ID, or podcast episode. As long as you have `user_id`, `item_id`, and `timestamp` per interaction, NBP will generate recommendations. |
| How do I activate recommendations in a campaign? | The output table contains a `rec_items` array for each customer. From there, join it onto your Master Segment to expose recommendations as customer attributes, push them to an email or push-notification tool via Treasure AI activations, or feed them into Journeys, Triggers, or Personalization for real-time use. |
| My dataset has 200M profiles — can NBP handle it? | Yes, with some care. For `similar_to_latest` and `popular`, train on a sample (e.g., 10%) and predict across the full set using parallelized prediction. `als` at this scale requires training on the full set and will not recommend for untrained users — consider using it alongside `similar_to_latest` rather than alone. Contact your account team for tuning guidance. |
| What do the `lastk` and `topk` parameters actually do? | `topk` controls how many items each user gets in their recommendation list (default 10, max 100). `lastk`, specific to `similar_to_latest`, controls how many of a user's most recent transactions feed into the recommendation — raising it from 1 to 5 often improves quality when users have multi-item baskets, at the cost of more memory and time. |