Class: Legion::LLM::Inference::RoutingSession

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

Overview

Per-logical-request routing state (SSOT v3 §14.2). Owns one immutable routing seed (in requirements), the accumulated request-local exclusion set, and the consumed provider+instance+model target set. Reused by initial dispatch, retries, streaming failover, tool-continuation turns, fleet retry, and embedding batch restart — never cached globally, never shared by another external request. Router.next_lane is the only selector.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request:, requirements:) ⇒ RoutingSession

Returns a new instance of RoutingSession.



21
22
23
24
25
26
27
# File 'lib/legion/llm/inference/routing_session.rb', line 21

def initialize(request:, requirements:)
  @request = request
  @requirements = requirements
  @exclusions = []
  @consumed_targets = {}
  @attempt_count = 0
end

Instance Attribute Details

#attempt_countObject (readonly)

Returns the value of attribute attempt_count.



19
20
21
# File 'lib/legion/llm/inference/routing_session.rb', line 19

def attempt_count
  @attempt_count
end

#requestObject (readonly)

Returns the value of attribute request.



19
20
21
# File 'lib/legion/llm/inference/routing_session.rb', line 19

def request
  @request
end

#requirementsObject (readonly)

Returns the value of attribute requirements.



19
20
21
# File 'lib/legion/llm/inference/routing_session.rb', line 19

def requirements
  @requirements
end

Instance Method Details

#add_exclusion(exclusion:) ⇒ Object

Additional request-local exclusion (quota domain, policy, etc.). Cannot remove or overwrite a consumed attempt-target exclusion.



73
74
75
76
# File 'lib/legion/llm/inference/routing_session.rb', line 73

def add_exclusion(exclusion:)
  @exclusions << exclusion
  exclusion
end

#classify(dispatch_result:, attempt_context:) ⇒ Object

Classify one SelectionDispatch::Result, apply the returned action's exclusions and (for instance_unavailable) the exact Phase 1 global transition, and return the Action.



81
82
83
84
85
86
87
88
89
# File 'lib/legion/llm/inference/routing_session.rb', line 81

def classify(dispatch_result:, attempt_context:)
  action = Legion::LLM::Router::OutcomeClassifier.call(
    outcome: dispatch_result.outcome, attempt_context: attempt_context,
    attempts_remaining: attempts_remaining
  )
  apply_global_transition(action.global_transition) if action.global_transition
  action.exclusions.each { |ex| add_exclusion(exclusion: ex) }
  action
end

#consumed_targetsObject



37
38
39
# File 'lib/legion/llm/inference/routing_session.rb', line 37

def consumed_targets
  @consumed_targets.keys.freeze
end

#exclusionsObject



33
34
35
# File 'lib/legion/llm/inference/routing_session.rb', line 33

def exclusions
  @exclusions.dup.freeze
end

#next_attempt(snapshot:) ⇒ Object

=> AttemptContext or Phase 1 Rejection.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/legion/llm/inference/routing_session.rb', line 42

def next_attempt(snapshot:)
  return attempts_exhausted(snapshot) if @attempt_count >= @requirements.maximum_attempts

  selection = Legion::LLM::Router.next_lane(
    requirements: @requirements, exclusions: exclusions, snapshot: snapshot
  )
  return selection if rejection?(selection)

  consume!(selection)

  begin
    Legion::LLM::Inference::AttemptContext.build(
      selection: selection, snapshot: snapshot, attempt_number: @attempt_count
    )
  rescue Legion::LLM::Inference::AttemptContext::Stale => e
    # Target stays consumed; owner captures a fresh snapshot and retries.
    log.debug("[llm][routing_session] action=stale_selection reason=#{e.message}")
    stale_selection(snapshot)
  end
end

#next_attempt!(snapshot:) ⇒ Object

=> AttemptContext; raises RoutingRejected when next_attempt rejected.



64
65
66
67
68
69
# File 'lib/legion/llm/inference/routing_session.rb', line 64

def next_attempt!(snapshot:)
  result = next_attempt(snapshot: snapshot)
  return result unless rejection?(result)

  raise Legion::LLM::Errors::RoutingRejected.new(rejection: result)
end

#routing_seedObject



29
30
31
# File 'lib/legion/llm/inference/routing_session.rb', line 29

def routing_seed
  @requirements.routing_seed
end