Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

Use this file to discover all available pages before exploring further.

modelType: "scorecard" — a points-based scoring model where each rule contributes a configurable number of points when its condition matches. Points accumulate from a base score, then normalize to a probability via sigmoid (or linear). The math is intentionally simple so operators, auditors, and regulators can read it line-by-line.

When to use

  • Day-1 launch — no interaction history yet. Hand-craft rules from domain expertise.
  • Auditability is non-negotiable — financial services, healthcare, anything regulated. Every rule fired is recorded in the score explanation.
  • Cold-start mitigation while you build a real model — scorecard runs as the active model while you accumulate outcomes for a future bayesian or gradient_boosted candidate.
Skip it when you have ≥ 1k labeled outcomes and meaningful feature interactions — a learned model (logistic, GBT) will outperform on accuracy, and you can fall back to scorecard for the cold-start segment via Score.overrides[].

The math

rawScore = baseScore + Σ (rule.points if rule.matches(customer) else 0)

# Sigmoid normalization (default):
midpoint = (maxScore + minScore) / 2
range    = maxScore - minScore
x        = ((rawScore - midpoint) / range) * 6   # 6 maps ±range to ±3 σ
score    = 1 / (1 + e^(-x))

# Linear normalization:
score    = (rawScore - minScore) / (maxScore - minScore)   # clamped to [0, 1]
Each rule applies one of 10 operators (eq, neq, gt, gte, lt, lte, in, not_in, contains, starts_with) to one attribute on the candidate or its customer enrichment.

Fixture config

{
  "name": "Prime credit scorecard",
  "baseScore": 50,
  "minScore": 0,
  "maxScore": 100,
  "normalization": "sigmoid",
  "rules": [
    { "id": "r1", "field": "credit_score", "operator": "gte", "value": 740, "points": 20, "description": "Prime credit" },
    { "id": "r2", "field": "credit_score", "operator": "gte", "value": 800, "points": 10, "description": "Super-prime bonus" },
    { "id": "r3", "field": "income",       "operator": "gte", "value": 75000, "points": 10, "description": "High income" },
    { "id": "r4", "field": "segment",      "operator": "eq",  "value": "Gold", "points": 8, "description": "Loyalty boost" },
    { "id": "r5", "field": "age",          "operator": "gte", "value": 25,    "points": 2, "description": "Established demo" }
  ]
}
This fixture is exercised in the algorithm-coverage proof: platform/scripts/proof-algorithms-e2e.mts shows it scores 0.917 for a customer with {credit_score: 760, income: 95000, age: 38, segment: "Gold"} — 4 of 5 rules fire (the super-prime bonus at 800+ doesn’t, credit_score 760 < 800).

Training

There’s no training step. Operators add and tune rules through the Algorithms → Models → Scorecard UI. Each rule’s points value is the only knob. If you want data-driven rule weights, train a logistic_regression model on the same predictors and read off the weights as a starting point for scorecard points.

Score interpretation

  • score[0, 1] — the engine consumes this as the propensity component (P) in PRIE, or as the raw score in propensity strategy.
  • rawScore[minScore, maxScore] — the pre-normalization point total. Operators reading the trace can tell exactly how many points each rule contributed.
  • explanations[] — one entry per rule, with {matched, points, field, expected, actual, description}. This is the audit trail.

Pitfalls

  • All-or-nothing rule sets — if all your rules are points: 10 and only one fires per candidate, every score is 50 or 60. Vary the point values so high-value rules can dominate.
  • Forgetting to set minScore / maxScore — defaults are [0, 100]. If your rules total > 100 in worst-case, the sigmoid will saturate at 1.0 for every prime customer.
  • No rules at all — every candidate scores baseScore normalized (= 0.5 by default). Documented in T20 Test C of the proof bundle, where scorecard-v2 was created with zero rules and Platinum’s adaptation positiveRate=0 triggered the starvation bug (now fixed via the propensity floor).
  • Categorical fields with high cardinalityeq rules need one rule per value. Use in with an array instead.

Cross-reference