ruby_llm 1.14.0 → 1.14.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac485bae964a23af2c0a7ed48fa45fdb3207ad52d1ef6cbdca9b008b4c2429ba
4
- data.tar.gz: 7219680107ccf2af1bd7378b0e1b50b2eb328280e8e896cf8f9af7ac270c761a
3
+ metadata.gz: 2e29291ded69046aa32b77f524a148e14ce1b1bfbcaddea1da99b5cee66f7b13
4
+ data.tar.gz: '08a7aaa292f898f0e25f69658f19289799eb5e520feabf8a736bb3737d05fb9d'
5
5
  SHA512:
6
- metadata.gz: cfed1faf8354e9be7b39cfd44bd51596eaca75fb5d810bea7da72691ed7a7494a3ba779504acc20f8e92767be522bb3d6b77fab7db435ab91994b2db21255d2f
7
- data.tar.gz: 39b8ed657d27655a1f179fd46915da6acf81a8d0144ef2891bacb4f156311ab1be924d07018b9a095005864f3fb750a63a793d93db6a44de22c4c9bf6fab040f
6
+ metadata.gz: e9d4a4c8f284fc94669217c0979da4f6e6eccc95e0e47a8429b64c35c447ade3d994f278431c1593bc1fef804545e2bc0f5529775bc209b72dd728eeb4d99016
7
+ data.tar.gz: c6ed2232f289a940ad3b9ee29279005528bf74a5921b911fda19e8e2cc6ecb939405e46db76a7e1e83f580da69ed368fa197355b05efada524a537419ac37381
data/README.md CHANGED
@@ -9,10 +9,10 @@
9
9
 
10
10
  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) — *Your AI coworker*
11
11
 
