lex-llm 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +106 -0
- data/RULES.md +97 -0
- data/lib/legion/extensions/llm/auto_registration.rb +4 -13
- data/lib/legion/extensions/llm/canonical/chunk.rb +106 -92
- data/lib/legion/extensions/llm/canonical/content_block.rb +66 -75
- data/lib/legion/extensions/llm/canonical/message.rb +52 -67
- data/lib/legion/extensions/llm/canonical/params.rb +59 -33
- data/lib/legion/extensions/llm/canonical/request.rb +67 -54
- data/lib/legion/extensions/llm/canonical/response.rb +61 -76
- data/lib/legion/extensions/llm/canonical/strict.rb +105 -0
- data/lib/legion/extensions/llm/canonical/thinking.rb +99 -51
- data/lib/legion/extensions/llm/canonical/tool_call.rb +42 -51
- data/lib/legion/extensions/llm/canonical/tool_definition.rb +56 -46
- data/lib/legion/extensions/llm/canonical/tool_schema.rb +15 -22
- data/lib/legion/extensions/llm/canonical/usage.rb +47 -40
- data/lib/legion/extensions/llm/canonical.rb +6 -5
- data/lib/legion/extensions/llm/configuration.rb +40 -10
- data/lib/legion/extensions/llm/connection.rb +8 -30
- data/lib/legion/extensions/llm/credential_sources.rb +32 -49
- data/lib/legion/extensions/llm/discovery/actor.rb +92 -0
- data/lib/legion/extensions/llm/discovery/pipeline.rb +604 -0
- data/lib/legion/extensions/llm/error.rb +0 -14
- data/lib/legion/extensions/llm/fleet/contract_error.rb +15 -0
- data/lib/legion/extensions/llm/fleet/envelope_validation.rb +7 -6
- data/lib/legion/extensions/llm/fleet/fleet_envelope.rb +66 -0
- data/lib/legion/extensions/llm/fleet/protocol.rb +18 -5
- data/lib/legion/extensions/llm/fleet/provider_responder.rb +58 -153
- data/lib/legion/extensions/llm/fleet/token_validator.rb +15 -21
- data/lib/legion/extensions/llm/fleet/worker_execution.rb +107 -150
- data/lib/legion/extensions/llm/inventory/errors.rb +0 -1
- data/lib/legion/extensions/llm/inventory/evidence.rb +1 -1
- data/lib/legion/extensions/llm/inventory/identity.rb +55 -39
- data/lib/legion/extensions/llm/inventory/probe_token.rb +9 -12
- data/lib/legion/extensions/llm/inventory/publisher.rb +15 -53
- data/lib/legion/extensions/llm/inventory/records.rb +82 -99
- data/lib/legion/extensions/llm/inventory/registry.rb +54 -46
- data/lib/legion/extensions/llm/inventory/snapshot.rb +7 -21
- data/lib/legion/extensions/llm/inventory/weight_reconciler.rb +249 -0
- data/lib/legion/extensions/llm/inventory/weight_schema.rb +146 -0
- data/lib/legion/extensions/llm/provider/open_ai_compatible.rb +172 -182
- data/lib/legion/extensions/llm/provider.rb +192 -315
- data/lib/legion/extensions/llm/provider_contract.rb +25 -8
- data/lib/legion/extensions/llm/provider_settings.rb +5 -26
- data/lib/legion/extensions/llm/responses/thinking_extractor.rb +8 -1
- data/lib/legion/extensions/llm/responses/tool_arguments.rb +34 -0
- data/lib/legion/extensions/llm/routing/provider_outcome.rb +25 -0
- data/lib/legion/extensions/llm/routing/records.rb +34 -17
- data/lib/legion/extensions/llm/stream_accumulator.rb +186 -270
- data/lib/legion/extensions/llm/streaming.rb +50 -35
- data/lib/legion/extensions/llm/taxonomies.rb +29 -17
- data/lib/legion/extensions/llm/transport/fleet_lane.rb +8 -10
- data/lib/legion/extensions/llm/transport/messages/fleet_error.rb +3 -2
- data/lib/legion/extensions/llm/transport/messages/fleet_request.rb +6 -8
- data/lib/legion/extensions/llm/transport/messages/fleet_response.rb +10 -9
- data/lib/legion/extensions/llm/utils.rb +23 -5
- data/lib/legion/extensions/llm/version.rb +1 -1
- data/lib/legion/extensions/llm.rb +10 -98
- data/spec/legion/extensions/llm/auto_registration_spec.rb +4 -9
- data/spec/legion/extensions/llm/canonical/chunk_spec.rb +66 -252
- data/spec/legion/extensions/llm/canonical/content_block_spec.rb +52 -197
- data/spec/legion/extensions/llm/canonical/message_spec.rb +89 -204
- data/spec/legion/extensions/llm/canonical/params_spec.rb +57 -136
- data/spec/legion/extensions/llm/canonical/request_spec.rb +81 -143
- data/spec/legion/extensions/llm/canonical/response_spec.rb +68 -204
- data/spec/legion/extensions/llm/canonical/thinking_spec.rb +68 -148
- data/spec/legion/extensions/llm/canonical/tool_call_spec.rb +59 -162
- data/spec/legion/extensions/llm/canonical/tool_definition_spec.rb +55 -191
- data/spec/legion/extensions/llm/canonical/tool_schema_spec.rb +26 -67
- data/spec/legion/extensions/llm/canonical/usage_spec.rb +46 -155
- data/spec/legion/extensions/llm/configuration_spec.rb +31 -5
- data/spec/legion/extensions/llm/conformance/canonical_type_examples.rb +106 -0
- data/spec/legion/extensions/llm/conformance/conformance.rb +10 -2
- data/spec/legion/extensions/llm/conformance/provider_translator_examples.rb +1 -1
- data/spec/legion/extensions/llm/conformance/ssot_contract_conformance_spec.rb +130 -0
- data/spec/legion/extensions/llm/conformance/ssot_contract_examples.rb +507 -0
- data/spec/legion/extensions/llm/conformance/ssot_provider_examples.rb +11 -10
- data/spec/legion/extensions/llm/credential_sources_spec.rb +12 -13
- data/spec/legion/extensions/llm/error_spec.rb +2 -12
- data/spec/legion/extensions/llm/fleet/exact_offering_spec.rb +59 -45
- data/spec/legion/extensions/llm/fleet/provider_responder_spec.rb +178 -67
- data/spec/legion/extensions/llm/fleet/token_validator_spec.rb +7 -2
- data/spec/legion/extensions/llm/fleet/worker_execution_spec.rb +101 -62
- data/spec/legion/extensions/llm/fleet_messages_spec.rb +118 -123
- data/spec/legion/extensions/llm/inventory/boot_spec.rb +4 -4
- data/spec/legion/extensions/llm/inventory/identity_spec.rb +127 -110
- data/spec/legion/extensions/llm/inventory/probe_token_spec.rb +4 -4
- data/spec/legion/extensions/llm/inventory/publisher_spec.rb +8 -61
- data/spec/legion/extensions/llm/inventory/records_spec.rb +129 -41
- data/spec/legion/extensions/llm/inventory/registry_activation_spec.rb +55 -4
- data/spec/legion/extensions/llm/inventory/registry_replacement_spec.rb +5 -4
- data/spec/legion/extensions/llm/inventory/snapshot_spec.rb +11 -5
- data/spec/legion/extensions/llm/inventory/weight_reconciler_spec.rb +312 -0
- data/spec/legion/extensions/llm/inventory/weight_schema_spec.rb +141 -0
- data/spec/legion/extensions/llm/provider/open_ai_compatible_spec.rb +105 -68
- data/spec/legion/extensions/llm/provider/open_ai_compatible_tool_calls_array_spec.rb +7 -31
- data/spec/legion/extensions/llm/provider_contract_spec.rb +10 -15
- data/spec/legion/extensions/llm/provider_spec.rb +98 -78
- data/spec/legion/extensions/llm/routing/records_spec.rb +38 -5
- data/spec/legion/extensions/llm/stream_accumulator_spec.rb +174 -144
- data/spec/legion/extensions/llm/streaming_spec.rb +27 -0
- data/spec/legion/extensions/llm/taxonomies_spec.rb +43 -16
- data/spec/legion/extensions/llm/transport/fleet_lane_spec.rb +1 -1
- data/spec/legion/extensions/llm/utils_spec.rb +26 -7
- data/spec/legion/extensions/llm_base_contract_spec.rb +55 -90
- data/spec/legion/extensions/llm_extension_spec.rb +5 -5
- data/spec/support/fake_llm_provider.rb +45 -39
- data/spec/support/fake_ssot_harness.rb +7 -2
- data/spec/support/ssot_registry_helpers.rb +3 -2
- metadata +15 -54
- data/lib/legion/extensions/llm/agent.rb +0 -366
- data/lib/legion/extensions/llm/aliases.json +0 -436
- data/lib/legion/extensions/llm/aliases.rb +0 -67
- data/lib/legion/extensions/llm/attachment.rb +0 -229
- data/lib/legion/extensions/llm/chat.rb +0 -354
- data/lib/legion/extensions/llm/chunk.rb +0 -10
- data/lib/legion/extensions/llm/content.rb +0 -81
- data/lib/legion/extensions/llm/context.rb +0 -33
- data/lib/legion/extensions/llm/embedding.rb +0 -33
- data/lib/legion/extensions/llm/image.rb +0 -109
- data/lib/legion/extensions/llm/inventory/capabilities.rb +0 -40
- data/lib/legion/extensions/llm/inventory/scoped_refresher.rb +0 -311
- data/lib/legion/extensions/llm/message.rb +0 -118
- data/lib/legion/extensions/llm/mime_type.rb +0 -75
- data/lib/legion/extensions/llm/model/info.rb +0 -286
- data/lib/legion/extensions/llm/model/modalities.rb +0 -26
- data/lib/legion/extensions/llm/model/pricing.rb +0 -52
- data/lib/legion/extensions/llm/model/pricing_category.rb +0 -50
- data/lib/legion/extensions/llm/model/pricing_tier.rb +0 -37
- data/lib/legion/extensions/llm/model.rb +0 -11
- data/lib/legion/extensions/llm/models.json +0 -57313
- data/lib/legion/extensions/llm/models.rb +0 -530
- data/lib/legion/extensions/llm/models_schema.json +0 -168
- data/lib/legion/extensions/llm/moderation.rb +0 -60
- data/lib/legion/extensions/llm/registry_event_builder.rb +0 -141
- data/lib/legion/extensions/llm/registry_publisher.rb +0 -107
- data/lib/legion/extensions/llm/responses/chat_response.rb +0 -43
- data/lib/legion/extensions/llm/responses/embedding_response.rb +0 -38
- data/lib/legion/extensions/llm/responses/stream_chunk.rb +0 -43
- data/lib/legion/extensions/llm/routing/lane_key.rb +0 -66
- data/lib/legion/extensions/llm/routing/model_offering.rb +0 -241
- data/lib/legion/extensions/llm/routing/offering_registry.rb +0 -101
- data/lib/legion/extensions/llm/routing/registry_event.rb +0 -167
- data/lib/legion/extensions/llm/thinking.rb +0 -53
- data/lib/legion/extensions/llm/tokens.rb +0 -51
- data/lib/legion/extensions/llm/tool_call.rb +0 -34
- data/lib/legion/extensions/llm/transcription.rb +0 -39
- data/lib/legion/extensions/llm/transport/messages/registry_event.rb +0 -44
- data/spec/legion/extensions/llm/agent_spec.rb +0 -179
- data/spec/legion/extensions/llm/attachment_spec.rb +0 -25
- data/spec/legion/extensions/llm/conformance/fixtures/ssot_identity_vectors.json +0 -84
- data/spec/legion/extensions/llm/context_spec.rb +0 -127
- data/spec/legion/extensions/llm/inventory/capabilities_spec.rb +0 -43
- data/spec/legion/extensions/llm/inventory/scoped_refresher_spec.rb +0 -337
- data/spec/legion/extensions/llm/message_spec.rb +0 -64
- data/spec/legion/extensions/llm/model/info_spec.rb +0 -222
- data/spec/legion/extensions/llm/models_spec.rb +0 -104
- data/spec/legion/extensions/llm/registry_event_builder_spec.rb +0 -68
- data/spec/legion/extensions/llm/registry_publisher_spec.rb +0 -22
- data/spec/legion/extensions/llm/responses/response_objects_spec.rb +0 -75
- data/spec/legion/extensions/llm/routing/model_offering_spec.rb +0 -281
- data/spec/legion/extensions/llm/routing/offering_registry_spec.rb +0 -50
- data/spec/legion/extensions/llm/routing/registry_event_spec.rb +0 -120
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'legion/logging'
|
|
4
3
|
require 'legion/extensions/llm/inventory/errors'
|
|
5
4
|
require 'legion/extensions/llm/inventory/identity'
|
|
6
5
|
require 'legion/extensions/llm/inventory/registry'
|
|
@@ -12,16 +11,14 @@ module Legion
|
|
|
12
11
|
# Provider-facing direct wrapper over the local Registry. It constructs
|
|
13
12
|
# and validates the exact InstanceKey from its fixed provider family and
|
|
14
13
|
# delegates to the registry with the exact kwargs. It does no retries,
|
|
15
|
-
# selection, scheduling, defaulting, provider discovery
|
|
16
|
-
#
|
|
17
|
-
#
|
|
14
|
+
# selection, scheduling, defaulting, or provider discovery. M7: the
|
|
15
|
+
# legacy dual-sink seam (compatibility_adapter / old-coordinator
|
|
16
|
+
# projection) is deleted — one representation, one routing authority;
|
|
17
|
+
# the SSOT registry is the only inventory sink.
|
|
18
18
|
class Publisher
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def initialize(provider_family:, registry: Registry, compatibility_adapter: nil)
|
|
19
|
+
def initialize(provider_family:, registry: Registry)
|
|
22
20
|
@provider_family = provider_family
|
|
23
21
|
@registry = registry
|
|
24
|
-
@compatibility_adapter = compatibility_adapter
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
# Every instance operation takes `instance_id:` — the operator's
|
|
@@ -30,9 +27,7 @@ module Legion
|
|
|
30
27
|
# dedup and diagnostics only. See Identity::InstanceKey.
|
|
31
28
|
def claim_instance(instance_id:, callable:, probe_request_handle:, physical_id: nil)
|
|
32
29
|
key = instance_key(instance_id: instance_id, physical_id: physical_id)
|
|
33
|
-
|
|
34
|
-
sync_compatibility(key, :claimed)
|
|
35
|
-
token
|
|
30
|
+
@registry.claim_instance(instance_key: key, callable: callable, probe_request_handle: probe_request_handle)
|
|
36
31
|
end
|
|
37
32
|
|
|
38
33
|
def readiness_probe_started(instance_id:, publisher_token:, physical_id: nil)
|
|
@@ -42,35 +37,29 @@ module Legion
|
|
|
42
37
|
end
|
|
43
38
|
|
|
44
39
|
def activate_instance_snapshot(instance_id:, publisher_token:, offerings:, sequence:, probe_token:, physical_id: nil) # rubocop:disable Metrics/ParameterLists
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
sequence: sequence, probe_token: probe_token
|
|
40
|
+
@registry.activate_instance_snapshot(
|
|
41
|
+
publisher_token: publisher_token, instance_key: instance_key(instance_id: instance_id, physical_id: physical_id),
|
|
42
|
+
offerings: offerings, sequence: sequence, probe_token: probe_token
|
|
49
43
|
)
|
|
50
|
-
sync_applied(key, result)
|
|
51
44
|
end
|
|
52
45
|
|
|
53
46
|
def replace_instance_snapshot(instance_id:, publisher_token:, offerings:, sequence:, physical_id: nil)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
@registry.replace_instance_snapshot(
|
|
48
|
+
publisher_token: publisher_token, instance_key: instance_key(instance_id: instance_id, physical_id: physical_id),
|
|
49
|
+
offerings: offerings, sequence: sequence
|
|
57
50
|
)
|
|
58
|
-
sync_applied(key, result)
|
|
59
51
|
end
|
|
60
52
|
|
|
61
53
|
def readiness_succeeded(instance_id:, probe_token:, physical_id: nil)
|
|
62
|
-
|
|
63
|
-
sync_applied(key, @registry.readiness_succeeded(instance_key: key, probe_token: probe_token))
|
|
54
|
+
@registry.readiness_succeeded(instance_key: instance_key(instance_id: instance_id, physical_id: physical_id), probe_token: probe_token)
|
|
64
55
|
end
|
|
65
56
|
|
|
66
57
|
def readiness_failed(instance_id:, probe_token:, reason:, physical_id: nil)
|
|
67
|
-
|
|
68
|
-
sync_applied(key, @registry.readiness_failed(instance_key: key, probe_token: probe_token, reason: reason))
|
|
58
|
+
@registry.readiness_failed(instance_key: instance_key(instance_id: instance_id, physical_id: physical_id), probe_token: probe_token, reason: reason)
|
|
69
59
|
end
|
|
70
60
|
|
|
71
61
|
def remove_instance(instance_id:, publisher_token:, physical_id: nil)
|
|
72
|
-
|
|
73
|
-
sync_applied(key, @registry.remove_instance(instance_key: key, publisher_token: publisher_token))
|
|
62
|
+
@registry.remove_instance(instance_key: instance_key(instance_id: instance_id, physical_id: physical_id), publisher_token: publisher_token)
|
|
74
63
|
end
|
|
75
64
|
|
|
76
65
|
def snapshot
|
|
@@ -82,33 +71,6 @@ module Legion
|
|
|
82
71
|
def instance_key(instance_id:, physical_id: nil)
|
|
83
72
|
Identity::InstanceKey.new(provider_family: @provider_family, instance_id: instance_id, physical_id: physical_id)
|
|
84
73
|
end
|
|
85
|
-
|
|
86
|
-
def sync_applied(instance_key, result)
|
|
87
|
-
sync_compatibility(instance_key, result.reason) if result.applied
|
|
88
|
-
result
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Best-effort, post-commit projection into the old coordinator. It never
|
|
92
|
-
# changes the local return and can never roll back or authorize the SSOT.
|
|
93
|
-
def sync_compatibility(instance_key, mutation_reason)
|
|
94
|
-
return if @compatibility_adapter.nil?
|
|
95
|
-
|
|
96
|
-
outcome = @compatibility_adapter.sync_snapshot(
|
|
97
|
-
snapshot: @registry.snapshot, instance_key: instance_key, mutation_reason: mutation_reason
|
|
98
|
-
)
|
|
99
|
-
return unless outcome == :failed
|
|
100
|
-
|
|
101
|
-
log.warn(
|
|
102
|
-
'[llm][inventory][publisher] action=compatibility_sync result=failed ' \
|
|
103
|
-
"provider_family=#{instance_key.provider_family} instance=#{instance_key.instance_id} reason=#{mutation_reason}"
|
|
104
|
-
)
|
|
105
|
-
rescue StandardError => e
|
|
106
|
-
handle_exception(
|
|
107
|
-
e, handled: true, level: :warn, operation: 'llm.inventory.publisher.compatibility_sync',
|
|
108
|
-
provider_family: instance_key.provider_family, instance_id: instance_key.instance_id,
|
|
109
|
-
mutation_reason: mutation_reason
|
|
110
|
-
)
|
|
111
|
-
end
|
|
112
74
|
end
|
|
113
75
|
end
|
|
114
76
|
end
|
|
@@ -13,10 +13,10 @@ module Legion
|
|
|
13
13
|
module Llm
|
|
14
14
|
module Inventory
|
|
15
15
|
# Documentation namespace anchor for the immutable inventory records
|
|
16
|
-
# defined in this file: OfferingDraft,
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
16
|
+
# defined in this file: OfferingDraft, LaneRecord, AvailabilityFact,
|
|
17
|
+
# ReadinessResult, InstanceRecord, PublicationStatus, and
|
|
18
|
+
# MutationResult. The records themselves live directly under Inventory
|
|
19
|
+
# so their canonical constant paths stay flat.
|
|
20
20
|
module Records; end
|
|
21
21
|
|
|
22
22
|
# Shared normalization/validation used by the immutable inventory and
|
|
@@ -31,6 +31,35 @@ module Legion
|
|
|
31
31
|
|
|
32
32
|
PUBLICATION_SOURCES = %i[provider_catalog provider_static_catalog provider_control_plane].freeze
|
|
33
33
|
|
|
34
|
+
WEIGHT_INPUT_KEYS = %i[instance model_or_offering provider tier].freeze
|
|
35
|
+
IDENTITY_WEIGHT_INPUTS = {
|
|
36
|
+
tier: 100, provider: 100, instance: 100, model_or_offering: 100
|
|
37
|
+
}.freeze
|
|
38
|
+
IDENTITY_BASE_WEIGHT = 100_000_000
|
|
39
|
+
|
|
40
|
+
def validated_weight_pair(weight_inputs:, base_weight:)
|
|
41
|
+
raise Errors::ValidationError, 'weight_inputs and base_weight must be supplied together' \
|
|
42
|
+
if weight_inputs.nil? != base_weight.nil?
|
|
43
|
+
|
|
44
|
+
return [IDENTITY_WEIGHT_INPUTS, IDENTITY_BASE_WEIGHT] if weight_inputs.nil?
|
|
45
|
+
|
|
46
|
+
raise Errors::ValidationError, 'weight_inputs must be a Hash' \
|
|
47
|
+
unless weight_inputs.is_a?(::Hash)
|
|
48
|
+
unless weight_inputs.keys.length == WEIGHT_INPUT_KEYS.length &&
|
|
49
|
+
WEIGHT_INPUT_KEYS.all? { |key| weight_inputs.key?(key) }
|
|
50
|
+
raise Errors::ValidationError,
|
|
51
|
+
'weight_inputs must have keys tier/provider/instance/model_or_offering'
|
|
52
|
+
end
|
|
53
|
+
raise Errors::ValidationError, 'weight_inputs values must be Integers >= 0' \
|
|
54
|
+
unless weight_inputs.values.all? { |value| value.is_a?(::Integer) && value >= 0 }
|
|
55
|
+
raise Errors::ValidationError, 'base_weight must be an Integer >= 0' \
|
|
56
|
+
unless base_weight.is_a?(::Integer) && base_weight >= 0
|
|
57
|
+
raise Errors::ValidationError, 'base_weight must equal the product of weight_inputs' \
|
|
58
|
+
unless base_weight == weight_inputs.values.reduce(1, :*)
|
|
59
|
+
|
|
60
|
+
[weight_inputs.dup.freeze, base_weight]
|
|
61
|
+
end
|
|
62
|
+
|
|
34
63
|
def check_unknown_kwargs!(kwargs:, members:)
|
|
35
64
|
unknown = kwargs.keys - members
|
|
36
65
|
raise Errors::ValidationError, "unknown keyword(s): #{unknown.join(', ')}" unless unknown.empty?
|
|
@@ -122,7 +151,7 @@ module Legion
|
|
|
122
151
|
|
|
123
152
|
normalized = {}
|
|
124
153
|
evidence.each do |key, value|
|
|
125
|
-
op = Taxonomies.normalize_operation(value: key
|
|
154
|
+
op = Taxonomies.normalize_operation(value: key)
|
|
126
155
|
raise Errors::ValidationError, "operation_evidence[#{op}] must be an OperationEvidence" unless value.is_a?(OperationEvidence)
|
|
127
156
|
raise Errors::ValidationError, "operation_evidence[#{op}] operation must match key" unless value.operation == op
|
|
128
157
|
raise Errors::ValidationError, "duplicate operation_evidence key #{op}" if normalized.key?(op)
|
|
@@ -155,7 +184,7 @@ module Legion
|
|
|
155
184
|
|
|
156
185
|
normalized = {}
|
|
157
186
|
quota_domains.each do |key, value|
|
|
158
|
-
op = Taxonomies.normalize_operation(value: key
|
|
187
|
+
op = Taxonomies.normalize_operation(value: key)
|
|
159
188
|
normalized[op] = validate_quota_domain_value!(value: value, field: "quota_domains[#{op}]")
|
|
160
189
|
end
|
|
161
190
|
normalized.freeze
|
|
@@ -168,7 +197,7 @@ module Legion
|
|
|
168
197
|
end
|
|
169
198
|
|
|
170
199
|
# Validates and returns the five scalar ValueEvidence fields shared by
|
|
171
|
-
# OfferingDraft
|
|
200
|
+
# OfferingDraft and LaneRecord as a member Hash.
|
|
172
201
|
def scalar_value_evidences(kwargs)
|
|
173
202
|
{
|
|
174
203
|
context_evidence: positive_int_value_evidence!(kwargs[:context_evidence], :context_evidence),
|
|
@@ -251,106 +280,56 @@ module Legion
|
|
|
251
280
|
end
|
|
252
281
|
end
|
|
253
282
|
|
|
254
|
-
# An off-registry provider draft of one offering. Carries
|
|
255
|
-
#
|
|
256
|
-
# default model. See section 10.1.
|
|
283
|
+
# An off-registry provider draft of one offering. Carries the validated
|
|
284
|
+
# write-time weight pair, but no provider family, instance ID, offering ID,
|
|
285
|
+
# lane ID, callable, health, or default model. See section 10.1.
|
|
257
286
|
OfferingDraft = ::Data.define(
|
|
258
287
|
:provider_native_key, :model, :tier, :operation_evidence, :capability_evidence,
|
|
259
288
|
:context_evidence, :max_output_evidence, :embedding_dimensions_evidence,
|
|
260
|
-
:model_revision_evidence, :tokenizer_evidence, :quota_domains, :metadata, :publication_source
|
|
289
|
+
:model_revision_evidence, :tokenizer_evidence, :quota_domains, :metadata, :publication_source,
|
|
290
|
+
:weight_inputs, :base_weight
|
|
261
291
|
) do
|
|
262
292
|
def initialize(**kwargs)
|
|
263
293
|
kwargs = { capability_evidence: {}, quota_domains: {}, metadata: {} }.merge(kwargs)
|
|
264
294
|
RecordSupport.check_unknown_kwargs!(kwargs: kwargs, members: self.class.members)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
provider_native_key: Identity.normalize_text(value: kwargs[:provider_native_key], field: :provider_native_key),
|
|
268
|
-
model: Identity.normalize_text(value: kwargs[:model], field: :model),
|
|
269
|
-
tier: Identity.normalize_enum(value: kwargs[:tier], field: :tier, allowed: Taxonomies::TIERS),
|
|
270
|
-
operation_evidence: RecordSupport.validate_operation_evidence!(kwargs[:operation_evidence]),
|
|
271
|
-
capability_evidence: RecordSupport.validate_capability_evidence!(kwargs[:capability_evidence]),
|
|
272
|
-
quota_domains: RecordSupport.validate_quota_domains!(kwargs[:quota_domains]),
|
|
273
|
-
metadata: RecordSupport.frozen_metadata(value: kwargs[:metadata]),
|
|
274
|
-
publication_source: RecordSupport.publication_source!(value: kwargs[:publication_source]),
|
|
275
|
-
**RecordSupport.scalar_value_evidences(kwargs)
|
|
295
|
+
weight_inputs, base_weight = RecordSupport.validated_weight_pair(
|
|
296
|
+
weight_inputs: kwargs[:weight_inputs], base_weight: kwargs[:base_weight]
|
|
276
297
|
)
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# A registry-owned offering with canonical identity and captured callable.
|
|
281
|
-
# Only Inventory::Publisher/Registry constructs it. See section 10.2.
|
|
282
|
-
OfferingRecord = ::Data.define(
|
|
283
|
-
:offering_id, :provider_native_key, :instance_key, :model, :tier, :operation_evidence,
|
|
284
|
-
:capability_evidence, :context_evidence, :max_output_evidence, :embedding_dimensions_evidence,
|
|
285
|
-
:model_revision_evidence, :tokenizer_evidence, :quota_domains, :metadata, :callable_handle,
|
|
286
|
-
:publication_source
|
|
287
|
-
) do
|
|
288
|
-
def initialize(**kwargs)
|
|
289
|
-
RecordSupport.check_unknown_kwargs!(kwargs: kwargs, members: self.class.members)
|
|
290
|
-
instance_key = kwargs[:instance_key]
|
|
291
|
-
callable_handle = kwargs[:callable_handle]
|
|
292
|
-
raise Errors::ValidationError, 'instance_key must be an InstanceKey' unless instance_key.is_a?(Identity::InstanceKey)
|
|
293
|
-
raise Errors::ValidationError, 'callable_handle must be a CallableHandle' unless callable_handle.is_a?(CallableHandle)
|
|
294
|
-
|
|
295
|
-
native_key = Identity.normalize_text(value: kwargs[:provider_native_key], field: :provider_native_key)
|
|
296
|
-
Identity.validate_offering_id!(value: kwargs[:offering_id], instance_key: instance_key, provider_native_key: native_key)
|
|
297
298
|
|
|
298
299
|
super(
|
|
299
|
-
|
|
300
|
-
provider_native_key: native_key,
|
|
301
|
-
instance_key: instance_key,
|
|
300
|
+
provider_native_key: Identity.normalize_text(value: kwargs[:provider_native_key], field: :provider_native_key),
|
|
302
301
|
model: Identity.normalize_text(value: kwargs[:model], field: :model),
|
|
303
302
|
tier: Identity.normalize_enum(value: kwargs[:tier], field: :tier, allowed: Taxonomies::TIERS),
|
|
304
303
|
operation_evidence: RecordSupport.validate_operation_evidence!(kwargs[:operation_evidence]),
|
|
305
304
|
capability_evidence: RecordSupport.validate_capability_evidence!(kwargs[:capability_evidence]),
|
|
306
305
|
quota_domains: RecordSupport.validate_quota_domains!(kwargs[:quota_domains]),
|
|
307
306
|
metadata: RecordSupport.frozen_metadata(value: kwargs[:metadata]),
|
|
308
|
-
callable_handle: callable_handle,
|
|
309
307
|
publication_source: RecordSupport.publication_source!(value: kwargs[:publication_source]),
|
|
308
|
+
weight_inputs: weight_inputs,
|
|
309
|
+
base_weight: base_weight,
|
|
310
310
|
**RecordSupport.scalar_value_evidences(kwargs)
|
|
311
311
|
)
|
|
312
312
|
end
|
|
313
|
-
|
|
314
|
-
def supported_operations
|
|
315
|
-
operation_evidence.select { |_op, evidence| evidence.supported? }.keys.sort
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
def unsupported_operations
|
|
319
|
-
operation_evidence.select { |_op, evidence| evidence.unsupported? }.keys.sort
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
def unknown_operations
|
|
323
|
-
operation_evidence.select { |_op, evidence| evidence.unknown? }.keys.sort
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
def operation_status(operation:)
|
|
327
|
-
operation_evidence.fetch(Taxonomies.normalize_operation(value: operation, allow_aliases: false)).status
|
|
328
|
-
end
|
|
329
|
-
|
|
330
|
-
def capability_evidence_for(capability:)
|
|
331
|
-
capability_evidence[Legion::Extensions::Llm::Capabilities.canonical(capability)]
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
def capability_status(capability:)
|
|
335
|
-
evidence = capability_evidence_for(capability: capability)
|
|
336
|
-
evidence.nil? ? :unknown : evidence.status
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
def quota_domain(operation:)
|
|
340
|
-
quota_domains[Taxonomies.normalize_operation(value: operation, allow_aliases: false)]
|
|
341
|
-
end
|
|
342
313
|
end
|
|
343
314
|
|
|
344
|
-
# An executable lane
|
|
345
|
-
#
|
|
315
|
+
# An executable lane: the ONE stored inventory unit, keyed by the
|
|
316
|
+
# 5-tuple id `tier:provider_family:instance_id:type:model`. Derived by
|
|
317
|
+
# the registry from one supported operation of an OfferingDraft, with
|
|
318
|
+
# its write-time weight pair copied unchanged. The 5 tuple is composed
|
|
319
|
+
# at validation from the record's own fields; there is no separate
|
|
320
|
+
# offering id (D2 — in the one bucket an offering IS a lane).
|
|
321
|
+
# See section 10.3.
|
|
346
322
|
LaneRecord = ::Data.define(
|
|
347
|
-
:lane_id, :
|
|
323
|
+
:lane_id, :instance_key, :provider_family, :instance_id, :model, :tier, :operation,
|
|
348
324
|
:capability_evidence, :context_evidence, :max_output_evidence, :embedding_dimensions_evidence,
|
|
349
325
|
:model_revision_evidence, :tokenizer_evidence, :quota_domain, :metadata, :callable_handle,
|
|
350
|
-
:publication_source
|
|
326
|
+
:publication_source, :weight_inputs, :base_weight
|
|
351
327
|
) do
|
|
352
328
|
def initialize(**kwargs)
|
|
353
329
|
RecordSupport.check_unknown_kwargs!(kwargs: kwargs, members: self.class.members)
|
|
330
|
+
weight_inputs, base_weight = RecordSupport.validated_weight_pair(
|
|
331
|
+
weight_inputs: kwargs[:weight_inputs], base_weight: kwargs[:base_weight]
|
|
332
|
+
)
|
|
354
333
|
instance_key = kwargs[:instance_key]
|
|
355
334
|
callable_handle = kwargs[:callable_handle]
|
|
356
335
|
raise Errors::ValidationError, 'instance_key must be an InstanceKey' unless instance_key.is_a?(Identity::InstanceKey)
|
|
@@ -362,27 +341,32 @@ module Legion
|
|
|
362
341
|
raise Errors::ValidationError, 'provider_family and instance_id must equal instance_key'
|
|
363
342
|
end
|
|
364
343
|
|
|
344
|
+
canonical_tier = Identity.normalize_enum(value: kwargs[:tier], field: :tier, allowed: Taxonomies::TIERS)
|
|
365
345
|
canonical_model = Identity.normalize_text(value: kwargs[:model], field: :model)
|
|
366
|
-
canonical_operation = Taxonomies.normalize_operation(value: kwargs[:operation]
|
|
367
|
-
Identity.validate_lane_id!(
|
|
368
|
-
|
|
369
|
-
|
|
346
|
+
canonical_operation = Taxonomies.normalize_operation(value: kwargs[:operation])
|
|
347
|
+
Identity.validate_lane_id!(value: kwargs[:lane_id])
|
|
348
|
+
expected_lane_id = Identity.compose_lane_id(
|
|
349
|
+
tier: canonical_tier, provider_family: family, instance_id: resolved_instance,
|
|
350
|
+
type: Taxonomies.lane_type_for(operation: canonical_operation), model: canonical_model
|
|
370
351
|
)
|
|
352
|
+
raise Errors::ValidationError, 'lane_id does not reproduce from its identity fields' \
|
|
353
|
+
unless kwargs[:lane_id].to_s == expected_lane_id
|
|
371
354
|
|
|
372
355
|
super(
|
|
373
|
-
lane_id: kwargs[:lane_id].dup.freeze,
|
|
374
|
-
offering_id: kwargs[:offering_id].dup.freeze,
|
|
356
|
+
lane_id: kwargs[:lane_id].to_s.dup.freeze,
|
|
375
357
|
instance_key: instance_key,
|
|
376
358
|
provider_family: family,
|
|
377
359
|
instance_id: resolved_instance,
|
|
378
360
|
model: canonical_model,
|
|
379
|
-
tier:
|
|
361
|
+
tier: canonical_tier,
|
|
380
362
|
operation: canonical_operation,
|
|
381
363
|
capability_evidence: RecordSupport.validate_capability_evidence!(kwargs[:capability_evidence]),
|
|
382
364
|
quota_domain: kwargs[:quota_domain].nil? ? nil : RecordSupport.validate_quota_domain_value!(value: kwargs[:quota_domain], field: :quota_domain),
|
|
383
365
|
metadata: RecordSupport.frozen_metadata(value: kwargs[:metadata]),
|
|
384
366
|
callable_handle: callable_handle,
|
|
385
367
|
publication_source: RecordSupport.publication_source!(value: kwargs[:publication_source]),
|
|
368
|
+
weight_inputs: weight_inputs,
|
|
369
|
+
base_weight: base_weight,
|
|
386
370
|
**RecordSupport.scalar_value_evidences(kwargs)
|
|
387
371
|
)
|
|
388
372
|
end
|
|
@@ -460,10 +444,11 @@ module Legion
|
|
|
460
444
|
end
|
|
461
445
|
end
|
|
462
446
|
|
|
463
|
-
# An activated exact instance's complete published state. Its
|
|
464
|
-
#
|
|
447
|
+
# An activated exact instance's complete published state. Its lanes are
|
|
448
|
+
# keyed by the 5-tuple lane id; its availability is available or
|
|
449
|
+
# unavailable, never initializing. See section 10.6.
|
|
465
450
|
InstanceRecord = ::Data.define(
|
|
466
|
-
:instance_key, :callable_handle, :availability, :
|
|
451
|
+
:instance_key, :callable_handle, :availability, :lanes_by_id,
|
|
467
452
|
:publisher_id, :publisher_token_id, :published_sequence, :published_at
|
|
468
453
|
) do
|
|
469
454
|
def initialize(**kwargs)
|
|
@@ -481,7 +466,7 @@ module Legion
|
|
|
481
466
|
instance_key: instance_key,
|
|
482
467
|
callable_handle: callable_handle,
|
|
483
468
|
availability: availability,
|
|
484
|
-
|
|
469
|
+
lanes_by_id: validate_lanes!(kwargs[:lanes_by_id], instance_key, callable_handle),
|
|
485
470
|
publisher_id: nonempty_id!(kwargs[:publisher_id], :publisher_id),
|
|
486
471
|
publisher_token_id: nonempty_id!(kwargs[:publisher_token_id], :publisher_token_id),
|
|
487
472
|
published_sequence: RecordSupport.nonnegative_integer(value: kwargs[:published_sequence], field: :published_sequence),
|
|
@@ -489,17 +474,15 @@ module Legion
|
|
|
489
474
|
)
|
|
490
475
|
end
|
|
491
476
|
|
|
492
|
-
def
|
|
493
|
-
raise Errors::ValidationError, '
|
|
477
|
+
def validate_lanes!(lanes_by_id, instance_key, callable_handle)
|
|
478
|
+
raise Errors::ValidationError, 'lanes_by_id must be a Hash' unless lanes_by_id.is_a?(::Hash)
|
|
494
479
|
|
|
495
|
-
|
|
496
|
-
raise Errors::ValidationError, "
|
|
497
|
-
raise Errors::ValidationError, "
|
|
498
|
-
unless
|
|
499
|
-
raise Errors::ValidationError, "offering #{offering_id} must share the instance callable/key"
|
|
500
|
-
end
|
|
480
|
+
lanes_by_id.each do |lane_id, lane|
|
|
481
|
+
raise Errors::ValidationError, "lane #{lane_id} must be a LaneRecord" unless lane.is_a?(LaneRecord)
|
|
482
|
+
raise Errors::ValidationError, "lane #{lane_id} key mismatch" unless lane.lane_id == lane_id
|
|
483
|
+
raise Errors::ValidationError, "lane #{lane_id} must share the instance callable/key" unless lane.instance_key == instance_key && lane.callable_handle.equal?(callable_handle)
|
|
501
484
|
end
|
|
502
|
-
|
|
485
|
+
lanes_by_id.dup.freeze
|
|
503
486
|
end
|
|
504
487
|
|
|
505
488
|
def nonempty_id!(value, field)
|
|
@@ -9,6 +9,7 @@ require 'legion/extensions/llm/inventory/callable_handle'
|
|
|
9
9
|
require 'legion/extensions/llm/inventory/probe_token'
|
|
10
10
|
require 'legion/extensions/llm/inventory/records'
|
|
11
11
|
require 'legion/extensions/llm/inventory/snapshot'
|
|
12
|
+
require 'legion/extensions/llm/taxonomies'
|
|
12
13
|
|
|
13
14
|
module Legion
|
|
14
15
|
module Extensions
|
|
@@ -21,7 +22,7 @@ module Legion
|
|
|
21
22
|
# Private per-instance state. Never leaves registry.rb.
|
|
22
23
|
ScopeState = ::Data.define(
|
|
23
24
|
:instance_key, :publisher_token, :callable, :callable_handle, :probe_request_handle,
|
|
24
|
-
:publication_status, :last_sequence, :availability, :
|
|
25
|
+
:publication_status, :last_sequence, :availability, :lanes,
|
|
25
26
|
:availability_revision, :unavailable_revision, :published_at
|
|
26
27
|
)
|
|
27
28
|
|
|
@@ -196,7 +197,7 @@ module Legion
|
|
|
196
197
|
@scopes[instance_key] = ScopeState.new(
|
|
197
198
|
instance_key: instance_key, publisher_token: token, callable: callable, callable_handle: handle,
|
|
198
199
|
probe_request_handle: probe_request_handle, publication_status: status,
|
|
199
|
-
last_sequence: -1, availability: nil,
|
|
200
|
+
last_sequence: -1, availability: nil, lanes: {},
|
|
200
201
|
availability_revision: prior&.availability_revision || 0,
|
|
201
202
|
unavailable_revision: prior&.unavailable_revision, published_at: nil
|
|
202
203
|
)
|
|
@@ -218,7 +219,7 @@ module Legion
|
|
|
218
219
|
status = complete_status(scope, sequence, probe_token, now, :success)
|
|
219
220
|
new_scope = scope.with(
|
|
220
221
|
publication_status: status, last_sequence: sequence, availability: availability,
|
|
221
|
-
|
|
222
|
+
lanes: prepared[1], availability_revision: new_rev,
|
|
222
223
|
unavailable_revision: nil, published_at: now
|
|
223
224
|
)
|
|
224
225
|
@scopes[instance_key] = new_scope
|
|
@@ -237,7 +238,7 @@ module Legion
|
|
|
237
238
|
|
|
238
239
|
def apply_replacement(scope, instance_key, prepared, sequence)
|
|
239
240
|
status = scope.publication_status.with(published_sequence: sequence)
|
|
240
|
-
new_scope = scope.with(
|
|
241
|
+
new_scope = scope.with(lanes: prepared[1], last_sequence: sequence, publication_status: status)
|
|
241
242
|
@scopes[instance_key] = new_scope
|
|
242
243
|
bump_and_snapshot!
|
|
243
244
|
applied(:snapshot_replaced, new_scope)
|
|
@@ -428,7 +429,6 @@ module Legion
|
|
|
428
429
|
|
|
429
430
|
def build_snapshot_locked
|
|
430
431
|
instances = {}
|
|
431
|
-
offerings = {}
|
|
432
432
|
lanes = {}
|
|
433
433
|
statuses = {}
|
|
434
434
|
@scopes.each_pair do |key, scope|
|
|
@@ -436,11 +436,10 @@ module Legion
|
|
|
436
436
|
next if scope.availability.nil?
|
|
437
437
|
|
|
438
438
|
instances[key] = instance_record_for(scope)
|
|
439
|
-
offerings.merge!(scope.offerings)
|
|
440
439
|
lanes.merge!(scope.lanes)
|
|
441
440
|
end
|
|
442
441
|
Snapshot.new(
|
|
443
|
-
generation: @generation, instances_by_key: instances,
|
|
442
|
+
generation: @generation, instances_by_key: instances,
|
|
444
443
|
lanes_by_id: lanes, publication_status_by_key: statuses
|
|
445
444
|
)
|
|
446
445
|
end
|
|
@@ -448,7 +447,7 @@ module Legion
|
|
|
448
447
|
def instance_record_for(scope)
|
|
449
448
|
InstanceRecord.new(
|
|
450
449
|
instance_key: scope.instance_key, callable_handle: scope.callable_handle, availability: scope.availability,
|
|
451
|
-
|
|
450
|
+
lanes_by_id: scope.lanes, publisher_id: scope.publisher_token.publisher_id,
|
|
452
451
|
publisher_token_id: scope.publisher_token.publisher_token_id, published_sequence: scope.last_sequence,
|
|
453
452
|
published_at: scope.published_at
|
|
454
453
|
)
|
|
@@ -460,67 +459,76 @@ module Legion
|
|
|
460
459
|
scope = @scopes[instance_key]
|
|
461
460
|
return nil if scope.nil?
|
|
462
461
|
|
|
463
|
-
|
|
464
|
-
[scope.callable_handle, offerings_by_id, lanes_by_id]
|
|
462
|
+
[scope.callable_handle, build_records(instance_key, scope.callable_handle, drafts)]
|
|
465
463
|
end
|
|
466
464
|
|
|
467
465
|
def prepared_matches?(prepared, scope)
|
|
468
466
|
!prepared.nil? && prepared[0].equal?(scope.callable_handle)
|
|
469
467
|
end
|
|
470
468
|
|
|
469
|
+
# The stored inventory is lanes ONLY, keyed by the 5 tuple
|
|
470
|
+
# tier:provider_family:instance_id:type:model. The 4th part is the
|
|
471
|
+
# COARSE type, not the fine operation: the operations a draft
|
|
472
|
+
# supports collapse to one lane per distinct type (chat +
|
|
473
|
+
# stream_chat + count_tokens are ONE inference lane — the v0.15.2
|
|
474
|
+
# model, where the operation is a request property matched against
|
|
475
|
+
# the lane type, not a lane identity part). The LaneRecord's
|
|
476
|
+
# operation member is the first supported operation of the lane's
|
|
477
|
+
# type in canonical order — the representative, not the identity.
|
|
478
|
+
# A duplicate (operation, model) published under a conflicting
|
|
479
|
+
# tier, or a second draft claiming an already-published 5 tuple,
|
|
480
|
+
# raises — never a silent merge (D1).
|
|
471
481
|
def build_records(instance_key, handle, drafts)
|
|
472
|
-
|
|
482
|
+
lanes = {}
|
|
473
483
|
native_keys = {}
|
|
484
|
+
op_model_tiers = {}
|
|
474
485
|
drafts.each do |draft|
|
|
475
|
-
offering_id = Identity.offering_id(instance_key: instance_key, provider_native_key: draft.provider_native_key)
|
|
476
486
|
raise Errors::ValidationError, 'duplicate provider_native_key' if native_keys.key?(draft.provider_native_key)
|
|
477
|
-
raise Errors::ValidationError, 'duplicate offering_id' if offerings_by_id.key?(offering_id)
|
|
478
487
|
|
|
479
488
|
native_keys[draft.provider_native_key] = true
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
[offerings_by_id.freeze, build_lanes(instance_key, handle, offerings_by_id).freeze]
|
|
483
|
-
end
|
|
489
|
+
draft.operation_evidence.each_value do |evidence|
|
|
490
|
+
next unless evidence.supported?
|
|
484
491
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
offering_id: offering_id, provider_native_key: draft.provider_native_key, instance_key: instance_key,
|
|
488
|
-
model: draft.model, tier: draft.tier, operation_evidence: draft.operation_evidence,
|
|
489
|
-
capability_evidence: draft.capability_evidence, context_evidence: draft.context_evidence,
|
|
490
|
-
max_output_evidence: draft.max_output_evidence,
|
|
491
|
-
embedding_dimensions_evidence: draft.embedding_dimensions_evidence,
|
|
492
|
-
model_revision_evidence: draft.model_revision_evidence, tokenizer_evidence: draft.tokenizer_evidence,
|
|
493
|
-
quota_domains: draft.quota_domains, metadata: draft.metadata, callable_handle: handle,
|
|
494
|
-
publication_source: draft.publication_source
|
|
495
|
-
)
|
|
496
|
-
end
|
|
492
|
+
op_model = [evidence.operation, draft.model]
|
|
493
|
+
raise Errors::ValidationError, 'duplicate (operation, model) published under a conflicting tier' if op_model_tiers.key?(op_model) && op_model_tiers[op_model] != draft.tier
|
|
497
494
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
495
|
+
op_model_tiers[op_model] = draft.tier
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
# One lane per distinct type the draft supports.
|
|
499
|
+
draft.operation_evidence.each_value
|
|
500
|
+
.select(&:supported?)
|
|
501
|
+
.group_by { |evidence| Taxonomies.lane_type_for(operation: evidence.operation) }
|
|
502
|
+
.each do |type, evidences|
|
|
503
|
+
representative = evidences.min_by { |evidence| Taxonomies::OPERATIONS.index(evidence.operation) }
|
|
504
|
+
lane_id = Identity.compose_lane_id(
|
|
505
|
+
tier: draft.tier, provider_family: instance_key.provider_family,
|
|
506
|
+
instance_id: instance_key.instance_id, type: type, model: draft.model
|
|
504
507
|
)
|
|
505
508
|
raise Errors::ValidationError, 'duplicate lane_id' if lanes.key?(lane_id)
|
|
506
509
|
|
|
507
|
-
lanes[lane_id] = build_lane_record(instance_key, handle,
|
|
510
|
+
lanes[lane_id] = build_lane_record(instance_key, handle, draft, type, representative.operation)
|
|
508
511
|
end
|
|
509
512
|
end
|
|
510
|
-
lanes
|
|
513
|
+
lanes.freeze
|
|
511
514
|
end
|
|
512
515
|
|
|
513
|
-
def build_lane_record(instance_key, handle,
|
|
516
|
+
def build_lane_record(instance_key, handle, draft, type, operation)
|
|
514
517
|
LaneRecord.new(
|
|
515
|
-
lane_id:
|
|
518
|
+
lane_id: Identity.compose_lane_id(
|
|
519
|
+
tier: draft.tier, provider_family: instance_key.provider_family,
|
|
520
|
+
instance_id: instance_key.instance_id, type: type, model: draft.model
|
|
521
|
+
),
|
|
522
|
+
instance_key: instance_key,
|
|
516
523
|
provider_family: instance_key.provider_family, instance_id: instance_key.instance_id,
|
|
517
|
-
model:
|
|
518
|
-
capability_evidence:
|
|
519
|
-
max_output_evidence:
|
|
520
|
-
embedding_dimensions_evidence:
|
|
521
|
-
model_revision_evidence:
|
|
522
|
-
quota_domain:
|
|
523
|
-
callable_handle: handle, publication_source:
|
|
524
|
+
model: draft.model, tier: draft.tier, operation: operation,
|
|
525
|
+
capability_evidence: draft.capability_evidence, context_evidence: draft.context_evidence,
|
|
526
|
+
max_output_evidence: draft.max_output_evidence,
|
|
527
|
+
embedding_dimensions_evidence: draft.embedding_dimensions_evidence,
|
|
528
|
+
model_revision_evidence: draft.model_revision_evidence, tokenizer_evidence: draft.tokenizer_evidence,
|
|
529
|
+
quota_domain: draft.quota_domains[operation], metadata: draft.metadata,
|
|
530
|
+
callable_handle: handle, publication_source: draft.publication_source,
|
|
531
|
+
weight_inputs: draft.weight_inputs, base_weight: draft.base_weight
|
|
524
532
|
)
|
|
525
533
|
end
|
|
526
534
|
|