Skip to content

Commit eb602d0

Browse files
committed
Model aliases.
1 parent 012dd5f commit eb602d0

File tree

5 files changed

+168
-2
lines changed

5 files changed

+168
-2
lines changed

docs/guides/models.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,35 @@ google_models = RubyLLM.models.by_provider('gemini')
6363
deepseek_models = RubyLLM.models.by_provider('deepseek')
6464
```
6565

66+
## Using Model Aliases
67+
68+
RubyLLM provides convenient aliases for popular models, so you don't have to remember specific version numbers:
69+
70+
```ruby
71+
# These are equivalent
72+
chat = RubyLLM.chat(model: 'claude-3-5-sonnet')
73+
chat = RubyLLM.chat(model: 'claude-3-5-sonnet-20241022')
74+
75+
# These are also equivalent
76+
chat = RubyLLM.chat(model: 'gpt-4o')
77+
chat = RubyLLM.chat(model: 'gpt-4o-2024-11-20')
78+
```
79+
80+
Aliases for common models include:
81+
82+
| Alias | Resolves To |
83+
|--------|-------------|
84+
| `claude-3-5-sonnet` | `claude-3-5-sonnet-20241022` |
85+
| `claude-3-5-haiku` | `claude-3-5-haiku-20241022` |
86+
| `claude-3-7-sonnet` | `claude-3-7-sonnet-20250219` |
87+
| `claude-3-opus` | `claude-3-opus-20240229` |
88+
| `gpt-4o` | `gpt-4o-2024-11-20` |
89+
| `gpt-4o-mini` | `gpt-4o-mini-2024-07-18` |
90+
| `gemini-1.5-flash` | `gemini-1.5-flash-002` |
91+
| `gemini-2.0-flash` | `gemini-2.0-flash-001` |
92+
93+
Aliases are particularly useful when you want your code to always use the latest stable version of a model without having to update your codebase when providers release new model versions.
94+
6695
## Chaining Filters
6796

6897
You can chain multiple filters to find exactly what you need:

lib/ruby_llm/aliases.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"claude-3-5-sonnet": {
3+
"anthropic": "claude-3-5-sonnet-20241022"
4+
},
5+
"claude-3-5-haiku": {
6+
"anthropic": "claude-3-5-haiku-20241022"
7+
},
8+
"claude-3-7-sonnet": {
9+
"anthropic": "claude-3-7-sonnet-20250219"
10+
},
11+
"claude-3-opus": {
12+
"anthropic": "claude-3-opus-20240229"
13+
},
14+
"claude-3-sonnet": {
15+
"anthropic": "claude-3-sonnet-20240229"
16+
},
17+
"claude-3-haiku": {
18+
"anthropic": "claude-3-haiku-20240307"
19+
},
20+
"claude-3": {
21+
"anthropic": "claude-3-sonnet-20240229"
22+
},
23+
"gpt-4o": {
24+
"openai": "gpt-4o-2024-11-20"
25+
},
26+
"gpt-4o-mini": {
27+
"openai": "gpt-4o-mini-2024-07-18"
28+
},
29+
"gpt-4-turbo": {
30+
"openai": "gpt-4-turbo-2024-04-09"
31+
},
32+
"gemini-1.5-flash": {
33+
"gemini": "gemini-1.5-flash-002"
34+
},
35+
"gemini-1.5-flash-8b": {
36+
"gemini": "gemini-1.5-flash-8b-001"
37+
},
38+
"gemini-1.5-pro": {
39+
"gemini": "gemini-1.5-pro-002"
40+
},
41+
"gemini-2.0-flash": {
42+
"gemini": "gemini-2.0-flash-001"
43+
},
44+
"o1": {
45+
"openai": "o1-2024-12-17"
46+
},
47+
"o3-mini": {
48+
"openai": "o3-mini-2025-01-31"
49+
}
50+
}

lib/ruby_llm/aliases.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# frozen_string_literal: true
2+
3+
module RubyLLM
4+
# Manages model aliases, allowing users to reference models by simpler names
5+
# that map to specific model versions across different providers.
6+
#
7+
# Aliases are defined in aliases.json and follow the format:
8+
# {
9+
# "simple-name": {
10+
# "provider1": "specific-version-for-provider1",
11+
# "provider2": "specific-version-for-provider2"
12+
# }
13+
# }
14+
class Aliases
15+
class << self
16+
# Resolves a model ID to its provider-specific version
17+
#
18+
# @param model_id [String] the model identifier or alias
19+
# @param provider_slug [String, Symbol, nil] optional provider to resolve for
20+
# @return [String] the resolved model ID or the original if no alias exists
21+
def resolve(model_id, provider_slug = nil)
22+
provider_aliases = aliases[model_id]
23+
return model_id unless provider_aliases
24+
25+
if provider_slug
26+
provider_aliases[provider_slug.to_s] || model_id
27+
else
28+
provider_aliases.values.first || model_id
29+
end
30+
end
31+
32+
# Returns the loaded aliases mapping
33+
# @return [Hash] the aliases mapping
34+
def aliases
35+
@aliases ||= load_aliases
36+
end
37+
38+
# Loads aliases from the JSON file
39+
# @return [Hash] the loaded aliases
40+
def load_aliases
41+
file_path = File.expand_path('aliases.json', __dir__)
42+
if File.exist?(file_path)
43+
JSON.parse(File.read(file_path))
44+
else
45+
{}
46+
end
47+
end
48+
49+
# Reloads aliases from disk
50+
# @return [Hash] the reloaded aliases
51+
def reload!
52+
@aliases = load_aliases
53+
end
54+
end
55+
end
56+
end

lib/ruby_llm/models.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,19 @@ def each(&)
7474

7575
# Find a specific model by ID
7676
def find(model_id)
77-
all.find { |m| m.id == model_id } or
78-
raise ModelNotFoundError, "Unknown model: #{model_id}"
77+
# Try exact match first
78+
exact_match = all.find { |m| m.id == model_id }
79+
return exact_match if exact_match
80+
81+
# Try to resolve via alias
82+
resolved_id = Aliases.resolve(model_id)
83+
if resolved_id != model_id
84+
alias_match = all.find { |m| m.id == resolved_id }
85+
return alias_match if alias_match
86+
end
87+
88+
# Not found
89+
raise ModelNotFoundError, "Unknown model: #{model_id}"
7990
end
8091

8192
# Filter to only chat models
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
require 'dotenv/load'
5+
6+
RSpec.describe RubyLLM::Chat do
7+
include_context 'with configured RubyLLM'
8+
9+
it 'finds models by alias name' do
10+
# Core test - can we find a model using just its alias?
11+
chat = RubyLLM.chat(model: 'claude-3-5-sonnet')
12+
expect(chat.model.id).to eq('claude-3-5-sonnet-20241022')
13+
end
14+
15+
it 'still supports exact model IDs' do
16+
# Backward compatibility check
17+
chat = RubyLLM.chat(model: 'claude-3-5-sonnet-20241022')
18+
expect(chat.model.id).to eq('claude-3-5-sonnet-20241022')
19+
end
20+
end

0 commit comments

Comments
 (0)