Class: ActiveHarness::FallbackRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/active_harness/pipeline/fallback_runner.rb

Overview

Executes a model request against a fallback chain. Returns a ModelResponse on the first successful attempt.

Constant Summary collapse

RETRYABLE_ERRORS =
[
  Errors::TimeoutError,
  Errors::RateLimitError,
  Errors::ProviderUnavailableError,
  Errors::ServerError
].freeze
STOP_ERRORS =
[
  Errors::InvalidRequestError,
  Errors::InvalidApiKeyError,
  Errors::SafetyBlockedError,
  Errors::SchemaValidationError
].freeze
RETRYABLE_STATUS =
{
  Errors::TimeoutError             => :timeout,
  Errors::RateLimitError           => :rate_limit,
  Errors::ProviderUnavailableError => :provider_unavailable,
  Errors::ServerError              => :server_error
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_config) ⇒ FallbackRunner

Returns a new instance of FallbackRunner.



28
29
30
31
# File 'lib/active_harness/pipeline/fallback_runner.rb', line 28

def initialize(model_config)
  @model_config = model_config
  @attempts     = []
end

Instance Attribute Details

#attemptsObject (readonly)

Returns the value of attribute attempts.



26
27
28
# File 'lib/active_harness/pipeline/fallback_runner.rb', line 26

def attempts
  @attempts
end

Instance Method Details

#run(request) ⇒ ModelResponse

Parameters:

  • request (ModelRequest)

    — template; provider/model will be overridden per entry

Returns:

Raises:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/active_harness/pipeline/fallback_runner.rb', line 35

def run(request)
  chain.each do |entry|
    provider = ProviderRegistry.find(entry[:provider])
    req      = adapt(request, entry)

    begin
      ActiveHarness.config.on_model_attempt&.call(entry[:provider], entry[:model])
      response = provider.call(req)
      @attempts << { provider: entry[:provider], model: entry[:model], status: :success }
      return response
    rescue *STOP_ERRORS => e
      @attempts << { provider: entry[:provider], model: entry[:model], status: :stop, error: e.message }
      raise
    rescue *RETRYABLE_ERRORS => e
      status = RETRYABLE_STATUS.fetch(e.class, :error)
      @attempts << { provider: entry[:provider], model: entry[:model], status: status, error: e.message }
      ActiveHarness.config.on_model_failure&.call(entry[:provider], entry[:model], status, e.message)
      next
    end
  end

  raise Errors::ProviderError, "All providers failed. Attempts: #{@attempts.inspect}"
end