Class: Legion::LLM::Router::Ranker

Inherits:
Object
  • Object
show all
Includes:
Legion::Logging::Helper
Defined in:
lib/legion/llm/router/ranker.rb

Overview

Soft preference, integer weight/affinity, and rendezvous tie-breaking (§10). Returns the winning RankedCandidate, or nil when no ready candidate exists.

PRIVATE — no call site outside router.rb may invoke Ranker directly.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(evaluation_set:, requirements:, settings_snapshot:) ⇒ Ranker

Returns a new instance of Ranker.



56
57
58
59
60
# File 'lib/legion/llm/router/ranker.rb', line 56

def initialize(evaluation_set:, requirements:, settings_snapshot:)
  @evaluation_set    = evaluation_set
  @requirements      = requirements
  @settings_snapshot = settings_snapshot
end

Class Method Details

.call(evaluation_set:, requirements:, settings_snapshot:) ⇒ RankedCandidate?

Parameters:

Returns:

  • (RankedCandidate, nil)


50
51
52
53
54
# File 'lib/legion/llm/router/ranker.rb', line 50

def self.call(evaluation_set:, requirements:, settings_snapshot:)
  new(evaluation_set:    evaluation_set,
      requirements:      requirements,
      settings_snapshot: settings_snapshot).call
end

Instance Method Details

#callObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/legion/llm/router/ranker.rb', line 62

def call
  # Step 1 (§10): start with ready candidates only.
  ready = @evaluation_set.ready_candidates
  return nil if ready.empty?

  log.debug("[llm][ranker] action=rank ready_count=#{ready.size} " \
            "seed=#{@requirements.routing_seed[0, 8]}...")

  # Two-pass band ordering (preferred != required): pass 1 ranks the in-band
  # lanes; pass 2 (only when pass 1 is empty) ranks everything else,
  # band-ignoring. No lane is excluded by the band -- the band is a priority,
  # not a filter. Only the selected pass is computed, so the ranked log lines
  # are exactly the lanes eligible for this attempt.
  in_band, out_of_band = band_partition(ready)

  log.debug("[llm][ranker] action=preferred_band_partition ready=#{ready.size} " \
            "in_band=#{in_band.size} out_of_band=#{out_of_band.size}")

  # Steps 3–4 (§10.2 + D17): base weight, affinity, effective weight.
  # Step 5 (§10.3): rendezvous score.
  # Pass 1 wins if non-empty; otherwise pass 2. Within a pass: greatest
  # effective_weight bucket -> greatest rendezvous score -> ascending lane_id.
  ranked = compute_ranked(in_band) if in_band.any?
  ranked ||= compute_ranked(out_of_band)

  # Select the winner (greatest effective_weight bucket → greatest rendezvous
  # score → lexicographically ascending lane_id for cryptographically
  # improbable score collisions).
  select_winner(ranked)
end