Class: LittleGhost::ModelRegistry
- Inherits:
-
Object
- Object
- LittleGhost::ModelRegistry
- Defined in:
- lib/little_ghost/model_registry.rb
Overview
Give application roles stable model choices without coupling agents to vendors. A registry joins provider factories with named, inheritable profiles.
A support application can keep its general and research agents on related profiles while selecting one provider in one place:
class CustomerSupportModels < LittleGhost::ModelRegistry
def initialize
super
provider(:openai) do |model:, **|
LittleGhost::Providers::OpenAI.new(
api_key: ENV.fetch("OPENAI_API_KEY"), model: model
)
end
profile "customer_support", provider: :openai, model: "gpt-5"
profile "customer_support.research", inherit: "customer_support",
settings: {temperature: 0.1}
end
end
model = CustomerSupportModels.new.resolve("customer_support.research")
model.id # => "gpt-5"
model.settings # => {temperature: 0.1}
Dotted roles resolve from the exact role toward shorter registered parents.
Explicit profile inheritance supplies provider, model, settings, and metadata;
per-invocation overrides then layer from inherited parents through the exact
requested role. A final override passed to resolve wins over both.
Settings and overrides are control-plane input: construct or allowlist them
in application code rather than copying unchecked request fields. An
override can select a different registered provider or model and change the
destination, capability, and cost of a request.
Provider factories receive the resolved identity, settings, metadata, invocation, run context, and forwarding options. Resolution raises ConfigurationError for missing roles, providers, models, factories, or circular inheritance; exceptions raised inside a factory are not masked.
Direct Known Subclasses
Instance Method Summary collapse
-
#initialize ⇒ ModelRegistry
constructor
Starts an empty registry ready for provider factories and model profiles.
-
#profile(name, provider: nil, model: nil, settings: {}, metadata: {}, inherit: nil) ⇒ Object
Adds an inheritable model profile named
nameand returnsself. -
#provider(name, callable = nil, &factory) ⇒ Object
Associates
namewith a provider factory and returnsself. -
#resolve(name, invocation: nil, override: nil, run: nil, context: nil, **options) ⇒ Object
Materializes
nameas a configured Model for the current invocation.
Constructor Details
#initialize ⇒ ModelRegistry
Starts an empty registry ready for provider factories and model profiles.
43 44 45 46 |
# File 'lib/little_ghost/model_registry.rb', line 43 def initialize @providers = {} @profiles = {} end |
Instance Method Details
#profile(name, provider: nil, model: nil, settings: {}, metadata: {}, inherit: nil) ⇒ Object
Adds an inheritable model profile named name and returns self.
Parent settings and metadata merge into the child. A child may inherit its provider and model or replace either one.
61 62 63 64 65 66 67 68 69 70 |
# File 'lib/little_ghost/model_registry.rb', line 61 def profile(name, provider: nil, model: nil, settings: {}, metadata: {}, inherit: nil) @profiles[name.to_s] = { provider: provider&.to_sym, model: model&.to_s, settings: settings.to_h.transform_keys(&:to_sym), metadata: .to_h, inherit: inherit&.to_s } self end |
#provider(name, callable = nil, &factory) ⇒ Object
Associates name with a provider factory and returns self.
The factory receives the resolved model, logical role, profile
settings and metadata, invocation, run context, and resolution options.
52 53 54 55 |
# File 'lib/little_ghost/model_registry.rb', line 52 def provider(name, callable = nil, &factory) @providers[name.to_sym] = factory || callable || raise(ArgumentError, "provider factory is required") self end |
#resolve(name, invocation: nil, override: nil, run: nil, context: nil, **options) ⇒ Object
Materializes name as a configured Model for the current invocation.
override applies after registered profiles and invocation profile
overrides. context takes precedence over the legacy run argument when
passed to the provider factory.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/little_ghost/model_registry.rb', line 77 def resolve(name, invocation: nil, override: nil, run: nil, context: nil, **) role = name.to_s profile_name = profile_for(role) configuration = resolved_profile(profile_name) override_profiles(profile_name, role).each do |profile| configuration = merge(configuration, profile_override(invocation, profile)) end configuration = merge(configuration, override) provider_name = configuration[:provider] model_id = configuration[:model] raise ConfigurationError, "Model profile #{profile_name} does not define a provider" unless provider_name raise ConfigurationError, "Model profile #{profile_name} does not define a model" unless model_id factory = @providers.fetch(provider_name) do raise ConfigurationError, "No provider is registered for #{provider_name}" end provider = factory.call( model: model_id, role:, settings: configuration.fetch(:settings), metadata: configuration.fetch(:metadata), invocation:, context: context || run, ** ) Model.new( provider:, provider_name:, model: model_id, settings: configuration.fetch(:settings), metadata: configuration.fetch(:metadata), role: ) end |