Module: Protege::ProviderMixin
- Included in:
- Provider
- Defined in:
- lib/protege/extensions/provider_mixin.rb
Overview
Marker mixin for LLM provider extensions.
A concrete provider class subclasses Protege::Provider (which includes this module) and
declares its symbolic identifier via the protege_id class macro:
class OpenRouterProvider < Protege::Provider
protege_id :openrouter
def initialize(api_key:); @api_key = api_key; end
def generate(request); ...; end
end
Providers are referenced by id (the symbol passed to protege_id). On include, the class is
auto-tracked in Provider.registered; the registry uses this list to map a configured
provider_id to its class without scanning ObjectSpace or requiring explicit registration calls.
The generation request/response value objects it exchanges live in the Inference::Provider
namespace (+Inference::Provider::Request+, ::Response, …).
Contract:
def self.id; end # returns the Symbol declared above (provided by the DSL)
def generate(request); end # Request -> Response, raises a Protege::*Error on failure
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
-
.included(base) ⇒ void
Extend the including class with the +protege_id+/+id+ DSL.
-
.registered ⇒ Array<Class>
List every concrete provider class.
Instance Method Summary collapse
-
#generate(_request) ⇒ Hash
Generate a response for
request(abstract). -
#generate_stream(request) {|chunk| ... } ⇒ Hash
Generate a response, yielding incremental chunks as they arrive.
-
#model ⇒ String?
The model id this provider targets, read from its own
config.providersslice (+:model+). -
#settings ⇒ Hash
The sampling settings this provider applies beyond the model — the generation knobs (temperature, max tokens, …) that shape the output and so matter for training/reproducibility.
Class Method Details
.included(base) ⇒ void
This method returns an undefined value.
Extend the including class with the +protege_id+/+id+ DSL.
33 34 35 |
# File 'lib/protege/extensions/provider_mixin.rb', line 33 def included(base) base.extend(ClassMethods) end |
.registered ⇒ Array<Class>
List every concrete provider class.
Reads from Provider.descendants so the registry survives Zeitwerk reloads without a
manual registration step.
43 44 45 |
# File 'lib/protege/extensions/provider_mixin.rb', line 43 def registered Provider.descendants end |
Instance Method Details
#generate(_request) ⇒ Hash
Generate a response for request (abstract).
The provider contract is hash in, hash out: request is the standard (OpenAI-compatible)
request hash — { messages:, tools: } — and the return is the response hash —
{ content:, tool_calls:, finish_reason: } (see the providers doc). The provider adds its own
model/sampling/credentials from config, and raises a Protege::Error subclass on transport, auth,
or parse failure. Providers never touch Protege's internal value types. Concrete providers must
override this; the default body exists only to give a clear failure when one forgets to.
60 61 62 63 |
# File 'lib/protege/extensions/provider_mixin.rb', line 60 def generate(_request) raise NotImplementedError, "#{self.class} must implement #generate(request_hash) -> response hash" end |
#generate_stream(request) {|chunk| ... } ⇒ Hash
Generate a response, yielding incremental chunks as they arrive.
The default implementation does not truly stream: it calls #generate and yields the whole
text as one :text chunk (only when non-blank), then returns the response hash. Providers with
native streaming should override this to yield finer-grained chunks.
75 76 77 78 79 |
# File 'lib/protege/extensions/provider_mixin.rb', line 75 def generate_stream(request, &) response = generate(request) yield({ type: :text, content: response[:content] }) if response[:content].present? response end |
#model ⇒ String?
The model id this provider targets, read from its own config.providers slice (+:model+).
Public so the harness can record which model produced a turn (for tracing); resolved per call, so
a future persona-level override is reflected here. Providers may treat a missing model as a hard
error at generation time — that enforcement is theirs, not this soft reader's.
87 88 89 |
# File 'lib/protege/extensions/provider_mixin.rb', line 87 def model Protege.configuration.(self.class.id)[:model] end |
#settings ⇒ Hash
The sampling settings this provider applies beyond the model — the generation knobs (temperature,
max tokens, …) that shape the output and so matter for training/reproducibility. The default is
empty; a provider overrides this to expose its own knobs. Captured alongside #model in a trace.
96 97 98 |
# File 'lib/protege/extensions/provider_mixin.rb', line 96 def settings {} end |