Skip to content

Stop NaN/Inf Phoenix heads from poisoning For You rank - #74

Closed
Pitchfork-and-Torch wants to merge 1 commit into
mainfrom
cursor/nan-inf-rank-feature-fail-open-cbe1
Closed

Stop NaN/Inf Phoenix heads from poisoning For You rank#74
Pitchfork-and-Torch wants to merge 1 commit into
mainfrom
cursor/nan-inf-rank-feature-fail-open-cbe1

Conversation

@Pitchfork-and-Torch

Copy link
Copy Markdown
Owner

Problem

Phoenix can emit NaN (logged in model_runner, still returned). RankingScorer::apply did unwrap_or(0.0) * weight, so Some(NaN) / Some(±Inf) entered the sum. Dwell-regret then added that NaN into the slate mean, and every candidate’s score became NaN. TopKScoreSelector kept Some(NaN) (partial_cmp → Equal). DedupConversationFilter used score > best, which is false for NaN, so a NaN first-post locked the conversation.

This is not xai-org#142 (all heads None still ranked). This is not xai-org#181 (engagement-count store errors zeroing features). A present non-finite feature fail-opened into rank.

Five-line proof

  1. Phoenix has_nan increments a metric and still reply_requests the batch (phoenix/xrex/inference/model_runner.py).
  2. RankingScorer::apply / dwell-regret means used unwrap_or(0.0)Some(NaN) stays NaN; one head NaNs mean_favorite.
  3. centered_ratio then NaNs every candidate; offset_score writes Some(NaN).
  4. TopKScoreSelector / Selector::sort treat NaN as Equal, so poisoned posts occupy For You slots; +Inf wins the slate.
  5. After: non-finite heads are missing (0); persisted scores are finite or None; TopK last-places the rest; conversation collapse ignores NaN.

Change

  • RankingScorer::finite_head / persistable_score — NaN/Inf heads do not enter the weighted sum or dwell-regret means; non-finite finals are unset.
  • PhoenixScoresRankingScorer — same persist rule.
  • TopKScoreSelector — non-finite → NEG_INFINITY.
  • DedupConversationFilter — non-finite → 0 so a finite sibling can win.

Tests

  • nan_favorite_head_does_not_poison_dwell_regret_slate
  • inf_favorite_head_does_not_win_weighted_rank
  • non_finite_final_score_is_unset_for_topk
  • nan_score_does_not_lock_the_conversation
  • non_finite_scores_sort_last

cargo test cannot run here: the public dump has no home-mixer crate manifest.

Survey

Open in Web Open in Cursor 

One non-finite Phoenix head was used as a real feature. Dwell-regret
means then went NaN and TopK kept the poisoned scores. Treat non-finite
heads as missing, persist only finite ranks, and last-place the rest.

Co-authored-by: Jon Bailey <Pitchfork-and-Torch@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants