Class: OpenRouter::ModelSelector
- Inherits:
-
Object
- Object
- OpenRouter::ModelSelector
- Defined in:
- lib/open_router/model_selector.rb
Overview
ModelSelector provides a fluent DSL interface for selecting the best AI model based on specific requirements. It wraps the ModelRegistry functionality with an intuitive, chainable API.
Constant Summary collapse
- STRATEGIES =
Available optimization strategies
{ cost: { sort_by: :cost, pick_newer: false }, performance: { sort_by: :performance, pick_newer: false }, latest: { sort_by: :date, pick_newer: true }, context: { sort_by: :context_length, pick_newer: false } }.freeze
Instance Method Summary collapse
-
#avoid_patterns(*patterns) ⇒ ModelSelector
Avoid models matching specific patterns.
-
#avoid_providers(*providers) ⇒ ModelSelector
Avoid specific providers (blacklist).
-
#choose(return_specs: false) ⇒ String, ...
Select the best model based on configured requirements.
-
#choose_with_fallback ⇒ String?
Choose with graceful degradation if no models meet all requirements.
-
#choose_with_fallbacks(limit: 3) ⇒ Array<String>, Array
Select the best model with fallback options.
-
#estimate_cost(model, input_tokens: 1000, output_tokens: 1000) ⇒ Float
Estimate cost for a given model with expected token usage.
-
#initialize(requirements: {}, strategy: :cost, provider_preferences: {}, fallback_options: {}) ⇒ ModelSelector
constructor
A new instance of ModelSelector.
-
#min_context(tokens) ⇒ ModelSelector
Set minimum context length requirement.
-
#newer_than(date) ⇒ ModelSelector
Require models released after a specific date.
-
#optimize_for(strategy) ⇒ ModelSelector
Set the optimization strategy for model selection.
-
#prefer_providers(*providers) ⇒ ModelSelector
Set provider preferences (soft preference - won’t exclude other providers).
-
#require(*capabilities) ⇒ ModelSelector
Require specific capabilities from the selected model.
-
#require_providers(*providers) ⇒ ModelSelector
Require specific providers (hard filter - only these providers).
-
#selection_criteria ⇒ Hash
Get detailed information about the current selection criteria.
-
#with_fallbacks(max: 3, strategy: :similar) ⇒ ModelSelector
Configure fallback behavior.
-
#within_budget(max_cost: nil, max_output_cost: nil) ⇒ ModelSelector
Set budget constraints for model selection.
Constructor Details
#initialize(requirements: {}, strategy: :cost, provider_preferences: {}, fallback_options: {}) ⇒ ModelSelector
Returns a new instance of ModelSelector.
38 39 40 41 42 43 |
# File 'lib/open_router/model_selector.rb', line 38 def initialize(requirements: {}, strategy: :cost, provider_preferences: {}, fallback_options: {}) @requirements = requirements.dup @strategy = strategy @provider_preferences = provider_preferences.dup = .dup end |
Instance Method Details
#avoid_patterns(*patterns) ⇒ ModelSelector
Avoid models matching specific patterns
226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/open_router/model_selector.rb', line 226 def avoid_patterns(*patterns) new_provider_preferences = @provider_preferences.dup new_provider_preferences[:avoided_patterns] = patterns.flatten self.class.new( requirements: @requirements, strategy: @strategy, provider_preferences: new_provider_preferences, fallback_options: ) end |
#avoid_providers(*providers) ⇒ ModelSelector
Avoid specific providers (blacklist)
207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/open_router/model_selector.rb', line 207 def avoid_providers(*providers) new_provider_preferences = @provider_preferences.dup new_provider_preferences[:avoided] = providers.flatten self.class.new( requirements: @requirements, strategy: @strategy, provider_preferences: new_provider_preferences, fallback_options: ) end |
#choose(return_specs: false) ⇒ String, ...
Select the best model based on configured requirements
266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/open_router/model_selector.rb', line 266 def choose(return_specs: false) # Get all models that meet basic requirements candidates = filter_by_providers(ModelRegistry.models_meeting_requirements(@requirements)) return nil if candidates.empty? # Apply strategy-specific sorting best_match = apply_strategy_sorting(candidates) return nil unless best_match return_specs ? best_match : best_match.first end |
#choose_with_fallback ⇒ String?
Choose with graceful degradation if no models meet all requirements
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/open_router/model_selector.rb', line 307 def choose_with_fallback # Try with all requirements first result = choose return result if result # Try dropping least important requirements progressively fallback_requirements = @requirements.dup # Drop requirements in order of importance (least to most important) i[ released_after_date performance_tier max_output_cost min_context_length max_input_cost ].each do |requirement| next unless fallback_requirements.key?(requirement) fallback_requirements.delete(requirement) candidates = filter_by_providers(ModelRegistry.models_meeting_requirements(fallback_requirements)) unless candidates.empty? result = apply_strategy_sorting(candidates) return result&.first end end # Last resort: just pick any model that meets capability requirements if fallback_requirements[:capabilities] basic_requirements = { capabilities: fallback_requirements[:capabilities] } candidates = filter_by_providers(ModelRegistry.models_meeting_requirements(basic_requirements)) result = apply_strategy_sorting(candidates) unless candidates.empty? return result&.first if result end # Final fallback: cheapest available model all_candidates = filter_by_providers(ModelRegistry.all_models) return nil if all_candidates.empty? all_candidates.min_by { |_, specs| specs[:cost_per_1k_tokens][:input] }&.first end |
#choose_with_fallbacks(limit: 3) ⇒ Array<String>, Array
Select the best model with fallback options
289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/open_router/model_selector.rb', line 289 def choose_with_fallbacks(limit: 3) candidates = filter_by_providers(ModelRegistry.models_meeting_requirements(@requirements)) return [] if candidates.empty? # Apply strategy-specific sorting to get ordered list sorted_candidates = apply_strategy_sorting_all(candidates) # Return up to `limit` models sorted_candidates.first(limit).map(&:first) end |
#estimate_cost(model, input_tokens: 1000, output_tokens: 1000) ⇒ Float
Estimate cost for a given model with expected token usage
367 368 369 |
# File 'lib/open_router/model_selector.rb', line 367 def estimate_cost(model, input_tokens: 1000, output_tokens: 1000) ModelRegistry.calculate_estimated_cost(model, input_tokens:, output_tokens:) end |
#min_context(tokens) ⇒ ModelSelector
Set minimum context length requirement
130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/open_router/model_selector.rb', line 130 def min_context(tokens) new_requirements = @requirements.dup new_requirements[:min_context_length] = tokens self.class.new( requirements: new_requirements, strategy: @strategy, provider_preferences: @provider_preferences, fallback_options: ) end |
#newer_than(date) ⇒ ModelSelector
Require models released after a specific date
150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/open_router/model_selector.rb', line 150 def newer_than(date) new_requirements = @requirements.dup new_requirements[:released_after_date] = date self.class.new( requirements: new_requirements, strategy: @strategy, provider_preferences: @provider_preferences, fallback_options: ) end |
#optimize_for(strategy) ⇒ ModelSelector
Set the optimization strategy for model selection
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/open_router/model_selector.rb', line 56 def optimize_for(strategy) unless STRATEGIES.key?(strategy) raise ArgumentError, "Unknown strategy: #{strategy}. Available: #{STRATEGIES.keys.join(", ")}" end new_requirements = @requirements.dup # Apply strategy-specific requirements case strategy when :performance new_requirements[:performance_tier] = :premium when :latest new_requirements[:pick_newer] = true end self.class.new( requirements: new_requirements, strategy:, provider_preferences: @provider_preferences, fallback_options: ) end |
#prefer_providers(*providers) ⇒ ModelSelector
Set provider preferences (soft preference - won’t exclude other providers)
169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/open_router/model_selector.rb', line 169 def prefer_providers(*providers) new_provider_preferences = @provider_preferences.dup new_provider_preferences[:preferred] = providers.flatten self.class.new( requirements: @requirements, strategy: @strategy, provider_preferences: new_provider_preferences, fallback_options: ) end |
#require(*capabilities) ⇒ ModelSelector
Require specific capabilities from the selected model
88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/open_router/model_selector.rb', line 88 def require(*capabilities) new_requirements = @requirements.dup new_requirements[:capabilities] = Array(new_requirements[:capabilities]) + capabilities new_requirements[:capabilities].uniq! self.class.new( requirements: new_requirements, strategy: @strategy, provider_preferences: @provider_preferences, fallback_options: ) end |
#require_providers(*providers) ⇒ ModelSelector
Require specific providers (hard filter - only these providers)
188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/open_router/model_selector.rb', line 188 def require_providers(*providers) new_provider_preferences = @provider_preferences.dup new_provider_preferences[:required] = providers.flatten self.class.new( requirements: @requirements, strategy: @strategy, provider_preferences: new_provider_preferences, fallback_options: ) end |
#selection_criteria ⇒ Hash
Get detailed information about the current selection criteria
352 353 354 355 356 357 358 359 |
# File 'lib/open_router/model_selector.rb', line 352 def selection_criteria { requirements: deep_dup(@requirements), strategy: @strategy, provider_preferences: deep_dup(@provider_preferences), fallback_options: deep_dup() } end |
#with_fallbacks(max: 3, strategy: :similar) ⇒ ModelSelector
Configure fallback behavior
246 247 248 249 250 251 252 253 254 255 |
# File 'lib/open_router/model_selector.rb', line 246 def with_fallbacks(max: 3, strategy: :similar) = { max_fallbacks: max, strategy: } self.class.new( requirements: @requirements, strategy: @strategy, provider_preferences: @provider_preferences, fallback_options: ) end |
#within_budget(max_cost: nil, max_output_cost: nil) ⇒ ModelSelector
Set budget constraints for model selection
110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/open_router/model_selector.rb', line 110 def within_budget(max_cost: nil, max_output_cost: nil) new_requirements = @requirements.dup new_requirements[:max_input_cost] = max_cost if max_cost new_requirements[:max_output_cost] = max_output_cost if max_output_cost self.class.new( requirements: new_requirements, strategy: @strategy, provider_preferences: @provider_preferences, fallback_options: ) end |