lex-llm-ollama 0.2.8 → 0.2.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20e5e1a5989633a805483200893d6d11c6f0af9b3d9b3204defad0e33e0be5ed
4
- data.tar.gz: 8dd17ebb04df4e90b75438f8f4ba86bb289db4ccde25f1b71d36253a9075450c
3
+ metadata.gz: 367e593d0f98eed36e553e82356f0c86e37dd8e4a1324674c388f0383e59034d
4
+ data.tar.gz: f9d24ec554a9be7be90d33c76ddbb7d475a976c8158ceda71f596fcc8bfa42dd
5
5
  SHA512:
6
- metadata.gz: '0944f1f288b824bcc09b9ca13e9ece5d67553fe4d706e26a7d77b37c1fa71c594eaeb8b0f2f8fd9817259463e9289257019b700a4a02019077f1c889e0b7aa8a'
7
- data.tar.gz: 32c4de66b95c05e9b0349a2c1da79f826fd701fd9aa61d25957291076c3e6ca87fa79338fd323e652c1e441342bb54f6a1dc97b03bd5ffafe56c3eb32411eeb1
6
+ metadata.gz: 5be0235ede9a88b3b355cd2d6232c885332f6bcf8f5e0041922d496a76b5335c1533edd193b50c8ffe1f04953305b6527d7c60ac1a46b8d35d9cf28535902c36
7
+ data.tar.gz: cce2dd847b6fa13f1c8bf2c2a84df522315ed1d8af2f0e524e0564309a24494b4336432a57c60e3b2570402354923f1de805c7d721131d30939e633624f8aa4e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.10 - 2026-05-16
4
+
5
+ - Stop assuming every non-embedding Ollama model supports tools; fallback chat discovery now advertises completion, streaming, and vision only.
6
+ - Add canonical Ollama capability normalization so reported `tools`/function-calling metadata is preserved and streaming is inferred for chat/completion models.
7
+ - Include reported capability metadata from `/api/show` model detail responses.
8
+
9
+ ## 0.2.9 - 2026-05-13
10
+
11
+ - Add `fetch_model_detail` — calls POST `/api/show` to retrieve the real context window from Ollama.
12
+ - Add `resolve_context_window` — tries live model detail cache first, falls back to static prefix map.
13
+ - Add `extract_context_window` — parses `num_ctx` from `model_info` hash or `parameters` string in the `/api/show` response.
14
+ - Add `CONTEXT_WINDOWS` static fallback map covering common Ollama model families.
15
+ - Add `rescue Faraday::ConnectionFailed` in `discover_offerings` with a concise warn log instead of an unhandled exception.
16
+ - Add `show_model_url` endpoint helper returning `/api/show`.
17
+
3
18
  ## 0.2.8 - 2026-05-12
4
19
 
5
20
  - Include `Legion::Logging::Helper` directly in Ollama provider, actor, and fleet runner runtime surfaces.
@@ -87,6 +87,16 @@ module Legion
87
87
  raise
88
88
  end
89
89
 
90
+ def fetch_model_detail(model_name)
91
+ raw = show_model(model_name)
92
+ context_window = extract_context_window(raw)
93
+ { context_window: context_window, capabilities: extract_capabilities(raw) }.compact
94
+ rescue StandardError => e
95
+ handle_exception(e, level: :warn, handled: true, operation: 'ollama.fetch_model_detail',
96
+ model: model_name)
97
+ nil
98
+ end
99
+
90
100
  def pull_model(model, stream: false)
91
101
  log.debug { "ollama provider pulling model=#{model} stream=#{stream}" }
92
102
  log.info { "pulling model #{model} stream=#{stream}" }
@@ -100,21 +110,49 @@ module Legion
100
110
  log.debug do
101
111
  "ollama provider discovering offerings live=#{live} cached_model_count=#{Array(@cached_models).size}"
102
112
  end
103
- models = if live
104
- @cached_models = list_models
105
- else
106
- Array(@cached_models)
107
- end
108
- models.map { |model_info| offering_from_model(model_info) }.tap do |offerings|
113
+ resolve_models(live).map { |model_info| offering_from_model(model_info) }.tap do |offerings|
109
114
  log.debug { "ollama provider built offering_count=#{offerings.size} live=#{live}" }
110
115
  end
116
+ rescue Faraday::ConnectionFailed => e
117
+ log.warn("[ollama] instance=#{provider_instance_id} unreachable: #{e.message}")
118
+ []
111
119
  rescue StandardError => e
112
- handle_exception(e, level: :warn, handled: true, operation: 'ollama.discover_offerings')
120
+ handle_exception(e, level: :warn, handled: true, operation: 'ollama.discover_offerings',
121
+ backtrace_limit: 3)
113
122
  []
114
123
  end
115
124
 
