Quickstart¶
Orchid has one adaptive-practice workflow:
- Fit completed learner attempts.
- Inspect data readiness.
- Recommend from pedagogically eligible exercises.
- Observe the scored result.
Install¶
Prepare four columns¶
| Column | Meaning |
|---|---|
user_id |
The learner receiving practice |
item_id |
The exercise identifier (and ideally content version) |
outcome |
Binary result: 1 for correct/completed, 0 for not yet correct |
timestamp |
A non-negative attempt 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 practice attempts, not impressions. Timestamps must preserve each learner's event order.
Fit, recommend, observe¶
from orchid_ranker import AdaptiveRanker
ranker = AdaptiveRanker().fit(history)
readiness = ranker.learning_readiness()
print(readiness["active_tracer"])
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 learner immediately. Call recommend again to
get the adapted ranking. On sparse pilot data, active_tracer is empirical:
a transparent, smoothed learner/exercise baseline. Orchid moves to knowledge
tracing only after its configurable data-support checks pass.
Your application must construct the candidate set using authored curriculum rules. Pass only exercises that are available, appropriate, prerequisite-ready, and not reserved for assessment.
Optional information¶
If you already have a real skill/category or author-reviewed difficulty column, identify it while fitting:
These fields are optional for a pilot. Do not invent them merely to use Orchid; an outcome-derived difficulty is a proxy, not an instructional-design fact.
Production logging¶
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. For a real learning pilot, also persist an independent delayed assessment outcome; see Run a learning-efficacy pilot.
Common issues¶
- 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.