dify_llm 1.6.4
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +157 -0
- data/lib/generators/ruby_llm/install/templates/chat_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/install/templates/create_chats_legacy_migration.rb.tt +8 -0
- data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +8 -0
- data/lib/generators/ruby_llm/install/templates/create_messages_legacy_migration.rb.tt +16 -0
- data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +16 -0
- data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +43 -0
- data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +15 -0
- data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +9 -0
- data/lib/generators/ruby_llm/install/templates/message_model.rb.tt +4 -0
- data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +3 -0
- data/lib/generators/ruby_llm/install_generator.rb +184 -0
- data/lib/generators/ruby_llm/migrate_model_fields/templates/migration.rb.tt +142 -0
- data/lib/generators/ruby_llm/migrate_model_fields_generator.rb +84 -0
- data/lib/ruby_llm/active_record/acts_as.rb +137 -0
- data/lib/ruby_llm/active_record/acts_as_legacy.rb +398 -0
- data/lib/ruby_llm/active_record/chat_methods.rb +315 -0
- data/lib/ruby_llm/active_record/message_methods.rb +72 -0
- data/lib/ruby_llm/active_record/model_methods.rb +84 -0
- data/lib/ruby_llm/aliases.json +274 -0
- data/lib/ruby_llm/aliases.rb +38 -0
- data/lib/ruby_llm/attachment.rb +191 -0
- data/lib/ruby_llm/chat.rb +212 -0
- data/lib/ruby_llm/chunk.rb +6 -0
- data/lib/ruby_llm/configuration.rb +69 -0
- data/lib/ruby_llm/connection.rb +137 -0
- data/lib/ruby_llm/content.rb +50 -0
- data/lib/ruby_llm/context.rb +29 -0
- data/lib/ruby_llm/embedding.rb +29 -0
- data/lib/ruby_llm/error.rb +76 -0
- data/lib/ruby_llm/image.rb +49 -0
- data/lib/ruby_llm/message.rb +76 -0
- data/lib/ruby_llm/mime_type.rb +67 -0
- data/lib/ruby_llm/model/info.rb +103 -0
- data/lib/ruby_llm/model/modalities.rb +22 -0
- data/lib/ruby_llm/model/pricing.rb +48 -0
- data/lib/ruby_llm/model/pricing_category.rb +46 -0
- data/lib/ruby_llm/model/pricing_tier.rb +33 -0
- data/lib/ruby_llm/model.rb +7 -0
- data/lib/ruby_llm/models.json +31418 -0
- data/lib/ruby_llm/models.rb +235 -0
- data/lib/ruby_llm/models_schema.json +168 -0
- data/lib/ruby_llm/provider.rb +215 -0
- data/lib/ruby_llm/providers/anthropic/capabilities.rb +134 -0
- data/lib/ruby_llm/providers/anthropic/chat.rb +106 -0
- data/lib/ruby_llm/providers/anthropic/embeddings.rb +20 -0
- data/lib/ruby_llm/providers/anthropic/media.rb +91 -0
- data/lib/ruby_llm/providers/anthropic/models.rb +48 -0
- data/lib/ruby_llm/providers/anthropic/streaming.rb +43 -0
- data/lib/ruby_llm/providers/anthropic/tools.rb +107 -0
- data/lib/ruby_llm/providers/anthropic.rb +36 -0
- data/lib/ruby_llm/providers/bedrock/capabilities.rb +167 -0
- data/lib/ruby_llm/providers/bedrock/chat.rb +63 -0
- data/lib/ruby_llm/providers/bedrock/media.rb +60 -0
- data/lib/ruby_llm/providers/bedrock/models.rb +98 -0
- data/lib/ruby_llm/providers/bedrock/signing.rb +831 -0
- data/lib/ruby_llm/providers/bedrock/streaming/base.rb +51 -0
- data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +56 -0
- data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +67 -0
- data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +78 -0
- data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +78 -0
- data/lib/ruby_llm/providers/bedrock/streaming.rb +18 -0
- data/lib/ruby_llm/providers/bedrock.rb +82 -0
- data/lib/ruby_llm/providers/deepseek/capabilities.rb +130 -0
- data/lib/ruby_llm/providers/deepseek/chat.rb +16 -0
- data/lib/ruby_llm/providers/deepseek.rb +30 -0
- data/lib/ruby_llm/providers/dify/capabilities.rb +16 -0
- data/lib/ruby_llm/providers/dify/chat.rb +59 -0
- data/lib/ruby_llm/providers/dify/media.rb +37 -0
- data/lib/ruby_llm/providers/dify/streaming.rb +28 -0
- data/lib/ruby_llm/providers/dify.rb +48 -0
- data/lib/ruby_llm/providers/gemini/capabilities.rb +276 -0
- data/lib/ruby_llm/providers/gemini/chat.rb +171 -0
- data/lib/ruby_llm/providers/gemini/embeddings.rb +37 -0
- data/lib/ruby_llm/providers/gemini/images.rb +47 -0
- data/lib/ruby_llm/providers/gemini/media.rb +54 -0
- data/lib/ruby_llm/providers/gemini/models.rb +40 -0
- data/lib/ruby_llm/providers/gemini/streaming.rb +61 -0
- data/lib/ruby_llm/providers/gemini/tools.rb +77 -0
- data/lib/ruby_llm/providers/gemini.rb +36 -0
- data/lib/ruby_llm/providers/gpustack/chat.rb +27 -0
- data/lib/ruby_llm/providers/gpustack/media.rb +45 -0
- data/lib/ruby_llm/providers/gpustack/models.rb +90 -0
- data/lib/ruby_llm/providers/gpustack.rb +34 -0
- data/lib/ruby_llm/providers/mistral/capabilities.rb +155 -0
- data/lib/ruby_llm/providers/mistral/chat.rb +24 -0
- data/lib/ruby_llm/providers/mistral/embeddings.rb +33 -0
- data/lib/ruby_llm/providers/mistral/models.rb +48 -0
- data/lib/ruby_llm/providers/mistral.rb +32 -0
- data/lib/ruby_llm/providers/ollama/chat.rb +27 -0
- data/lib/ruby_llm/providers/ollama/media.rb +45 -0
- data/lib/ruby_llm/providers/ollama/models.rb +36 -0
- data/lib/ruby_llm/providers/ollama.rb +30 -0
- data/lib/ruby_llm/providers/openai/capabilities.rb +291 -0
- data/lib/ruby_llm/providers/openai/chat.rb +83 -0
- data/lib/ruby_llm/providers/openai/embeddings.rb +33 -0
- data/lib/ruby_llm/providers/openai/images.rb +38 -0
- data/lib/ruby_llm/providers/openai/media.rb +80 -0
- data/lib/ruby_llm/providers/openai/models.rb +39 -0
- data/lib/ruby_llm/providers/openai/streaming.rb +41 -0
- data/lib/ruby_llm/providers/openai/tools.rb +78 -0
- data/lib/ruby_llm/providers/openai.rb +42 -0
- data/lib/ruby_llm/providers/openrouter/models.rb +73 -0
- data/lib/ruby_llm/providers/openrouter.rb +26 -0
- data/lib/ruby_llm/providers/perplexity/capabilities.rb +137 -0
- data/lib/ruby_llm/providers/perplexity/chat.rb +16 -0
- data/lib/ruby_llm/providers/perplexity/models.rb +42 -0
- data/lib/ruby_llm/providers/perplexity.rb +48 -0
- data/lib/ruby_llm/providers/vertexai/chat.rb +14 -0
- data/lib/ruby_llm/providers/vertexai/embeddings.rb +32 -0
- data/lib/ruby_llm/providers/vertexai/models.rb +130 -0
- data/lib/ruby_llm/providers/vertexai/streaming.rb +14 -0
- data/lib/ruby_llm/providers/vertexai.rb +55 -0
- data/lib/ruby_llm/railtie.rb +41 -0
- data/lib/ruby_llm/stream_accumulator.rb +97 -0
- data/lib/ruby_llm/streaming.rb +153 -0
- data/lib/ruby_llm/tool.rb +83 -0
- data/lib/ruby_llm/tool_call.rb +22 -0
- data/lib/ruby_llm/utils.rb +45 -0
- data/lib/ruby_llm/version.rb +5 -0
- data/lib/ruby_llm.rb +97 -0
- data/lib/tasks/models.rake +525 -0
- data/lib/tasks/release.rake +67 -0
- data/lib/tasks/ruby_llm.rake +15 -0
- data/lib/tasks/vcr.rake +92 -0
- metadata +291 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyLLM
|
4
|
+
module Providers
|
5
|
+
class Bedrock
|
6
|
+
# Determines capabilities and pricing for AWS Bedrock models
|
7
|
+
module Capabilities
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def context_window_for(model_id)
|
11
|
+
case model_id
|
12
|
+
when /anthropic\.claude-2/ then 100_000
|
13
|
+
else 200_000
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def max_tokens_for(_model_id)
|
18
|
+
4_096
|
19
|
+
end
|
20
|
+
|
21
|
+
def input_price_for(model_id)
|
22
|
+
PRICES.dig(model_family(model_id), :input) || default_input_price
|
23
|
+
end
|
24
|
+
|
25
|
+
def output_price_for(model_id)
|
26
|
+
PRICES.dig(model_family(model_id), :output) || default_output_price
|
27
|
+
end
|
28
|
+
|
29
|
+
def supports_chat?(model_id)
|
30
|
+
model_id.match?(/anthropic\.claude/)
|
31
|
+
end
|
32
|
+
|
33
|
+
def supports_streaming?(model_id)
|
34
|
+
model_id.match?(/anthropic\.claude/)
|
35
|
+
end
|
36
|
+
|
37
|
+
def supports_images?(model_id)
|
38
|
+
model_id.match?(/anthropic\.claude/)
|
39
|
+
end
|
40
|
+
|
41
|
+
def supports_vision?(model_id)
|
42
|
+
model_id.match?(/anthropic\.claude/)
|
43
|
+
end
|
44
|
+
|
45
|
+
def supports_functions?(model_id)
|
46
|
+
model_id.match?(/anthropic\.claude/)
|
47
|
+
end
|
48
|
+
|
49
|
+
def supports_audio?(_model_id)
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
53
|
+
def supports_json_mode?(model_id)
|
54
|
+
model_id.match?(/anthropic\.claude/)
|
55
|
+
end
|
56
|
+
|
57
|
+
def format_display_name(model_id)
|
58
|
+
model_id.then { |id| humanize(id) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def model_type(_model_id)
|
62
|
+
'chat'
|
63
|
+
end
|
64
|
+
|
65
|
+
def supports_structured_output?(_model_id)
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
# Model family patterns for capability lookup
|
70
|
+
MODEL_FAMILIES = {
|
71
|
+
/anthropic\.claude-3-opus/ => :claude3_opus,
|
72
|
+
/anthropic\.claude-3-sonnet/ => :claude3_sonnet,
|
73
|
+
/anthropic\.claude-3-5-sonnet/ => :claude3_sonnet,
|
74
|
+
/anthropic\.claude-3-7-sonnet/ => :claude3_sonnet,
|
75
|
+
/anthropic\.claude-3-haiku/ => :claude3_haiku,
|
76
|
+
/anthropic\.claude-3-5-haiku/ => :claude3_5_haiku,
|
77
|
+
/anthropic\.claude-v2/ => :claude2,
|
78
|
+
/anthropic\.claude-instant/ => :claude_instant
|
79
|
+
}.freeze
|
80
|
+
|
81
|
+
def model_family(model_id)
|
82
|
+
MODEL_FAMILIES.find { |pattern, _family| model_id.match?(pattern) }&.last || :other
|
83
|
+
end
|
84
|
+
|
85
|
+
# Pricing information for Bedrock models (per million tokens)
|
86
|
+
PRICES = {
|
87
|
+
claude3_opus: { input: 15.0, output: 75.0 },
|
88
|
+
claude3_sonnet: { input: 3.0, output: 15.0 },
|
89
|
+
claude3_haiku: { input: 0.25, output: 1.25 },
|
90
|
+
claude3_5_haiku: { input: 0.8, output: 4.0 },
|
91
|
+
claude2: { input: 8.0, output: 24.0 },
|
92
|
+
claude_instant: { input: 0.8, output: 2.4 }
|
93
|
+
}.freeze
|
94
|
+
|
95
|
+
def default_input_price
|
96
|
+
0.1
|
97
|
+
end
|
98
|
+
|
99
|
+
def default_output_price
|
100
|
+
0.2
|
101
|
+
end
|
102
|
+
|
103
|
+
def humanize(id)
|
104
|
+
id.tr('-', ' ')
|
105
|
+
.split('.')
|
106
|
+
.last
|
107
|
+
.split
|
108
|
+
.map(&:capitalize)
|
109
|
+
.join(' ')
|
110
|
+
end
|
111
|
+
|
112
|
+
def modalities_for(model_id)
|
113
|
+
modalities = {
|
114
|
+
input: ['text'],
|
115
|
+
output: ['text']
|
116
|
+
}
|
117
|
+
|
118
|
+
if model_id.match?(/anthropic\.claude/) && supports_vision?(model_id)
|
119
|
+
modalities[:input] << 'image'
|
120
|
+
modalities[:input] << 'pdf'
|
121
|
+
end
|
122
|
+
|
123
|
+
modalities
|
124
|
+
end
|
125
|
+
|
126
|
+
def capabilities_for(model_id)
|
127
|
+
capabilities = []
|
128
|
+
|
129
|
+
capabilities << 'streaming' if model_id.match?(/anthropic\.claude/)
|
130
|
+
|
131
|
+
capabilities << 'function_calling' if supports_functions?(model_id)
|
132
|
+
|
133
|
+
capabilities << 'reasoning' if model_id.match?(/claude-3-7/)
|
134
|
+
|
135
|
+
if model_id.match?(/claude-3\.5|claude-3-7/)
|
136
|
+
capabilities << 'batch'
|
137
|
+
capabilities << 'citations'
|
138
|
+
end
|
139
|
+
|
140
|
+
capabilities
|
141
|
+
end
|
142
|
+
|
143
|
+
def pricing_for(model_id)
|
144
|
+
family = model_family(model_id)
|
145
|
+
prices = PRICES.fetch(family, { input: default_input_price, output: default_output_price })
|
146
|
+
|
147
|
+
standard_pricing = {
|
148
|
+
input_per_million: prices[:input],
|
149
|
+
output_per_million: prices[:output]
|
150
|
+
}
|
151
|
+
|
152
|
+
batch_pricing = {
|
153
|
+
input_per_million: prices[:input] * 0.5,
|
154
|
+
output_per_million: prices[:output] * 0.5
|
155
|
+
}
|
156
|
+
|
157
|
+
{
|
158
|
+
text_tokens: {
|
159
|
+
standard: standard_pricing,
|
160
|
+
batch: batch_pricing
|
161
|
+
}
|
162
|
+
}
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyLLM
|
4
|
+
module Providers
|
5
|
+
class Bedrock
|
6
|
+
# Chat methods for the AWS Bedrock API implementation
|
7
|
+
module Chat
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def sync_response(connection, payload, additional_headers = {})
|
11
|
+
signature = sign_request("#{connection.connection.url_prefix}#{completion_url}", payload:)
|
12
|
+
response = connection.post completion_url, payload do |req|
|
13
|
+
req.headers.merge! build_headers(signature.headers, streaming: block_given?)
|
14
|
+
req.headers = additional_headers.merge(req.headers) unless additional_headers.empty?
|
15
|
+
end
|
16
|
+
Anthropic::Chat.parse_completion_response response
|
17
|
+
end
|
18
|
+
|
19
|
+
def format_message(msg)
|
20
|
+
if msg.tool_call?
|
21
|
+
Anthropic::Tools.format_tool_call(msg)
|
22
|
+
elsif msg.tool_result?
|
23
|
+
Anthropic::Tools.format_tool_result(msg)
|
24
|
+
else
|
25
|
+
format_basic_message(msg)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def format_basic_message(msg)
|
30
|
+
{
|
31
|
+
role: Anthropic::Chat.convert_role(msg.role),
|
32
|
+
content: Media.format_content(msg.content)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def completion_url
|
39
|
+
"model/#{@model_id}/invoke"
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_payload(messages, tools:, temperature:, model:, stream: false, schema: nil) # rubocop:disable Lint/UnusedMethodArgument,Metrics/ParameterLists
|
43
|
+
@model_id = model.id
|
44
|
+
|
45
|
+
system_messages, chat_messages = Anthropic::Chat.separate_messages(messages)
|
46
|
+
system_content = Anthropic::Chat.build_system_content(system_messages)
|
47
|
+
|
48
|
+
build_base_payload(chat_messages, model).tap do |payload|
|
49
|
+
Anthropic::Chat.add_optional_fields(payload, system_content:, tools:, temperature:)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_base_payload(chat_messages, model)
|
54
|
+
{
|
55
|
+
anthropic_version: 'bedrock-2023-05-31',
|
56
|
+
messages: chat_messages.map { |msg| format_message(msg) },
|
57
|
+
max_tokens: model.max_tokens || 4096
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyLLM
|
4
|
+
module Providers
|
5
|
+
class Bedrock
|
6
|
+
# Media handling methods for the Bedrock API integration
|
7
|
+
# NOTE: Bedrock does not support url attachments
|
8
|
+
module Media
|
9
|
+
extend Anthropic::Media
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
def format_content(content)
|
14
|
+
return [Anthropic::Media.format_text(content.to_json)] if content.is_a?(Hash) || content.is_a?(Array)
|
15
|
+
return [Anthropic::Media.format_text(content)] unless content.is_a?(Content)
|
16
|
+
|
17
|
+
parts = []
|
18
|
+
parts << Anthropic::Media.format_text(content.text) if content.text
|
19
|
+
|
20
|
+
content.attachments.each do |attachment|
|
21
|
+
case attachment.type
|
22
|
+
when :image
|
23
|
+
parts << format_image(attachment)
|
24
|
+
when :pdf
|
25
|
+
parts << format_pdf(attachment)
|
26
|
+
when :text
|
27
|
+
parts << Anthropic::Media.format_text_file(attachment)
|
28
|
+
else
|
29
|
+
raise UnsupportedAttachmentError, attachment.type
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
parts
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_image(image)
|
37
|
+
{
|
38
|
+
type: 'image',
|
39
|
+
source: {
|
40
|
+
type: 'base64',
|
41
|
+
media_type: image.mime_type,
|
42
|
+
data: image.encoded
|
43
|
+
}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_pdf(pdf)
|
48
|
+
{
|
49
|
+
type: 'document',
|
50
|
+
source: {
|
51
|
+
type: 'base64',
|
52
|
+
media_type: pdf.mime_type,
|
53
|
+
data: pdf.encoded
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyLLM
|
4
|
+
module Providers
|
5
|
+
class Bedrock
|
6
|
+
# Models methods for the AWS Bedrock API implementation
|
7
|
+
module Models
|
8
|
+
def list_models
|
9
|
+
mgmt_api_base = "https://bedrock.#{@config.bedrock_region}.amazonaws.com"
|
10
|
+
full_models_url = "#{mgmt_api_base}/#{models_url}"
|
11
|
+
signature = sign_request(full_models_url, method: :get)
|
12
|
+
response = @connection.get(full_models_url) do |req|
|
13
|
+
req.headers.merge! signature.headers
|
14
|
+
end
|
15
|
+
|
16
|
+
parse_list_models_response(response, slug, capabilities)
|
17
|
+
end
|
18
|
+
|
19
|
+
module_function
|
20
|
+
|
21
|
+
def models_url
|
22
|
+
'foundation-models'
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_list_models_response(response, slug, capabilities)
|
26
|
+
models = Array(response.body['modelSummaries'])
|
27
|
+
|
28
|
+
models.select { |m| m['modelId'].include?('claude') }.map do |model_data|
|
29
|
+
model_id = model_data['modelId']
|
30
|
+
|
31
|
+
Model::Info.new(
|
32
|
+
id: model_id_with_region(model_id, model_data),
|
33
|
+
name: model_data['modelName'] || capabilities.format_display_name(model_id),
|
34
|
+
provider: slug,
|
35
|
+
family: capabilities.model_family(model_id),
|
36
|
+
created_at: nil,
|
37
|
+
context_window: capabilities.context_window_for(model_id),
|
38
|
+
max_output_tokens: capabilities.max_tokens_for(model_id),
|
39
|
+
modalities: capabilities.modalities_for(model_id),
|
40
|
+
capabilities: capabilities.capabilities_for(model_id),
|
41
|
+
pricing: capabilities.pricing_for(model_id),
|
42
|
+
metadata: {
|
43
|
+
provider_name: model_data['providerName'],
|
44
|
+
inference_types: model_data['inferenceTypesSupported'] || [],
|
45
|
+
streaming_supported: model_data['responseStreamingSupported'] || false,
|
46
|
+
input_modalities: model_data['inputModalities'] || [],
|
47
|
+
output_modalities: model_data['outputModalities'] || []
|
48
|
+
}
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_model_info(model_data, slug, _capabilities)
|
54
|
+
model_id = model_data['modelId']
|
55
|
+
|
56
|
+
Model::Info.new(
|
57
|
+
id: model_id_with_region(model_id, model_data),
|
58
|
+
name: model_data['modelName'] || model_id,
|
59
|
+
provider: slug,
|
60
|
+
family: 'claude',
|
61
|
+
created_at: nil,
|
62
|
+
context_window: 200_000,
|
63
|
+
max_output_tokens: 4096,
|
64
|
+
modalities: { input: ['text'], output: ['text'] },
|
65
|
+
capabilities: [],
|
66
|
+
pricing: {},
|
67
|
+
metadata: {}
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def model_id_with_region(model_id, model_data)
|
72
|
+
return model_id unless model_data['inferenceTypesSupported']&.include?('INFERENCE_PROFILE')
|
73
|
+
return model_id if model_data['inferenceTypesSupported']&.include?('ON_DEMAND')
|
74
|
+
|
75
|
+
desired_region_prefix = inference_profile_region_prefix
|
76
|
+
|
77
|
+
# Return unchanged if model already has the correct region prefix
|
78
|
+
return model_id if model_id.start_with?("#{desired_region_prefix}.")
|
79
|
+
|
80
|
+
# Remove any existing region prefix (e.g., "us.", "eu.", "ap.")
|
81
|
+
clean_model_id = model_id.sub(/^[a-z]{2}\./, '')
|
82
|
+
|
83
|
+
# Apply the desired region prefix
|
84
|
+
"#{desired_region_prefix}.#{clean_model_id}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def inference_profile_region_prefix
|
88
|
+
# Extract region prefix from bedrock_region (e.g., "eu-west-3" -> "eu")
|
89
|
+
region = @config.bedrock_region.to_s
|
90
|
+
return 'us' if region.empty? # Default fallback
|
91
|
+
|
92
|
+
# Take first two characters as the region prefix
|
93
|
+
region[0, 2]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|