lex-llm-bedrock 0.4.0 → 0.4.3
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 +14 -0
- data/Gemfile +0 -9
- data/lib/legion/extensions/llm/bedrock/actors/discovery_refresh.rb +7 -0
- data/lib/legion/extensions/llm/bedrock/provider.rb +140 -18
- data/lib/legion/extensions/llm/bedrock/translator.rb +21 -2
- data/lib/legion/extensions/llm/bedrock/version.rb +1 -1
- data/lib/legion/extensions/llm/bedrock.rb +3 -6
- 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: 05badbea355fec879dbd270070928472682c35d8709e3e6336e0080ca00aeb36
|
|
4
|
+
data.tar.gz: ec34813a7de565ad347c95777715054d27bd53ce71b04d8ddfd57de149852c9e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '073218f79b092a425703aa62f45b8d07d69afcf01d1249b66435fa4dce7211f74cbfab184e7df61f506f92c0ca4322d1d8448e6317ed5d52870d699ff42757e9'
|
|
7
|
+
data.tar.gz: 415524d66dcb863b18036935b15b7965996adb249d78779845b6f53679e22745b9316a438de386e490051cf7c46af6bc3264cf3db24d2b7517a7c5c4d49c9375
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.3 - 2026-06-16
|
|
4
|
+
|
|
5
|
+
- Dependency updates and code quality improvements.
|
|
6
|
+
|
|
7
|
+
## 0.4.2 - 2026-06-15
|
|
8
|
+
|
|
9
|
+
- **CapabilityPolicy integration** — AWS model summaries used as `:model_metadata`; Converse tool use from `:provider_envelope`. Settings overrides at provider/instance/model level supported.
|
|
10
|
+
|
|
11
|
+
## 0.4.1 - 2026-06-13
|
|
12
|
+
|
|
13
|
+
- **Gemfile cleanup** — Remove local path overrides; dependencies resolve from gemspec via rubygems.
|
|
14
|
+
- **RuboCop fixes** — Auto-corrected 6 offenses (style/layout).
|
|
15
|
+
- 199 examples, 0 failures; 17 files, 0 rubocop offenses.
|
|
16
|
+
|
|
3
17
|
## 0.4.0 - 2026-06-10
|
|
4
18
|
|
|
5
19
|
### Added
|
data/Gemfile
CHANGED
|
@@ -4,15 +4,6 @@ source 'https://rubygems.org'
|
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
|
-
group :test do
|
|
8
|
-
transport_path = ENV.fetch('LEGION_TRANSPORT_PATH', File.expand_path('../../legion-transport', __dir__))
|
|
9
|
-
gem 'legion-transport', path: transport_path if File.directory?(transport_path)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# lex-llm (>= 0.5.0) comes from gemspec with canonical types + conformance kit.
|
|
13
|
-
# Override with a path/branch reference for local development only:
|
|
14
|
-
# gem 'lex-llm', path: ENV.fetch('LEX_LLM_PATH', '../lex-llm')
|
|
15
|
-
|
|
16
7
|
group :development do
|
|
17
8
|
gem 'bundler', '>= 2.0'
|
|
18
9
|
gem 'rake', '>= 13.0'
|
|
@@ -36,6 +36,13 @@ module Legion
|
|
|
36
36
|
return unless defined?(Legion::LLM::Discovery)
|
|
37
37
|
|
|
38
38
|
Legion::LLM::Discovery.refresh_discovered_models!(provider: :bedrock)
|
|
39
|
+
|
|
40
|
+
if defined?(Legion::LLM::Router) && Legion::LLM::Router.respond_to?(:populate_auto_rules)
|
|
41
|
+
Legion::LLM::Router.populate_auto_rules(Legion::LLM::Discovery.discovered_instances)
|
|
42
|
+
end
|
|
43
|
+
if defined?(Legion::LLM::Inventory) && Legion::LLM::Inventory.respond_to?(:invalidate_offerings_cache!)
|
|
44
|
+
Legion::LLM::Inventory.invalidate_offerings_cache!
|
|
45
|
+
end
|
|
39
46
|
rescue StandardError => e
|
|
40
47
|
handle_exception(e, level: :warn, handled: true, operation: 'bedrock.actor.discovery_refresh')
|
|
41
48
|
end
|
|
@@ -11,6 +11,8 @@ module Legion
|
|
|
11
11
|
module Extensions
|
|
12
12
|
module Llm
|
|
13
13
|
module Bedrock
|
|
14
|
+
class StaticCredentialsBlockedError < Legion::Extensions::Llm::ConfigurationError; end
|
|
15
|
+
|
|
14
16
|
# Amazon Bedrock provider implementation for the Legion::Extensions::Llm contract.
|
|
15
17
|
class Provider < Legion::Extensions::Llm::Provider # rubocop:disable Metrics/ClassLength
|
|
16
18
|
include Legion::Logging::Helper
|
|
@@ -18,6 +20,10 @@ module Legion
|
|
|
18
20
|
STATIC_MODELS = [
|
|
19
21
|
{ model: 'anthropic.claude-3-haiku-20240307-v1:0', alias: 'claude-3-haiku' },
|
|
20
22
|
{ model: 'anthropic.claude-sonnet-4-20250514-v1:0', alias: 'anthropic.claude-sonnet-4' },
|
|
23
|
+
{ model: 'anthropic.claude-sonnet-4-20250514-v1:0', alias: 'claude-sonnet-4-6' },
|
|
24
|
+
{ model: 'anthropic.claude-sonnet-4-20250514-v1:0', alias: 'claude-sonnet-4-5-20241022' },
|
|
25
|
+
{ model: 'anthropic.claude-opus-4-20250515-v1:0', alias: 'claude-opus-4-8' },
|
|
26
|
+
{ model: 'anthropic.claude-haiku-4-20250506-v1:0', alias: 'claude-haiku-4-5' },
|
|
21
27
|
{ model: 'amazon.titan-text-express-v1', alias: 'titan-text-express' },
|
|
22
28
|
{ model: 'amazon.titan-embed-text-v2:0', alias: 'titan-embed-text-v2', usage_type: :embedding },
|
|
23
29
|
{ model: 'meta.llama3-2-11b-instruct-v1:0', alias: 'llama-3.2-11b-instruct' },
|
|
@@ -117,6 +123,10 @@ module Legion
|
|
|
117
123
|
end
|
|
118
124
|
end
|
|
119
125
|
|
|
126
|
+
def translator
|
|
127
|
+
@translator ||= Translator.new(region: region)
|
|
128
|
+
end
|
|
129
|
+
|
|
120
130
|
def api_base
|
|
121
131
|
config.bedrock_endpoint || "https://bedrock-runtime.#{region}.amazonaws.com"
|
|
122
132
|
end
|
|
@@ -499,8 +509,15 @@ module Legion
|
|
|
499
509
|
state[:raw_events] << { event: event_type, data: raw_event } if dump_path
|
|
500
510
|
handle_invoke_model_stream_json(raw_event, state, mid) { |chunk| yield chunk if block_given? }
|
|
501
511
|
end
|
|
512
|
+
rescue Legion::JSON::ParseError => e
|
|
513
|
+
handle_exception(e, level: :warn, handled: true,
|
|
514
|
+
operation: 'bedrock.provider.invoke_model_stream.chunk_decode')
|
|
502
515
|
rescue StandardError => e
|
|
503
|
-
|
|
516
|
+
# Never swallow non-parse errors here — a silent rescue in this
|
|
517
|
+
# event handler previously hid streaming bugs as dead-air streams.
|
|
518
|
+
handle_exception(e, level: :error, handled: false,
|
|
519
|
+
operation: 'bedrock.provider.invoke_model_stream.chunk_event')
|
|
520
|
+
raise
|
|
504
521
|
end
|
|
505
522
|
|
|
506
523
|
stream.on_error_event do |event|
|
|
@@ -555,12 +572,14 @@ module Legion
|
|
|
555
572
|
Legion::Extensions::Llm::Message.new(**msg_attrs)
|
|
556
573
|
end
|
|
557
574
|
|
|
558
|
-
def build_invoke_model_body(messages:, temperature:, max_tokens:, tools:, tool_prefs:, thinking:, **
|
|
575
|
+
def build_invoke_model_body(messages:, temperature:, max_tokens:, tools:, tool_prefs:, thinking:, **rest)
|
|
576
|
+
system_content = extract_invoke_model_system(messages, system: rest[:system])
|
|
559
577
|
body = {
|
|
560
578
|
max_tokens: max_tokens || 4096,
|
|
561
579
|
messages: format_invoke_model_messages(messages),
|
|
562
580
|
anthropic_version: 'bedrock-2023-05-31'
|
|
563
581
|
}
|
|
582
|
+
body[:system] = system_content if system_content
|
|
564
583
|
body[:temperature] = temperature if temperature
|
|
565
584
|
if tools && !tools.empty?
|
|
566
585
|
tool_format = format_invoke_model_tools(tools, tool_prefs)
|
|
@@ -568,11 +587,25 @@ module Legion
|
|
|
568
587
|
body[:tool_choice] = tool_format[:tool_choice] if tool_format[:tool_choice]
|
|
569
588
|
end
|
|
570
589
|
body[:thinking] = invoke_model_thinking(thinking) if thinking
|
|
571
|
-
# NOTE: Don't include body[:stream] = true in the JSON body for invoke_model_with_response_stream.
|
|
572
|
-
# The endpoint itself implies streaming; Bedrock rejects the extra field.
|
|
573
590
|
body
|
|
574
591
|
end
|
|
575
592
|
|
|
593
|
+
def extract_invoke_model_system(messages, system: nil)
|
|
594
|
+
parts = []
|
|
595
|
+
parts << system.to_s unless system.to_s.empty?
|
|
596
|
+
messages.each do |msg|
|
|
597
|
+
role = msg.respond_to?(:role) ? msg.role.to_s : (msg[:role] || msg['role']).to_s
|
|
598
|
+
next unless role == 'system'
|
|
599
|
+
|
|
600
|
+
content = msg.respond_to?(:content) ? msg.content : (msg[:content] || msg['content'])
|
|
601
|
+
text = content.is_a?(Array) ? content.filter_map { |b| b[:text] || b['text'] }.join("\n") : content.to_s
|
|
602
|
+
parts << text unless text.empty?
|
|
603
|
+
end
|
|
604
|
+
return nil if parts.empty?
|
|
605
|
+
|
|
606
|
+
parts.map { |t| { type: 'text', text: t } }
|
|
607
|
+
end
|
|
608
|
+
|
|
576
609
|
# Strip provider-specific keys (e.g. effort from OpenAI) that Bedrock/Anthropic APIs don't accept.
|
|
577
610
|
def invoke_model_thinking(thinking)
|
|
578
611
|
return thinking unless thinking.is_a?(Hash)
|
|
@@ -581,7 +614,7 @@ module Legion
|
|
|
581
614
|
end
|
|
582
615
|
|
|
583
616
|
def format_invoke_model_messages(messages)
|
|
584
|
-
messages.filter_map do |msg|
|
|
617
|
+
formatted = messages.filter_map do |msg|
|
|
585
618
|
role = msg.respond_to?(:role) ? msg.role.to_s : (msg[:role] || msg['role']).to_s
|
|
586
619
|
next if role == 'system'
|
|
587
620
|
|
|
@@ -598,6 +631,19 @@ module Legion
|
|
|
598
631
|
|
|
599
632
|
{ role: role == 'tool' ? 'user' : role, content: content }
|
|
600
633
|
end
|
|
634
|
+
consolidate_adjacent_roles(formatted)
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
def consolidate_adjacent_roles(messages)
|
|
638
|
+
return messages if messages.size < 2
|
|
639
|
+
|
|
640
|
+
messages.each_with_object([]) do |msg, result|
|
|
641
|
+
if result.last && result.last[:role] == msg[:role]
|
|
642
|
+
result.last[:content] = Array(result.last[:content]) + Array(msg[:content])
|
|
643
|
+
else
|
|
644
|
+
result << msg
|
|
645
|
+
end
|
|
646
|
+
end
|
|
601
647
|
end
|
|
602
648
|
|
|
603
649
|
def format_invoke_model_content(msg)
|
|
@@ -664,11 +710,11 @@ module Legion
|
|
|
664
710
|
|
|
665
711
|
def format_invoke_model_tools(tools, tool_prefs)
|
|
666
712
|
tool_list = tools.values.map do |tool|
|
|
713
|
+
raw_schema = tool[:params_schema] || tool['params_schema'] || tool[:parameters] || tool['parameters']
|
|
667
714
|
{
|
|
668
715
|
name: tool[:name] || tool['name'],
|
|
669
716
|
description: tool[:description] || tool['description'] || '',
|
|
670
|
-
input_schema:
|
|
671
|
-
{ type: 'object', properties: {} }
|
|
717
|
+
input_schema: Legion::Extensions::Llm::Canonical::ToolDefinition.normalize_parameters(raw_schema)
|
|
672
718
|
}
|
|
673
719
|
end
|
|
674
720
|
|
|
@@ -802,7 +848,11 @@ module Legion
|
|
|
802
848
|
state[:stop_reason] = delta['stop_reason']
|
|
803
849
|
end
|
|
804
850
|
rescue StandardError => e
|
|
805
|
-
|
|
851
|
+
# Re-raise — a swallowed error here turns a streaming bug into a
|
|
852
|
+
# silent dead-air stream (message_start then nothing).
|
|
853
|
+
handle_exception(e, level: :error, handled: false,
|
|
854
|
+
operation: 'bedrock.provider.invoke_model_stream_json')
|
|
855
|
+
raise
|
|
806
856
|
end
|
|
807
857
|
|
|
808
858
|
def static_offerings(**filters)
|
|
@@ -816,12 +866,24 @@ module Legion
|
|
|
816
866
|
|
|
817
867
|
def offering_from_summary(summary)
|
|
818
868
|
model = value(summary, :model_id)
|
|
869
|
+
real = real_capabilities_from_summary(summary)
|
|
870
|
+
policy = Legion::Extensions::Llm::CapabilityPolicy.resolve(
|
|
871
|
+
real: real,
|
|
872
|
+
provider_catalog: {},
|
|
873
|
+
probe: {},
|
|
874
|
+
provider_envelope: provider_envelope_capabilities,
|
|
875
|
+
provider_config: provider_capability_config,
|
|
876
|
+
instance_config: instance_capability_config,
|
|
877
|
+
model_config: model_capability_config(model)
|
|
878
|
+
)
|
|
879
|
+
|
|
819
880
|
build_offering(
|
|
820
881
|
model: model,
|
|
821
882
|
alias_name: alias_for(model),
|
|
822
883
|
model_family: normalize_provider(value(summary, :provider_name)) || model_family_for(model),
|
|
823
884
|
usage_type: usage_type_from_modalities(value(summary, :output_modalities)),
|
|
824
|
-
capabilities:
|
|
885
|
+
capabilities: policy[:capabilities],
|
|
886
|
+
capability_sources: policy[:sources],
|
|
825
887
|
metadata: normalize_response(summary)
|
|
826
888
|
)
|
|
827
889
|
end
|
|
@@ -844,7 +906,7 @@ module Legion
|
|
|
844
906
|
end
|
|
845
907
|
|
|
846
908
|
def build_offering(model:, model_family:, usage_type:, instance_id: :default, alias_name: nil,
|
|
847
|
-
capabilities: nil, metadata: {})
|
|
909
|
+
capabilities: nil, capability_sources: nil, metadata: {})
|
|
848
910
|
limits = infer_limits(model)
|
|
849
911
|
Legion::Extensions::Llm::Routing::ModelOffering.new(
|
|
850
912
|
provider_family: :bedrock,
|
|
@@ -854,6 +916,7 @@ module Legion
|
|
|
854
916
|
model: model,
|
|
855
917
|
usage_type: usage_type,
|
|
856
918
|
capabilities: capabilities || default_capabilities(model),
|
|
919
|
+
capability_sources: capability_sources,
|
|
857
920
|
limits: limits,
|
|
858
921
|
metadata: metadata.merge(model_family: model_family, alias: alias_name).compact
|
|
859
922
|
)
|
|
@@ -903,13 +966,14 @@ module Legion
|
|
|
903
966
|
|
|
904
967
|
def format_messages(messages)
|
|
905
968
|
total = messages.size
|
|
906
|
-
messages.filter_map.with_index do |message, idx|
|
|
969
|
+
formatted = messages.filter_map.with_index do |message, idx|
|
|
907
970
|
blocks = build_content_blocks(message)
|
|
908
971
|
next if blocks.empty?
|
|
909
972
|
|
|
910
973
|
cache_blocks = should_cache_message?(idx, total) ? add_cache_control_to_blocks(blocks) : blocks
|
|
911
974
|
{ role: bedrock_role(message.role), content: cache_blocks }
|
|
912
975
|
end
|
|
976
|
+
consolidate_adjacent_roles(formatted)
|
|
913
977
|
end
|
|
914
978
|
|
|
915
979
|
def tool_result_blocks(message)
|
|
@@ -967,7 +1031,9 @@ module Legion
|
|
|
967
1031
|
text = content_text(message.content)
|
|
968
1032
|
blocks << { text: text } if text && !text.strip.empty?
|
|
969
1033
|
|
|
970
|
-
|
|
1034
|
+
# Array is canonical (name-keyed hashes dropped parallel same-name calls)
|
|
1035
|
+
calls = message.tool_calls.is_a?(Hash) ? message.tool_calls.values : Array(message.tool_calls)
|
|
1036
|
+
calls.each do |call|
|
|
971
1037
|
blocks << {
|
|
972
1038
|
tool_use: {
|
|
973
1039
|
tool_use_id: call.id,
|
|
@@ -1062,9 +1128,12 @@ module Legion
|
|
|
1062
1128
|
end
|
|
1063
1129
|
|
|
1064
1130
|
def tool_schema(tool)
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1131
|
+
raw = if tool.respond_to?(:params_schema) && tool.params_schema
|
|
1132
|
+
tool.params_schema
|
|
1133
|
+
elsif tool.respond_to?(:parameters)
|
|
1134
|
+
tool.parameters
|
|
1135
|
+
end
|
|
1136
|
+
Legion::Extensions::Llm::Canonical::ToolDefinition.normalize_parameters(raw)
|
|
1068
1137
|
end
|
|
1069
1138
|
|
|
1070
1139
|
def tool_choice(tool_prefs)
|
|
@@ -1273,8 +1342,8 @@ module Legion
|
|
|
1273
1342
|
# Bedrock streaming: text blocks use delta.text,
|
|
1274
1343
|
# reasoning/thinking blocks use delta.reasoning.text or delta.thinking.text
|
|
1275
1344
|
text = value(delta, :text) ||
|
|
1276
|
-
(value(delta, :reasoning)
|
|
1277
|
-
(value(delta, :thinking)
|
|
1345
|
+
value(value(delta, :reasoning), :text) ||
|
|
1346
|
+
value(value(delta, :thinking), :text)
|
|
1278
1347
|
if text
|
|
1279
1348
|
if state[:in_thinking]
|
|
1280
1349
|
state[:thinking] << text
|
|
@@ -1399,7 +1468,7 @@ module Legion
|
|
|
1399
1468
|
return nil unless config.bedrock_access_key_id
|
|
1400
1469
|
|
|
1401
1470
|
if static_credentials_blocked?
|
|
1402
|
-
raise
|
|
1471
|
+
raise StaticCredentialsBlockedError,
|
|
1403
1472
|
'Static AWS credentials are disabled (security.block_static_aws_credentials=true); use IAM roles'
|
|
1404
1473
|
end
|
|
1405
1474
|
log.warn('[bedrock] Using static AWS credentials — prefer IAM roles for production')
|
|
@@ -1467,6 +1536,59 @@ module Legion
|
|
|
1467
1536
|
caps
|
|
1468
1537
|
end
|
|
1469
1538
|
|
|
1539
|
+
def real_capabilities_from_summary(summary)
|
|
1540
|
+
caps = {}
|
|
1541
|
+
caps[:streaming] = true if value(summary, :response_streaming_supported)
|
|
1542
|
+
input_mods = Array(value(summary, :input_modalities)).map { |m| m.to_s.upcase }
|
|
1543
|
+
caps[:vision] = true if input_mods.include?('IMAGE')
|
|
1544
|
+
output_mods = Array(value(summary, :output_modalities)).map { |m| m.to_s.upcase }
|
|
1545
|
+
caps[:embeddings] = true if output_mods.include?('EMBEDDING')
|
|
1546
|
+
caps
|
|
1547
|
+
end
|
|
1548
|
+
|
|
1549
|
+
def provider_envelope_capabilities
|
|
1550
|
+
# Bedrock Converse API supports tool use across all active chat model families
|
|
1551
|
+
{ tools: true }
|
|
1552
|
+
end
|
|
1553
|
+
|
|
1554
|
+
def provider_capability_config
|
|
1555
|
+
return {} unless defined?(Legion::Extensions::Llm::CredentialSources)
|
|
1556
|
+
|
|
1557
|
+
conf = Legion::Extensions::Llm::CredentialSources.setting(:extensions, :llm, :bedrock)
|
|
1558
|
+
conf.is_a?(Hash) ? conf.to_h.except(:instances, 'instances') : {}
|
|
1559
|
+
rescue StandardError => e
|
|
1560
|
+
handle_exception(e, level: :debug, handled: true, operation: 'bedrock.provider_capability_config')
|
|
1561
|
+
{}
|
|
1562
|
+
end
|
|
1563
|
+
|
|
1564
|
+
def instance_capability_config
|
|
1565
|
+
cfg = config
|
|
1566
|
+
result = {}
|
|
1567
|
+
%i[capabilities enable_thinking enable_tools enable_streaming enable_vision enable_embeddings
|
|
1568
|
+
thinking_flag tools_flag streaming_flag vision_flag embedding_flag embeddings_flag
|
|
1569
|
+
tool_flag images_flag image_flag].each do |key|
|
|
1570
|
+
next unless cfg.respond_to?(key)
|
|
1571
|
+
|
|
1572
|
+
val = cfg.send(key)
|
|
1573
|
+
result[key] = val unless val.nil?
|
|
1574
|
+
rescue StandardError
|
|
1575
|
+
next
|
|
1576
|
+
end
|
|
1577
|
+
result
|
|
1578
|
+
end
|
|
1579
|
+
|
|
1580
|
+
def model_capability_config(model_id)
|
|
1581
|
+
models_conf = nil
|
|
1582
|
+
models_conf = config.models if config.respond_to?(:models)
|
|
1583
|
+
models_conf ||= config[:models] if config.respond_to?(:[])
|
|
1584
|
+
return {} unless models_conf.respond_to?(:to_h)
|
|
1585
|
+
|
|
1586
|
+
models_conf.to_h[model_id.to_s] || models_conf.to_h[model_id.to_sym] || {}
|
|
1587
|
+
rescue StandardError => e
|
|
1588
|
+
handle_exception(e, level: :debug, handled: true, operation: 'bedrock.model_capability_config')
|
|
1589
|
+
{}
|
|
1590
|
+
end
|
|
1591
|
+
|
|
1470
1592
|
def model_family_for(model)
|
|
1471
1593
|
normalize_provider(model.to_s.split('.').first)
|
|
1472
1594
|
end
|
|
@@ -205,7 +205,7 @@ module Legion
|
|
|
205
205
|
tool_spec: {
|
|
206
206
|
name: tool.name,
|
|
207
207
|
description: tool.description.to_s,
|
|
208
|
-
input_schema: { json: tool.parameters
|
|
208
|
+
input_schema: { json: tool.parameters }
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
end
|
|
@@ -234,6 +234,9 @@ module Legion
|
|
|
234
234
|
anthropic_version: 'bedrock-2023-05-31'
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
sys = render_invoke_system(canonical)
|
|
238
|
+
body[:system] = sys if sys
|
|
239
|
+
|
|
237
240
|
temp = canonical.params&.temperature
|
|
238
241
|
body[:temperature] = temp if temp
|
|
239
242
|
|
|
@@ -256,6 +259,22 @@ module Legion
|
|
|
256
259
|
{ type: 'enabled', budget_tokens: budget }
|
|
257
260
|
end
|
|
258
261
|
|
|
262
|
+
def render_invoke_system(canonical)
|
|
263
|
+
sys = canonical.system
|
|
264
|
+
return nil if sys.nil? || sys.to_s.strip.empty?
|
|
265
|
+
|
|
266
|
+
if sys.is_a?(Array)
|
|
267
|
+
sys.map do |block|
|
|
268
|
+
wire = { type: 'text', text: (block[:text] || block['text'] || block.to_s).to_s }
|
|
269
|
+
cc = block[:cache_control] || block['cache_control']
|
|
270
|
+
wire[:cache_control] = cc if cc
|
|
271
|
+
wire
|
|
272
|
+
end
|
|
273
|
+
else
|
|
274
|
+
[{ type: 'text', text: sys.to_s }]
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
259
278
|
def build_invoke_tools(canonical)
|
|
260
279
|
return nil unless canonical.tools && !canonical.tools.empty?
|
|
261
280
|
|
|
@@ -263,7 +282,7 @@ module Legion
|
|
|
263
282
|
{
|
|
264
283
|
name: tool.name,
|
|
265
284
|
description: (tool.description || '').to_s,
|
|
266
|
-
input_schema: tool.parameters
|
|
285
|
+
input_schema: tool.parameters
|
|
267
286
|
}
|
|
268
287
|
end
|
|
269
288
|
|
|
@@ -5,6 +5,7 @@ require 'legion/extensions/llm/bedrock/provider'
|
|
|
5
5
|
require 'legion/extensions/llm/bedrock/translator'
|
|
6
6
|
require 'legion/extensions/llm/bedrock/version'
|
|
7
7
|
require 'legion/logging/helper'
|
|
8
|
+
require_relative 'bedrock/actors/discovery_refresh'
|
|
8
9
|
|
|
9
10
|
module Legion
|
|
10
11
|
module Extensions
|
|
@@ -44,10 +45,7 @@ module Legion
|
|
|
44
45
|
fleet: {
|
|
45
46
|
enabled: false,
|
|
46
47
|
respond_to_requests: false,
|
|
47
|
-
capabilities: %i[chat stream_chat embed]
|
|
48
|
-
lanes: [],
|
|
49
|
-
concurrency: 4,
|
|
50
|
-
queue_suffix: nil
|
|
48
|
+
capabilities: %i[chat stream_chat embed tools]
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
)
|
|
@@ -223,8 +221,7 @@ module Legion
|
|
|
223
221
|
config.except(:api_key)
|
|
224
222
|
end
|
|
225
223
|
|
|
226
|
-
Legion::Extensions::Llm::Configuration.register_provider_options(Provider.configuration_options)
|
|
227
|
-
Legion::Extensions::Llm::Configuration.respond_to?(:register_provider_options)
|
|
224
|
+
Legion::Extensions::Llm::Configuration.register_provider_options(Provider.configuration_options)
|
|
228
225
|
end
|
|
229
226
|
end
|
|
230
227
|
end
|