Module: Legion::Extensions::Llm::Inventory::WeightSchema

Defined in:
lib/legion/extensions/llm/inventory/weight_schema.rb

Overview

Write-time lane-weight computation (RANKING v2 law): the stateless router reads the stored scalar; it is computed ONLY here, at write events, from a live settings read. Each multiplicative axis reads ITS OWN scope — never a fall-through cascade (a fall-through would double-count the other axes). The offering-scope settings key is the lane's 5 tuple — operator-readable, composed via Identity.compose_lane_id.

Constant Summary collapse

IDENTITY =
100

Class Method Summary collapse

Class Method Details

.base_weight(weight_inputs) ⇒ Object

Pinned return contract: TWO methods. The writer calls both:

wi = WeightSchema.weight_inputs(...)
base = WeightSchema.base_weight(wi)


139
140
141
# File 'lib/legion/extensions/llm/inventory/weight_schema.rb', line 139

def base_weight(weight_inputs)
  weight_inputs.values.reduce(1, :*)
end

.component(value, default) ⇒ Object

nil → default; an explicit 0 passes through (0 = operator disable — 0 is TRUTHY in Ruby and must not be defaulted); any other non-Integer RAISES instead of silently applying a different weight.

Raises:

  • (ArgumentError)


117
118
119
120
121
122
123
124
# File 'lib/legion/extensions/llm/inventory/weight_schema.rb', line 117

def component(value, default)
  return default if value.nil?

  raise ArgumentError, "weight component must be an Integer >= 0, got #{value.inspect}" \
    unless value.is_a?(::Integer) && value >= 0

  value
end

.offering_scope_weight(offerings:, instance_key:, model:, tier:, operation_evidence:) ⇒ Object

The configured offering-scope weight for the draft: the operator keys extensions.llm.<provider>.offerings by the lane's 5 tuple. The lanes a draft supports are one 5 tuple per distinct lane type; the draft carries a SINGLE weight pair, so configured weights across its lanes must agree — a disagreement is an ambiguous operator input and RAISES instead of silently picking one.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/legion/extensions/llm/inventory/weight_schema.rb', line 83

def offering_scope_weight(offerings:, instance_key:, model:, tier:, operation_evidence:)
  lane_ids = supported_lane_ids(
    instance_key: instance_key, model: model, tier: tier, operation_evidence: operation_evidence
  )
  weights = lane_ids.filter_map do |lane_id|
    scope = scope_hash(SettingsCascade.lookup(offerings, lane_id), path: "provider.offerings.#{lane_id}")
    SettingsCascade.lookup(scope, :weight)
  end
  return nil if weights.empty?

  unless weights.uniq.length == 1
    raise ArgumentError, "offering weight scope is ambiguous: the draft's lanes " \
                         "#{lane_ids.join(', ')} carry differing configured weights"
  end

  weights.first
end

.scope_hash(value, path:) ⇒ Object

Missing scope is the identity default. A present malformed scope is never treated as missing (false || {} would silently erase operator input and recreate a flat identity result).

Raises:

  • (ArgumentError)


129
130
131
132
133
134
# File 'lib/legion/extensions/llm/inventory/weight_schema.rb', line 129

def scope_hash(value, path:)
  return {} if value.nil?
  return value if value.is_a?(::Hash)

  raise ArgumentError, "#{path} must be a Hash, got #{value.inspect}"
end

.supported_lane_ids(instance_key:, model:, tier:, operation_evidence:) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/legion/extensions/llm/inventory/weight_schema.rb', line 101

def supported_lane_ids(instance_key:, model:, tier:, operation_evidence:)
  operation_evidence.each_value.with_object([]) do |evidence, lane_ids|
    next unless evidence.supported?

    lane_id = Identity.compose_lane_id(
      tier: tier, provider_family: instance_key.provider_family,
      instance_id: instance_key.instance_id,
      type: Taxonomies.lane_type_for(operation: evidence.operation), model: model
    )
    lane_ids << lane_id unless lane_ids.include?(lane_id)
  end
end

.weight_inputs(settings:, instance_key:, model:, tier:, operation_evidence:) ⇒ Object

Exact 4-key hash. The offering-scope settings key is the 5 tuple of the lanes the draft's operation evidence supports (one per distinct lane type) — finally operator-usable, no digest.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/legion/extensions/llm/inventory/weight_schema.rb', line 25

def weight_inputs(settings:, instance_key:, model:, tier:, operation_evidence:)
  llm_conf = scope_hash(settings.dig(:extensions, :llm), path: 'extensions.llm')
  provider_conf = scope_hash(
    SettingsCascade.lookup(llm_conf, instance_key.provider_family),
    path: "extensions.llm.#{instance_key.provider_family}"
  )
  instances = scope_hash(
    SettingsCascade.lookup(provider_conf, :instances), path: 'provider.instances'
  )
  instance_cfg = scope_hash(
    SettingsCascade.lookup(instances, instance_key.instance_id),
    path: "provider.instances.#{instance_key.instance_id}"
  )
  tier_weights = scope_hash(
    settings.dig(:llm, :routing, :tier_weights), path: 'llm.routing.tier_weights'
  )
  offerings = scope_hash(SettingsCascade.lookup(provider_conf, :offerings), path: 'provider.offerings')
  offering_w = offering_scope_weight(
    offerings: offerings, instance_key: instance_key, model: model, tier: tier,
    operation_evidence: operation_evidence
  )
  provider_models = scope_hash(
    SettingsCascade.lookup(provider_conf, :models), path: 'provider.models'
  )
  instance_models = scope_hash(
    SettingsCascade.lookup(instance_cfg, :models), path: 'instance.models'
  )
  scope_hash(
    SettingsCascade.lookup(provider_models, model), path: "provider.models.#{model}"
  )
  scope_hash(
    SettingsCascade.lookup(instance_models, model), path: "instance.models.#{model}"
  )
  model_scopes = scope_hash(
    SettingsCascade.merge_model_scopes(
      provider_conf: provider_conf, instance_cfg: instance_cfg, model: model
    ),
    path: "merged model scope #{model}"
  )

  model_w = SettingsCascade.lookup(model_scopes, :weight)
  {
    tier: component(SettingsCascade.lookup(tier_weights, tier), IDENTITY),
    provider: component(SettingsCascade.lookup(provider_conf, :weight), IDENTITY),
    instance: component(SettingsCascade.lookup(instance_cfg, :weight), IDENTITY),
    # Explicit nil? precedence (NEVER `||`): offering overrides the model
    # component only; nil offering → model; both nil → identity. A
    # non-nil non-Integer (false, strings, negatives) RAISES in `component`.
    model_or_offering: component(offering_w.nil? ? model_w : offering_w, IDENTITY)
  }
end