Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/rubyai.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require_relative "rubyai/providers/openai"
require_relative "rubyai/providers/anthropic"
require_relative "rubyai/providers/gemini"
require_relative "rubyai/providers/bedrock_anthropic"
require_relative "rubyai/provider"
require_relative "rubyai/configuration"
require_relative "rubyai/http"
Expand Down
4 changes: 2 additions & 2 deletions lib/rubyai/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
module RubyAI
class Configuration
# providers config accessors
attr_accessor :openai,
:anthropic,
:gemini,
# default api config accessors
:bedrock_anthropic,
:api,
:model,
:messages,
Expand All @@ -15,6 +14,7 @@ def initialize(config = nil)
@openai ||= Providers::OpenAI.new
@anthropic ||= Providers::Anthropic.new
@gemini ||= Providers::Gemini.new
@bedrock_anthropic ||= Providers::BedrockAnthropic.new
return if config.nil? || config.empty?

provider_key = if config.fetch(:model,
Expand Down
2 changes: 1 addition & 1 deletion lib/rubyai/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def connect(messages:, provider: , model:, temperature:)
response = case provider
when "bedrock_anthropic"
RubyAI.config.bedrock_anthropic.client.invoke_model(model_id: model,
body: BedrockAnthropic.build_http_body.to_json,
body: RubyAI.config.bedrock_anthropic.build_http_body.to_json,
content_type: "application/json")
else
connection.post do |req|
Expand Down
112 changes: 112 additions & 0 deletions lib/rubyai/providers/bedrock_anthropic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
require "aws-sdk-bedrockruntime"
require "json"

module RubyAI
module Providers
class BedrockAnthropic < Base
attr_accessor :messages,
:temperature,
:max_tokens,
:model,
:region,
:aws_access_key_id,
:aws_secret_access_key,
:aws_session_token

def initialize(
region: "us-east-1",
messages: nil,
temperature: 0.7,
model: "claude-3-sonnet",
max_tokens: 4096,
aws_access_key_id: nil,
aws_secret_access_key: nil,
aws_session_token: nil
)
@messages = messages
@temperature = temperature
@model = model
@max_tokens = max_tokens
@region = region

# Initialize AWS Bedrock Runtime client
@client_options = { region: @region }

@aws_access_key_id = aws_access_key_id
@aws_secret_access_key = aws_secret_access_key
@aws_session_token = aws_session_token

# Use explicit credentials if provided, otherwise fall back to default credential chain
return unless aws_access_key_id && aws_secret_access_key

build_credentials
end

def models
{
"claude-3-opus" => "anthropic.claude-3-opus-20240229-v1:0",
"claude-3-sonnet" => "anthropic.claude-3-sonnet-20240229-v1:0",
"claude-3-haiku" => "anthropic.claude-3-haiku-20240307-v1:0",
"claude-3-5-sonnet" => "anthropic.claude-3-5-sonnet-20240620-v1:0",
"claude-3-5-haiku" => "anthropic.claude-3-5-haiku-20241022-v1:0",
"claude-instant" => "anthropic.claude-instant-v1",
"claude-v2" => "anthropic.claude-v2",
"claude-v2-1" => "anthropic.claude-v2:1"
}.freeze
end

def build_http_body(messages = nil, _model = nil, temperature = nil)
{
"anthropic_version" => "bedrock-2023-05-31",
"max_tokens" => @max_tokens,
"messages" => format_messages_for_bedrock(messages || @messages),
"temperature" => temperature || @temperature
}
end

def build_http_headers(_provider)
# For Bedrock, headers are handled by AWS SDK
# Return empty hash as headers are not needed for direct HTTP calls
{}
end

def format_messages_for_bedrock(messages)
case messages
when String
[{ "role" => "user", "content" => messages }]
when Array
messages.map do |msg|
case msg
when Hash
# Ensure required keys exist
{
"role" => msg["role"] || msg[:role] || "user",
"content" => msg["content"] || msg[:content] || ""
}
when String
{ "role" => "user", "content" => msg }
else
{ "role" => "user", "content" => msg.to_s }
end
end
else
[{ "role" => "user", "content" => messages.to_s }]
end
end

def build_credentials
credentials = Aws::Credentials.new(
aws_access_key_id,
aws_secret_access_key,
aws_session_token
)
@client_options[:credentials] = credentials
end

def client
build_credentials
@client ||= Aws::BedrockRuntime::Client.new(@client_options)
end
end
end
end
Loading