Class: RubyPi::LLM::Fallback
- Inherits:
-
BaseProvider
- Object
- BaseProvider
- RubyPi::LLM::Fallback
- Defined in:
- lib/ruby_pi/llm/fallback.rb
Overview
A resilient provider wrapper that tries a primary provider first and automatically falls back to an alternative provider on failure. Both providers must conform to the BaseProvider interface.
Authentication errors are NOT retried with the fallback since they indicate a configuration problem rather than a transient failure.
Issue #23: When streaming, the Fallback now buffers deltas from the primary provider. If the primary fails mid-stream, the buffered deltas are discarded and the fallback provider streams fresh from the start. This prevents the consumer from seeing partial output from the primary concatenated with the complete output from the fallback.
Instance Attribute Summary collapse
-
#fallback ⇒ RubyPi::LLM::BaseProvider
readonly
The fallback provider.
-
#primary ⇒ RubyPi::LLM::BaseProvider
readonly
The primary provider.
Attributes inherited from BaseProvider
#max_retries, #retry_base_delay, #retry_max_delay
Instance Method Summary collapse
-
#complete(messages:, tools: [], stream: false) {|event| ... } ⇒ RubyPi::LLM::Response
Overrides BaseProvider#complete to skip the outer retry wrapper.
-
#initialize(primary:, fallback:, **options) ⇒ Fallback
constructor
Creates a new Fallback wrapper with a primary and fallback provider.
-
#model_name ⇒ String
Returns the model name of the primary provider.
-
#provider_name ⇒ Symbol
Returns :fallback as the provider identifier.
Constructor Details
#initialize(primary:, fallback:, **options) ⇒ Fallback
Creates a new Fallback wrapper with a primary and fallback provider.
44 45 46 47 48 |
# File 'lib/ruby_pi/llm/fallback.rb', line 44 def initialize(primary:, fallback:, **) super(**) @primary = primary @fallback = fallback end |
Instance Attribute Details
#fallback ⇒ RubyPi::LLM::BaseProvider (readonly)
Returns the fallback provider.
37 38 39 |
# File 'lib/ruby_pi/llm/fallback.rb', line 37 def fallback @fallback end |
#primary ⇒ RubyPi::LLM::BaseProvider (readonly)
Returns the primary provider.
34 35 36 |
# File 'lib/ruby_pi/llm/fallback.rb', line 34 def primary @primary end |
Instance Method Details
#complete(messages:, tools: [], stream: false) {|event| ... } ⇒ RubyPi::LLM::Response
Overrides BaseProvider#complete to skip the outer retry wrapper.
Without this override, Fallback inherits BaseProvider#complete which wraps perform_complete in a retry loop. Since perform_complete calls (also with retries), the retry layers compose multiplicatively:
outer_retries x (primary_retries + fallback_retries)
With default max_retries=3, that’s 4 x (4 + 4) = 32 total attempts instead of the expected 4 + 4 = 8.
This override calls perform_complete directly — no outer retry loop. Each inner provider handles its own retries independently.
82 83 84 |
# File 'lib/ruby_pi/llm/fallback.rb', line 82 def complete(messages:, tools: [], stream: false, &block) perform_complete(messages: , tools: tools, stream: stream, &block) end |
#model_name ⇒ String
Returns the model name of the primary provider.
53 54 55 |
# File 'lib/ruby_pi/llm/fallback.rb', line 53 def model_name @primary.model_name end |
#provider_name ⇒ Symbol
Returns :fallback as the provider identifier.
60 61 62 |
# File 'lib/ruby_pi/llm/fallback.rb', line 60 def provider_name :fallback end |