Module: Smith::Models
- Extended by:
- Dry::Container::Mixin
- Defined in:
- lib/smith/models.rb,
lib/smith/models/profile.rb,
lib/smith/models/inference.rb,
lib/smith/models/normalizer.rb
Overview
Capability registry for model ids. Decoupled from Smith.config.pricing (per-installation billing) — this catalog describes payload-shape capabilities (thinking encoding, temperature acceptance, endpoint preferences for tools+thinking).
The library ships NO specific model_id declarations. Smith::Models::Inference provides PATTERN-BASED PROVIDER RULES that match model_ids at runtime (e.g., “Anthropic Opus 4.7+ uses adaptive thinking”). Applications register explicit Profile overrides via Smith::Models.register ONLY when they have a custom model that diverges from its provider’s default behavior.
Resolution order in find_or_infer(model_id):
1. Application-registered explicit Profile (override wins)
2. Library Inference rule match
3. Safe default (no thinking, accepts temp, no routing)
Defined Under Namespace
Modules: Inference Classes: CollisionError, Normalizer, Profile
Class Method Summary collapse
- .all ⇒ Object
- .clear! ⇒ Object
- .find(model_id) ⇒ Object
-
.find_or_infer(model_id, provider: nil) ⇒ Object
Application overrides first, then Inference rules, then safe default.
- .guess_provider(model_id) ⇒ Object
- .infer(model_id, provider: nil) ⇒ Object
- .normalize_key(model_id) ⇒ Object
-
.register(profile) ⇒ Object
Register a Profile.
- .registry_monitor ⇒ Object
Class Method Details
.all ⇒ Object
92 93 94 95 96 |
# File 'lib/smith/models.rb', line 92 def self.all registry_monitor.synchronize do keys.sort.map { |k| resolve(k) } end end |
.clear! ⇒ Object
98 99 100 |
# File 'lib/smith/models.rb', line 98 def self.clear! registry_monitor.synchronize { @_container&.clear } end |
.find(model_id) ⇒ Object
31 32 33 34 35 36 |
# File 'lib/smith/models.rb', line 31 def self.find(model_id) registry_monitor.synchronize do key = normalize_key(model_id) key?(key) ? resolve(key) : nil end end |
.find_or_infer(model_id, provider: nil) ⇒ Object
Application overrides first, then Inference rules, then safe default.
39 40 41 |
# File 'lib/smith/models.rb', line 39 def self.find_or_infer(model_id, provider: nil) find(model_id) || infer(model_id, provider: provider) end |
.guess_provider(model_id) ⇒ Object
118 119 120 121 122 |
# File 'lib/smith/models.rb', line 118 def self.guess_provider(model_id) key = normalize_key(model_id) PROVIDER_PATTERNS.each { |provider, pattern| return provider if key.match?(pattern) } :unknown end |
.infer(model_id, provider: nil) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/smith/models.rb', line 43 def self.infer(model_id, provider: nil) inferred = Inference.profile_for(model_id) if defined?(Inference) return inferred if inferred Profile.new( model_id: normalize_key(model_id), provider: provider || guess_provider(model_id), thinking_shape: nil, accepts_temperature: true, tools_with_thinking_native: false, tools_with_thinking_route: nil ) end |
.normalize_key(model_id) ⇒ Object
27 28 29 |
# File 'lib/smith/models.rb', line 27 def self.normalize_key(model_id) model_id.to_s end |
.register(profile) ⇒ Object
Register a Profile. Idempotent when re-registering an identical profile; replaces silently on Rails-reload (same model_id, possibly different Profile object after autoload swap); raises CollisionError on a genuinely conflicting registration.
The stale-reload-binding pattern mirrors Smith::Agent::Registry (agent/registry.rb:118-124) which solves the same problem for agent classes during Rails autoreload.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/smith/models.rb', line 65 def self.register(profile) registry_monitor.synchronize do key = normalize_key(profile.model_id) existing = key?(key) ? resolve(key) : nil return profile if existing == profile if existing && stale_reload_binding?(existing, profile) # Same model_id, value-unequal Profile — Rails reload swap. # Document trade-off: a host that intentionally re-registers with # different capabilities also gets silent replacement (same # behavior Smith::Agent::Registry chose). _container.delete(key) super(key, profile) return profile end if existing raise CollisionError, "model #{key.inspect} already registered with a different profile" end super(key, profile) profile end end |
.registry_monitor ⇒ Object
107 108 109 |
# File 'lib/smith/models.rb', line 107 def self.registry_monitor @_registry_monitor end |