Class: Legion::Extensions::Llm::Bedrock::Translator

Inherits:
Object
  • Object
show all
Includes:
Logging::Helper
Defined in:
lib/legion/extensions/llm/bedrock/translator.rb

Overview

Canonical provider translator for Bedrock.

Converts between Canonical::Request/Response/Chunk and Bedrock wire formats. Supports two render targets:

- :converse (default) — Bedrock Converse API
- :invoke_model — Bedrock invoke_model with Anthropic Messages payload

Constant Summary collapse

DEFAULT_MAX_TOKENS =
4096

Instance Method Summary collapse

Constructor Details

#initialize(region: nil) ⇒ Translator

Returns a new instance of Translator.



23
24
25
# File 'lib/legion/extensions/llm/bedrock/translator.rb', line 23

def initialize(region: nil)
  @region = region
end

Instance Method Details

#capabilitiesObject



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/legion/extensions/llm/bedrock/translator.rb', line 27

def capabilities
  {
    provider: 'bedrock',
    render_targets: %i[converse invoke_model],
    thinking: :budget_tokens,
    streaming: true,
    tool_calls: true,
    cache_control: false,
    stop_reasons: {
      'end_turn' => :end_turn,
      'tool_use' => :tool_use,
      'max_tokens' => :max_tokens,
      'guardrail_intervened' => :content_filter
    }
  }
end

#parse_chunk(raw, model: nil) ⇒ Canonical::Chunk?

Parameters:

  • raw (Hash)

    Raw streaming event

  • model (String, nil) (defaults to: nil)

Returns:

  • (Canonical::Chunk, nil)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/legion/extensions/llm/bedrock/translator.rb', line 85

def parse_chunk(raw, model: nil) # rubocop:disable Lint/UnusedMethodArgument
  return nil unless raw.is_a?(Hash) && !raw.empty?

  type = (raw['type'] || raw[:type] || '').to_s

  case type
  when 'text_delta' then parse_text_delta(raw)
  when 'thinking_delta' then parse_thinking_delta(raw)
  when 'tool_call_delta' then parse_tool_call_delta(raw)
  when 'done' then parse_done_chunk(raw)
  when 'error' then parse_error_chunk(raw)
  else parse_anthropic_event(raw)
  end
end

#parse_response(wire, model: nil) ⇒ Canonical::Response

Parameters:

  • wire (Hash)

    Raw wire response (String or Symbol keyed)

  • model (String, nil) (defaults to: nil)

Returns:

  • (Canonical::Response)


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/legion/extensions/llm/bedrock/translator.rb', line 59

def parse_response(wire, model: nil)
  if wire.nil? || wire.empty?
    return Canonical::Response.build(
      text: '',
      tool_calls: [],
      usage: Canonical::Usage.from_hash({}),
      stop_reason: nil,
      model: model,
      routing: {},
      metadata: {}
    )
  end

  # Canonical form passthrough (for conformance kit self-test)
  if wire.key?('text') || wire.key?(:text)
    Legion::Extensions::Llm::Canonical::Response.from_hash(wire)
  elsif wire.key?('output') || wire.key?(:output)
    parse_converse_response(wire, model)
  else
    parse_invoke_model_response(wire, model)
  end
end

#render_request(canonical, target: nil) ⇒ Hash

Returns Bedrock wire-format payload.

Parameters:

  • canonical (Canonical::Request)
  • target (Symbol, nil) (defaults to: nil)

    :converse, :invoke_model, or nil (auto)

Returns:

  • (Hash)

    Bedrock wire-format payload



47
48
49
50
51
52
53
54
# File 'lib/legion/extensions/llm/bedrock/translator.rb', line 47

def render_request(canonical, target: nil)
  target ||= target_for(canonical)
  case target
  when :converse then render_converse(canonical)
  when :invoke_model then render_invoke_model(canonical)
  else raise ArgumentError, "Unknown render target: #{target.inspect}"
  end
end

#target_for(canonical) ⇒ Symbol

Returns :converse or :invoke_model.

Parameters:

  • canonical (Canonical::Request)

Returns:

  • (Symbol)

    :converse or :invoke_model



102
103
104
105
106
107
108
# File 'lib/legion/extensions/llm/bedrock/translator.rb', line 102

def target_for(canonical)
  mid = model_from_request(canonical)
  has_thinking = canonical.thinking.respond_to?(:enabled?) && canonical.thinking.enabled?
  has_tools = canonical.tools && !canonical.tools.empty?

  anthropic_model?(mid) && (has_thinking || has_tools) ? :invoke_model : :converse
end