Orchid has one workflow:
- Fit historical outcomes.
- Recommend from eligible candidates.
- Observe the result.
python -m pip install orchid-ranker| Column | Meaning |
|---|---|
user_id |
The person, account, or agent receiving the item |
item_id |
The exercise, step, task, or content identifier |
outcome |
Binary result: 1 for success, 0 otherwise |
timestamp |
A non-negative time or sequence number |
import pandas as pd
history = pd.DataFrame({
"user_id": ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
"item_id": [101, 102, 201, 101, 102, 201, 101, 102, 201],
"outcome": [1, 1, 0, 1, 0, 0, 1, 1, 1],
"timestamp": [1, 2, 3, 1, 2, 3, 1, 2, 3],
})Rows represent completed interactions with meaningful outcomes, not impressions. Timestamps must preserve each user's event order.
from orchid_ranker import AdaptiveRanker
ranker = AdaptiveRanker().fit(history)
ranked = ranker.recommend(
user_id="a",
candidate_item_ids=[101, 102, 201],
top_k=2,
)
for recommendation in ranked:
print(
recommendation.item_id,
recommendation.score,
recommendation.outcome_probability,
)
ranker.observe(
user_id="a",
item_id=ranked[0].item_id,
outcome=1,
timestamp=4,
)The new outcome updates that user immediately. Call recommend again to get
the adapted ranking.
Your application must construct the candidate set using its hard constraints. Pass only items that are available, safe, licensed, or otherwise eligible.
If you already have a meaningful category or difficulty column, identify it while fitting:
ranker.fit(
history,
category_col="skill_id",
difficulty_col="difficulty",
)These fields are optional. Do not invent them merely to use Orchid.
When you need an immutable decision record:
ranked, decision = ranker.recommend_and_log(
user_id="a",
candidate_item_ids=[101, 102, 201],
timestamp=5,
exploration=0.05,
)
ranker.observe_decision(
decision.decision_id,
outcome=1,
timestamp=6,
)Persist the decision before returning the recommendation. See Production serving for the operational contract.
- No recommendations: an empty eligible list returns
[]; make sure the list contains fitted or registered catalog items. - An outcome is rejected: values must be exactly binary
0or1. - Results do not adapt: call
observeafter completed interactions. - Timestamp errors: use finite, non-negative numeric values in chronological order.