Skip to main content

Prediction evidence and peer frames

Behavioral signals say how surprising an entity's recent behavior is. Two options make them explainable and comparable:

  • Prediction evidence attaches, to every scored state, the events that drove the surprise: the top transitions (which event was expected and which one was observed) and the top attribute values (a never-seen port, an unusual payment method), each with its own calibrated surprisal_percentile.
  • An attribute peer frame calibrates behavior_surprise against entities that share the value of one contracted categorical attribute (for example, the payment method of their orders) instead of the whole population. Peers with too little test-split support fall back to the population (frame: count_decile_fallback).
{
"signals": {
"behavior_surprise": 0.97,
"frame": "peer:order.placed.payment_method",
"evidence": {
"transitions": [
{
"event_id": "evt_01j9…",
"event_type": "order.paid",
"expected_mass": 0.71,
"observed_type": "order.refunded",
"nll": 4.2,
"surprisal_percentile": 0.99
}
],
"attributes": [
{
"event_id": "evt_01j9…",
"attr_key": "payment_method",
"nll": 6.1,
"surprisal_percentile": 0.98
}
]
}
}
}

Both options are computed at evaluation time (the calibration artifact gains per-transition, per-attribute and per-peer references), so you enable them by evaluating the model with them, then bundling that evaluation.

Enable them​

  1. Start a signals evaluation of the model:

    curl -X POST "$TESSERA_API_BASE/models/$MODEL_ID/signals-evaluations" -H "authorization: Bearer $TESSERA_API_KEY" -H "content-type: application/json" \
    -d '{"evidence": {"enabled": true}, "peer_frame": {"kind": "attribute", "event_type": "order.placed", "attribute": "payment_method"}}'

    At least one option is required. evidence.top_k (1–8, default 8) bounds the transitions and attributes kept per state. The peer attribute must be a contracted categorical feature of an included event type; anything else is 400 invalid_argument. The answer is 202 with the evaluation (status: running) and its report_id. Send an Idempotency-Key header to make retries of the request safe.

  2. Poll it until it settles:

    curl "$TESSERA_API_BASE/models/$MODEL_ID/signals-evaluations/$REPORT_ID" \
    -H "authorization: Bearer $TESSERA_API_KEY"

    status is running, succeeded (with gates_passed) or failed with a failure_reason:

    failure_reasonMeaning
    job_failedThe evaluation Job failed on every retry.
    job_deadline_exceededThe Job ran past its 6-hour deadline.
    report_missingThe Job completed without recording its report.
    job_missingThe Job never appeared after the launch, or it finished and was cleaned up (finished Jobs are kept 24 hours) before the evaluation was read; a failed Job read within those 24 hours reads job_failed.
    launch_failedThe Job could not be created.
    timeoutThe evaluation outlived the evaluation timeout.

    Re-sending the identical request relaunches a failed evaluation.

  3. Create the bundle with signals enabled, then activate it on a slot:

    curl -X POST "$TESSERA_API_BASE/models/$MODEL_ID/bundles" -H "authorization: Bearer $TESSERA_API_KEY" \
    -H "content-type: application/json" -d '{"signals": {"enabled": true}}'

    The succeeded evaluation is now the model's evaluation of record (GET /models/{model_id}/eval-report serves it), so the bundle pins it and copies its signals.config — including evidence and peer_frame — into runtime.signals.

What changes, and what does not​

  • Gates do not move. The signals evaluation is the model's default evaluation (same seed, baselines and signals) plus these options. G1–G6, the label metrics and the baselines are identical to the default evaluation's; only the report's signals block differs (its config and the references in the calibration artifact).
  • The evaluation of record moves. When the signals evaluation succeeds, it becomes the model's evaluation of record. Bundles you created earlier are immutable: they keep their pinned report, gates and runtime, and a slot serving one keeps serving exactly what it served.
  • One at a time. A model runs one signals evaluation at a time; a second request while one runs is 400 failed_precondition with detail reason: evaluation_in_progress and the running evaluation's report_id. Re-sending the identical request returns the running evaluation, and makes an already succeeded one the evaluation of record again.
  • Access. Starting one needs a member role (or an API key with the admin scope); reading one needs read.
  • Usage. Like the model's default evaluation, a signals evaluation is not metered separately.