Module: Legion::LLM::Router::OutcomeClassifier
- Extended by:
- Legion::Logging::Helper
- Defined in:
- lib/legion/llm/router/outcome_classifier.rb
Overview
Provider-neutral outcome classification (SSOT v3 §16). Consumes ONLY a Phase 1 normalized ProviderOutcome plus the exact AttemptContext; it never sees a provider name, HTTP status, or response body for branching.
Defined Under Namespace
Classes: Action, GlobalTransition
Constant Summary collapse
- RETRYABLE =
Outcomes that retry against a different eligible target when attempts remain.
%i[ instance_unavailable overloaded model_not_ready timeout connection_failure provider_error malformed_output tool_failure rate_limited authentication authorization billing model_missing context_rejected ].freeze
- TERMINAL_REJECTION_KIND =
Terminal provider outcomes → best-fit Rejection kind. cancelled/client_disconnect preserve the outcome so the owner can skip HTTP rendering for a gone client.
{ policy: :policy_denied, invalid_request: :invalid_request, safety_refusal: :invalid_request, cancelled: :invalid_request, client_disconnect: :invalid_request }.freeze
Class Method Summary collapse
Class Method Details
.call(outcome:, attempt_context:, attempts_remaining:) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/legion/llm/router/outcome_classifier.rb', line 89 def self.call(outcome:, attempt_context:, attempts_remaining:) kind = outcome.kind return Action.success(outcome: outcome) if kind == :success if kind == :instance_unavailable # The exact instance MUST be marked unavailable regardless of attempts; # attempts_exhausted (if any) is produced by RoutingSession#next_attempt's # counter guard on the following selection. return Action.retry( exclusions: [], outcome: outcome, global_transition: GlobalTransition.new( instance_key: attempt_context.selection.instance_key, publisher_token_id: attempt_context.selection.publisher_token_id, reason: outcome.reason ) ) end if RETRYABLE.include?(kind) return attempts_exhausted(outcome) unless attempts_remaining.positive? return Action.retry(exclusions: quota_exclusions(outcome), outcome: outcome) end rejection_kind = TERMINAL_REJECTION_KIND[kind] raise ArgumentError, "unclassifiable provider outcome kind: #{kind.inspect}" if rejection_kind.nil? Action.terminal(outcome: outcome, rejection: terminal_rejection(rejection_kind, outcome)) end |