12
- [![Gem Version](https://badge.fury.io/rb/ruby_llm.svg?a=10)](https://badge.fury.io/rb/ruby_llm)
12
+ [![Gem Version](https://badge.fury.io/rb/ruby_llm.svg)](https://badge.fury.io/rb/ruby_llm)
13
13
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
14
14
  [![Gem Downloads](https://img.shields.io/gem/dt/ruby_llm)](https://rubygems.org/gems/ruby_llm)
15
- [![codecov](https://codecov.io/gh/crmne/ruby_llm/branch/main/graph/badge.svg?a=2)](https://codecov.io/gh/crmne/ruby_llm)
15
+ [![codecov](https://codecov.io/gh/crmne/ruby_llm/branch/main/graph/badge.svg)](https://codecov.io/gh/crmne/ruby_llm)
16
16
 
17
17
  <a href="https://trendshift.io/repositories/13640" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13640" alt="crmne%2Fruby_llm | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
18
18
  </div>
@@ -24,6 +24,10 @@ Battle tested at [<picture><source media="(prefers-color-scheme: dark)" srcset="
24
24
 
25
25
  Build chatbots, AI agents, RAG applications. Works with OpenAI, xAI, Anthropic, Google, AWS, local models, and any OpenAI-compatible API.
26
26
 
27
+ ## From zero to AI chat app in under two minutes
28
+
29
+ https://github.com/user-attachments/assets/65422091-9338-47da-a303-92b918bd1345
30
+
27
31
  ## Why RubyLLM?
28
32
 
29
33
  Every AI provider ships their own bloated client. Different APIs. Different response formats. Different conventions. It's exhausting.
@@ -417,11 +417,18 @@ module RubyLLM
417
417
 
418
418
  attachment = source.is_a?(RubyLLM::Attachment) ? source : RubyLLM::Attachment.new(source)
419
419
 
420
- {
421
- io: StringIO.new(attachment.content),
422
- filename: attachment.filename,
423
- content_type: attachment.mime_type
424
- }
420
+ if attachment.active_storage?
421
+ case attachment.source
422
+ when ActiveStorage::Blob then attachment.source
423
+ when ActiveStorage::Attached::One, ActiveStorage::Attached::Many then attachment.source.blobs
424
+ end
425
+ else
426
+ {
427
+ io: StringIO.new(attachment.content),
428
+ filename: attachment.filename,
429
+ content_type: attachment.mime_type
430
+ }
431
+ end
425
432
  rescue StandardError => e
426
433
  RubyLLM.logger.warn "Failed to process attachment #{source}: #{e.message}"
427
434
  nil
@@ -5,6 +5,7 @@ module RubyLLM
5
5
  # Methods mixed into message models.
6
6
  module MessageMethods
7
7
  extend ActiveSupport::Concern
8
+ include PayloadHelpers
8
9
 
9
10
  class_methods do
10
11
  attr_reader :chat_class, :tool_call_class, :chat_foreign_key, :tool_call_foreign_key
@@ -52,10 +53,7 @@ module RubyLLM
52
53
  end
53
54
 
54
55
  def tool_error_message
55
- payload = parse_payload(content)
56
- return unless payload.is_a?(Hash)
57
-
58
- payload['error'] || payload[:error]
56
+ payload_error_message(content)
59
57
  end
60
58
 
61
59
  private
@@ -128,15 +126,6 @@ module RubyLLM
128
126
  @_tempfiles << tempfile
129
127
  tempfile
130
128
  end
131
-
132
- def parse_payload(value)
133
- return value if value.is_a?(Hash) || value.is_a?(Array)
134
- return if value.blank?
135
-
136
- JSON.parse(value)
137
- rescue JSON::ParserError
138
- nil
139
- end
140
129
  end
141
130
  end
142
131
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module ActiveRecord
5
+ # Shared helpers for parsing serialized payloads on ActiveRecord-backed models.
6
+ module PayloadHelpers
7
+ private
8
+
9
+ def payload_error_message(value)
10
+ payload = parse_payload(value)
11
+ return unless payload.is_a?(Hash)
12
+
13
+ payload['error'] || payload[:error]
14
+ end
15
+
16
+ def parse_payload(value)
17
+ return value if value.is_a?(Hash) || value.is_a?(Array)
18
+ return if value.blank?
19
+
20
+ JSON.parse(value)
21
+ rescue JSON::ParserError
22
+ nil
23
+ end
24
+ end
25
+ end
26
+ end
@@ -5,23 +5,10 @@ module RubyLLM
5
5
  # Methods mixed into tool call models.
6
6
  module ToolCallMethods
7
7
  extend ActiveSupport::Concern
8
+ include PayloadHelpers
8
9
 
9
10
  def tool_error_message
10
- payload = parse_payload(arguments)
11
- return unless payload.is_a?(Hash)
12
-
13
- payload['error'] || payload[:error]
14
- end
15
-
16
- private
17
-
18
- def parse_payload(value)
19
- return value if value.is_a?(Hash) || value.is_a?(Array)
20
- return if value.blank?
21
-
22
- JSON.parse(value)
23
- rescue JSON::ParserError
24
- nil
11
+ payload_error_message(arguments)
25
12
  end
26
13
  end
27
14
  end
@@ -10,7 +10,7 @@
10
10
  "claude-3-5-sonnet": {
11
11
  "anthropic": "claude-3-5-sonnet-20241022",
12
12
  "openrouter": "anthropic/claude-3.5-sonnet",
13
- "bedrock": "anthropic.claude-3-5-sonnet-20240620-v1:0:200k"
13
+ "bedrock": "anthropic.claude-3-5-sonnet-20241022-v2:0"
14
14
  },
15
15
  "claude-3-7-sonnet": {
16
16
  "anthropic": "claude-3-7-sonnet-20250219",
@@ -190,7 +190,8 @@
190
190
  },
191
191
  "gemini-3.1-flash-lite-preview": {
192
192
  "gemini": "gemini-3.1-flash-lite-preview",
193
- "openrouter": "google/gemini-3.1-flash-lite-preview"
193
+ "openrouter": "google/gemini-3.1-flash-lite-preview",
194
+ "vertexai": "gemini-3.1-flash-lite-preview"
194
195
  },
195
196
  "gemini-3.1-pro-preview": {
196
197
  "gemini": "gemini-3.1-pro-preview",
@@ -247,18 +248,10 @@
247
248
  "openrouter": "openai/gpt-4",
248
249
  "azure": "gpt-4"
249
250
  },
250
- "gpt-4-1106-preview": {
251
- "openai": "gpt-4-1106-preview",
252
- "openrouter": "openai/gpt-4-1106-preview"
253
- },
254
251
  "gpt-4-turbo": {
255
252
  "openai": "gpt-4-turbo",
256
253
  "openrouter": "openai/gpt-4-turbo"
257
254
  },
258
- "gpt-4-turbo-preview": {
259
- "openai": "gpt-4-turbo-preview",
260
- "openrouter": "openai/gpt-4-turbo-preview"
261
- },
262
255
  "gpt-4.1": {
263
256
  "openai": "gpt-4.1",
264
257
  "openrouter": "openai/gpt-4.1",
@@ -373,6 +366,14 @@
373
366
  "openai": "gpt-5.4",
374
367
  "openrouter": "openai/gpt-5.4"
375
368
  },
369
+ "gpt-5.4-mini": {
370
+ "openai": "gpt-5.4-mini",
371
+ "openrouter": "openai/gpt-5.4-mini"
372
+ },
373
+ "gpt-5.4-nano": {
374
+ "openai": "gpt-5.4-nano",
375
+ "openrouter": "openai/gpt-5.4-nano"
376
+ },
376
377
  "gpt-5.4-pro": {
377
378
  "openai": "gpt-5.4-pro",
378
379
  "openrouter": "openai/gpt-5.4-pro"
@@ -385,6 +386,14 @@
385
386
  "openai": "gpt-audio-mini",
386
387
  "openrouter": "openai/gpt-audio-mini"
387
388
  },
389
+ "lyria-3-clip-preview": {
390
+ "gemini": "lyria-3-clip-preview",
391
+ "openrouter": "google/lyria-3-clip-preview"
392
+ },
393
+ "lyria-3-pro-preview": {
394
+ "gemini": "lyria-3-pro-preview",
395
+ "openrouter": "google/lyria-3-pro-preview"
396
+ },
388
397
  "o1": {
389
398
  "openai": "o1",
390
399
  "openrouter": "openai/o1"