ruby_llm 1.3.0rc1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruby_llm/active_record/acts_as.rb +66 -148
  3. data/lib/ruby_llm/aliases.json +170 -42
  4. data/lib/ruby_llm/attachment.rb +164 -0
  5. data/lib/ruby_llm/chat.rb +12 -4
  6. data/lib/ruby_llm/configuration.rb +5 -1
  7. data/lib/ruby_llm/connection.rb +28 -2
  8. data/lib/ruby_llm/content.rb +9 -40
  9. data/lib/ruby_llm/error.rb +1 -0
  10. data/lib/ruby_llm/image.rb +2 -3
  11. data/lib/ruby_llm/message.rb +2 -2
  12. data/lib/ruby_llm/mime_type.rb +67 -0
  13. data/lib/ruby_llm/model/info.rb +101 -0
  14. data/lib/ruby_llm/model/modalities.rb +22 -0
  15. data/lib/ruby_llm/model/pricing.rb +51 -0
  16. data/lib/ruby_llm/model/pricing_category.rb +48 -0
  17. data/lib/ruby_llm/model/pricing_tier.rb +34 -0
  18. data/lib/ruby_llm/model.rb +7 -0
  19. data/lib/ruby_llm/models.json +2220 -1915
  20. data/lib/ruby_llm/models.rb +20 -20
  21. data/lib/ruby_llm/provider.rb +1 -1
  22. data/lib/ruby_llm/providers/anthropic/media.rb +14 -3
  23. data/lib/ruby_llm/providers/anthropic/models.rb +1 -1
  24. data/lib/ruby_llm/providers/bedrock/media.rb +7 -4
  25. data/lib/ruby_llm/providers/bedrock/models.rb +2 -2
  26. data/lib/ruby_llm/providers/gemini/images.rb +3 -2
  27. data/lib/ruby_llm/providers/gemini/media.rb +12 -24
  28. data/lib/ruby_llm/providers/gemini/models.rb +1 -1
  29. data/lib/ruby_llm/providers/ollama/media.rb +8 -4
  30. data/lib/ruby_llm/providers/openai/capabilities.rb +1 -1
  31. data/lib/ruby_llm/providers/openai/images.rb +3 -2
  32. data/lib/ruby_llm/providers/openai/media.rb +18 -8
  33. data/lib/ruby_llm/providers/openai/models.rb +1 -1
  34. data/lib/ruby_llm/providers/openrouter/models.rb +1 -1
  35. data/lib/ruby_llm/streaming.rb +46 -11
  36. data/lib/ruby_llm/utils.rb +14 -9
  37. data/lib/ruby_llm/version.rb +1 -1
  38. data/lib/tasks/aliases.rake +235 -0
  39. data/lib/tasks/release.rake +32 -0
  40. metadata +40 -25
  41. data/lib/ruby_llm/attachments/audio.rb +0 -12
  42. data/lib/ruby_llm/attachments/image.rb +0 -9
  43. data/lib/ruby_llm/attachments/pdf.rb +0 -9
  44. data/lib/ruby_llm/attachments.rb +0 -78
  45. data/lib/ruby_llm/mime_types.rb +0 -713
  46. data/lib/ruby_llm/model_info.rb +0 -237
  47. data/lib/tasks/{models.rake → models_update.rake} +13 -13
