Class: LittleGhost::Providers::Bedrock::HTTPClient

Inherits:
Object
  • Object
show all
Defined in:
lib/little_ghost/providers/bedrock/http_client.rb

Overview

Stdlib Bedrock Runtime client with the small ConverseStream surface used by the adapter.

Defined Under Namespace

Classes: InvokeResponse, Response

Constant Summary collapse

DEFAULT_MAX_RESPONSE_BYTES =
256 * 1024 * 1024

Instance Method Summary collapse

Constructor Details

#initialize(region:, credentials: nil, credential_resolver: nil, endpoint: nil, open_timeout: 10, read_timeout: 120, max_response_bytes: DEFAULT_MAX_RESPONSE_BYTES, max_frame_bytes: EventStreamDecoder::DEFAULT_MAX_FRAME_BYTES, clock: -> { Time.now.utc }) ⇒ HTTPClient

Returns a new instance of HTTPClient.

Raises:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/little_ghost/providers/bedrock/http_client.rb', line 16

def initialize(region:, credentials: nil, credential_resolver: nil, endpoint: nil,
  open_timeout: 10, read_timeout: 120, max_response_bytes: DEFAULT_MAX_RESPONSE_BYTES,
  max_frame_bytes: EventStreamDecoder::DEFAULT_MAX_FRAME_BYTES, clock: -> { Time.now.utc })
  @region = region.to_s
  raise ConfigurationError, "Bedrock region is required" if @region.empty?

  @credential_resolver = credential_resolver || -> { credentials || CredentialResolver.new.call }
  @endpoint = URI(endpoint || "https://bedrock-runtime.#{@region}.amazonaws.com")
  raise ConfigurationError, "Bedrock endpoint must use HTTPS" unless @endpoint.scheme == "https"

  @max_frame_bytes = Integer(max_frame_bytes)
  @clock = clock
  @http_client = Support::HTTPClient.new(open_timeout:, read_timeout:, max_response_bytes:)
end

Instance Method Details

#converse_stream(**parameters) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/little_ghost/providers/bedrock/http_client.rb', line 31

def converse_stream(**parameters)
  model_id = parameters.delete(:model_id)
  body = JSON.generate(camelize(parameters))
  uri = URI.join(@endpoint.to_s, "/model/#{escape_path(model_id)}/converse-stream")
  credentials = @credential_resolver.call
  signer = AwsSigV4.new(service: "bedrock", region: @region, credentials:, clock: @clock)
  headers = signer.headers(method: :post, uri:, headers: {"content-type" => "application/json"}, body:)
  stream = Enumerator.new do |events|
    decoder = EventStreamDecoder.new(max_frame_bytes: @max_frame_bytes)
    @http_client.each_chunk(uri:, method: :post, headers:, body:, label: "Bedrock request") do |chunk|
      decoder.<<(chunk).each { |event_headers, payload| events << event(event_headers, payload) }
    end
    decoder.finish
  end
  Response.new(stream:)
end

#invoke_model(model_id:, body:, max_response_bytes:, cancellation_token: nil, deadline: nil) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/little_ghost/providers/bedrock/http_client.rb', line 48

def invoke_model(model_id:, body:, max_response_bytes:, cancellation_token: nil, deadline: nil)
  payload = JSON.generate(camelize(body))
  uri = URI.join(@endpoint.to_s, "/model/#{escape_path(model_id)}/invoke")
  credentials = @credential_resolver.call
  signer = AwsSigV4.new(service: "bedrock", region: @region, credentials:, clock: @clock)
  headers = signer.headers(method: :post, uri:, headers: {"content-type" => "application/json", "accept" => "application/json"}, body: payload)
  response = @http_client.request(
    uri:, method: :post, headers:, body: payload,
    cancellation_token:, deadline:, label: "Bedrock request", max_response_bytes:
  )
  InvokeResponse.new(body: response)
end