lex-llm-vertex 0.2.9 → 0.2.13
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 +20 -0
- data/Gemfile +0 -7
- data/lex-llm-vertex.gemspec +1 -1
- data/lib/legion/extensions/llm/vertex/actors/discovery_refresh.rb +54 -0
- data/lib/legion/extensions/llm/vertex/provider.rb +108 -7
- data/lib/legion/extensions/llm/vertex/version.rb +1 -1
- data/lib/legion/extensions/llm/vertex.rb +3 -10
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 31112ce3580ae2a99c27285cbc5385d742faf52f4aaa854212802254c423112a
|
|
4
|
+
data.tar.gz: 64ba36b8b97732e2d2b63605e2f7edb33f82b42065f5f79d8c2328d0dd3e3b35
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 924fe07b104555a416524b8d7e9994e0a09e6051e307034161d485d285cad2bd44c7cc26653420cfee4d629e757b6cdbd02088d2c375e032c437eb660fd7a28d
|
|
7
|
+
data.tar.gz: a1467f3de89eba4f4cc7e852e49f33153fe8caa79878a2da1b57e147a95a50a8122a1b1c60ab018cbb90e12c6b2a7c0b774dc9962f0288815b7e871fae6fdcc6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.13 - 2026-06-16
|
|
4
|
+
|
|
5
|
+
- Dependency updates and code quality improvements.
|
|
6
|
+
|
|
7
|
+
## 0.2.12 - 2026-06-15
|
|
8
|
+
|
|
9
|
+
- **CapabilityPolicy integration** — Model-family heuristics tagged as `:provider_catalog`; Vertex features as `:model_metadata`. Settings overrides at provider/instance/model level supported.
|
|
10
|
+
|
|
11
|
+
## 0.2.11 - 2026-06-13
|
|
12
|
+
|
|
13
|
+
- **Gemfile cleanup** — Remove local path overrides; dependencies resolve from gemspec via rubygems.
|
|
14
|
+
- **Dependency bump** — Require `lex-llm >= 0.5.0` for canonical types support.
|
|
15
|
+
- **Canonical tool support** — Use `ToolSchema.extract` and add `:tools` capability.
|
|
16
|
+
- **Bug fix** — Handle Array tool_calls in `tool_call_parts`.
|
|
17
|
+
- 29 examples, 0 failures; 13 files, 0 rubocop offenses.
|
|
18
|
+
|
|
19
|
+
## 0.2.10 - 2026-06-02
|
|
20
|
+
|
|
21
|
+
- Add per-provider scoped discovery refresh actor
|
|
22
|
+
|
|
3
23
|
## 0.2.9 - 2026-05-21
|
|
4
24
|
|
|
5
25
|
- Add `default_transport`/`default_tier` class declarations, remove `configured_transport`/`configured_tier`
|
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.5.0'
|
|
31
31
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'legion/extensions/actors/every'
|
|
5
|
+
rescue LoadError => e
|
|
6
|
+
warn(e.message) if $VERBOSE
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
return unless defined?(Legion::Extensions::Actors::Every)
|
|
10
|
+
|
|
11
|
+
module Legion
|
|
12
|
+
module Extensions
|
|
13
|
+
module Llm
|
|
14
|
+
module Vertex
|
|
15
|
+
module Actor
|
|
16
|
+
class DiscoveryRefresh < Legion::Extensions::Actors::Every # rubocop:disable Style/Documentation
|
|
17
|
+
include Legion::Logging::Helper
|
|
18
|
+
|
|
19
|
+
REFRESH_INTERVAL = 1800
|
|
20
|
+
|
|
21
|
+
def runner_class = self.class
|
|
22
|
+
def runner_function = 'manual'
|
|
23
|
+
def run_now? = true
|
|
24
|
+
def use_runner? = false
|
|
25
|
+
def check_subtask? = false
|
|
26
|
+
def generate_task? = false
|
|
27
|
+
|
|
28
|
+
def time
|
|
29
|
+
return REFRESH_INTERVAL unless defined?(Legion::Settings)
|
|
30
|
+
|
|
31
|
+
Legion::Settings.dig(:extensions, :llm, :vertex, :discovery_interval) || REFRESH_INTERVAL
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def manual
|
|
35
|
+
log.debug('[vertex][discovery_refresh] refreshing model list')
|
|
36
|
+
return unless defined?(Legion::LLM::Discovery)
|
|
37
|
+
|
|
38
|
+
Legion::LLM::Discovery.refresh_discovered_models!(provider: :vertex)
|
|
39
|
+
|
|
40
|
+
if defined?(Legion::LLM::Router) && Legion::LLM::Router.respond_to?(:populate_auto_rules)
|
|
41
|
+
Legion::LLM::Router.populate_auto_rules(Legion::LLM::Discovery.discovered_instances)
|
|
42
|
+
end
|
|
43
|
+
if defined?(Legion::LLM::Inventory) && Legion::LLM::Inventory.respond_to?(:invalidate_offerings_cache!)
|
|
44
|
+
Legion::LLM::Inventory.invalidate_offerings_cache!
|
|
45
|
+
end
|
|
46
|
+
rescue StandardError => e
|
|
47
|
+
handle_exception(e, level: :warn, handled: true, operation: 'vertex.actor.discovery_refresh')
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -327,6 +327,8 @@ module Legion
|
|
|
327
327
|
|
|
328
328
|
def build_offering(model:, model_family:, usage_type:, publisher:, api:, instance_id: :default,
|
|
329
329
|
alias_name: nil, metadata: {})
|
|
330
|
+
policy = resolve_capability_policy(model, api:, metadata:, instance_id:)
|
|
331
|
+
|
|
330
332
|
Legion::Extensions::Llm::Routing::ModelOffering.new(
|
|
331
333
|
provider_family: :vertex,
|
|
332
334
|
instance_id: instance_id,
|
|
@@ -334,7 +336,8 @@ module Legion
|
|
|
334
336
|
tier: offering_tier,
|
|
335
337
|
model: model,
|
|
336
338
|
usage_type: usage_type,
|
|
337
|
-
capabilities:
|
|
339
|
+
capabilities: base_capabilities(model, api:) + policy[:capabilities],
|
|
340
|
+
capability_sources: policy[:sources],
|
|
338
341
|
limits: metadata.delete(:limits) || {},
|
|
339
342
|
metadata: metadata.merge(
|
|
340
343
|
model_family: model_family,
|
|
@@ -478,7 +481,9 @@ module Legion
|
|
|
478
481
|
end
|
|
479
482
|
|
|
480
483
|
def tool_call_parts(message)
|
|
481
|
-
|
|
484
|
+
# Array is canonical (name-keyed hashes dropped parallel same-name calls)
|
|
485
|
+
calls = message.tool_calls.is_a?(Hash) ? message.tool_calls.values : Array(message.tool_calls)
|
|
486
|
+
calls.map do |tool_call|
|
|
482
487
|
{ functionCall: { name: tool_call.name, args: tool_call.arguments } }
|
|
483
488
|
end
|
|
484
489
|
end
|
|
@@ -497,9 +502,11 @@ module Legion
|
|
|
497
502
|
|
|
498
503
|
[{
|
|
499
504
|
functionDeclarations: tools.values.map do |tool|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
505
|
+
{
|
|
506
|
+
name: Legion::Extensions::Llm::Canonical::ToolSchema.tool_name(tool),
|
|
507
|
+
description: Legion::Extensions::Llm::Canonical::ToolSchema.tool_description(tool),
|
|
508
|
+
parameters: Legion::Extensions::Llm::Canonical::ToolSchema.extract(tool)
|
|
509
|
+
}
|
|
503
510
|
end
|
|
504
511
|
}]
|
|
505
512
|
end
|
|
@@ -623,15 +630,109 @@ module Legion
|
|
|
623
630
|
end
|
|
624
631
|
|
|
625
632
|
def default_capabilities(model, api:)
|
|
633
|
+
base_capabilities(model, api:) + policy_optional_capabilities(model, api:)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
def base_capabilities(model, api:)
|
|
626
637
|
return %i[embedding] if Capabilities.embeddings?(model)
|
|
627
638
|
|
|
628
639
|
capabilities = %i[chat]
|
|
629
640
|
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
641
|
capabilities
|
|
633
642
|
end
|
|
634
643
|
|
|
644
|
+
def policy_optional_capabilities(model, api:)
|
|
645
|
+
return [] if Capabilities.embeddings?(model)
|
|
646
|
+
|
|
647
|
+
caps = []
|
|
648
|
+
caps << :vision if Capabilities.vision?(model)
|
|
649
|
+
caps << :tools if generate_content_model?(model) && api == :generate_content
|
|
650
|
+
caps
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
def resolve_capability_policy(model, api:, metadata:, instance_id:)
|
|
654
|
+
provider_catalog = capability_catalog_for(model, api:)
|
|
655
|
+
real_caps = capability_real_for(metadata)
|
|
656
|
+
provider_cfg = vertex_provider_config
|
|
657
|
+
instance_cfg = vertex_instance_config(instance_id)
|
|
658
|
+
model_cfg = vertex_model_config(model)
|
|
659
|
+
|
|
660
|
+
Legion::Extensions::Llm::CapabilityPolicy.resolve(
|
|
661
|
+
real: real_caps,
|
|
662
|
+
provider_catalog: provider_catalog,
|
|
663
|
+
probe: {},
|
|
664
|
+
provider_envelope: {},
|
|
665
|
+
provider_config: provider_cfg,
|
|
666
|
+
instance_config: instance_cfg,
|
|
667
|
+
model_config: model_cfg
|
|
668
|
+
)
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
def capability_catalog_for(model, api:)
|
|
672
|
+
return {} if Capabilities.embeddings?(model)
|
|
673
|
+
|
|
674
|
+
catalog = {}
|
|
675
|
+
catalog[:vision] = Capabilities.vision?(model)
|
|
676
|
+
catalog[:tools] = api == :generate_content
|
|
677
|
+
catalog[:streaming] = %i[generate_content raw_predict].include?(api)
|
|
678
|
+
catalog
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def capability_real_for(metadata)
|
|
682
|
+
return {} unless metadata.is_a?(Hash)
|
|
683
|
+
|
|
684
|
+
features = metadata[:supportedFeatures] || metadata['supportedFeatures']
|
|
685
|
+
return {} unless features.is_a?(Hash)
|
|
686
|
+
|
|
687
|
+
real = {}
|
|
688
|
+
real[:tools] = features['functionCalling'] if features.key?('functionCalling')
|
|
689
|
+
real[:vision] = features['multimodalInput'] if features.key?('multimodalInput')
|
|
690
|
+
real[:thinking] = features['thinking'] if features.key?('thinking')
|
|
691
|
+
real
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
def vertex_provider_config
|
|
695
|
+
cfg = CredentialSources.setting(:extensions, :llm, :vertex)
|
|
696
|
+
return {} unless cfg.is_a?(Hash)
|
|
697
|
+
|
|
698
|
+
cfg.except(:instances, 'instances')
|
|
699
|
+
rescue StandardError => e
|
|
700
|
+
handle_exception(e, level: :debug, handled: true, operation: 'vertex.provider.capability_policy_config')
|
|
701
|
+
{}
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
def vertex_instance_config(instance_id)
|
|
705
|
+
cfg = CredentialSources.setting(:extensions, :llm, :vertex)
|
|
706
|
+
return {} unless cfg.is_a?(Hash)
|
|
707
|
+
|
|
708
|
+
instances = cfg[:instances] || cfg['instances']
|
|
709
|
+
return {} unless instances.is_a?(Hash)
|
|
710
|
+
|
|
711
|
+
(instances[instance_id] || instances[instance_id.to_s] || {}).to_h
|
|
712
|
+
rescue StandardError => e
|
|
713
|
+
handle_exception(e, level: :debug, handled: true, operation: 'vertex.provider.instance_config')
|
|
714
|
+
{}
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
def vertex_model_config(model)
|
|
718
|
+
cfg = CredentialSources.setting(:extensions, :llm, :vertex)
|
|
719
|
+
return {} unless cfg.is_a?(Hash)
|
|
720
|
+
|
|
721
|
+
models = cfg[:models] || cfg['models']
|
|
722
|
+
return {} unless models.is_a?(Hash)
|
|
723
|
+
|
|
724
|
+
id = short_model_id(model)
|
|
725
|
+
(models[id.to_sym] || models[id.to_s] || {}).to_h
|
|
726
|
+
rescue StandardError => e
|
|
727
|
+
handle_exception(e, level: :debug, handled: true, operation: 'vertex.provider.model_config')
|
|
728
|
+
{}
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
def short_model_id(model)
|
|
732
|
+
id = model_id(model)
|
|
733
|
+
id.include?('/') ? id.split('/').last : id
|
|
734
|
+
end
|
|
735
|
+
|
|
635
736
|
def bearer_token
|
|
636
737
|
token = config.vertex_access_token
|
|
637
738
|
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.13
|
|
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.5.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.5.0
|
|
82
82
|
description: Google Cloud Vertex AI provider integration for the LegionIO LLM routing
|
|
83
83
|
framework.
|
|
84
84
|
email:
|
|
@@ -98,6 +98,7 @@ files:
|
|
|
98
98
|
- README.md
|
|
99
99
|
- lex-llm-vertex.gemspec
|
|
100
100
|
- lib/legion/extensions/llm/vertex.rb
|
|
101
|
+
- lib/legion/extensions/llm/vertex/actors/discovery_refresh.rb
|
|
101
102
|
- lib/legion/extensions/llm/vertex/actors/fleet_worker.rb
|
|
102
103
|
- lib/legion/extensions/llm/vertex/provider.rb
|
|
103
104
|
- lib/legion/extensions/llm/vertex/runners/fleet_worker.rb
|