lex-llm-ollama 0.1.6 → 0.1.7
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 +10 -0
- data/README.md +16 -21
- data/lex-llm-ollama.gemspec +1 -1
- data/lib/legion/extensions/llm/ollama/provider.rb +37 -7
- data/lib/legion/extensions/llm/ollama/version.rb +1 -1
- data/lib/legion/extensions/llm/ollama.rb +14 -15
- metadata +3 -7
- data/lib/legion/extensions/llm/ollama/registry_event_builder.rb +0 -146
- data/lib/legion/extensions/llm/ollama/registry_publisher.rb +0 -94
- data/lib/legion/extensions/llm/ollama/transport/exchanges/llm_registry.rb +0 -24
- data/lib/legion/extensions/llm/ollama/transport/messages/registry_event.rb +0 -42
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '04731865b67b0980013a81e3c1c076e39daa788b7e1136b78c7bb25ec5f3ac8b'
|
|
4
|
+
data.tar.gz: 7dad2cff87b97058266b5a96c8b7bdd5600f3436ca73115fd81c0db517bf2d0d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 45071306f61626d92ff3037f713dab35426170010bdecdf26dee092553a2d07d52595e44e26d7c3ec692a350f024c01df2e56e5c6f2445a9cdfbedfeba8030c7
|
|
7
|
+
data.tar.gz: bc489708640e30d27c306433d5f1e2f82d335550c66bb758a49cfc0a02183a048f3667a1007240f3ff7ee8b2f69192bbb22e4cdf4f0ec4a62e57cae4eef36fb3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.7 - 2026-04-30
|
|
4
|
+
|
|
5
|
+
- Provider contract overhaul: adopt lex-llm >= 0.1.9 base contract.
|
|
6
|
+
- Replace `default_settings` with full schema (enabled, base_url, default_model, whitelist/blacklist, model_cache_ttl, tls, instances).
|
|
7
|
+
- Remove `Provider.register` call; providers are now discovered via the extension registry.
|
|
8
|
+
- Delete local `RegistryPublisher`, `RegistryEventBuilder`, and `Transport/` directory; use shared classes from lex-llm base.
|
|
9
|
+
- Replace `config.ollama_api_base` with `resolve_base_url` multi-host resolution from the base provider contract.
|
|
10
|
+
- Enrich `parse_list_models_response` to infer embedding capabilities and modalities from model name and family.
|
|
11
|
+
- Add `settings` and `config_base_url` accessors to the provider for whitelist/blacklist and base URL resolution support.
|
|
12
|
+
|
|
3
13
|
## 0.1.6 - 2026-04-30
|
|
4
14
|
|
|
5
15
|
- Add `Legion::Logging::Helper` to Ollama module, RegistryPublisher, and RegistryEventBuilder.
|
data/README.md
CHANGED
|
@@ -2,22 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
LegionIO LLM provider extension for [Ollama](https://ollama.ai).
|
|
4
4
|
|
|
5
|
-
This gem lives under `Legion::Extensions::Llm::Ollama` and depends on `lex-llm` for shared provider-neutral routing, fleet, and
|
|
5
|
+
This gem lives under `Legion::Extensions::Llm::Ollama` and depends on `lex-llm` (>= 0.1.9) for shared provider-neutral routing, fleet, transport, and registry primitives.
|
|
6
6
|
|
|
7
7
|
Load it with `require 'legion/extensions/llm/ollama'`.
|
|
8
8
|
|
|
9
9
|
## What It Provides
|
|
10
10
|
|
|
11
|
-
- `Legion::Extensions::Llm::Provider` registration as `:ollama`
|
|
12
11
|
- Ollama-native chat requests through `POST /api/chat`
|
|
13
12
|
- Streaming chat support
|
|
14
|
-
- Model discovery through `GET /api/tags`
|
|
13
|
+
- Model discovery through `GET /api/tags` with automatic embedding capability inference
|
|
15
14
|
- Running model inspection through `GET /api/ps`
|
|
16
15
|
- Model details through `POST /api/show`
|
|
17
16
|
- Model download helper through `POST /api/pull`
|
|
18
17
|
- Embeddings through `POST /api/embed`
|
|
19
|
-
- Best-effort `llm.registry` availability events
|
|
20
|
-
-
|
|
18
|
+
- Best-effort `llm.registry` availability events via the shared `Legion::Extensions::Llm::RegistryPublisher`
|
|
19
|
+
- Full settings schema with model whitelist/blacklist, TLS, and multi-host base URL resolution
|
|
21
20
|
- Full `Legion::Logging::Helper` integration with structured `handle_exception` in every rescue block
|
|
22
21
|
|
|
23
22
|
## Architecture
|
|
@@ -25,11 +24,10 @@ Load it with `require 'legion/extensions/llm/ollama'`.
|
|
|
25
24
|
```
|
|
26
25
|
Legion::Extensions::Llm::Ollama
|
|
27
26
|
├── Provider # Ollama provider (chat, stream, embed, models, readiness)
|
|
28
|
-
|
|
29
|
-
├──
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
└── Messages::RegistryEvent # AMQP message wrapper for registry events
|
|
27
|
+
└── (shared from lex-llm)
|
|
28
|
+
├── RegistryPublisher # Best-effort async llm.registry event publishing
|
|
29
|
+
├── RegistryEventBuilder # Sanitized registry envelope construction
|
|
30
|
+
└── Transport/ # Shared exchange and message classes
|
|
33
31
|
```
|
|
34
32
|
|
|
35
33
|
## Defaults
|
|
@@ -37,16 +35,14 @@ Legion::Extensions::Llm::Ollama
|
|
|
37
35
|
```ruby
|
|
38
36
|
Legion::Extensions::Llm::Ollama.default_settings
|
|
39
37
|
# {
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
# }
|
|
49
|
-
# }
|
|
38
|
+
# enabled: false,
|
|
39
|
+
# base_url: '127.0.0.1:11434',
|
|
40
|
+
# default_model: 'qwen3.5:latest',
|
|
41
|
+
# model_whitelist: [],
|
|
42
|
+
# model_blacklist: [],
|
|
43
|
+
# model_cache_ttl: 60,
|
|
44
|
+
# tls: { enabled: false, verify: :peer },
|
|
45
|
+
# instances: {}
|
|
50
46
|
# }
|
|
51
47
|
```
|
|
52
48
|
|
|
@@ -54,7 +50,6 @@ Legion::Extensions::Llm::Ollama.default_settings
|
|
|
54
50
|
|
|
55
51
|
```ruby
|
|
56
52
|
Legion::Extensions::Llm.configure do |config|
|
|
57
|
-
config.ollama_api_base = "http://localhost:11434"
|
|
58
53
|
config.default_model = "qwen3.6:27b"
|
|
59
54
|
config.default_embedding_model = "nomic-embed-text:latest"
|
|
60
55
|
end
|
data/lex-llm-ollama.gemspec
CHANGED
|
@@ -26,5 +26,5 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
spec.add_dependency 'legion-json', '>= 1.2.1'
|
|
27
27
|
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
28
28
|
spec.add_dependency 'legion-settings', '>= 1.3.14'
|
|
29
|
-
spec.add_dependency 'lex-llm', '>= 0.1.
|
|
29
|
+
spec.add_dependency 'lex-llm', '>= 0.1.9'
|
|
30
30
|
end
|
|
@@ -13,12 +13,11 @@ module Legion
|
|
|
13
13
|
|
|
14
14
|
def slug = 'ollama'
|
|
15
15
|
def local? = true
|
|
16
|
-
def configuration_options = %i[ollama_api_base ollama_keep_alive]
|
|
17
16
|
def configuration_requirements = []
|
|
18
17
|
def capabilities = Capabilities
|
|
19
18
|
|
|
20
19
|
def registry_publisher
|
|
21
|
-
@registry_publisher ||=
|
|
20
|
+
@registry_publisher ||= Ollama.registry_publisher
|
|
22
21
|
end
|
|
23
22
|
end
|
|
24
23
|
|
|
@@ -33,8 +32,16 @@ module Legion
|
|
|
33
32
|
def embeddings?(_model) = true
|
|
34
33
|
end
|
|
35
34
|
|
|
35
|
+
def settings
|
|
36
|
+
Ollama.default_settings
|
|
37
|
+
end
|
|
38
|
+
|
|
36
39
|
def api_base
|
|
37
|
-
|
|
40
|
+
resolve_base_url || normalize_url(settings[:base_url] || '127.0.0.1:11434')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def config_base_url
|
|
44
|
+
settings[:base_url]
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
def completion_url = '/api/chat'
|
|
@@ -87,13 +94,17 @@ module Legion
|
|
|
87
94
|
|
|
88
95
|
private
|
|
89
96
|
|
|
97
|
+
def ollama_keep_alive
|
|
98
|
+
settings[:keep_alive]
|
|
99
|
+
end
|
|
100
|
+
|
|
90
101
|
def render_payload(messages, tools:, temperature:, model:, stream:, schema:, thinking:, tool_prefs:) # rubocop:disable Metrics/ParameterLists
|
|
91
102
|
{
|
|
92
103
|
model: model.id,
|
|
93
104
|
messages: format_messages(messages),
|
|
94
105
|
stream: stream,
|
|
95
106
|
think: thinking ? true : nil,
|
|
96
|
-
keep_alive:
|
|
107
|
+
keep_alive: ollama_keep_alive,
|
|
97
108
|
format: schema_format(schema),
|
|
98
109
|
options: { temperature: temperature }.compact,
|
|
99
110
|
tools: format_tools(tools),
|
|
@@ -193,17 +204,36 @@ module Legion
|
|
|
193
204
|
|
|
194
205
|
def parse_list_models_response(response, provider, _capabilities)
|
|
195
206
|
response.body.fetch('models', []).map do |model|
|
|
207
|
+
family = model.dig('details', 'family')
|
|
208
|
+
caps = infer_capabilities(model.fetch('name'), family, Array(model['capabilities']))
|
|
209
|
+
output_mods = embedding_model?(model.fetch('name'), family) ? [:embeddings] : [:text]
|
|
210
|
+
|
|
196
211
|
Legion::Extensions::Llm::Model::Info.new(
|
|
197
212
|
id: model.fetch('name'),
|
|
198
213
|
name: model.fetch('name'),
|
|
199
214
|
provider: provider,
|
|
200
|
-
|
|
201
|
-
capabilities:
|
|
202
|
-
|
|
215
|
+
family: family,
|
|
216
|
+
capabilities: caps,
|
|
217
|
+
modalities_output: output_mods,
|
|
218
|
+
metadata: model.merge('created_at' => model['modified_at'])
|
|
203
219
|
)
|
|
204
220
|
end
|
|
205
221
|
end
|
|
206
222
|
|
|
223
|
+
def infer_capabilities(name, family, api_caps)
|
|
224
|
+
return api_caps.map(&:to_sym) unless api_caps.empty?
|
|
225
|
+
|
|
226
|
+
if embedding_model?(name, family)
|
|
227
|
+
[:embedding]
|
|
228
|
+
else
|
|
229
|
+
%i[completion streaming tools vision]
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def embedding_model?(name, family)
|
|
234
|
+
name.to_s.match?(/embed|embedding/i) || family.to_s.match?(/bert|nomic/i)
|
|
235
|
+
end
|
|
236
|
+
|
|
207
237
|
def render_embedding_payload(text, model:, dimensions:)
|
|
208
238
|
{ model: model, input: text, dimensions: dimensions }.compact
|
|
209
239
|
end
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'legion/extensions/llm'
|
|
4
|
-
require 'legion/extensions/llm/ollama/registry_event_builder'
|
|
5
4
|
require 'legion/extensions/llm/ollama/provider'
|
|
6
|
-
require 'legion/extensions/llm/ollama/registry_publisher'
|
|
7
5
|
require 'legion/extensions/llm/ollama/version'
|
|
8
6
|
|
|
9
7
|
module Legion
|
|
@@ -17,25 +15,26 @@ module Legion
|
|
|
17
15
|
PROVIDER_FAMILY = :ollama
|
|
18
16
|
|
|
19
17
|
def self.default_settings
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
18
|
+
{
|
|
19
|
+
enabled: false,
|
|
20
|
+
base_url: '127.0.0.1:11434',
|
|
21
|
+
default_model: 'qwen3.5:latest',
|
|
22
|
+
model_whitelist: [],
|
|
23
|
+
model_blacklist: [],
|
|
24
|
+
model_cache_ttl: 60,
|
|
25
|
+
tls: { enabled: false, verify: :peer },
|
|
26
|
+
instances: {}
|
|
27
|
+
}
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
def self.provider_class
|
|
33
31
|
Provider
|
|
34
32
|
end
|
|
33
|
+
|
|
34
|
+
def self.registry_publisher
|
|
35
|
+
@registry_publisher ||= Legion::Extensions::Llm::RegistryPublisher.new(provider_family: PROVIDER_FAMILY)
|
|
36
|
+
end
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
|
-
|
|
40
|
-
Legion::Extensions::Llm::Provider.register(Legion::Extensions::Llm::Ollama::PROVIDER_FAMILY,
|
|
41
|
-
Legion::Extensions::Llm::Ollama::Provider)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-llm-ollama
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LegionIO
|
|
@@ -57,14 +57,14 @@ dependencies:
|
|
|
57
57
|
requirements:
|
|
58
58
|
- - ">="
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 0.1.
|
|
60
|
+
version: 0.1.9
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - ">="
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: 0.1.
|
|
67
|
+
version: 0.1.9
|
|
68
68
|
description: Ollama provider integration for the LegionIO LLM routing framework.
|
|
69
69
|
email:
|
|
70
70
|
- matthewdiverson@gmail.com
|
|
@@ -84,10 +84,6 @@ files:
|
|
|
84
84
|
- lex-llm-ollama.gemspec
|
|
85
85
|
- lib/legion/extensions/llm/ollama.rb
|
|
86
86
|
- lib/legion/extensions/llm/ollama/provider.rb
|
|
87
|
-
- lib/legion/extensions/llm/ollama/registry_event_builder.rb
|
|
88
|
-
- lib/legion/extensions/llm/ollama/registry_publisher.rb
|
|
89
|
-
- lib/legion/extensions/llm/ollama/transport/exchanges/llm_registry.rb
|
|
90
|
-
- lib/legion/extensions/llm/ollama/transport/messages/registry_event.rb
|
|
91
87
|
- lib/legion/extensions/llm/ollama/version.rb
|
|
92
88
|
homepage: https://github.com/LegionIO/lex-llm-ollama
|
|
93
89
|
licenses:
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Legion
|
|
4
|
-
module Extensions
|
|
5
|
-
module Llm
|
|
6
|
-
module Ollama
|
|
7
|
-
# Builds sanitized lex-llm registry envelopes for Ollama provider state.
|
|
8
|
-
class RegistryEventBuilder # rubocop:disable Metrics/ClassLength
|
|
9
|
-
include Legion::Logging::Helper
|
|
10
|
-
|
|
11
|
-
def readiness(readiness)
|
|
12
|
-
registry_event_class.public_send(
|
|
13
|
-
readiness[:ready] ? :available : :unavailable,
|
|
14
|
-
provider_offering(readiness),
|
|
15
|
-
runtime: runtime_metadata,
|
|
16
|
-
health: readiness_health(readiness),
|
|
17
|
-
metadata: readiness_metadata(readiness)
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def model_available(model, readiness:)
|
|
22
|
-
registry_event_class.available(
|
|
23
|
-
model_offering(model),
|
|
24
|
-
runtime: runtime_metadata,
|
|
25
|
-
health: model_health(readiness),
|
|
26
|
-
metadata: model_metadata(model)
|
|
27
|
-
)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def provider_offering(readiness)
|
|
33
|
-
{
|
|
34
|
-
provider_family: :ollama,
|
|
35
|
-
provider_instance: provider_instance,
|
|
36
|
-
transport: :http,
|
|
37
|
-
model: 'provider-readiness',
|
|
38
|
-
usage_type: :inference,
|
|
39
|
-
capabilities: [],
|
|
40
|
-
health: readiness_health(readiness),
|
|
41
|
-
metadata: { lex: :llm_ollama, provider_readiness: true }
|
|
42
|
-
}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def model_offering(model)
|
|
46
|
-
{
|
|
47
|
-
provider_family: :ollama,
|
|
48
|
-
provider_instance: provider_instance,
|
|
49
|
-
transport: :http,
|
|
50
|
-
model: model.id,
|
|
51
|
-
usage_type: usage_type_for(model),
|
|
52
|
-
capabilities: capabilities_for(model),
|
|
53
|
-
limits: model_limits(model),
|
|
54
|
-
metadata: model_metadata(model)
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def readiness_health(readiness)
|
|
59
|
-
health = {
|
|
60
|
-
ready: readiness[:ready] == true,
|
|
61
|
-
status: readiness[:ready] ? :available : :unavailable,
|
|
62
|
-
checked: readiness.dig(:health, :checked) != false
|
|
63
|
-
}
|
|
64
|
-
add_readiness_error(health, readiness[:health])
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def add_readiness_error(health, source)
|
|
68
|
-
error = source.is_a?(Hash) ? source : {}
|
|
69
|
-
error_class = error[:error] || error['error']
|
|
70
|
-
error_message = error[:message] || error['message']
|
|
71
|
-
health[:error_class] = error_class if error_class
|
|
72
|
-
health[:error] = error_message if error_message
|
|
73
|
-
health
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def model_health(readiness)
|
|
77
|
-
ready = readiness.fetch(:ready, true) == true
|
|
78
|
-
{ ready:, status: ready ? :available : :degraded }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def readiness_metadata(readiness)
|
|
82
|
-
{
|
|
83
|
-
extension: :lex_llm_ollama,
|
|
84
|
-
provider: :ollama,
|
|
85
|
-
configured: readiness[:configured] == true,
|
|
86
|
-
live: readiness[:live] == true
|
|
87
|
-
}
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def model_metadata(model)
|
|
91
|
-
metadata = model.metadata || {}
|
|
92
|
-
{
|
|
93
|
-
extension: :lex_llm_ollama,
|
|
94
|
-
provider: :ollama,
|
|
95
|
-
model_name: model.name,
|
|
96
|
-
family: metadata.dig('details', 'family'),
|
|
97
|
-
parameter_size: metadata.dig('details', 'parameter_size'),
|
|
98
|
-
quantization_level: metadata.dig('details', 'quantization_level')
|
|
99
|
-
}.compact
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def runtime_metadata
|
|
103
|
-
{ node: provider_instance }
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def model_limits(model)
|
|
107
|
-
context_window = model.metadata&.dig('model_info', 'general.context_length') ||
|
|
108
|
-
model.metadata&.dig('model_info', "#{model_family(model)}.context_length")
|
|
109
|
-
{ context_window: context_window }.compact
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def capabilities_for(model)
|
|
113
|
-
configured = Array(model.capabilities).map(&:to_sym)
|
|
114
|
-
return configured unless configured.empty?
|
|
115
|
-
|
|
116
|
-
usage_type_for(model) == :embedding ? [:embedding] : %i[chat streaming tools vision]
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def usage_type_for(model)
|
|
120
|
-
return :embedding if model.id.to_s.match?(/embed|embedding/i)
|
|
121
|
-
|
|
122
|
-
family = model_family(model).to_s
|
|
123
|
-
family.match?(/bert|nomic/i) ? :embedding : :inference
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def model_family(model)
|
|
127
|
-
model.metadata&.dig('details', 'family') || model.metadata&.dig(:details, :family)
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def provider_instance
|
|
131
|
-
configured_node = (::Legion::Settings.dig(:node, :canonical_name) if defined?(::Legion::Settings))
|
|
132
|
-
value = configured_node.to_s.strip
|
|
133
|
-
value.empty? ? :ollama : value.to_sym
|
|
134
|
-
rescue StandardError => e
|
|
135
|
-
handle_exception(e, level: :debug, handled: true, operation: 'ollama.registry.provider_instance')
|
|
136
|
-
:ollama
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def registry_event_class
|
|
140
|
-
::Legion::Extensions::Llm::Routing::RegistryEvent
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Legion
|
|
4
|
-
module Extensions
|
|
5
|
-
module Llm
|
|
6
|
-
module Ollama
|
|
7
|
-
# Best-effort publisher for Ollama provider availability events.
|
|
8
|
-
class RegistryPublisher
|
|
9
|
-
include Legion::Logging::Helper
|
|
10
|
-
|
|
11
|
-
APP_ID = 'lex-llm-ollama'
|
|
12
|
-
|
|
13
|
-
def initialize(builder: RegistryEventBuilder.new)
|
|
14
|
-
@builder = builder
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def publish_readiness_async(readiness)
|
|
18
|
-
log.info { 'publishing readiness event to llm.registry' }
|
|
19
|
-
schedule { publish_event(@builder.readiness(readiness)) }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def publish_models_async(models, readiness:)
|
|
23
|
-
log.info { "publishing #{Array(models).size} model event(s) to llm.registry" }
|
|
24
|
-
schedule do
|
|
25
|
-
Array(models).each do |model|
|
|
26
|
-
publish_event(@builder.model_available(model, readiness:))
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
def schedule(&)
|
|
34
|
-
return false unless publishing_available?
|
|
35
|
-
|
|
36
|
-
Thread.new do
|
|
37
|
-
Thread.current.abort_on_exception = false
|
|
38
|
-
yield
|
|
39
|
-
rescue StandardError => e
|
|
40
|
-
handle_exception(e, level: :debug, handled: true, operation: 'ollama.registry.schedule_thread')
|
|
41
|
-
end
|
|
42
|
-
rescue StandardError => e
|
|
43
|
-
handle_exception(e, level: :debug, handled: true, operation: 'ollama.registry.schedule')
|
|
44
|
-
false
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def publish_event(event)
|
|
48
|
-
return false unless publishing_available?
|
|
49
|
-
|
|
50
|
-
message_class.new(event:, app_id: APP_ID).publish(spool: false)
|
|
51
|
-
rescue StandardError => e
|
|
52
|
-
handle_exception(e, level: :warn, handled: true, operation: 'ollama.registry.publish_event')
|
|
53
|
-
false
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def publishing_available?
|
|
57
|
-
return false unless registry_event_available?
|
|
58
|
-
return false unless transport_message_available?
|
|
59
|
-
return true unless defined?(::Legion::Transport::Connection)
|
|
60
|
-
return true unless ::Legion::Transport::Connection.respond_to?(:session_open?)
|
|
61
|
-
|
|
62
|
-
::Legion::Transport::Connection.session_open?
|
|
63
|
-
rescue StandardError => e
|
|
64
|
-
handle_exception(e, level: :debug, handled: true, operation: 'ollama.registry.publishing_available?')
|
|
65
|
-
false
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def registry_event_available?
|
|
69
|
-
defined?(::Legion::Extensions::Llm::Routing::RegistryEvent)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def transport_message_available?
|
|
73
|
-
return true if message_class_defined?
|
|
74
|
-
return false unless defined?(::Legion::Transport::Message) && defined?(::Legion::Transport::Exchange)
|
|
75
|
-
|
|
76
|
-
require 'legion/extensions/llm/ollama/transport/messages/registry_event'
|
|
77
|
-
message_class_defined?
|
|
78
|
-
rescue LoadError => e
|
|
79
|
-
handle_exception(e, level: :debug, handled: true, operation: 'ollama.registry.transport_load')
|
|
80
|
-
false
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def message_class_defined?
|
|
84
|
-
defined?(::Legion::Extensions::Llm::Ollama::Transport::Messages::RegistryEvent)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def message_class
|
|
88
|
-
::Legion::Extensions::Llm::Ollama::Transport::Messages::RegistryEvent
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Legion
|
|
4
|
-
module Extensions
|
|
5
|
-
module Llm
|
|
6
|
-
module Ollama
|
|
7
|
-
module Transport
|
|
8
|
-
module Exchanges
|
|
9
|
-
# Topic exchange for Ollama provider availability events.
|
|
10
|
-
class LlmRegistry < ::Legion::Transport::Exchange
|
|
11
|
-
def exchange_name
|
|
12
|
-
'llm.registry'
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def default_type
|
|
16
|
-
'topic'
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'legion/extensions/llm/ollama/transport/exchanges/llm_registry'
|
|
4
|
-
|
|
5
|
-
module Legion
|
|
6
|
-
module Extensions
|
|
7
|
-
module Llm
|
|
8
|
-
module Ollama
|
|
9
|
-
module Transport
|
|
10
|
-
module Messages
|
|
11
|
-
# Publishes lex-llm RegistryEvent envelopes to the llm.registry exchange.
|
|
12
|
-
class RegistryEvent < ::Legion::Transport::Message
|
|
13
|
-
def initialize(event:, **options)
|
|
14
|
-
super(**event.to_h.merge(options))
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def exchange
|
|
18
|
-
Transport::Exchanges::LlmRegistry
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def routing_key
|
|
22
|
-
@options[:routing_key] || "llm.registry.#{@options.fetch(:event_type)}"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def type
|
|
26
|
-
'llm.registry.event'
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def app_id
|
|
30
|
-
@options[:app_id] || RegistryPublisher::APP_ID
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def persistent # rubocop:disable Naming/PredicateMethod
|
|
34
|
-
false
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|