Module: Legion::LLM::Router
- Extended by:
- Legion::Logging::Helper
- Defined in:
- lib/legion/llm/router.rb,
lib/legion/llm/router/ranker.rb,
lib/legion/llm/router/resolution.rb,
lib/legion/llm/router/input_bound.rb,
lib/legion/llm/router/settings_state.rb,
lib/legion/llm/router/settings_snapshot.rb,
lib/legion/llm/router/header_constraints.rb,
lib/legion/llm/router/outcome_classifier.rb,
lib/legion/llm/router/candidate_evaluator.rb,
lib/legion/llm/router/candidate_evaluation.rb,
lib/legion/llm/router/request_requirements.rb,
lib/legion/llm/router/rejection_diagnostics.rb,
lib/legion/llm/router/required_capabilities.rb,
lib/legion/llm/router/body_model_hint_policy.rb
Defined Under Namespace
Modules: BodyModelHintPolicy, CandidateEvaluator, HeaderConstraints, InputBound, OutcomeClassifier, RejectionDiagnostics, RequiredCapabilities, SettingsState Classes: CandidateEvaluation, EvaluationSet, Ranker, RequestRequirements, Resolution, SettingsSnapshot
Constant Summary collapse
- PROVIDER_TIER =
{ bedrock: :cloud, anthropic: :frontier, openai: :frontier, gemini: :cloud, azure: :cloud, ollama: :local, vllm: :fleet }.freeze
- PROVIDER_ORDER =
%i[ollama vllm bedrock azure gemini anthropic openai].freeze
- TIER_EXTERNAL =
Set[:cloud, :frontier].freeze
- TIER_RANK =
{ local: 0, direct: 1, fleet: 2, cloud: 3, frontier: 4 }.freeze
- CAPABILITY_ALIASES =
{ function_calling: :tools, functions: :tools, tool: :tools, tool_use: :tools, stream: :streaming, stream_chat: :streaming }.freeze
- CANONICAL_EFFORT_LEVELS =
%i[low moderate high reasoning].freeze
- EFFORT_ALIASES =
{ medium: :moderate }.freeze
- EFFORT_LEVELS =
(CANONICAL_EFFORT_LEVELS + EFFORT_ALIASES.keys).freeze
- EFFORT_RANK =
{ low: 0, moderate: 1, high: 2, reasoning: 3 }.freeze
- OPERATIONS =
%i[chat stream embed image structured_output].freeze
- OPERATION_ALIASES =
{ completion: :chat, stream_chat: :stream, embedding: :embed }.freeze
- DEFAULT_OPERATION =
:chat- DEFAULT_EFFORT =
:moderate- OLLAMA_MODEL_PATTERN =
%r{[:/]}
Class Method Summary collapse
- .auto_rules_populated? ⇒ Boolean
-
.build_selection(ranked:, snapshot:) ⇒ Object
Construct the Phase 1 Selection from the chosen RankedCandidate and its evaluation's same-generation records.
-
.next_lane(requirements:, exclusions:, snapshot:) ⇒ Object
SSOT v3 §12: the single selection method.
-
.populate_auto_rules(_discovered_instances = nil) ⇒ Object
DEPRECATED in v0.14.0; delete in v0.15.0.
-
.privacy_mode? ⇒ Boolean
Public query for status endpoints (/api/llm/tiers).
- .reset! ⇒ Object
-
.routing_enabled? ⇒ Boolean
SSOT has no operator routing toggle (auto-rules era is gone): routing is enabled whenever at least one instance has a complete publication in the Registry.
-
.tier_available?(tier) ⇒ Boolean
Check whether a tier can be used right now.
- .tier_priority ⇒ Object
- .tier_rank ⇒ Object
- .validate_exclusions!(exclusions) ⇒ Object
- .validate_snapshot!(snapshot) ⇒ Object
Class Method Details
.auto_rules_populated? ⇒ Boolean
152 153 154 |
# File 'lib/legion/llm/router.rb', line 152 def auto_rules_populated? @auto_rules_populated == true end |
.build_selection(ranked:, snapshot:) ⇒ Object
Construct the Phase 1 Selection from the chosen RankedCandidate and its evaluation's same-generation records. Never re-reads the registry.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/legion/llm/router.rb', line 116 def build_selection(ranked:, snapshot:) evaluation = ranked.evaluation lane = evaluation.lane offering = evaluation.offering instance = evaluation.instance Legion::Extensions::Llm::Routing::Selection.new( inventory_generation: snapshot.generation, lane_id: lane.lane_id, instance_key: lane.instance_key, offering_id: lane.offering_id, provider_family: lane.provider_family, instance_id: lane.instance_id, model: lane.model, operation: lane.operation, callable_handle: lane.callable_handle, publisher_token_id: instance.publisher_token_id, capability_evidence: offering.capability_evidence, context_evidence: offering.context_evidence, weight_inputs: ranked.weight_inputs, base_weight: ranked.base_weight, preference_ppm: ranked.preference_ppm, effective_weight: ranked.effective_weight, rendezvous_score: ranked.rendezvous_score ) end |
.next_lane(requirements:, exclusions:, snapshot:) ⇒ Object
SSOT v3 §12: the single selection method. Pure function of (routing_seed+requirements, exclusions, one snapshot generation, one settings generation). Returns exactly one Phase 1 Selection or Rejection — never nil, a lane hash, a model/provider string, a chain, or an array.
55 56 57 58 59 60 61 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 92 93 94 95 96 97 |
# File 'lib/legion/llm/router.rb', line 55 def next_lane(requirements:, exclusions:, snapshot:) validate_exclusions!(exclusions) validate_snapshot!(snapshot) snapshot.generation # capture once (immutable snapshot) settings_snapshot = Legion::LLM::Router::SettingsState.current evaluation_set = Legion::LLM::Router::CandidateEvaluator.call( requirements: requirements, exclusions: exclusions, snapshot: snapshot, settings_snapshot: settings_snapshot ) ranked = Legion::LLM::Router::Ranker.call( evaluation_set: evaluation_set, requirements: requirements, settings_snapshot: settings_snapshot ) if ranked.nil? && hint_model_pin_active?(requirements) # v2 parity (v2 executor/routing.rb resolve_model_to_local_provider # model_discovery_miss: state[:model]=nil, auto_route=true): an # HONORED body-model hint that no candidate matches is not a caller # error — clear the hint pin and re-evaluate with normal weighted # selection (N x N: route to ANY qualifying lane). A trusted # X-Legion-Model pin never reaches this branch — explicit pins stay # hard. If the re-evaluation finds nothing, the normal no-lane # rejection stands (a real no-lane, not a hint problem). log.info("[llm][router] action=model_hint_miss model=#{requirements.model_pin} " \ 'falling_back=weighted_selection') requirements = requirements.without_model_pin evaluation_set = Legion::LLM::Router::CandidateEvaluator.call( requirements: requirements, exclusions: exclusions, snapshot: snapshot, settings_snapshot: settings_snapshot ) ranked = Legion::LLM::Router::Ranker.call( evaluation_set: evaluation_set, requirements: requirements, settings_snapshot: settings_snapshot ) end if ranked.nil? return Legion::LLM::Router::RejectionDiagnostics.call( requirements: requirements, evaluation_set: evaluation_set, snapshot: snapshot ) end build_selection(ranked: ranked, snapshot: snapshot) end |
.populate_auto_rules(_discovered_instances = nil) ⇒ Object
DEPRECATED in v0.14.0; delete in v0.15.0. See GitHub issues:
#155 — remove this stub in v0.15.0 (blocked-by #154)
#154 — drop call sites from 9 lex-llm-* gems
160 161 162 163 164 165 166 |
# File 'lib/legion/llm/router.rb', line 160 def populate_auto_rules(_discovered_instances = nil, **) return if @populate_auto_rules_warned @populate_auto_rules_warned = true log.warn '[llm][router] populate_auto_rules is deprecated and is a no-op as of v0.14.0; ' \ 'lex-llm-* gems should drop this call (RANKING v2 replaces auto-rules with lane weights)' end |
.privacy_mode? ⇒ Boolean
Public query for status endpoints (/api/llm/tiers). Reflects the enterprise-privacy setting (or LEGION_ENTERPRISE_PRIVACY env override).
213 214 215 216 217 218 219 |
# File 'lib/legion/llm/router.rb', line 213 def privacy_mode? if Legion::Settings.respond_to?(:enterprise_privacy?) Legion::Settings.enterprise_privacy? else ENV['LEGION_ENTERPRISE_PRIVACY'] == 'true' end end |
.reset! ⇒ Object
168 169 170 171 172 |
# File 'lib/legion/llm/router.rb', line 168 def reset! @auto_rules = [] @auto_rules_populated = false @populate_auto_rules_warned = false end |
.routing_enabled? ⇒ Boolean
SSOT has no operator routing toggle (auto-rules era is gone): routing is enabled whenever at least one instance has a complete publication in the Registry.
147 148 149 150 |
# File 'lib/legion/llm/router.rb', line 147 def routing_enabled? Legion::Extensions::Llm::Inventory::Registry.snapshot .each_publication_status.any? { |ps| ps.state == :complete } end |
.tier_available?(tier) ⇒ Boolean
Check whether a tier can be used right now. :local — always available :direct — always available (remote self-hosted instances) :fleet — available when Legion::Transport is loaded :cloud — available unless privacy mode :frontier — available unless privacy mode
196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/legion/llm/router.rb', line 196 def tier_available?(tier) sym = tier.to_sym if external_tier?(sym) && privacy_mode? log.debug "[llm][router] action=tier_available tier=#{sym} available=false reason=privacy_mode" return false end if sym == :fleet available = Legion.const_defined?('Transport', false) log.debug "[llm][router] action=tier_available tier=fleet available=#{available}" return available end true end |
.tier_priority ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/legion/llm/router.rb', line 174 def tier_priority configured = Legion::Settings[:llm][:tier_order] configured = Legion::Settings[:llm][:routing][:tier_order] if configured.nil? || Array(configured).empty? configured = Legion::Settings[:llm][:routing][:tier_priority] if configured.nil? || Array(configured).empty? normalized = Array(configured).filter_map { |tier| tier.to_sym if tier.respond_to?(:to_sym) } normalized = TIER_RANK.keys if normalized.empty? (normalized + TIER_RANK.keys).uniq rescue StandardError => e handle_exception(e, level: :warn, handled: true, operation: 'router.tier_priority') TIER_RANK.keys end |
.tier_rank ⇒ Object
186 187 188 |
# File 'lib/legion/llm/router.rb', line 186 def tier_rank tier_priority.each_with_index.to_h end |
.validate_exclusions!(exclusions) ⇒ Object
99 100 101 102 103 104 |
# File 'lib/legion/llm/router.rb', line 99 def validate_exclusions!(exclusions) unless exclusions.is_a?(Array) && exclusions.all?(Legion::Extensions::Llm::Routing::Exclusion) raise ArgumentError, 'exclusions must be an Array of Phase 1 Routing::Exclusion records' end end |
.validate_snapshot!(snapshot) ⇒ Object
107 108 109 110 111 |
# File 'lib/legion/llm/router.rb', line 107 def validate_snapshot!(snapshot) return if snapshot.is_a?(Legion::Extensions::Llm::Inventory::Snapshot) raise ArgumentError, 'snapshot must be a Phase 1 Inventory::Snapshot' end |