lex-llm-vertex 0.2.10 → 0.2.15
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 +32 -0
- data/Gemfile +0 -7
- data/lex-llm-vertex.gemspec +1 -1
- data/lib/legion/extensions/llm/vertex/actors/discovery_refresh.rb +109 -7
- data/lib/legion/extensions/llm/vertex/provider.rb +157 -24
- data/lib/legion/extensions/llm/vertex/version.rb +1 -1
- data/lib/legion/extensions/llm/vertex.rb +3 -10
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b1b2e665277fea3299658b992eac2b441a363e3c81dbf87d69e86c7328c6c99c
|
|
4
|
+
data.tar.gz: d81b38ce8e5e797a074d30a670a5e6fa9bcb92762c5dcd066ed86ad8196d5340
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 97009f1dd75f9f053ec06dfba726627f7c6202f92bb56a0185e9250d7579ff73de1c7c410b3ae6a82b4ad308032384362a0dd5c12ed2eeddc30e3c690d381753
|
|
7
|
+
data.tar.gz: 2f36d16c24610e1355ee50cdeb26e99818e8a1b7cc6441b9ef88f7e0d17130bd8691bba88e8db3c71bc3becd33a1abe5962ee65802a957abdcc6dec7bc4f839d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.15] - 2026-06-20
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Align Vertex offerings to the current `lex-llm` contract: shared `discover_offerings` now rebuilds
|
|
7
|
+
resource-name offerings from discovered models, preserves provider health on offerings, and keeps the
|
|
8
|
+
shared capability-override path intact.
|
|
9
|
+
- Fix the provider tail introduced during the contract refactor so the provider file closes cleanly again.
|
|
10
|
+
|
|
11
|
+
## [0.2.14] - 2026-06-19
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Adopt `Legion::Extensions::Llm::Inventory::ScopedRefresher` mixin (lex-llm 0.6.0). Discovery
|
|
15
|
+
refresh actors now write directly to the live `Inventory` catalog via `Inventory.write_lane`.
|
|
16
|
+
- Pin `lex-llm >= 0.6.0` and `legion-llm >= 0.14.0` in gemspec.
|
|
17
|
+
- Standard `weight: 100` default added to provider instance settings schema.
|
|
18
|
+
|
|
19
|
+
## 0.2.13 - 2026-06-16
|
|
20
|
+
|
|
21
|
+
- Dependency updates and code quality improvements.
|
|
22
|
+
|
|
23
|
+
## 0.2.12 - 2026-06-15
|
|
24
|
+
|
|
25
|
+
- **CapabilityPolicy integration** — Model-family heuristics tagged as `:provider_catalog`; Vertex features as `:model_metadata`. Settings overrides at provider/instance/model level supported.
|
|
26
|
+
|
|
27
|
+
## 0.2.11 - 2026-06-13
|
|
28
|
+
|
|
29
|
+
- **Gemfile cleanup** — Remove local path overrides; dependencies resolve from gemspec via rubygems.
|
|
30
|
+
- **Dependency bump** — Require `lex-llm >= 0.5.0` for canonical types support.
|
|
31
|
+
- **Canonical tool support** — Use `ToolSchema.extract` and add `:tools` capability.
|
|
32
|
+
- **Bug fix** — Handle Array tool_calls in `tool_call_parts`.
|
|
33
|
+
- 29 examples, 0 failures; 13 files, 0 rubocop offenses.
|
|
34
|
+
|
|
3
35
|
## 0.2.10 - 2026-06-02
|
|
4
36
|
|
|
5
37
|
- Add per-provider scoped discovery refresh actor
|
data/Gemfile
CHANGED
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
source 'https://rubygems.org'
|
|
4
4
|
|
|
5
|
-
group :test do
|
|
6
|
-
llm_base_path = ENV.fetch('LEX_LLM_PATH', File.expand_path('../lex-llm', __dir__))
|
|
7
|
-
transport_path = ENV.fetch('LEGION_TRANSPORT_PATH', File.expand_path('../../legion-transport', __dir__))
|
|
8
|
-
gem 'legion-transport', path: transport_path if File.directory?(transport_path)
|
|
9
|
-
gem 'lex-llm', path: llm_base_path if File.directory?(llm_base_path)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
5
|
gemspec
|
|
13
6
|
|
|
14
7
|
group :development do
|
data/lex-llm-vertex.gemspec
CHANGED
|
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
28
28
|
spec.add_dependency 'legion-settings', '>= 1.3.14'
|
|
29
29
|
spec.add_dependency 'legion-transport', '>= 1.4.14'
|
|
30
|
-
spec.add_dependency 'lex-llm', '>= 0.
|
|
30
|
+
spec.add_dependency 'lex-llm', '>= 0.6.0'
|
|
31
31
|
end
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'digest'
|
|
4
|
+
|
|
3
5
|
begin
|
|
4
6
|
require 'legion/extensions/actors/every'
|
|
5
7
|
rescue LoadError => e
|
|
6
8
|
warn(e.message) if $VERBOSE
|
|
7
9
|
end
|
|
8
10
|
|
|
11
|
+
begin
|
|
12
|
+
require 'legion/extensions/llm/inventory/scoped_refresher'
|
|
13
|
+
rescue LoadError => e
|
|
14
|
+
warn(e.message) if $VERBOSE
|
|
15
|
+
end
|
|
16
|
+
|
|
9
17
|
return unless defined?(Legion::Extensions::Actors::Every)
|
|
10
18
|
|
|
11
19
|
module Legion
|
|
@@ -16,7 +24,11 @@ module Legion
|
|
|
16
24
|
class DiscoveryRefresh < Legion::Extensions::Actors::Every # rubocop:disable Style/Documentation
|
|
17
25
|
include Legion::Logging::Helper
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
if defined?(Legion::Extensions::Llm::Inventory::ScopedRefresher)
|
|
28
|
+
include Legion::Extensions::Llm::Inventory::ScopedRefresher
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.every_seconds = 3600
|
|
20
32
|
|
|
21
33
|
def runner_class = self.class
|
|
22
34
|
def runner_function = 'manual'
|
|
@@ -26,16 +38,106 @@ module Legion
|
|
|
26
38
|
def generate_task? = false
|
|
27
39
|
|
|
28
40
|
def time
|
|
29
|
-
return
|
|
41
|
+
return self.class.every_seconds unless defined?(Legion::Settings)
|
|
30
42
|
|
|
31
|
-
Legion::Settings.dig(:extensions, :llm, :vertex, :discovery_interval) ||
|
|
43
|
+
Legion::Settings.dig(:extensions, :llm, :vertex, :discovery_interval) || self.class.every_seconds
|
|
32
44
|
end
|
|
33
45
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
def scope_key
|
|
47
|
+
{ provider: :vertex }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def compute_lanes_for_scope(**)
|
|
51
|
+
return [] unless defined?(Legion::LLM::Call::Registry)
|
|
52
|
+
|
|
53
|
+
settings = Legion::Settings.dig(:extensions, :llm, :vertex) || {}
|
|
54
|
+
fleet_enabled = settings.dig(:fleet, :dispatch, :enabled)
|
|
55
|
+
instances = Legion::LLM::Call::Registry.all_instances.select do |e|
|
|
56
|
+
(e[:provider] || '').to_sym == :vertex
|
|
57
|
+
end
|
|
37
58
|
|
|
38
|
-
|
|
59
|
+
instances.flat_map do |entry|
|
|
60
|
+
lanes_for_instance(entry, fleet_enabled: fleet_enabled)
|
|
61
|
+
end
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
handle_exception(e, level: :warn, handled: true, operation: 'vertex.actor.compute_lanes_for_scope')
|
|
64
|
+
[]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def lanes_for_instance(entry, fleet_enabled: false)
|
|
70
|
+
adapter = entry[:adapter]
|
|
71
|
+
instance_id = entry[:instance] || entry[:instance_id] || entry[:id]
|
|
72
|
+
lanes = []
|
|
73
|
+
Array(adapter.discover_offerings(live: false)).each do |raw_offering|
|
|
74
|
+
offering = offering_to_hash(raw_offering)
|
|
75
|
+
next unless offering
|
|
76
|
+
|
|
77
|
+
lane = build_lane(offering, instance_id)
|
|
78
|
+
lanes << lane
|
|
79
|
+
lanes << fleet_lane(lane, instance_id, offering) if fleet_enabled && lane[:type] == :inference
|
|
80
|
+
end
|
|
81
|
+
lanes
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def offering_to_hash(offering)
|
|
85
|
+
return nil if offering.nil?
|
|
86
|
+
return offering if offering.is_a?(Hash)
|
|
87
|
+
|
|
88
|
+
hash = offering.to_h
|
|
89
|
+
hash[:type] ||= hash[:usage_type]
|
|
90
|
+
hash[:enabled] = offering.respond_to?(:enabled?) ? offering.enabled? : true
|
|
91
|
+
hash
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def build_lane(offering, instance_id)
|
|
95
|
+
type = offering_type(offering)
|
|
96
|
+
tier = offering[:tier]&.to_sym || :cloud
|
|
97
|
+
caps = normalize_capabilities(offering[:capabilities])
|
|
98
|
+
flds = { tier: tier, provider_family: :vertex, instance_id: instance_id,
|
|
99
|
+
type: type, model: offering[:model] }
|
|
100
|
+
{
|
|
101
|
+
id: Legion::Extensions::Llm::Inventory::ScopedRefresher.compose_id(flds),
|
|
102
|
+
tier: tier,
|
|
103
|
+
provider_family: :vertex,
|
|
104
|
+
instance_id: instance_id,
|
|
105
|
+
model: offering[:model],
|
|
106
|
+
canonical_model_alias: offering[:canonical_model_alias],
|
|
107
|
+
type: type,
|
|
108
|
+
capabilities: caps,
|
|
109
|
+
limits: offering[:limits] || {},
|
|
110
|
+
enabled: offering.fetch(:enabled, true),
|
|
111
|
+
cost: offering[:cost] || {}
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def fleet_lane(lane, instance_id, offering)
|
|
116
|
+
flds = { tier: :fleet, provider_family: :vertex, instance_id: instance_id,
|
|
117
|
+
type: lane[:type], model: offering[:model] }
|
|
118
|
+
lane.merge(id: Legion::Extensions::Llm::Inventory::ScopedRefresher.compose_id(flds), tier: :fleet)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def offering_type(offering)
|
|
122
|
+
%i[embed embedding].include?(offering[:type]&.to_sym) ? :embedding : :inference
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def normalize_capabilities(caps)
|
|
126
|
+
return [] unless defined?(Legion::Extensions::Llm::Inventory::Capabilities) &&
|
|
127
|
+
Legion::Extensions::Llm::Inventory::Capabilities.respond_to?(:normalize)
|
|
128
|
+
|
|
129
|
+
Legion::Extensions::Llm::Inventory::Capabilities.normalize(caps)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
public
|
|
133
|
+
|
|
134
|
+
def credential_hash(**)
|
|
135
|
+
settings = Legion::Settings.dig(:extensions, :llm, :vertex) || {}
|
|
136
|
+
::Digest::SHA256.hexdigest(settings[:api_key].to_s + settings[:instances].to_s)[0, 16]
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def manual
|
|
140
|
+
tick if respond_to?(:tick)
|
|
39
141
|
rescue StandardError => e
|
|
40
142
|
handle_exception(e, level: :warn, handled: true, operation: 'vertex.actor.discovery_refresh')
|
|
41
143
|
end
|
|
@@ -116,7 +116,7 @@ module Legion
|
|
|
116
116
|
"#{publisher_model_path(model)}:#{suffix}"
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
-
def list_models(**)
|
|
119
|
+
def list_models(**_filters)
|
|
120
120
|
log.info { 'listing available Vertex models from static catalog' }
|
|
121
121
|
STATIC_MODELS.map { |entry| model_info_from_static(entry) }.tap do |models|
|
|
122
122
|
log.info { "discovered #{models.size} Vertex model(s); publishing to registry" }
|
|
@@ -125,22 +125,13 @@ module Legion
|
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
def discover_offerings(live: false, **filters)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
models = response.body['publisherModels'] || response.body['models'] || []
|
|
133
|
-
offerings = models.filter_map do |model|
|
|
134
|
-
offering = offering_from_live_model(model)
|
|
135
|
-
model_id = offering.respond_to?(:model) ? offering.model : (offering[:model] || offering[:id])
|
|
136
|
-
next unless model_allowed?(model_id.to_s)
|
|
137
|
-
|
|
138
|
-
offering
|
|
128
|
+
unless live
|
|
129
|
+
return static_offerings(**filters).select do |offering|
|
|
130
|
+
model_allowed?(short_model_id(offering.model))
|
|
131
|
+
end
|
|
139
132
|
end
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
self.class.registry_publisher.publish_models_async(model_infos, readiness: readiness(live: false))
|
|
143
|
-
offerings
|
|
133
|
+
|
|
134
|
+
super
|
|
144
135
|
end
|
|
145
136
|
|
|
146
137
|
def offering_for(model:, model_family: nil, instance_id: :default, **metadata)
|
|
@@ -325,8 +316,50 @@ module Legion
|
|
|
325
316
|
offering_for(model: id, publisher:, metadata: model)
|
|
326
317
|
end
|
|
327
318
|
|
|
319
|
+
def offering_from_model(model_info, health: {})
|
|
320
|
+
metadata = model_info.respond_to?(:metadata) ? model_info.metadata.to_h : {}
|
|
321
|
+
raw_model = model_info.respond_to?(:id) ? model_info.id : model_info
|
|
322
|
+
publisher = metadata[:publisher] || metadata['publisher'] || publisher_for(raw_model)
|
|
323
|
+
api = metadata[:api] || metadata['api'] || api_for(raw_model)
|
|
324
|
+
alias_name = model_info.respond_to?(:name) ? model_info.name : nil
|
|
325
|
+
alias_name = nil if alias_name.to_s.empty? || alias_name.to_s == raw_model.to_s
|
|
326
|
+
|
|
327
|
+
build_offering(
|
|
328
|
+
model: resource_name(raw_model, publisher: publisher),
|
|
329
|
+
alias_name: alias_name,
|
|
330
|
+
model_family: if model_info.respond_to?(:family) && model_info.family
|
|
331
|
+
model_info.family.to_sym
|
|
332
|
+
else
|
|
333
|
+
model_family_for(
|
|
334
|
+
raw_model, publisher
|
|
335
|
+
)
|
|
336
|
+
end,
|
|
337
|
+
instance_id: if model_info.respond_to?(:instance)
|
|
338
|
+
model_info.instance || provider_instance_id
|
|
339
|
+
else
|
|
340
|
+
provider_instance_id
|
|
341
|
+
end,
|
|
342
|
+
publisher: publisher,
|
|
343
|
+
usage_type: if model_info.respond_to?(:embedding?) && model_info.embedding?
|
|
344
|
+
:embedding
|
|
345
|
+
else
|
|
346
|
+
usage_type_for(raw_model)
|
|
347
|
+
end,
|
|
348
|
+
api: api,
|
|
349
|
+
health: health,
|
|
350
|
+
metadata: metadata.merge(
|
|
351
|
+
limits: {
|
|
352
|
+
context_window: model_info.respond_to?(:context_length) ? model_info.context_length : nil,
|
|
353
|
+
max_output_tokens: model_info.respond_to?(:max_output_tokens) ? model_info.max_output_tokens : nil
|
|
354
|
+
}.compact
|
|
355
|
+
)
|
|
356
|
+
)
|
|
357
|
+
end
|
|
358
|
+
|
|
328
359
|
def build_offering(model:, model_family:, usage_type:, publisher:, api:, instance_id: :default,
|
|
329
|
-
alias_name: nil, metadata: {})
|
|
360
|
+
alias_name: nil, health: {}, metadata: {})
|
|
361
|
+
policy = resolve_capability_policy(model, api:, metadata:, instance_id:)
|
|
362
|
+
|
|
330
363
|
Legion::Extensions::Llm::Routing::ModelOffering.new(
|
|
331
364
|
provider_family: :vertex,
|
|
332
365
|
instance_id: instance_id,
|
|
@@ -334,8 +367,10 @@ module Legion
|
|
|
334
367
|
tier: offering_tier,
|
|
335
368
|
model: model,
|
|
336
369
|
usage_type: usage_type,
|
|
337
|
-
capabilities:
|
|
370
|
+
capabilities: base_capabilities(model, api:) + policy[:capabilities],
|
|
371
|
+
capability_sources: policy[:sources],
|
|
338
372
|
limits: metadata.delete(:limits) || {},
|
|
373
|
+
health: health,
|
|
339
374
|
metadata: metadata.merge(
|
|
340
375
|
model_family: model_family,
|
|
341
376
|
alias: alias_name,
|
|
@@ -478,7 +513,9 @@ module Legion
|
|
|
478
513
|
end
|
|
479
514
|
|
|
480
515
|
def tool_call_parts(message)
|
|
481
|
-
|
|
516
|
+
# Array is canonical (name-keyed hashes dropped parallel same-name calls)
|
|
517
|
+
calls = message.tool_calls.is_a?(Hash) ? message.tool_calls.values : Array(message.tool_calls)
|
|
518
|
+
calls.map do |tool_call|
|
|
482
519
|
{ functionCall: { name: tool_call.name, args: tool_call.arguments } }
|
|
483
520
|
end
|
|
484
521
|
end
|
|
@@ -497,9 +534,11 @@ module Legion
|
|
|
497
534
|
|
|
498
535
|
[{
|
|
499
536
|
functionDeclarations: tools.values.map do |tool|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
537
|
+
{
|
|
538
|
+
name: Legion::Extensions::Llm::Canonical::ToolSchema.tool_name(tool),
|
|
539
|
+
description: Legion::Extensions::Llm::Canonical::ToolSchema.tool_description(tool),
|
|
540
|
+
parameters: Legion::Extensions::Llm::Canonical::ToolSchema.extract(tool)
|
|
541
|
+
}
|
|
503
542
|
end
|
|
504
543
|
}]
|
|
505
544
|
end
|
|
@@ -623,15 +662,109 @@ module Legion
|
|
|
623
662
|
end
|
|
624
663
|
|
|
625
664
|
def default_capabilities(model, api:)
|
|
665
|
+
base_capabilities(model, api:) + policy_optional_capabilities(model, api:)
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
def base_capabilities(model, api:)
|
|
626
669
|
return %i[embedding] if Capabilities.embeddings?(model)
|
|
627
670
|
|
|
628
671
|
capabilities = %i[chat]
|
|
629
672
|
capabilities << :streaming if %i[generate_content raw_predict].include?(api)
|
|
630
|
-
capabilities << :vision if Capabilities.vision?(model)
|
|
631
|
-
capabilities << :functions if generate_content_model?(model)
|
|
632
673
|
capabilities
|
|
633
674
|
end
|
|
634
675
|
|
|
676
|
+
def policy_optional_capabilities(model, api:)
|
|
677
|
+
return [] if Capabilities.embeddings?(model)
|
|
678
|
+
|
|
679
|
+
caps = []
|
|
680
|
+
caps << :vision if Capabilities.vision?(model)
|
|
681
|
+
caps << :tools if generate_content_model?(model) && api == :generate_content
|
|
682
|
+
caps
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
def resolve_capability_policy(model, api:, metadata:, instance_id:)
|
|
686
|
+
provider_catalog = capability_catalog_for(model, api:)
|
|
687
|
+
real_caps = capability_real_for(metadata)
|
|
688
|
+
provider_cfg = vertex_provider_config
|
|
689
|
+
instance_cfg = vertex_instance_config(instance_id)
|
|
690
|
+
model_cfg = vertex_model_config(model)
|
|
691
|
+
|
|
692
|
+
Legion::Extensions::Llm::CapabilityPolicy.resolve(
|
|
693
|
+
real: real_caps,
|
|
694
|
+
provider_catalog: provider_catalog,
|
|
695
|
+
probe: {},
|
|
696
|
+
provider_envelope: {},
|
|
697
|
+
provider_config: provider_cfg,
|
|
698
|
+
instance_config: instance_cfg,
|
|
699
|
+
model_config: model_cfg
|
|
700
|
+
)
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
def capability_catalog_for(model, api:)
|
|
704
|
+
return {} if Capabilities.embeddings?(model)
|
|
705
|
+
|
|
706
|
+
catalog = {}
|
|
707
|
+
catalog[:vision] = Capabilities.vision?(model)
|
|
708
|
+
catalog[:tools] = api == :generate_content
|
|
709
|
+
catalog[:streaming] = %i[generate_content raw_predict].include?(api)
|
|
710
|
+
catalog
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
def capability_real_for(metadata)
|
|
714
|
+
return {} unless metadata.is_a?(Hash)
|
|
715
|
+
|
|
716
|
+
features = metadata[:supportedFeatures] || metadata['supportedFeatures']
|
|
717
|
+
return {} unless features.is_a?(Hash)
|
|
718
|
+
|
|
719
|
+
real = {}
|
|
720
|
+
real[:tools] = features['functionCalling'] if features.key?('functionCalling')
|
|
721
|
+
real[:vision] = features['multimodalInput'] if features.key?('multimodalInput')
|
|
722
|
+
real[:thinking] = features['thinking'] if features.key?('thinking')
|
|
723
|
+
real
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
def vertex_provider_config
|
|
727
|
+
cfg = CredentialSources.setting(:extensions, :llm, :vertex)
|
|
728
|
+
return {} unless cfg.is_a?(Hash)
|
|
729
|
+
|
|
730
|
+
cfg.except(:instances, 'instances')
|
|
731
|
+
rescue StandardError => e
|
|
732
|
+
handle_exception(e, level: :warn, handled: true, operation: 'vertex.provider.capability_policy_config')
|
|
733
|
+
{}
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def vertex_instance_config(instance_id)
|
|
737
|
+
cfg = CredentialSources.setting(:extensions, :llm, :vertex)
|
|
738
|
+
return {} unless cfg.is_a?(Hash)
|
|
739
|
+
|
|
740
|
+
instances = cfg[:instances] || cfg['instances']
|
|
741
|
+
return {} unless instances.is_a?(Hash)
|
|
742
|
+
|
|
743
|
+
(instances[instance_id] || instances[instance_id.to_s] || {}).to_h
|
|
744
|
+
rescue StandardError => e
|
|
745
|
+
handle_exception(e, level: :warn, handled: true, operation: 'vertex.provider.instance_config')
|
|
746
|
+
{}
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
def vertex_model_config(model)
|
|
750
|
+
cfg = CredentialSources.setting(:extensions, :llm, :vertex)
|
|
751
|
+
return {} unless cfg.is_a?(Hash)
|
|
752
|
+
|
|
753
|
+
models = cfg[:models] || cfg['models']
|
|
754
|
+
return {} unless models.is_a?(Hash)
|
|
755
|
+
|
|
756
|
+
id = short_model_id(model)
|
|
757
|
+
(models[id.to_sym] || models[id.to_s] || {}).to_h
|
|
758
|
+
rescue StandardError => e
|
|
759
|
+
handle_exception(e, level: :warn, handled: true, operation: 'vertex.provider.model_config')
|
|
760
|
+
{}
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
def short_model_id(model)
|
|
764
|
+
id = model_id(model)
|
|
765
|
+
id.include?('/') ? id.split('/').last : id
|
|
766
|
+
end
|
|
767
|
+
|
|
635
768
|
def bearer_token
|
|
636
769
|
token = config.vertex_access_token
|
|
637
770
|
token ? "Bearer #{token}" : nil
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'legion/extensions/llm'
|
|
4
4
|
require 'legion/extensions/llm/vertex/provider'
|
|
5
5
|
require 'legion/extensions/llm/vertex/version'
|
|
6
|
+
require_relative 'vertex/actors/discovery_refresh'
|
|
6
7
|
|
|
7
8
|
module Legion
|
|
8
9
|
module Extensions
|
|
@@ -39,10 +40,7 @@ module Legion
|
|
|
39
40
|
fleet: {
|
|
40
41
|
enabled: false,
|
|
41
42
|
respond_to_requests: false,
|
|
42
|
-
capabilities: %i[chat stream_chat embed]
|
|
43
|
-
lanes: [],
|
|
44
|
-
concurrency: 4,
|
|
45
|
-
queue_suffix: nil
|
|
43
|
+
capabilities: %i[chat stream_chat embed tools]
|
|
46
44
|
}
|
|
47
45
|
}
|
|
48
46
|
)
|
|
@@ -103,12 +101,7 @@ module Legion
|
|
|
103
101
|
end
|
|
104
102
|
|
|
105
103
|
def self.register_provider_options
|
|
106
|
-
|
|
107
|
-
if configuration.respond_to?(:register_provider_options)
|
|
108
|
-
configuration.register_provider_options(Provider.configuration_options)
|
|
109
|
-
elsif configuration.respond_to?(:option, true)
|
|
110
|
-
Provider.configuration_options.each { |key| configuration.send(:option, key) }
|
|
111
|
-
end
|
|
104
|
+
Legion::Extensions::Llm::Configuration.register_provider_options(Provider.configuration_options)
|
|
112
105
|
end
|
|
113
106
|
|
|
114
107
|
private_class_method :discover_default_instance, :discover_named_instances, :vertex_credentials_present?,
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-llm-vertex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LegionIO
|
|
@@ -71,14 +71,14 @@ dependencies:
|
|
|
71
71
|
requirements:
|
|
72
72
|
- - ">="
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: 0.
|
|
74
|
+
version: 0.6.0
|
|
75
75
|
type: :runtime
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - ">="
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: 0.
|
|
81
|
+
version: 0.6.0
|
|
82
82
|
description: Google Cloud Vertex AI provider integration for the LegionIO LLM routing
|
|
83
83
|
framework.
|
|
84
84
|
email:
|