125
+ CONTEXT_WINDOWS = {
126
+ 'qwen3' => 128_000,
127
+ 'qwen2.5' => 128_000,
128
+ 'llama3' => 128_000,
129
+ 'llama3.1' => 128_000,
130
+ 'llama3.2' => 128_000,
131
+ 'llama3.3' => 128_000,
132
+ 'gemma2' => 8_192,
133
+ 'gemma3' => 128_000,
134
+ 'mistral' => 128_000,
135
+ 'deepseek' => 128_000,
136
+ 'phi3' => 128_000,
137
+ 'phi4' => 16_384,
138
+ 'command-r' => 128_000,
139
+ 'codellama' => 16_384,
140
+ 'nomic-embed' => 8_192,
141
+ 'mxbai-embed' => 512,
142
+ 'snowflake' => 512,
143
+ 'bge' => 512
144
+ }.freeze
145
+
116
146
  private
117
147
 
148
+ def resolve_models(live)
149
+ if live
150
+ @cached_models = list_models
151
+ else
152
+ Array(@cached_models)
153
+ end
154
+ end
155
+
118
156
  def offering_from_model(model_info)
119
157
  Legion::Extensions::Llm::Routing::ModelOffering.new(
120
158
  provider_family: :ollama,
@@ -146,7 +184,46 @@ module Legion
146
184
  end
147
185
 
148
186
  def offering_limits(model_info)
149
- { context_window: model_info.context_length }.compact
187
+ ctx = model_info.context_length || resolve_context_window(model_info.id)
188
+ ctx ? { context_window: ctx } : {}
189
+ end
190
+
191
+ def resolve_context_window(model_id)
192
+ detail = model_detail(model_id)
193
+ return detail[:context_window] if detail.is_a?(Hash) && detail[:context_window]
194
+
195
+ infer_context_window(model_id)
196
+ end
197
+
198
+ def infer_context_window(model_id)
199
+ name = model_id.to_s.split(':').first
200
+ CONTEXT_WINDOWS.find { |prefix, _| name.start_with?(prefix) }&.last
201
+ end
202
+
203
+ def extract_context_window(raw)
204
+ return nil unless raw.is_a?(Hash)
205
+
206
+ from_model_info(raw) || from_parameters_string(raw)
207
+ end
208
+
209
+ def from_model_info(raw)
210
+ model_info = raw['model_info'] || raw[:model_info]
211
+ return unless model_info.is_a?(Hash)
212
+
213
+ num_ctx_from_hash(model_info)&.to_i
214
+ end
215
+
216
+ def num_ctx_from_hash(model_info)
217
+ model_info['num_ctx'] || model_info[:num_ctx] ||
218
+ model_info.find { |k, _| k.to_s.end_with?('.context_length') }&.last
219
+ end
220
+
221
+ def from_parameters_string(raw)
222
+ params = raw['parameters'] || raw[:parameters]
223
+ return unless params.is_a?(String)
224
+
225
+ match = params.match(/num_ctx\s+(\d+)/)
226
+ match[1].to_i if match
150
227
  end
151
228
 
152
229
  def offering_metadata(model_info)
@@ -295,15 +372,35 @@ module Legion
295
372
  end
296
373
 
297
374
  def infer_capabilities(name, family, api_caps)
298
- return api_caps.map(&:to_sym) unless api_caps.empty?
375
+ normalized = normalize_ollama_capabilities(api_caps)
376
+ return normalized unless normalized.empty?
299
377
 
300
378
  if embedding_model?(name, family)
301
379
  [:embedding]
302
380
  else
303
- %i[completion streaming tools vision]
381
+ %i[completion streaming vision]
304
382
  end
305
383
  end
306
384
 
385
+ def normalize_ollama_capabilities(capabilities)
386
+ Array(capabilities).compact.each_with_object([]) do |capability, result|
387
+ capability_sym = capability.to_s.downcase.strip.to_sym
388
+ next if capability_sym.to_s.empty?
389
+
390
+ result << capability_sym
391
+ result << :tools if %i[function_calling functions tool tool_use].include?(capability_sym)
392
+ result << :streaming if %i[chat completion].include?(capability_sym)
393
+ end.uniq
394
+ end
395
+
396
+ def extract_capabilities(raw)
397
+ return nil unless raw.is_a?(Hash)
398
+
399
+ caps = raw['capabilities'] || raw[:capabilities]
400
+ normalized = normalize_ollama_capabilities(caps)
401
+ normalized unless normalized.empty?
402
+ end
403
+
307
404
  def embedding_model?(name, family)
308
405
  name.to_s.match?(/embed|embedding/i) || family.to_s.match?(/bert|nomic/i)
309
406
  end
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Llm
6
6
  module Ollama
7
- VERSION = '0.2.8'
7
+ VERSION = '0.2.10'
8
8
  end
9
9
  end
10
10
  end
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.2.8
4
+ version: 0.2.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - LegionIO