lex-llm-openai 0.3.7 → 0.3.9
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/.rubocop.yml +2 -0
- data/CHANGELOG.md +14 -0
- data/lib/legion/extensions/llm/openai/actors/fleet_worker.rb +23 -8
- data/lib/legion/extensions/llm/openai/provider.rb +28 -12
- data/lib/legion/extensions/llm/openai/runners/fleet_worker.rb +16 -0
- data/lib/legion/extensions/llm/openai/version.rb +1 -1
- data/lib/legion/extensions/llm/openai.rb +11 -3
- 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: 808223596350fde35cbbf0145a411842ce1c0a3009d431edd354ce500732666c
|
|
4
|
+
data.tar.gz: 9ed2580c07f4d4b1c35f9b90e8108b4ddbd9f74fa032998447b3639dda67e4db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a07fffb4a8a5652e3b14303102bc2811915efc374b32369f50e1d39a6397d44a8a2b7822aebedd300af37cecb1d447cbf3b517fdf8502138077de149c9e9e9ea
|
|
7
|
+
data.tar.gz: 51f75db914319c8c086d8ca63a0127b6ed79d21ee92dd1a3c25c45bc9082ba0b1fde55792f8e6040e20c247baad09147634b079d953606e3a8031063422ad7f2
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.9 - 2026-05-13
|
|
4
|
+
|
|
5
|
+
- Change `default_model` from `gpt-4o` to `gpt-5.5` in provider default settings and instance discovery fallback.
|
|
6
|
+
- Inject `default_model` into all discovered provider instances so every instance has an explicit model default.
|
|
7
|
+
- Add `context_window` to all `CAPABILITY_MAP` entries (gpt-4o=128K, gpt-4.1/gpt-5=1M, o3/o4/o1=200K, text-embedding=8K).
|
|
8
|
+
- Override `fetch_model_detail` to return `context_window` from the capability map instead of issuing a live API call.
|
|
9
|
+
- Use `model_detail` in `build_model_infos` to populate `context_length` from the cached capability map entry.
|
|
10
|
+
|
|
11
|
+
## 0.3.8 - 2026-05-13
|
|
12
|
+
|
|
13
|
+
- Route OpenAI fleet runner and actor diagnostics through `Legion::Logging::Helper` with debug-level request and enablement context.
|
|
14
|
+
- Report optional actor subscription load failures through `handle_exception` instead of raw warning output.
|
|
15
|
+
- Move routine OpenAI model discovery telemetry to debug-level logging while keeping failure handling structured.
|
|
16
|
+
|
|
3
17
|
## 0.3.7 - 2026-05-08
|
|
4
18
|
|
|
5
19
|
- Accept keyword arguments in `list_models` to match the base provider contract called by `discover_offerings`.
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
require 'legion/extensions/llm/openai'
|
|
4
|
+
require 'legion/extensions/llm/fleet/provider_responder'
|
|
5
|
+
|
|
6
|
+
unless defined?(Legion::Extensions::Actors::Subscription)
|
|
7
|
+
begin
|
|
8
|
+
require 'legion/extensions/actors/subscription'
|
|
9
|
+
rescue LoadError => e
|
|
10
|
+
Legion::Extensions::Llm::Openai.handle_exception(
|
|
11
|
+
e,
|
|
12
|
+
level: :warn,
|
|
13
|
+
handled: true,
|
|
14
|
+
operation: 'openai.fleet_worker.load_subscription'
|
|
15
|
+
)
|
|
16
|
+
end
|
|
7
17
|
end
|
|
8
18
|
|
|
9
19
|
unless defined?(Legion::Extensions::Actors::Subscription)
|
|
10
20
|
raise LoadError, 'LegionIO actor runtime is required for OpenAI fleet worker'
|
|
11
21
|
end
|
|
12
22
|
|
|
13
|
-
require 'legion/extensions/llm/openai'
|
|
14
|
-
require 'legion/extensions/llm/fleet/provider_responder'
|
|
15
|
-
|
|
16
23
|
module Legion
|
|
17
24
|
module Extensions
|
|
18
25
|
module Llm
|
|
@@ -20,6 +27,8 @@ module Legion
|
|
|
20
27
|
module Actor
|
|
21
28
|
# Subscription actor for OpenAI fleet request consumption.
|
|
22
29
|
class FleetWorker < Legion::Extensions::Actors::Subscription
|
|
30
|
+
include Legion::Logging::Helper
|
|
31
|
+
|
|
23
32
|
def runner_class
|
|
24
33
|
'Legion::Extensions::Llm::Openai::Runners::FleetWorker'
|
|
25
34
|
end
|
|
@@ -33,7 +42,13 @@ module Legion
|
|
|
33
42
|
end
|
|
34
43
|
|
|
35
44
|
def enabled?
|
|
36
|
-
|
|
45
|
+
instances = Openai.discover_instances
|
|
46
|
+
enabled = Legion::Extensions::Llm::Fleet::ProviderResponder.enabled_for?(instances)
|
|
47
|
+
log.debug { "OpenAI fleet worker enablement: enabled=#{enabled}, instance_count=#{instances.size}" }
|
|
48
|
+
enabled
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
handle_exception(e, level: :warn, handled: true, operation: 'openai.fleet_worker.enabled')
|
|
51
|
+
false
|
|
37
52
|
end
|
|
38
53
|
end
|
|
39
54
|
end
|
|
@@ -19,42 +19,50 @@ module Legion
|
|
|
19
19
|
'gpt-4o' => {
|
|
20
20
|
capabilities: %i[completion streaming function_calling vision structured_output],
|
|
21
21
|
modalities_input: %w[text image audio],
|
|
22
|
-
modalities_output: %w[text]
|
|
22
|
+
modalities_output: %w[text],
|
|
23
|
+
context_window: 128_000
|
|
23
24
|
},
|
|
24
25
|
'gpt-4.1' => {
|
|
25
26
|
capabilities: %i[completion streaming function_calling vision structured_output],
|
|
26
27
|
modalities_input: %w[text image],
|
|
27
|
-
modalities_output: %w[text]
|
|
28
|
+
modalities_output: %w[text],
|
|
29
|
+
context_window: 1_047_576
|
|
28
30
|
},
|
|
29
31
|
'gpt-4' => {
|
|
30
32
|
capabilities: %i[completion streaming function_calling vision],
|
|
31
33
|
modalities_input: %w[text image],
|
|
32
|
-
modalities_output: %w[text]
|
|
34
|
+
modalities_output: %w[text],
|
|
35
|
+
context_window: 128_000
|
|
33
36
|
},
|
|
34
37
|
'gpt-5' => {
|
|
35
38
|
capabilities: %i[completion streaming function_calling vision structured_output reasoning],
|
|
36
39
|
modalities_input: %w[text image],
|
|
37
|
-
modalities_output: %w[text]
|
|
40
|
+
modalities_output: %w[text],
|
|
41
|
+
context_window: 1_047_576
|
|
38
42
|
},
|
|
39
43
|
'o4' => {
|
|
40
44
|
capabilities: %i[completion streaming function_calling vision reasoning],
|
|
41
45
|
modalities_input: %w[text image],
|
|
42
|
-
modalities_output: %w[text]
|
|
46
|
+
modalities_output: %w[text],
|
|
47
|
+
context_window: 200_000
|
|
43
48
|
},
|
|
44
49
|
'o3' => {
|
|
45
50
|
capabilities: %i[completion streaming function_calling vision reasoning],
|
|
46
51
|
modalities_input: %w[text image],
|
|
47
|
-
modalities_output: %w[text]
|
|
52
|
+
modalities_output: %w[text],
|
|
53
|
+
context_window: 200_000
|
|
48
54
|
},
|
|
49
55
|
'o1' => {
|
|
50
56
|
capabilities: %i[completion streaming function_calling vision reasoning],
|
|
51
57
|
modalities_input: %w[text image],
|
|
52
|
-
modalities_output: %w[text]
|
|
58
|
+
modalities_output: %w[text],
|
|
59
|
+
context_window: 200_000
|
|
53
60
|
},
|
|
54
61
|
'text-embedding-' => {
|
|
55
62
|
capabilities: %i[embedding],
|
|
56
63
|
modalities_input: %w[text],
|
|
57
|
-
modalities_output: %w[embeddings]
|
|
64
|
+
modalities_output: %w[embeddings],
|
|
65
|
+
context_window: 8_191
|
|
58
66
|
},
|
|
59
67
|
'omni-moderation' => {
|
|
60
68
|
capabilities: %i[moderation],
|
|
@@ -172,7 +180,7 @@ module Legion
|
|
|
172
180
|
def images_url(with: nil, mask: nil) = super
|
|
173
181
|
|
|
174
182
|
def retrieve_model(model)
|
|
175
|
-
log.
|
|
183
|
+
log.debug { "Retrieving OpenAI model: #{model}" }
|
|
176
184
|
connection.get("#{models_url}/#{model}").body
|
|
177
185
|
rescue StandardError => e
|
|
178
186
|
handle_exception(e, level: :error, handled: true,
|
|
@@ -181,10 +189,10 @@ module Legion
|
|
|
181
189
|
end
|
|
182
190
|
|
|
183
191
|
def list_models(**)
|
|
184
|
-
log.
|
|
192
|
+
log.debug('Listing OpenAI models')
|
|
185
193
|
raw = connection.get(models_url)
|
|
186
194
|
models = build_model_infos(raw.body)
|
|
187
|
-
log.
|
|
195
|
+
log.debug { "Discovered #{models.size} OpenAI models; publishing registry availability" }
|
|
188
196
|
self.class.registry_publisher.publish_models_async(models, readiness: readiness(live: false))
|
|
189
197
|
models
|
|
190
198
|
rescue StandardError => e
|
|
@@ -199,12 +207,15 @@ module Legion
|
|
|
199
207
|
body.fetch('data', []).map do |raw_model|
|
|
200
208
|
id = raw_model.fetch('id')
|
|
201
209
|
cap_entry = capability_entry_for(id)
|
|
210
|
+
detail = model_detail(id)
|
|
211
|
+
ctx = detail&.dig(:context_window) || cap_entry[:context_window]
|
|
202
212
|
|
|
203
213
|
Legion::Extensions::Llm::Model::Info.new(
|
|
204
214
|
id: id,
|
|
205
215
|
name: id,
|
|
206
216
|
provider: :openai,
|
|
207
217
|
capabilities: cap_entry[:capabilities],
|
|
218
|
+
context_length: ctx,
|
|
208
219
|
modalities_input: cap_entry[:modalities_input],
|
|
209
220
|
modalities_output: cap_entry[:modalities_output],
|
|
210
221
|
metadata: {
|
|
@@ -220,7 +231,6 @@ module Legion
|
|
|
220
231
|
return entry if model_id.start_with?(prefix)
|
|
221
232
|
end
|
|
222
233
|
|
|
223
|
-
# Fallback for unknown models: assume chat-capable
|
|
224
234
|
{
|
|
225
235
|
capabilities: %i[completion streaming],
|
|
226
236
|
modalities_input: %w[text],
|
|
@@ -228,6 +238,12 @@ module Legion
|
|
|
228
238
|
}
|
|
229
239
|
end
|
|
230
240
|
|
|
241
|
+
def fetch_model_detail(model_name)
|
|
242
|
+
entry = capability_entry_for(model_name)
|
|
243
|
+
ctx = entry[:context_window]
|
|
244
|
+
ctx ? { context_window: ctx } : nil
|
|
245
|
+
end
|
|
246
|
+
|
|
231
247
|
def model_created_at(value)
|
|
232
248
|
value.is_a?(Numeric) ? Time.at(value).utc : value
|
|
233
249
|
end
|
|
@@ -10,9 +10,16 @@ module Legion
|
|
|
10
10
|
module Runners
|
|
11
11
|
# Runner entrypoint for OpenAI fleet request execution.
|
|
12
12
|
module FleetWorker
|
|
13
|
+
extend Legion::Logging::Helper
|
|
14
|
+
|
|
13
15
|
module_function
|
|
14
16
|
|
|
15
17
|
def handle_fleet_request(payload, delivery: nil, properties: nil)
|
|
18
|
+
log.debug do
|
|
19
|
+
"Handling OpenAI fleet request: request_id=#{payload_value(payload, :request_id) || 'unknown'}, " \
|
|
20
|
+
"provider_instance=#{payload_value(payload, :provider_instance) || 'default'}"
|
|
21
|
+
end
|
|
22
|
+
|
|
16
23
|
Legion::Extensions::Llm::Fleet::ProviderResponder.call(
|
|
17
24
|
payload: payload,
|
|
18
25
|
provider_family: Openai::PROVIDER_FAMILY,
|
|
@@ -21,6 +28,15 @@ module Legion
|
|
|
21
28
|
delivery: delivery,
|
|
22
29
|
properties: properties
|
|
23
30
|
)
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
handle_exception(e, level: :error, handled: true, operation: 'openai.fleet_worker.handle_request')
|
|
33
|
+
raise
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def payload_value(payload, key)
|
|
37
|
+
return unless payload.respond_to?(:[])
|
|
38
|
+
|
|
39
|
+
payload[key] || payload[key.to_s]
|
|
24
40
|
end
|
|
25
41
|
end
|
|
26
42
|
end
|
|
@@ -20,7 +20,7 @@ module Legion
|
|
|
20
20
|
family: PROVIDER_FAMILY,
|
|
21
21
|
instance: {
|
|
22
22
|
endpoint: 'https://api.openai.com',
|
|
23
|
-
default_model: 'gpt-
|
|
23
|
+
default_model: 'gpt-5.5',
|
|
24
24
|
tier: :frontier,
|
|
25
25
|
transport: :http,
|
|
26
26
|
credentials: {
|
|
@@ -53,6 +53,7 @@ module Legion
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def self.discover_instances # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
56
|
+
log.debug('Discovering OpenAI provider instances')
|
|
56
57
|
candidates = {}
|
|
57
58
|
|
|
58
59
|
# 1. OPENAI_API_KEY environment variable
|
|
@@ -100,8 +101,15 @@ module Legion
|
|
|
100
101
|
candidates[name.to_sym] = normalized.merge(tier: :frontier)
|
|
101
102
|
end
|
|
102
103
|
|
|
103
|
-
# 8. Dedup
|
|
104
|
-
CredentialSources.dedup_credentials(candidates).transform_values
|
|
104
|
+
# 8. Dedup + inject default_model
|
|
105
|
+
discovered = CredentialSources.dedup_credentials(candidates).transform_values do |config|
|
|
106
|
+
sanitized = sanitize_instance_config(config)
|
|
107
|
+
sanitized[:default_model] ||= 'gpt-5.5'
|
|
108
|
+
sanitized
|
|
109
|
+
end
|
|
110
|
+
instance_names = discovered.keys.sort_by(&:to_s).join(', ')
|
|
111
|
+
log.debug { "Discovered #{discovered.size} OpenAI provider instance candidate(s): #{instance_names}" }
|
|
112
|
+
discovered
|
|
105
113
|
end
|
|
106
114
|
|
|
107
115
|
def self.settings_instances(config)
|