Class: Legion::LLM::Call::NativeResponseAdapter
- Inherits:
-
Object
- Object
- Legion::LLM::Call::NativeResponseAdapter
- Defined in:
- lib/legion/llm/call/dispatch.rb
Overview
Wraps a native dispatch result hash so Pipeline::Executor and ConversationStore can consume a stable provider response object.
Constant Summary collapse
- HASH_KEY_MAP =
{ result: :content, content: :content, input_tokens: :input_tokens, output_tokens: :output_tokens, cache_read_tokens: :cache_read_tokens, cache_write_tokens: :cache_write_tokens, usage: :usage, metadata: :metadata, tool_calls: :tool_calls, stop_reason: :stop_reason, thinking: :thinking, data: :content, model: :model }.freeze
Instance Attribute Summary collapse
-
#cache_read_tokens ⇒ Object
readonly
Returns the value of attribute cache_read_tokens.
-
#cache_write_tokens ⇒ Object
readonly
Returns the value of attribute cache_write_tokens.
-
#content ⇒ Object
readonly
Returns the value of attribute content.
-
#input_tokens ⇒ Object
readonly
Returns the value of attribute input_tokens.
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#output_tokens ⇒ Object
readonly
Returns the value of attribute output_tokens.
-
#stop_reason ⇒ Object
readonly
Returns the value of attribute stop_reason.
-
#thinking ⇒ Object
readonly
Returns the value of attribute thinking.
-
#tool_calls ⇒ Object
readonly
Returns the value of attribute tool_calls.
-
#usage ⇒ Object
readonly
Returns the value of attribute usage.
Class Method Summary collapse
- .coerce_result(raw) ⇒ Object
- .coerce_usage(raw_usage) ⇒ Object
- .extract_result(result, metadata: {}, thinking: nil) ⇒ Object
- .merge_thinking_payloads(existing, extracted) ⇒ Object
- .normalize_thinking_payload(value = nil, content: nil, signature: nil) ⇒ Object
Instance Method Summary collapse
- #[](key) ⇒ Object
- #dig(*keys) ⇒ Object
-
#initialize(result_hash) ⇒ NativeResponseAdapter
constructor
A new instance of NativeResponseAdapter.
Constructor Details
#initialize(result_hash) ⇒ NativeResponseAdapter
Returns a new instance of NativeResponseAdapter.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/legion/llm/call/dispatch.rb', line 30 def initialize(result_hash) result_hash = self.class.coerce_result(result_hash) extracted = self.class.extract_result( result_hash[:result], metadata: result_hash[:metadata] || {}, thinking: result_hash[:thinking] ) @content = extracted[:result].to_s @model = result_hash[:model] @metadata = extracted[:metadata] || {} @tool_calls = result_hash[:tool_calls] || [] @stop_reason = result_hash[:stop_reason] @thinking = extracted[:thinking] usage = self.class.coerce_usage(result_hash[:usage]) @usage = usage @input_tokens = usage.input_tokens @output_tokens = usage.output_tokens @cache_read_tokens = usage.cache_read_tokens @cache_write_tokens = usage.cache_write_tokens end |
Instance Attribute Details
#cache_read_tokens ⇒ Object (readonly)
Returns the value of attribute cache_read_tokens.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def cache_read_tokens @cache_read_tokens end |
#cache_write_tokens ⇒ Object (readonly)
Returns the value of attribute cache_write_tokens.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def cache_write_tokens @cache_write_tokens end |
#content ⇒ Object (readonly)
Returns the value of attribute content.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def content @content end |
#input_tokens ⇒ Object (readonly)
Returns the value of attribute input_tokens.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def input_tokens @input_tokens end |
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def @metadata end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def model @model end |
#output_tokens ⇒ Object (readonly)
Returns the value of attribute output_tokens.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def output_tokens @output_tokens end |
#stop_reason ⇒ Object (readonly)
Returns the value of attribute stop_reason.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def stop_reason @stop_reason end |
#thinking ⇒ Object (readonly)
Returns the value of attribute thinking.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def thinking @thinking end |
#tool_calls ⇒ Object (readonly)
Returns the value of attribute tool_calls.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def tool_calls @tool_calls end |
#usage ⇒ Object (readonly)
Returns the value of attribute usage.
17 18 19 |
# File 'lib/legion/llm/call/dispatch.rb', line 17 def usage @usage end |
Class Method Details
.coerce_result(raw) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/legion/llm/call/dispatch.rb', line 64 def self.coerce_result(raw) return raw if raw.is_a?(Hash) { result: raw.respond_to?(:content) ? raw.content : raw, usage: Usage.new( input_tokens: raw.respond_to?(:input_tokens) ? raw.input_tokens.to_i : 0, output_tokens: raw.respond_to?(:output_tokens) ? raw.output_tokens.to_i : 0, cache_read_tokens: raw.respond_to?(:cached_tokens) ? raw.cached_tokens.to_i : 0, cache_write_tokens: raw.respond_to?(:cache_creation_tokens) ? raw.cache_creation_tokens.to_i : 0 ), metadata: raw.respond_to?(:metadata) && raw..is_a?(Hash) ? raw. : {}, tool_calls: raw.respond_to?(:tool_calls) ? raw.tool_calls : [], stop_reason: raw.respond_to?(:stop_reason) ? raw.stop_reason : nil, thinking: raw.respond_to?(:thinking) ? raw.thinking : nil }.compact end |
.coerce_usage(raw_usage) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/legion/llm/call/dispatch.rb', line 98 def self.coerce_usage(raw_usage) return raw_usage if raw_usage.is_a?(Usage) return Usage.new unless raw_usage.is_a?(Hash) Usage.new( input_tokens: (raw_usage[:input_tokens] || raw_usage['input_tokens']).to_i, output_tokens: (raw_usage[:output_tokens] || raw_usage['output_tokens']).to_i, cache_read_tokens: (raw_usage[:cache_read_tokens] || raw_usage['cache_read_tokens']).to_i, cache_write_tokens: (raw_usage[:cache_write_tokens] || raw_usage['cache_write_tokens']).to_i ) end |
.extract_result(result, metadata: {}, thinking: nil) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/legion/llm/call/dispatch.rb', line 82 def self.extract_result(result, metadata: {}, thinking: nil) extractor = defined?(::Legion::Extensions::Llm::Responses::ThinkingExtractor) && ::Legion::Extensions::Llm::Responses::ThinkingExtractor return { result: result, metadata: || {}, thinking: normalize_thinking_payload(thinking) } unless extractor extraction = extractor.extract(result, metadata: || {}) { result: extraction.content, metadata: extraction., thinking: merge_thinking_payloads( normalize_thinking_payload(thinking), normalize_thinking_payload(content: extraction.thinking, signature: extraction.signature) ) } end |
.merge_thinking_payloads(existing, extracted) ⇒ Object
110 111 112 113 114 115 116 117 118 119 |
# File 'lib/legion/llm/call/dispatch.rb', line 110 def self.merge_thinking_payloads(existing, extracted) return existing || extracted unless existing && extracted content = [existing[:content], extracted[:content]].compact.map(&:to_s).reject(&:empty?).join existing.merge( content: content.empty? ? nil : content, signature: existing[:signature] || extracted[:signature], enabled: true ).compact end |
.normalize_thinking_payload(value = nil, content: nil, signature: nil) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/legion/llm/call/dispatch.rb', line 121 def self.normalize_thinking_payload(value = nil, content: nil, signature: nil) value = { content: content, signature: signature } if value.nil? && (content || signature) return nil if value.nil? if value.is_a?(Hash) normalized = value.transform_keys { |key| key.respond_to?(:to_sym) ? key.to_sym : key } content = normalized[:content] || normalized[:text] signature = normalized[:signature] elsif value.respond_to?(:text) content = value.text signature = value.respond_to?(:signature) ? value.signature : nil else content = value signature = nil end content = content.to_s.strip unless content.nil? return nil if content.to_s.empty? && signature.to_s.empty? { content: content, signature: signature, enabled: true }.compact end |
Instance Method Details
#[](key) ⇒ Object
51 52 53 54 |
# File 'lib/legion/llm/call/dispatch.rb', line 51 def [](key) attr = HASH_KEY_MAP[key.to_sym] attr ? public_send(attr) : nil end |
#dig(*keys) ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/legion/llm/call/dispatch.rb', line 56 def dig(*keys) value = self[keys.first] return value if keys.length == 1 return nil unless value.respond_to?(:dig) value.dig(*keys[1..]) end |