Class: ActiveAgent::Providers::Common::Responses::Base Abstract

Inherits:
BaseModel
  • Object
show all
Defined in:
lib/active_agent/providers/common/responses/base.rb

Overview

This class is abstract.

Subclass and override #usage if provider uses non-standard format

Note:

Use specialized subclasses for specific response types:

  • Prompt for conversational/completion responses

  • Embed for embedding responses

Provides unified interface for AI provider responses across OpenAI, Anthropic, etc.

Examples:

Accessing response data

response = agent.prompt.generate_now
response.success?         #=> true
response.usage            #=> Usage object with normalized fields
response.total_tokens     #=> 30

Inspecting raw provider data

response.raw_request      #=> { "model" => "gpt-4", "messages" => [...] }
response.raw_response     #=> { "id" => "chatcmpl-...", "choices" => [...] }

See Also:

Direct Known Subclasses

Embed, Prompt

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from BaseModel

#<=>, #==, attribute, #deep_compact, #deep_dup, delegate_attributes, drop_attributes, inherited, #inspect, keys, #merge!, required_attributes, #serialize, #to_h, #to_hash

Constructor Details

#initialize(kwargs = {}) ⇒ Base

Initializes response with deep-duplicated attributes.

Deep duplication prevents external modifications from affecting internal state. The raw_response is deep symbolized for consistent key access across providers.

Parameters:

  • kwargs (Hash) (defaults to: {})

Options Hash (kwargs):

  • :context (Hash)
  • :raw_request (Hash)
  • :raw_response (Hash)


75
76
77
78
79
80
81
82
83
84
# File 'lib/active_agent/providers/common/responses/base.rb', line 75

def initialize(kwargs = {})
  kwargs = kwargs.deep_dup # Ensure that userland can't fuck with our memory space

  # Deep symbolize raw_response for consistent access across all extraction methods
  if kwargs[:raw_response].is_a?(Hash)
    kwargs[:raw_response] = kwargs[:raw_response].deep_symbolize_keys
  end

  super(kwargs)
end

Instance Attribute Details

#contextHash (readonly)

Original request context sent to the provider.

Includes instructions, messages, tools, and configuration.

Returns:

  • (Hash)


38
# File 'lib/active_agent/providers/common/responses/base.rb', line 38

attribute :context, writable: false

#raw_requestHash (readonly)

Most recent request in provider-specific format.

Useful for debugging and logging.

Returns:

  • (Hash)


46
# File 'lib/active_agent/providers/common/responses/base.rb', line 46

attribute :raw_request, writable: false

#raw_responseHash (readonly)

Most recent response in provider-specific format.

Includes metadata, usage stats, and provider-specific fields. Hash keys are deep symbolized for consistent access.

Returns:

  • (Hash)


55
# File 'lib/active_agent/providers/common/responses/base.rb', line 55

attribute :raw_response, writable: false

#usagesArray<Usage> (readonly)

Usage objects from each API call in multi-turn conversations.

Each call (e.g., for tool calling) tracks usage separately. These are summed to provide cumulative statistics via #usage.

Returns:



64
# File 'lib/active_agent/providers/common/responses/base.rb', line 64

attribute :usages, default: -> { [] }, writable: false

Instance Method Details

#finish_reasonString? Also known as: stop_reason

Finish reason from provider response.

Indicates why generation stopped (e.g., “stop”, “length”, “tool_calls”). Normalizes access across providers that use different field names.

Examples:

response.finish_reason  #=> "stop"
response.finish_reason  #=> "length"
response.finish_reason  #=> "tool_calls"
response.stop_reason    #=> "stop" (alias)

Returns:

  • (String, nil)


181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/active_agent/providers/common/responses/base.rb', line 181

def finish_reason
  @finish_reason ||= begin
    return nil unless raw_response

    if raw_response.is_a?(Hash)
      # OpenAI format: choices[0].finish_reason or choices[0].message.finish_reason
      raw_response.dig(:choices, 0, :finish_reason) ||
        raw_response.dig(:choices, 0, :message, :finish_reason) ||
        # Anthropic format: stop_reason
        raw_response[:stop_reason]
    end
  end
end

#idString?

Response ID from provider, useful for tracking and debugging.

Examples:

response.id  #=> "chatcmpl-CbDx1nXoNSBrNIMhiuy5fk7jXQjmT" (OpenAI)
response.id  #=> "msg_01RotDmSnYpKQjrTpaHUaEBz" (Anthropic)
response.id  #=> "gen-1761505659-yxgaVsqVABMQqw6oA7QF" (OpenRouter)

Returns:

  • (String, nil)


135
136
137
138
139
140
141
142
143
144
145
# File 'lib/active_agent/providers/common/responses/base.rb', line 135

def id
  @id ||= begin
    return nil unless raw_response

    if raw_response.is_a?(Hash)
      raw_response[:id]
    elsif raw_response.respond_to?(:id)
      raw_response.id
    end
  end
end

#instructionsString, ...

Returns:

  • (String, Array<Hash>, nil)


87
88
89
# File 'lib/active_agent/providers/common/responses/base.rb', line 87

def instructions
  context[:instructions]
end

#modelString?

Model name from provider response.

Useful for confirming which model was actually used, as providers may use different versions than requested.

Examples:

response.model  #=> "gpt-4o-mini-2024-07-18"
response.model  #=> "claude-3-5-haiku-20241022"

Returns:

  • (String, nil)


157
158
159
160
161
162
163
164
165
166
167
# File 'lib/active_agent/providers/common/responses/base.rb', line 157

def model
  @model ||= begin
    return nil unless raw_response

    if raw_response.is_a?(Hash)
      raw_response[:model]
    elsif raw_response.respond_to?(:model)
      raw_response.model
    end
  end
end

#success?Boolean

TODO:

Better handling of failure flows

Returns:

  • (Boolean)


93
94
95
# File 'lib/active_agent/providers/common/responses/base.rb', line 93

def success?
  true
end

#usageUsage?

Normalized usage statistics across all providers.

For multi-turn conversations with tool calling, returns cumulative usage across all API calls (sum of #usages).

Examples:

Single-turn usage

response.usage.input_tokens      #=> 100
response.usage.output_tokens     #=> 25
response.usage.total_tokens      #=> 125

Multi-turn usage (cumulative)

# After 3 API calls due to tool usage:
response.usage.input_tokens      #=> 350 (sum of all calls)
response.usage.output_tokens     #=> 120 (sum of all calls)

Returns:

See Also:



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/active_agent/providers/common/responses/base.rb', line 115

def usage
  @usage ||= begin
    if usages.any?
      usages.reduce(:+)
    elsif raw_response
      Usage.from_provider_usage(
        raw_response.is_a?(Hash) ? raw_response[:usage] : raw_response.usage
      )
    end
  end
end