hoops_ai.ml.context_layer.NumericWeightedRule

class hoops_ai.ml.context_layer.NumericWeightedRule(log_scale=True, min_evidence=3, interval_sigmas=1.0, relevance_weighter=None, auto_relevance_weight=True, score_temperature=None, nearest_neighbor_threshold=None)

Bases: AggregationRule

Predict continuous numeric context (e.g. cost, weight, time) from neighbors.

Three operating modes selected at construction:

  1. Plain weighted meanrelevance_weighter=None and auto_relevance_weight=False. Pure shape-weighted aggregation.

  2. Auto-fitted weighter (default) — the rule lazily fits a per-key RelevanceWeighter from the current call’s hit metadata.

  3. Explicit weighter — pass relevance_weighter=RelevanceWeighter(...) to skip auto-fit and use hand-tuned factors.

Confidence comes from the coefficient of variation (CV) of neighbor values: confidence = 1 / (1 + CV). Log-space is appropriate for multiplicative quantities (cost, weight, time); set log_scale=False for additive quantities.

Parameters:
  • log_scale (bool) – If True (default), operates in log-space. Set False for additive quantities (counts, dimensions).

  • min_evidence (int) – Minimum hits required before predicting. Default 3.

  • interval_sigmas (float) – Prediction-interval width in σ. Default 1.0 (≈68%).

  • relevance_weighter (RelevanceWeighter | None) – Explicit weighter; disables auto-fit for keys this rule sees.

  • auto_relevance_weight (bool) – When True (default) and relevance_weighter is None, the rule lazily fits a per-key weighter the first time predict_with_context() runs for that key, using the call’s hit metadata.

  • score_temperature (float | None) – When set, neighbour weights are computed by a softmax exp(T·s) / Σ exp(T·s) over the adjusted scores instead of the default linear s / Σ s. Sharper weighting: a hit that matches on shape and on every injected metadata key takes almost all of the mass, so the estimate converges to that neighbour’s value. Useful when the cost surface is highly non-linear and you want a near-duplicate, full-metadata-match neighbour to dominate. None (default) preserves the linear behaviour. Typical values: 4.0 (moderate sharpening) to 12.0 (near-argmax). Must be a positive finite number.

  • nearest_neighbor_threshold (float | None) – When set, the rule first checks whether any neighbour reaches a normalised global agreement score adjusted_i / max_possible_boost ≥ threshold. The numerator is the weighter-adjusted score (shape × per-key boosts); the denominator is what a perfect-match neighbour would score, so the ratio lives in [0, 1]. When the gate fires the rule short-circuits to that neighbour’s value with confidence equal to the normalised score — the same idea as NearestNeighborRule but ranked by a global signal that also reflects Material / Process / InternalFeatures agreement instead of raw shape similarity alone. When no neighbour clears the gate the rule falls through to the softmax / linear path as usual. None (default) disables the gate. Must be in (0, 1] when set. With no weighter and no query_context the normalisation degenerates to 1.0 and this is exactly NearestNeighborRule(threshold) on the raw shape score.

predict(values, scores, key)

Predict a context value from neighbor evidence.

Parameters:
  • values (list[Any]) – The context values collected from hits for this key, ordered by relevance (best match first).

  • scores (list[float]) – Similarity scores corresponding 1-to-1 with values (higher = more similar).

  • key (str) – The context key being inferred.

Returns:

ContextPrediction or None if insufficient evidence.

Return type:

ContextPrediction | None

predict_with_context(values, scores, key, query_context=None, *, hits=None)

Adjust scores via the (auto- or hand-fit) weighter, then aggregate.

Pipeline:

  1. Resolve the weighter for key: explicit relevance_weighter wins; otherwise lazy-fit per-key if auto_relevance_weight.

  2. Auto-infer a baseline query_context from the top-K hits’ metadata using the weighter’s known factor keys, then overlay any caller-supplied query_context on top (caller wins). This lets a partial injection (e.g. {Material, Process} forwarded from earlier categorical predictions) still benefit from neighbor-derived numeric factors like InternalFeatures.

  3. Multiply scores by the weighter’s per-hit boosts.

  4. Fall through to predict() on the adjusted scores.

Parameters:
Return type:

ContextPrediction | None

property relevance_weighter: RelevanceWeighter | None

The explicit weighter passed at construction (None if auto-fitting).