Generate
POST /generate
The value moment. Give the model a user's history and it emits semantic ID tokens one level at a time, exactly the way a language model emits text.
Beam search is constrained to prefixes that exist in the codebook, so the model cannot hallucinate an item that does not exist. Every returned sequence resolves.
- curl
- Python
- TypeScript
curl https://api.jeantechnologies.com/v1/generate \
-H "Authorization: Bearer $JEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tokenizer_id": "tok_9k2m",
"history": ["sku_310", "sku_884", "sku_771"],
"limit": 10,
"beam_width": 40,
"filters": { "in_stock": true }
}'
recs = requests.post(
"https://api.jeantechnologies.com/v1/generate",
headers={"Authorization": f"Bearer {os.environ['JEAN_API_KEY']}"},
json={
"tokenizer_id": "tok_9k2m",
"history": ["sku_310", "sku_884", "sku_771"],
"limit": 10,
"filters": {"in_stock": True},
},
).json()
const res = await fetch("https://api.jeantechnologies.com/v1/generate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.JEAN_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tokenizer_id: "tok_9k2m",
history: ["sku_310", "sku_884", "sku_771"],
limit: 10,
filters: { in_stock: true },
}),
});
const { recommendations } = await res.json();
Body
| Field | Type | Default | Notes |
|---|---|---|---|
tokenizer_id | string | required | |
history | string[] | required | The user's item interactions, oldest first. |
limit | integer | 10 | 1 to 100. |
beam_width | integer | 40 | Wider beams raise recall and latency. Must be at least limit. |
exclude_history | boolean | true | |
filters | object | Hard constraints applied to candidate items during decoding. |
Response
{
"recommendations": [
{
"item_id": "sku_402",
"codes": [1487, 302, 91, 12],
"tokens": "<sid_0_1487><sid_1_302><sid_2_91><sid_3_12>",
"score": 0.31
}
],
"beams_explored": 40,
"beams_pruned_invalid": 0
}
score is length-normalized sequence likelihood. It is comparable between candidates in one
response and not comparable across requests, so use it to rank, not to threshold.
beams_pruned_invalid should be 0. A nonzero value means beam search reached prefixes the
codebook no longer resolves, which almost always means the serving codebook is stale relative to
the catalog. Refit or re-sync before trusting the results.
History matters
history is ordered, oldest first, and the order is signal. A user who viewed A then B is a
different state from one who viewed B then A, and the model is trained to care.
Send the real sequence. Deduplicating it, sorting it, or collapsing it into a set throws away most of what makes a sequence model better than a co-occurrence table.
Long histories are truncated from the front, keeping the most recent interactions. If you have a strong reason to keep older context, say so during onboarding and we can weight the window differently for your tenant.
Tuning beam width
beam_width | Effect |
|---|---|
= limit | Fastest. Greedy in practice, and recall suffers on tail items. |
4x limit | Default territory. Good recall for most catalogs. |
10x limit | Diminishing returns on quality, meaningful latency cost. |
Filters are applied during decoding rather than after, so a restrictive filters object needs a
wider beam to fill limit. If you are getting back fewer results than you asked for, widen the
beam before you loosen the filter.
Feeding outcomes back
Generation is not the end of the loop. Send what actually happened so the model adapts to your objective rather than to a proxy. See Foundation models for how the adaptation stages fit together.