lex-llm-ollama 0.2.7 → 0.2.8
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 +5 -0
- data/lib/legion/extensions/llm/ollama/actors/fleet_worker.rb +6 -1
- data/lib/legion/extensions/llm/ollama/provider.rb +35 -8
- data/lib/legion/extensions/llm/ollama/runners/fleet_worker.rb +9 -0
- data/lib/legion/extensions/llm/ollama/version.rb +1 -1
- data/lib/legion/extensions/llm/ollama.rb +31 -17
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20e5e1a5989633a805483200893d6d11c6f0af9b3d9b3204defad0e33e0be5ed
|
|
4
|
+
data.tar.gz: 8dd17ebb04df4e90b75438f8f4ba86bb289db4ccde25f1b71d36253a9075450c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0944f1f288b824bcc09b9ca13e9ece5d67553fe4d706e26a7d77b37c1fa71c594eaeb8b0f2f8fd9817259463e9289257019b700a4a02019077f1c889e0b7aa8a'
|
|
7
|
+
data.tar.gz: 32c4de66b95c05e9b0349a2c1da79f826fd701fd9aa61d25957291076c3e6ca87fa79338fd323e652c1e441342bb54f6a1dc97b03bd5ffafe56c3eb32411eeb1
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.8 - 2026-05-12
|
|
4
|
+
|
|
5
|
+
- Include `Legion::Logging::Helper` directly in Ollama provider, actor, and fleet runner runtime surfaces.
|
|
6
|
+
- Add sanitized debug logging for provider discovery, payload rendering, tool formatting, embeddings, offerings, and fleet handoff.
|
|
7
|
+
|
|
3
8
|
## 0.2.7 - 2026-05-07
|
|
4
9
|
|
|
5
10
|
- Render Ollama embedding payloads with the canonical model id when callers pass `Model::Info` objects.
|
|
@@ -12,6 +12,7 @@ end
|
|
|
12
12
|
|
|
13
13
|
require 'legion/extensions/llm/ollama'
|
|
14
14
|
require 'legion/extensions/llm/fleet/provider_responder'
|
|
15
|
+
require 'legion/logging/helper'
|
|
15
16
|
|
|
16
17
|
module Legion
|
|
17
18
|
module Extensions
|
|
@@ -20,6 +21,8 @@ module Legion
|
|
|
20
21
|
module Actor
|
|
21
22
|
# Subscription actor for Ollama fleet request consumption.
|
|
22
23
|
class FleetWorker < Legion::Extensions::Actors::Subscription
|
|
24
|
+
include Legion::Logging::Helper
|
|
25
|
+
|
|
23
26
|
def runner_class
|
|
24
27
|
'Legion::Extensions::Llm::Ollama::Runners::FleetWorker'
|
|
25
28
|
end
|
|
@@ -33,7 +36,9 @@ module Legion
|
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def enabled?
|
|
36
|
-
Legion::Extensions::Llm::Fleet::ProviderResponder.enabled_for?(Ollama.discover_instances)
|
|
39
|
+
enabled = Legion::Extensions::Llm::Fleet::ProviderResponder.enabled_for?(Ollama.discover_instances)
|
|
40
|
+
log.debug { "ollama fleet worker actor enabled=#{enabled}" }
|
|
41
|
+
enabled
|
|
37
42
|
end
|
|
38
43
|
end
|
|
39
44
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'legion/extensions/llm'
|
|
4
|
+
require 'legion/logging/helper'
|
|
4
5
|
|
|
5
6
|
module Legion
|
|
6
7
|
module Extensions
|
|
@@ -8,6 +9,8 @@ module Legion
|
|
|
8
9
|
module Ollama
|
|
9
10
|
# Ollama provider implementation for the Legion::Extensions::Llm base provider contract.
|
|
10
11
|
class Provider < Legion::Extensions::Llm::Provider # rubocop:disable Metrics/ClassLength
|
|
12
|
+
include Legion::Logging::Helper
|
|
13
|
+
|
|
11
14
|
class << self
|
|
12
15
|
attr_writer :registry_publisher
|
|
13
16
|
|
|
@@ -54,7 +57,7 @@ module Legion
|
|
|
54
57
|
def version_url = '/api/version'
|
|
55
58
|
|
|
56
59
|
def list_running_models
|
|
57
|
-
log.
|
|
60
|
+
log.debug { "ollama provider listing running models endpoint=#{api_base}#{running_models_url}" }
|
|
58
61
|
connection.get(running_models_url).body.fetch('models', [])
|
|
59
62
|
rescue StandardError => e
|
|
60
63
|
handle_exception(e, level: :error, handled: true, operation: 'ollama.list_running_models')
|
|
@@ -62,22 +65,22 @@ module Legion
|
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
def readiness(live: false)
|
|
65
|
-
log.
|
|
68
|
+
log.debug { "ollama provider checking readiness live=#{live} endpoint=#{api_base}" }
|
|
66
69
|
super.tap do |metadata|
|
|
67
70
|
self.class.registry_publisher.publish_readiness_async(metadata) if live
|
|
68
71
|
end
|
|
69
72
|
end
|
|
70
73
|
|
|
71
74
|
def list_models
|
|
72
|
-
log.
|
|
75
|
+
log.debug { "ollama provider discovering models endpoint=#{api_base}#{models_url}" }
|
|
73
76
|
super.tap do |models|
|
|
74
|
-
log.
|
|
77
|
+
log.debug { "ollama provider discovered model_count=#{models.size}" }
|
|
75
78
|
self.class.registry_publisher.publish_models_async(models, readiness: readiness(live: false))
|
|
76
79
|
end
|
|
77
80
|
end
|
|
78
81
|
|
|
79
82
|
def show_model(model)
|
|
80
|
-
log.
|
|
83
|
+
log.debug { "ollama provider fetching model details model=#{model}" }
|
|
81
84
|
connection.post(show_model_url, { model: model }).body
|
|
82
85
|
rescue StandardError => e
|
|
83
86
|
handle_exception(e, level: :error, handled: true, operation: 'ollama.show_model')
|
|
@@ -85,6 +88,7 @@ module Legion
|
|
|
85
88
|
end
|
|
86
89
|
|
|
87
90
|
def pull_model(model, stream: false)
|
|
91
|
+
log.debug { "ollama provider pulling model=#{model} stream=#{stream}" }
|
|
88
92
|
log.info { "pulling model #{model} stream=#{stream}" }
|
|
89
93
|
connection.post(pull_url, { model: model, stream: stream }).body
|
|
90
94
|
rescue StandardError => e
|
|
@@ -93,12 +97,17 @@ module Legion
|
|
|
93
97
|
end
|
|
94
98
|
|
|
95
99
|
def discover_offerings(live: false, **)
|
|
100
|
+
log.debug do
|
|
101
|
+
"ollama provider discovering offerings live=#{live} cached_model_count=#{Array(@cached_models).size}"
|
|
102
|
+
end
|
|
96
103
|
models = if live
|
|
97
104
|
@cached_models = list_models
|
|
98
105
|
else
|
|
99
106
|
Array(@cached_models)
|
|
100
107
|
end
|
|
101
|
-
models.map { |model_info| offering_from_model(model_info) }
|
|
108
|
+
models.map { |model_info| offering_from_model(model_info) }.tap do |offerings|
|
|
109
|
+
log.debug { "ollama provider built offering_count=#{offerings.size} live=#{live}" }
|
|
110
|
+
end
|
|
102
111
|
rescue StandardError => e
|
|
103
112
|
handle_exception(e, level: :warn, handled: true, operation: 'ollama.discover_offerings')
|
|
104
113
|
[]
|
|
@@ -153,8 +162,14 @@ module Legion
|
|
|
153
162
|
end
|
|
154
163
|
|
|
155
164
|
def render_payload(messages, tools:, temperature:, model:, stream:, schema:, thinking:, tool_prefs:) # rubocop:disable Metrics/ParameterLists
|
|
165
|
+
model_id = model.respond_to?(:id) ? model.id : model
|
|
166
|
+
log.debug do
|
|
167
|
+
"ollama provider rendering chat payload model=#{model_id} message_count=#{messages.size} " \
|
|
168
|
+
"stream=#{stream} tools=#{tools.size} schema=#{!schema.nil?} thinking=#{thinking ? true : false}"
|
|
169
|
+
end
|
|
170
|
+
|
|
156
171
|
{
|
|
157
|
-
model:
|
|
172
|
+
model: model_id,
|
|
158
173
|
messages: format_messages(messages),
|
|
159
174
|
stream: stream,
|
|
160
175
|
think: thinking ? true : nil,
|
|
@@ -196,6 +211,9 @@ module Legion
|
|
|
196
211
|
def format_tools(tools)
|
|
197
212
|
return nil if tools.empty?
|
|
198
213
|
|
|
214
|
+
tool_names = tools.values.filter_map { |tool| tool.respond_to?(:name) ? tool.name : nil }
|
|
215
|
+
log.debug { "ollama provider formatting tools count=#{tools.size} names=#{tool_names.join(',')}" }
|
|
216
|
+
|
|
199
217
|
tools.values.map do |tool|
|
|
200
218
|
{
|
|
201
219
|
type: 'function',
|
|
@@ -243,6 +261,8 @@ module Legion
|
|
|
243
261
|
def parse_tool_calls(tool_calls)
|
|
244
262
|
return nil unless tool_calls
|
|
245
263
|
|
|
264
|
+
log.debug { "ollama provider parsing tool_call_count=#{tool_calls.size}" }
|
|
265
|
+
|
|
246
266
|
tool_calls.to_h do |call|
|
|
247
267
|
function = call.fetch('function', {})
|
|
248
268
|
[
|
|
@@ -289,7 +309,11 @@ module Legion
|
|
|
289
309
|
end
|
|
290
310
|
|
|
291
311
|
def render_embedding_payload(text, model:, dimensions:)
|
|
292
|
-
|
|
312
|
+
model_id = model.respond_to?(:id) ? model.id : model
|
|
313
|
+
input_count = text.respond_to?(:size) ? text.size : 1
|
|
314
|
+
log.debug { "ollama provider rendering embedding payload model=#{model_id} input_count=#{input_count}" }
|
|
315
|
+
|
|
316
|
+
{ model: model_id, input: text, dimensions: dimensions }.compact
|
|
293
317
|
end
|
|
294
318
|
|
|
295
319
|
def parse_embedding_response(response, model:, text:)
|
|
@@ -302,6 +326,9 @@ module Legion
|
|
|
302
326
|
body['embeddings']&.first
|
|
303
327
|
end
|
|
304
328
|
|
|
329
|
+
vector_count = vectors.respond_to?(:size) ? vectors.size : 0
|
|
330
|
+
log.debug { "ollama provider parsed embedding response model=#{model} vector_count=#{vector_count}" }
|
|
331
|
+
|
|
305
332
|
Legion::Extensions::Llm::Embedding.new(vectors: vectors, model: model,
|
|
306
333
|
input_tokens: body['prompt_eval_count'].to_i)
|
|
307
334
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'legion/extensions/llm/fleet/provider_responder'
|
|
4
4
|
require 'legion/extensions/llm/ollama'
|
|
5
|
+
require 'legion/logging/helper'
|
|
5
6
|
|
|
6
7
|
module Legion
|
|
7
8
|
module Extensions
|
|
@@ -10,9 +11,17 @@ module Legion
|
|
|
10
11
|
module Runners
|
|
11
12
|
# Runner entrypoint for Ollama fleet request execution.
|
|
12
13
|
module FleetWorker
|
|
14
|
+
extend Legion::Logging::Helper
|
|
15
|
+
|
|
13
16
|
module_function
|
|
14
17
|
|
|
15
18
|
def handle_fleet_request(payload, delivery: nil, properties: nil)
|
|
19
|
+
payload_keys = payload.respond_to?(:keys) ? payload.keys.join(',') : payload.class
|
|
20
|
+
log.debug do
|
|
21
|
+
"ollama fleet worker handing off request payload_keys=#{payload_keys} " \
|
|
22
|
+
"delivery=#{!delivery.nil?} properties=#{!properties.nil?}"
|
|
23
|
+
end
|
|
24
|
+
|
|
16
25
|
Legion::Extensions::Llm::Fleet::ProviderResponder.call(
|
|
17
26
|
payload: payload,
|
|
18
27
|
provider_family: Ollama::PROVIDER_FAMILY,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'legion/extensions/llm'
|
|
4
4
|
require 'legion/extensions/llm/ollama/provider'
|
|
5
5
|
require 'legion/extensions/llm/ollama/version'
|
|
6
|
+
require 'legion/logging/helper'
|
|
6
7
|
|
|
7
8
|
module Legion
|
|
8
9
|
module Extensions
|
|
@@ -49,24 +50,10 @@ module Legion
|
|
|
49
50
|
def self.discover_instances
|
|
50
51
|
instances = {}
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
base_url: 'http://127.0.0.1:11434',
|
|
55
|
-
tier: :local,
|
|
56
|
-
capabilities: %i[completion embedding vision]
|
|
57
|
-
}
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
configured = CredentialSources.setting(:extensions, :llm, :ollama, :instances)
|
|
61
|
-
if configured.is_a?(Hash)
|
|
62
|
-
configured.each do |name, config|
|
|
63
|
-
instances[name.to_sym] = normalize_instance_config(config).merge(
|
|
64
|
-
tier: :direct,
|
|
65
|
-
capabilities: %i[completion embedding vision]
|
|
66
|
-
)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
53
|
+
discover_local_instance(instances)
|
|
54
|
+
discover_configured_instances(instances)
|
|
69
55
|
|
|
56
|
+
log.debug { "ollama discovery returning instance_count=#{instances.size}" }
|
|
70
57
|
instances
|
|
71
58
|
end
|
|
72
59
|
|
|
@@ -77,6 +64,33 @@ module Legion
|
|
|
77
64
|
normalized[:base_url] ||= normalized.delete(:endpoint)
|
|
78
65
|
normalized.compact
|
|
79
66
|
end
|
|
67
|
+
|
|
68
|
+
def self.discover_local_instance(instances)
|
|
69
|
+
log.debug { 'ollama discovery probing local socket host=127.0.0.1 port=11434' }
|
|
70
|
+
return unless CredentialSources.socket_open?('127.0.0.1', 11_434, timeout: 0.1)
|
|
71
|
+
|
|
72
|
+
log.debug { 'ollama discovery found local socket instance' }
|
|
73
|
+
instances[:local] = {
|
|
74
|
+
base_url: 'http://127.0.0.1:11434',
|
|
75
|
+
tier: :local,
|
|
76
|
+
capabilities: %i[completion embedding vision]
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.discover_configured_instances(instances)
|
|
81
|
+
configured = CredentialSources.setting(:extensions, :llm, :ollama, :instances)
|
|
82
|
+
return unless configured.is_a?(Hash)
|
|
83
|
+
|
|
84
|
+
log.debug { "ollama discovery loading configured instance_count=#{configured.size}" }
|
|
85
|
+
configured.each do |name, config|
|
|
86
|
+
instances[name.to_sym] = normalize_instance_config(config).merge(
|
|
87
|
+
tier: :direct,
|
|
88
|
+
capabilities: %i[completion embedding vision]
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private_class_method :discover_local_instance, :discover_configured_instances
|
|
80
94
|
end
|
|
81
95
|
end
|
|
82
96
|
end
|