lex-llm-bedrock 0.3.8 → 0.3.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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0d6ffe6c93fec2590c74ed5a01a944c81694fb98316bf35bde08db6efecfed9
|
|
4
|
+
data.tar.gz: 3e5174849ecf00a36f79e8926237f430ce1b1e8a8572c4fede2463e5cc0a3bda
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 273bc8934934e7eb40e9365a57de5fb33c12114c84b435b353ffb3e0e83329ced120f94016ddc59bd8cfc484c3a35094814f41beb8b0361ece513417505954d5
|
|
7
|
+
data.tar.gz: 2d36dcff70b35577a0d5bbf6846ed6181851e6ac32d8cd65f67367429f32ec88869a084ccc4e3fdde200ab50ae3ca6c21509c84fa7a4af5ae360eaf75b85a2c5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.10 - 2026-05-21
|
|
4
|
+
|
|
5
|
+
- Add `default_transport`/`default_tier` class declarations, remove `configured_transport`/`configured_tier`
|
|
6
|
+
- Add `model_allowed?` filtering in `discover_offerings` (handles ModelOffering objects)
|
|
7
|
+
- Move `DEFAULT_REGION` to settings[:region]
|
|
8
|
+
- Default tier corrected from :frontier to :cloud
|
|
9
|
+
- Identity headers included via base provider
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## 0.3.9 - 2026-05-18
|
|
13
|
+
|
|
14
|
+
- Fix streaming tool call parsing: `stream_converse` now handles content_block_start/delta/stop events for tool_use blocks, capturing tool ids, names, and accumulated input JSON. Previously only text deltas were captured and tool calls were silently dropped.
|
|
15
|
+
|
|
16
|
+
|
|
3
17
|
## 0.3.8 - 2026-05-13
|
|
4
18
|
|
|
5
19
|
- Auto-prefix `us.` on `inference_profile_id` for Anthropic, Meta, Mistral, Cohere, and AI21 models at API call time.
|
|
@@ -14,8 +14,6 @@ module Legion
|
|
|
14
14
|
class Provider < Legion::Extensions::Llm::Provider # rubocop:disable Metrics/ClassLength
|
|
15
15
|
include Legion::Logging::Helper
|
|
16
16
|
|
|
17
|
-
DEFAULT_REGION = 'us-east-1'
|
|
18
|
-
|
|
19
17
|
STATIC_MODELS = [
|
|
20
18
|
{ model: 'anthropic.claude-3-haiku-20240307-v1:0', alias: 'claude-3-haiku' },
|
|
21
19
|
{ model: 'amazon.titan-text-express-v1', alias: 'titan-text-express' },
|
|
@@ -50,6 +48,8 @@ module Legion
|
|
|
50
48
|
|
|
51
49
|
class << self
|
|
52
50
|
def slug = 'bedrock'
|
|
51
|
+
def default_transport = :aws_sdk
|
|
52
|
+
def default_tier = :cloud
|
|
53
53
|
|
|
54
54
|
def configuration_options
|
|
55
55
|
%i[
|
|
@@ -113,7 +113,7 @@ module Legion
|
|
|
113
113
|
def count_tokens_url = 'CountTokens'
|
|
114
114
|
|
|
115
115
|
def region
|
|
116
|
-
config.bedrock_region ||
|
|
116
|
+
config.bedrock_region || settings[:region] || 'us-east-1'
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
def discover_offerings(live: false, **filters)
|
|
@@ -126,8 +126,12 @@ module Legion
|
|
|
126
126
|
|
|
127
127
|
log.info { "bedrock.provider.discover_offerings: listing foundation models (region=#{region})" }
|
|
128
128
|
response = bedrock_client.list_foundation_models(**filters)
|
|
129
|
-
@cached_offerings = Array(value(response, :model_summaries)).
|
|
130
|
-
offering_from_summary(summary)
|
|
129
|
+
@cached_offerings = Array(value(response, :model_summaries)).filter_map do |summary|
|
|
130
|
+
offering = offering_from_summary(summary)
|
|
131
|
+
model_id = offering.respond_to?(:model) ? offering.model : (offering[:model] || offering[:id])
|
|
132
|
+
next unless model_allowed?(model_id.to_s)
|
|
133
|
+
|
|
134
|
+
offering
|
|
131
135
|
end
|
|
132
136
|
log.info { "bedrock.provider.discover_offerings: found #{@cached_offerings.size} models" }
|
|
133
137
|
@cached_offerings
|
|
@@ -323,8 +327,8 @@ module Legion
|
|
|
323
327
|
Legion::Extensions::Llm::Routing::ModelOffering.new(
|
|
324
328
|
provider_family: :bedrock,
|
|
325
329
|
instance_id: instance_id,
|
|
326
|
-
transport:
|
|
327
|
-
tier:
|
|
330
|
+
transport: offering_transport,
|
|
331
|
+
tier: offering_tier,
|
|
328
332
|
model: model,
|
|
329
333
|
usage_type: usage_type,
|
|
330
334
|
capabilities: capabilities || default_capabilities(model),
|
|
@@ -346,14 +350,6 @@ module Legion
|
|
|
346
350
|
ctx ? { context_window: ctx } : nil
|
|
347
351
|
end
|
|
348
352
|
|
|
349
|
-
def configured_transport(default)
|
|
350
|
-
config.respond_to?(:transport) ? config.transport : default
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
def configured_tier(default)
|
|
354
|
-
config.respond_to?(:tier) ? config.tier : default
|
|
355
|
-
end
|
|
356
|
-
|
|
357
353
|
def converse_request(messages, model:, temperature:, max_tokens:, tools:, tool_prefs:)
|
|
358
354
|
{
|
|
359
355
|
model_id: self.class.inference_profile_id(model_id(model)),
|
|
@@ -474,30 +470,99 @@ module Legion
|
|
|
474
470
|
end
|
|
475
471
|
|
|
476
472
|
def stream_converse(request, fallback_model)
|
|
477
|
-
|
|
478
|
-
final_usage = nil
|
|
473
|
+
state = { accumulated: +'', final_usage: nil, stop_reason: nil, tool_use_blocks: [], current_tool_use: nil }
|
|
479
474
|
|
|
480
475
|
runtime_client.converse_stream(**request) do |stream|
|
|
481
|
-
stream
|
|
482
|
-
|
|
483
|
-
|
|
476
|
+
wire_stream_handlers(stream, state, fallback_model) { |chunk| yield chunk if block_given? }
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
Legion::Extensions::Llm::Message.new(
|
|
480
|
+
role: :assistant,
|
|
481
|
+
content: state[:accumulated],
|
|
482
|
+
model_id: fallback_model,
|
|
483
|
+
tool_calls: build_stream_tool_calls(state[:tool_use_blocks]),
|
|
484
|
+
input_tokens: value(state[:final_usage], :input_tokens),
|
|
485
|
+
output_tokens: value(state[:final_usage], :output_tokens),
|
|
486
|
+
stop_reason: state[:stop_reason]
|
|
487
|
+
)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
def wire_stream_handlers(stream, state, fallback_model, &)
|
|
491
|
+
wire_block_start(stream, state)
|
|
492
|
+
wire_block_delta(stream, state, fallback_model, &)
|
|
493
|
+
wire_block_stop(stream, state)
|
|
494
|
+
wire_message_stop(stream, state)
|
|
495
|
+
stream.on_metadata_event { |event| state[:final_usage] = value(event, :usage) }
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def wire_block_start(stream, state)
|
|
499
|
+
return unless stream.respond_to?(:on_content_block_start_event)
|
|
500
|
+
|
|
501
|
+
stream.on_content_block_start_event do |event|
|
|
502
|
+
start = value(event, :start)
|
|
503
|
+
tool_start = value(start, :tool_use) if start
|
|
504
|
+
next unless tool_start
|
|
505
|
+
|
|
506
|
+
state[:current_tool_use] = {
|
|
507
|
+
tool_use_id: value(tool_start, :tool_use_id),
|
|
508
|
+
name: value(tool_start, :name),
|
|
509
|
+
input_json: +''
|
|
510
|
+
}
|
|
511
|
+
end
|
|
512
|
+
end
|
|
484
513
|
|
|
485
|
-
|
|
514
|
+
def wire_block_delta(stream, state, fallback_model)
|
|
515
|
+
stream.on_content_block_delta_event do |event|
|
|
516
|
+
delta = value(event, :delta)
|
|
517
|
+
text = value(delta, :text)
|
|
518
|
+
if text
|
|
519
|
+
state[:accumulated] << text
|
|
486
520
|
if block_given?
|
|
487
521
|
yield Legion::Extensions::Llm::Chunk.new(role: :assistant, content: text,
|
|
488
522
|
model_id: fallback_model)
|
|
489
523
|
end
|
|
490
524
|
end
|
|
491
|
-
|
|
525
|
+
|
|
526
|
+
tool_input = value(delta, :tool_use)
|
|
527
|
+
next unless tool_input && state[:current_tool_use]
|
|
528
|
+
|
|
529
|
+
input_chunk = value(tool_input, :input)
|
|
530
|
+
state[:current_tool_use][:input_json] << input_chunk.to_s if input_chunk
|
|
492
531
|
end
|
|
532
|
+
end
|
|
493
533
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
534
|
+
def wire_block_stop(stream, state)
|
|
535
|
+
return unless stream.respond_to?(:on_content_block_stop_event)
|
|
536
|
+
|
|
537
|
+
stream.on_content_block_stop_event do |_event|
|
|
538
|
+
next unless state[:current_tool_use]
|
|
539
|
+
|
|
540
|
+
state[:tool_use_blocks] << state[:current_tool_use]
|
|
541
|
+
state[:current_tool_use] = nil
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def wire_message_stop(stream, state)
|
|
546
|
+
return unless stream.respond_to?(:on_message_stop_event)
|
|
547
|
+
|
|
548
|
+
stream.on_message_stop_event do |event|
|
|
549
|
+
state[:stop_reason] = value(event, :stop_reason)
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
def build_stream_tool_calls(tool_use_blocks)
|
|
554
|
+
return nil if tool_use_blocks.empty?
|
|
555
|
+
|
|
556
|
+
tool_use_blocks.to_h do |block|
|
|
557
|
+
input = begin
|
|
558
|
+
Legion::JSON.load(block[:input_json])
|
|
559
|
+
rescue StandardError
|
|
560
|
+
{}
|
|
561
|
+
end
|
|
562
|
+
name = block[:name]
|
|
563
|
+
id = block[:tool_use_id] || name
|
|
564
|
+
[id, Legion::Extensions::Llm::ToolCall.new(id: id, name: name, arguments: input)]
|
|
565
|
+
end
|
|
501
566
|
end
|
|
502
567
|
|
|
503
568
|
def parse_embedding_response(response, model:)
|