@@ -1,237 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyLLM
4
- # Information about an AI model's capabilities, pricing, and metadata.
5
- # Used by the Models registry to help developers choose the right model
6
- # for their needs.
7
- #
8
- # Example:
9
- # model = RubyLLM.models.find('gpt-4')
10
- # model.supports_vision? # => true
11
- # model.supports_functions? # => true
12
- # model.input_price_per_million # => 30.0
13
- class ModelInfo
14
- attr_reader :id, :name, :provider, :family, :created_at, :context_window, :max_output_tokens, :knowledge_cutoff,
15
- :modalities, :capabilities, :pricing, :metadata
16
-
17
- def initialize(data)
18
- @id = data[:id]
19
- @name = data[:name]
20
- @provider = data[:provider]
21
- @family = data[:family]
22
- @created_at = data[:created_at]
23
- @context_window = data[:context_window]
24
- @max_output_tokens = data[:max_output_tokens]
25
- @knowledge_cutoff = data[:knowledge_cutoff]
26
- @modalities = Modalities.new(data[:modalities] || {})
27
- @capabilities = data[:capabilities] || []
28
- @pricing = PricingCollection.new(data[:pricing] || {})
29
- @metadata = data[:metadata] || {}
30
- end
31
-
32
- # Capability methods
33
- def supports?(capability)
34
- capabilities.include?(capability.to_s)
35
- end
36
-
37
- %w[function_calling structured_output batch reasoning citations streaming].each do |cap|
38
- define_method "#{cap}?" do
39
- supports?(cap)
40
- end
41
- end
42
-
43
- # Backward compatibility methods
44
- def display_name
45
- name
46
- end
47
-
48
- def max_tokens
49
- max_output_tokens
50
- end
51
-
52
- def supports_vision?
53
- modalities.input.include?('image')
54
- end
55
-
56
- def supports_functions?
57
- function_calling?
58
- end
59
-
60
- def input_price_per_million
61
- pricing.text_tokens.input
62
- end
63
-
64
- def output_price_per_million
65
- pricing.text_tokens.output
66
- end
67
-
68
- def type # rubocop:disable Metrics/PerceivedComplexity
69
- if modalities.output.include?('embeddings') && !modalities.output.include?('text')
70
- 'embedding'
71
- elsif modalities.output.include?('image') && !modalities.output.include?('text')
72
- 'image'
73
- elsif modalities.output.include?('audio') && !modalities.output.include?('text')
74
- 'audio'
75
- elsif modalities.output.include?('moderation')
76
- 'moderation'
77
- else
78
- 'chat'
79
- end
80
- end
81
-
82
- def to_h
83
- {
84
- id: id,
85
- name: name,
86
- provider: provider,
87
- family: family,
88
- created_at: created_at,
89
- context_window: context_window,
90
- max_output_tokens: max_output_tokens,
91
- knowledge_cutoff: knowledge_cutoff,
92
- modalities: modalities.to_h,
93
- capabilities: capabilities,
94
- pricing: pricing.to_h,
95
- metadata: metadata
96
- }
97
- end
98
- end
99
-
100
- # Holds and manages input and output modalities for a language model
101
- class Modalities
102
- attr_reader :input, :output
103
-
104
- def initialize(data)
105
- @input = Array(data[:input]).map(&:to_s)
106
- @output = Array(data[:output]).map(&:to_s)
107
- end
108
-
109
- def to_h
110
- {
111
- input: input,
112
- output: output
113
- }
114
- end
115
- end
116
-
117
- # A collection that manages and provides access to different categories of pricing information
118
- # (text tokens, images, audio tokens, embeddings)
119
- class PricingCollection
120
- def initialize(data)
121
- @data = {}
122
-
123
- # Initialize pricing categories
124
- %i[text_tokens images audio_tokens embeddings].each do |category|
125
- @data[category] = PricingCategory.new(data[category]) if data[category] && !empty_pricing?(data[category])
126
- end
127
- end
128
-
129
- def method_missing(method, *args)
130
- if respond_to_missing?(method)
131
- @data[method.to_sym] || PricingCategory.new
132
- else
133
- super
134
- end
135
- end
136
-
137
- def respond_to_missing?(method, include_private = false)
138
- %i[text_tokens images audio_tokens embeddings].include?(method.to_sym) || super
139
- end
140
-
141
- def to_h
142
- @data.transform_values(&:to_h)
143
- end
144
-
145
- private
146
-
147
- def empty_pricing?(data)
148
- # Check if all pricing values in this category are zero or nil
149
- return true unless data
150
-
151
- %i[standard batch].each do |tier|
152
- next unless data[tier]
153
-
154
- data[tier].each_value do |value|
155
- return false if value && value != 0.0
156
- end
157
- end
158
-
159
- true
160
- end
161
- end
162
-
163
- # Represents pricing tiers for different usage categories (standard and batch), managing access to their respective
164
- # rates
165
- class PricingCategory
166
- attr_reader :standard, :batch
167
-
168
- def initialize(data = {})
169
- @standard = PricingTier.new(data[:standard] || {}) unless empty_tier?(data[:standard])
170
- @batch = PricingTier.new(data[:batch] || {}) unless empty_tier?(data[:batch])
171
- end
172
-
173
- # Shorthand methods that default to standard tier
174
- def input
175
- standard&.input_per_million
176
- end
177
-
178
- def output
179
- standard&.output_per_million
180
- end
181
-
182
- def cached_input
183
- standard&.cached_input_per_million
184
- end
185
-
186
- # Get value for a specific tier
187
- def [](key)
188
- key == :batch ? batch : standard
189
- end
190
-
191
- def to_h
192
- result = {}
193
- result[:standard] = standard.to_h if standard
194
- result[:batch] = batch.to_h if batch
195
- result
196
- end
197
-
198
- private
199
-
200
- def empty_tier?(tier_data)
201
- return true unless tier_data
202
-
203
- tier_data.values.all? { |v| v.nil? || v == 0.0 }
204
- end
205
- end
206
-
207
- # A dynamic class for storing non-zero pricing values with flexible attribute access
208
- class PricingTier
209
- def initialize(data = {})
210
- @values = {}
211
-
212
- # Only store non-zero values
213
- data.each do |key, value|
214
- @values[key.to_sym] = value if value && value != 0.0
215
- end
216
- end
217
-
218
- def method_missing(method, *args)
219
- if method.to_s.end_with?('=')
220
- key = method.to_s.chomp('=').to_sym
221
- @values[key] = args.first if args.first && args.first != 0.0
222
- elsif @values.key?(method)
223
- @values[method]
224
- else
225
- super
226
- end
227
- end
228
-
229
- def respond_to_missing?(method, include_private = false)
230
- method.to_s.end_with?('=') || @values.key?(method.to_sym) || super
231
- end
232
-
233
- def to_h
234
- @values
235
- end
236
- end
237
- end
@@ -3,6 +3,19 @@
3
3
  require 'dotenv/load'
4
4
  require 'ruby_llm'
5
5
 
6
+ task default: ['models:update']
7
+
8
+ namespace :models do
9
+ desc 'Update available models from providers (API keys needed)'
10
+ task :update do
11
+ puts 'Configuring RubyLLM...'
12
+ configure_from_env
13
+
14
+ refresh_models
15
+ display_model_stats
16
+ end
17
+ end
18
+
6
19
  def configure_from_env
7
20
  RubyLLM.configure do |config|
8
21
  config.openai_api_key = ENV.fetch('OPENAI_API_KEY', nil)
@@ -64,16 +77,3 @@ def status(provider_sym)
64
77
  ' (NOT CONFIGURED)'
65
78
  end
66
79
  end
67
-
68
- namespace :models do
69
- desc 'Update available models from providers (API keys needed)'
70
- task :update do
71
- puts 'Configuring RubyLLM...'
72
- configure_from_env
73
-
74
- refresh_models
75
- display_model_stats
76
- end
77
- end
78
-
79
- task default: ['models:update']