ruby_llm 2.0.0.rc3 → 2.0.0.rc4
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.
- checksums.yaml +4 -4
- data/.rdoc_options +2 -2
- data/README.md +32 -21
- data/lib/generators/ruby_llm/upgrade/online_copy_migration/data.rb +9 -0
- data/lib/generators/ruby_llm/upgrade/online_copy_migration.rb +5 -1
- data/lib/generators/ruby_llm/upgrade/templates/backfill_v2_data.rb.tt +6 -2
- data/lib/generators/ruby_llm/upgrade/templates/finish_v2_upgrade.rb.tt +8 -2
- data/lib/generators/ruby_llm/upgrade/templates/ruby_llm_upgrade.rb.tt +1 -1
- data/lib/generators/ruby_llm/upgrade/templates/upgrade_initializer.rb.tt +1 -1
- data/lib/generators/ruby_llm/upgrade/upgrade_generator.rb +11 -0
- data/lib/generators/ruby_llm/upgrade/upgrade_migration.rb +2 -1
- data/lib/ruby_llm/batch.rb +2 -2
- data/lib/ruby_llm/chat.rb +2 -2
- data/lib/ruby_llm/embedding.rb +1 -1
- data/lib/ruby_llm/image.rb +1 -1
- data/lib/ruby_llm/models.json +1654 -1791
- data/lib/ruby_llm/moderation.rb +1 -1
- data/lib/ruby_llm/ocr.rb +1 -1
- data/lib/ruby_llm/protocols/anthropic/chat.rb +1 -6
- data/lib/ruby_llm/protocols/chat_completions/chat.rb +2 -11
- data/lib/ruby_llm/protocols/converse/chat.rb +0 -1
- data/lib/ruby_llm/protocols/responses/chat.rb +0 -10
- data/lib/ruby_llm/providers/openrouter/chat.rb +1 -5
- data/lib/ruby_llm/rerank.rb +1 -1
- data/lib/ruby_llm/speech.rb +1 -1
- data/lib/ruby_llm/transcription.rb +1 -1
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/ruby_llm/video_job.rb +1 -1
- data/lib/ruby_llm.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c047801a2b7a5a642296f0ae84e81ab29b641353ffe8618b3ece44db0b0a3849
|
|
4
|
+
data.tar.gz: 05e4624f14a8e2045408dd21007758612f0644522bae4e250902fd60d66955e1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6e73e5f6818e70c607c3cabfc6e0dfb19f9271491375b71279e0a205f2ecff8fe0051c691c51230644d32f7ad8f377b8f8bddfcae919e33ff64015ccd9a942e7
|
|
7
|
+
data.tar.gz: fd4285734764621dc2cab77579b8c713aaff907930c1b6849472c470839b2a75e6975832baf4e43adeedd1d3326b92af816af4a63242bdfa2585fab2b72fdc58
|
data/.rdoc_options
CHANGED
|
@@ -17,8 +17,8 @@ exclude:
|
|
|
17
17
|
- \.json$
|
|
18
18
|
footer_content:
|
|
19
19
|
Documentation:
|
|
20
|
-
Guides: https://rubyllm.com/
|
|
21
|
-
Upgrading: https://rubyllm.com/
|
|
20
|
+
Guides: https://rubyllm.com/
|
|
21
|
+
Upgrading: https://rubyllm.com/upgrading/
|
|
22
22
|
Resources:
|
|
23
23
|
GitHub: https://github.com/crmne/ruby_llm
|
|
24
24
|
Issues: https://github.com/crmne/ruby_llm/issues
|
data/README.md
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
<strong>Build AI features the Ruby way</strong>
|
|
9
9
|
|
|
10
|
-
<p>
|
|
10
|
+
<p>RubyLLM is the Ruby-native AI framework. Work with models, tools, and agents through one consistent API, in plain Ruby or Rails.</p>
|
|
11
|
+
|
|
12
|
+
[Website](https://rubyllm.com/) · [Getting Started](https://rubyllm.com/getting-started/) · [What's New in 2.0](https://rubyllm.com/whats-new-in-2-0/)
|
|
11
13
|
|
|
12
14
|
Battle tested at [<picture><source media="(prefers-color-scheme: dark)" srcset="https://chatwithwork.com/logotype-dark.svg"><img src="https://chatwithwork.com/logotype.svg" alt="Chat with Work" height="30" align="absmiddle"></picture>](https://chatwithwork.com) - *Fully private work AI*
|
|
13
15
|
|
|
@@ -24,26 +26,19 @@ Battle tested at [<picture><source media="(prefers-color-scheme: dark)" srcset="
|
|
|
24
26
|
|
|
25
27
|
---
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Build a working Ruby AI chat in two minutes
|
|
30
|
-
|
|
31
|
-
https://github.com/user-attachments/assets/65422091-9338-47da-a303-92b918bd1345
|
|
32
|
-
|
|
33
|
-
## Why RubyLLM?
|
|
29
|
+
## 17 providers. One Ruby API.
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
Build with the models you want. Move between hosted and local providers without rewriting your application, or connect an OpenAI-compatible endpoint.
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
[Browse models and pricing](https://rubyllm.com/available-models/) · [Connect a provider](https://rubyllm.com/configuration-providers/)
|
|
38
34
|
|
|
39
|
-
##
|
|
35
|
+
## Start with one line. Add files, tools, and agents
|
|
40
36
|
|
|
41
|
-
These examples use **2.0.0.
|
|
37
|
+
These examples use **2.0.0.rc4 (prerelease)**. Follow [Getting Started](https://rubyllm.com/getting-started/) to install it and configure the providers you want to try. For 1.x, use the [stable-version docs](https://rubyllm.com/v1/).
|
|
42
38
|
|
|
43
39
|
```ruby
|
|
44
|
-
# Just ask
|
|
45
|
-
chat
|
|
46
|
-
chat.ask "What's the best way to learn Ruby?"
|
|
40
|
+
# Just ask
|
|
41
|
+
RubyLLM.chat.ask "What's the best way to learn Ruby?"
|
|
47
42
|
```
|
|
48
43
|
|
|
49
44
|
```ruby
|
|
@@ -155,7 +150,9 @@ response = chat.with_schema(ProductSchema).ask "Analyze this product", with: "pr
|
|
|
155
150
|
response.parsed
|
|
156
151
|
```
|
|
157
152
|
|
|
158
|
-
##
|
|
153
|
+
## A complete AI framework for Ruby
|
|
154
|
+
|
|
155
|
+
Agents, workflows, RAG, images, audio, and video. Built in, with usage tracking and Rails integration to bring them into your app.
|
|
159
156
|
|
|
160
157
|
* **Chat:** Conversational AI with `RubyLLM.chat`
|
|
161
158
|
* **Vision:** Analyze images and videos
|
|
@@ -195,7 +192,7 @@ response.parsed
|
|
|
195
192
|
Install the 2.0 release candidate:
|
|
196
193
|
|
|
197
194
|
```bash
|
|
198
|
-
bundle add ruby_llm --version 2.0.0.
|
|
195
|
+
bundle add ruby_llm --version 2.0.0.rc4
|
|
199
196
|
```
|
|
200
197
|
|
|
201
198
|
Configure a provider in your script, or in `config/initializers/ruby_llm.rb` in Rails:
|
|
@@ -208,9 +205,13 @@ RubyLLM.configure do |config|
|
|
|
208
205
|
end
|
|
209
206
|
```
|
|
210
207
|
|
|
211
|
-
Configure the other providers used by the examples as needed: Gemini for files, xAI for video, Mistral for OCR, and Cohere for reranking. [Getting Started](https://rubyllm.com/
|
|
208
|
+
Configure the other providers used by the examples as needed: Gemini for files, xAI for video, Mistral for OCR, and Cohere for reranking. [Getting Started](https://rubyllm.com/getting-started/) shows each setup beside its example. If your app uses 1.16, follow the [upgrade guide](https://rubyllm.com/upgrading/) before deploying 2.0.
|
|
212
209
|
|
|
213
|
-
## Rails
|
|
210
|
+
## Feels at home in Rails
|
|
211
|
+
|
|
212
|
+
Save conversations with Active Record and stream replies with Hotwire. The generators give you a working chat UI. Watch the two-minute demo.
|
|
213
|
+
|
|
214
|
+
https://github.com/user-attachments/assets/65422091-9338-47da-a303-92b918bd1345
|
|
214
215
|
|
|
215
216
|
```bash
|
|
216
217
|
# Install Rails Integration
|
|
@@ -231,11 +232,21 @@ chat = Chat.create! model: "gpt-5.6-luna"
|
|
|
231
232
|
chat.ask "What's in this file?", with: "report.pdf"
|
|
232
233
|
```
|
|
233
234
|
|
|
234
|
-
|
|
235
|
+
Start your Rails server and visit `http://localhost:3000/chats` to try the chat interface. See the [Rails guide](https://rubyllm.com/rails/) for persistence, streaming, and background jobs.
|
|
236
|
+
|
|
237
|
+
## AI coding assistants
|
|
238
|
+
|
|
239
|
+
Give your coding assistant the RubyLLM API and documentation that match your application. From your application directory, install the skill packaged with your gem:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
npx skills add "$(bundle show ruby_llm)" --skill rubyllm
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Choose your coding assistant and installation scope when prompted. See [AI Coding Assistants](https://rubyllm.com/ai-coding-assistants/) for setup and updates.
|
|
235
246
|
|
|
236
247
|
## Documentation
|
|
237
248
|
|
|
238
|
-
[Guides](https://rubyllm.com/
|
|
249
|
+
[Guides](https://rubyllm.com/getting-started/) · [API reference](https://rubyllm.com/api/) · [Models](https://rubyllm.com/available-models/) · [Upgrading](https://rubyllm.com/upgrading/) · [1.x docs](https://rubyllm.com/v1/)
|
|
239
250
|
|
|
240
251
|
## Contributing
|
|
241
252
|
|
|
@@ -63,6 +63,15 @@ module RubyLLM
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def discard_incomplete_tool_calls
|
|
67
|
+
source = records(configuration.fetch('tool_call_table'))
|
|
68
|
+
result_key = configuration.fetch('tool_call_foreign_key')
|
|
69
|
+
results = messages.where.not(result_key => nil).select(result_key)
|
|
70
|
+
owners = legacy_messages.select(messages.primary_key)
|
|
71
|
+
source.where(configuration.fetch('message_foreign_key') => owners)
|
|
72
|
+
.where.not(source.primary_key => results).delete_all
|
|
73
|
+
end
|
|
74
|
+
|
|
66
75
|
def catch_up(passes: nil)
|
|
67
76
|
sync_models
|
|
68
77
|
pass = 0
|
|
@@ -47,7 +47,7 @@ module RubyLLM
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def finish
|
|
50
|
+
def finish(discard_incomplete_tool_calls: false)
|
|
51
51
|
with_migration_lock do
|
|
52
52
|
state = states.first!
|
|
53
53
|
return if state.active_version == 2 && state.status == 'active' && data.finished?
|
|
@@ -55,6 +55,10 @@ module RubyLLM
|
|
|
55
55
|
raise 'Run the copy backfill before finish' unless data.completed?
|
|
56
56
|
|
|
57
57
|
pause(state, from: 1, statuses: %w[preparing active finishing])
|
|
58
|
+
if discard_incomplete_tool_calls
|
|
59
|
+
discarded = data.discard_incomplete_tool_calls
|
|
60
|
+
::ActiveRecord::Migration.say "Discarded #{discarded} incomplete legacy tool calls"
|
|
61
|
+
end
|
|
58
62
|
data.catch_up
|
|
59
63
|
data.verify
|
|
60
64
|
verify_completed_work
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'generators/ruby_llm/upgrade/legacy_content_sql'
|
|
4
3
|
<% if copy_mode? -%>
|
|
5
|
-
|
|
6
4
|
require 'generators/ruby_llm/upgrade/upgrade_migration'
|
|
5
|
+
<% else -%>
|
|
6
|
+
require 'generators/ruby_llm/upgrade/legacy_content_sql'
|
|
7
7
|
<% end -%>
|
|
8
8
|
|
|
9
9
|
class <%= backfill_migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
|
|
10
10
|
disable_ddl_transaction!
|
|
11
11
|
|
|
12
|
+
<% unless copy_mode? -%>
|
|
12
13
|
BATCH_SIZE = 10_000
|
|
14
|
+
<% end -%>
|
|
13
15
|
PROGRESS_TABLE = :ruby_llm_v2_backfills
|
|
14
16
|
|
|
15
17
|
def up
|
|
@@ -46,6 +48,7 @@ class <%= backfill_migration_class_name %> < ActiveRecord::Migration<%= migratio
|
|
|
46
48
|
raise 'The RubyLLM 2.0 upgrade is already finished. Do not run the backfill again.'
|
|
47
49
|
end
|
|
48
50
|
|
|
51
|
+
<% unless copy_mode? -%>
|
|
49
52
|
def backfill_required_defaults
|
|
50
53
|
{
|
|
51
54
|
<%= chat_table_name %>: {cancelled: false},
|
|
@@ -453,6 +456,7 @@ class <%= backfill_migration_class_name %> < ActiveRecord::Migration<%= migratio
|
|
|
453
456
|
yield
|
|
454
457
|
end
|
|
455
458
|
|
|
459
|
+
<% end -%>
|
|
456
460
|
def progress_records = migration_record(PROGRESS_TABLE)
|
|
457
461
|
|
|
458
462
|
def migration_record(table)
|
|
@@ -13,7 +13,7 @@ class <%= finish_migration_class_name %> < ActiveRecord::Migration<%= migration_
|
|
|
13
13
|
def up
|
|
14
14
|
<% if copy_mode? -%>
|
|
15
15
|
RubyLLM::Generators::UpgradeMigration.for.verify_settings(<%= copy_upgrade_settings.inspect %>)
|
|
16
|
-
RubyLLM::Generators::UpgradeMigration.for.finish do
|
|
16
|
+
RubyLLM::Generators::UpgradeMigration.for.finish<% if discard_incomplete_tool_calls? %>(discard_incomplete_tool_calls: true)<% end %> do
|
|
17
17
|
verify_completed_backfills
|
|
18
18
|
enforce_required_defaults
|
|
19
19
|
relax_legacy_message_constraints
|
|
@@ -113,6 +113,7 @@ class <%= finish_migration_class_name %> < ActiveRecord::Migration<%= migration_
|
|
|
113
113
|
raise "RubyLLM 2.0 backfills are incomplete: #{missing.join(', ')}"
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
<% unless copy_mode? -%>
|
|
116
117
|
def verify_message_content
|
|
117
118
|
return unless column_exists?(:<%= message_table_name %>, :content_raw)
|
|
118
119
|
|
|
@@ -220,17 +221,22 @@ class <%= finish_migration_class_name %> < ActiveRecord::Migration<%= migration_
|
|
|
220
221
|
<% end -%>
|
|
221
222
|
end
|
|
222
223
|
|
|
224
|
+
<% end -%>
|
|
223
225
|
def with_upgrade_safety(&)
|
|
224
226
|
return safety_assured(&) if respond_to?(:safety_assured, true)
|
|
225
227
|
|
|
226
228
|
yield
|
|
227
229
|
end
|
|
228
230
|
|
|
229
|
-
def message_value(column) = "legacy_messages.#{quote_column(column)}"
|
|
230
231
|
def column_definition(table, column) = connection.columns(table).find { |candidate| candidate.name == column.to_s }
|
|
232
|
+
<% unless copy_mode? -%>
|
|
233
|
+
def message_value(column) = "legacy_messages.#{quote_column(column)}"
|
|
231
234
|
def quoted_primary_key(table) = quote_column(connection.primary_key(table))
|
|
232
235
|
def quote_table(table) = connection.quote_table_name(table)
|
|
236
|
+
<% end -%>
|
|
237
|
+
<% if postgresql? || !copy_mode? -%>
|
|
233
238
|
def quote_column(column) = connection.quote_column_name(column)
|
|
239
|
+
<% end -%>
|
|
234
240
|
|
|
235
241
|
def migration_record(table)
|
|
236
242
|
Class.new(ActiveRecord::Base) do
|
|
@@ -15,7 +15,7 @@ module RubyLLMUpgrade # :nodoc: all
|
|
|
15
15
|
self.enumerate_columns_in_select_statements = true
|
|
16
16
|
default_scope { RubyLLMUpgrade.visible(self) }
|
|
17
17
|
after_initialize { @ruby_llm_upgrade_epoch = RubyLLMUpgrade.epoch }
|
|
18
|
-
around_save :guard_ruby_llm_upgrade
|
|
18
|
+
around_save :guard_ruby_llm_upgrade
|
|
19
19
|
around_destroy :guard_ruby_llm_upgrade, prepend: true
|
|
20
20
|
before_save { RubyLLMUpgrade.prepare_model(self) if ruby_llm_upgrade_kind == :chat }
|
|
21
21
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'active_record/base'
|
|
4
3
|
require Rails.root.join('app/models/concerns/ruby_llm_upgrade')
|
|
5
4
|
|
|
6
5
|
Rails.application.config.to_prepare do
|
|
6
|
+
require 'active_record/base'
|
|
7
7
|
tool_call = if Gem::Version.new(RubyLLM::VERSION).segments.first >= 2
|
|
8
8
|
RubyLLM::ActiveRecord::ToolCall
|
|
9
9
|
else
|
|
@@ -26,6 +26,8 @@ module RubyLLM
|
|
|
26
26
|
desc: 'Generate one upgrade phase; cleanup runs in a later deployment'
|
|
27
27
|
class_option :mode, type: :string, enum: %w[rename copy], default: 'rename',
|
|
28
28
|
desc: 'Copy prepares and backfills online, with protected 1.16 rollback until cleanup'
|
|
29
|
+
class_option :discard_incomplete_tool_calls, type: :boolean, default: false,
|
|
30
|
+
desc: 'Discard all incomplete legacy tool calls at copy finish'
|
|
29
31
|
|
|
30
32
|
argument :model_mappings,
|
|
31
33
|
type: :array,
|
|
@@ -39,6 +41,7 @@ module RubyLLM
|
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def create_migration_files
|
|
44
|
+
validate_cleanup_options
|
|
42
45
|
parse_model_mappings(allowed_types: MODEL_MAPPING_TYPES, defaults: MODEL_MAPPING_DEFAULTS)
|
|
43
46
|
say_status :models, resolved_model_mappings
|
|
44
47
|
|
|
@@ -132,6 +135,14 @@ module RubyLLM
|
|
|
132
135
|
private
|
|
133
136
|
|
|
134
137
|
def copy_mode? = options[:mode] == 'copy'
|
|
138
|
+
def discard_incomplete_tool_calls? = options[:discard_incomplete_tool_calls]
|
|
139
|
+
|
|
140
|
+
def validate_cleanup_options
|
|
141
|
+
return unless discard_incomplete_tool_calls?
|
|
142
|
+
return if copy_mode? && options[:phase].in?([nil, 'finish'])
|
|
143
|
+
|
|
144
|
+
raise Thor::Error, 'Discard incomplete tool calls only with --mode copy and the finish phase'
|
|
145
|
+
end
|
|
135
146
|
|
|
136
147
|
def copy_upgrade_settings
|
|
137
148
|
{
|
|
@@ -248,7 +248,8 @@ module RubyLLM
|
|
|
248
248
|
calls = records(:ruby_llm_tool_calls).where(message_type: configuration.fetch('message_class'), result_id: nil)
|
|
249
249
|
return unless calls.exists?
|
|
250
250
|
|
|
251
|
-
raise 'Finish pending tool calls and approvals before switching versions'
|
|
251
|
+
raise 'Finish pending tool calls and approvals before switching versions. ' \
|
|
252
|
+
'For abandoned legacy calls, see https://rubyllm.com/upgrading/#incomplete-tool-calls'
|
|
252
253
|
end
|
|
253
254
|
|
|
254
255
|
def reconcile
|
data/lib/ruby_llm/batch.rb
CHANGED
|
@@ -101,7 +101,7 @@ module RubyLLM
|
|
|
101
101
|
chats = normalize_chats(records)
|
|
102
102
|
|
|
103
103
|
provider = shared_provider(chats)
|
|
104
|
-
payload = { provider: provider.slug, provider_class: provider.
|
|
104
|
+
payload = { provider: provider.slug, provider_class: provider.name, requests: chats.size }
|
|
105
105
|
RubyLLM.instrument('batch.ruby_llm', payload, config: provider.config) do |event|
|
|
106
106
|
requests = chats.each_with_index.map do |chat, index|
|
|
107
107
|
{ custom_id: index.to_s, model: chat.model.id, payload: chat.render }
|
|
@@ -120,7 +120,7 @@ module RubyLLM
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
provider = shared_provider(requests)
|
|
123
|
-
payload = { provider: provider.slug, provider_class: provider.
|
|
123
|
+
payload = { provider: provider.slug, provider_class: provider.name, requests: requests.size }
|
|
124
124
|
RubyLLM.instrument('batch.ruby_llm', payload, config: provider.config) do |event|
|
|
125
125
|
lines = requests.each_with_index.map do |request, index|
|
|
126
126
|
{ custom_id: index.to_s, model: request.model.id, payload: request.render, text: request.text }
|
data/lib/ruby_llm/chat.rb
CHANGED
|
@@ -1003,7 +1003,7 @@ module RubyLLM
|
|
|
1003
1003
|
{
|
|
1004
1004
|
chat: self,
|
|
1005
1005
|
provider: @provider.slug,
|
|
1006
|
-
provider_class: @provider.
|
|
1006
|
+
provider_class: @provider.name,
|
|
1007
1007
|
model: @model.id,
|
|
1008
1008
|
model_info: @model,
|
|
1009
1009
|
input_messages: messages.dup,
|
|
@@ -1347,7 +1347,7 @@ module RubyLLM
|
|
|
1347
1347
|
payload = {
|
|
1348
1348
|
chat: self,
|
|
1349
1349
|
provider: @provider.slug,
|
|
1350
|
-
provider_class: @provider.
|
|
1350
|
+
provider_class: @provider.name,
|
|
1351
1351
|
model: @model.id,
|
|
1352
1352
|
model_info: @model,
|
|
1353
1353
|
tool: tool,
|
data/lib/ruby_llm/embedding.rb
CHANGED
data/lib/ruby_llm/image.rb
CHANGED