ruby_llm 0.1.0.pre40 → 0.1.0.pre42
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/.rspec_status +7 -4
- data/README.md +24 -1
- data/lib/ruby_llm/content.rb +24 -1
- data/lib/ruby_llm/models.json +345 -452
- data/lib/ruby_llm/provider.rb +1 -2
- data/lib/ruby_llm/providers/anthropic/chat.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/media.rb +66 -0
- data/lib/ruby_llm/providers/anthropic.rb +1 -0
- data/lib/ruby_llm/providers/gemini/chat.rb +140 -0
- data/lib/ruby_llm/providers/gemini/embeddings.rb +53 -0
- data/lib/ruby_llm/providers/gemini/images.rb +51 -0
- data/lib/ruby_llm/providers/gemini/media.rb +136 -0
- data/lib/ruby_llm/providers/gemini/models.rb +41 -6
- data/lib/ruby_llm/providers/gemini/streaming.rb +99 -0
- data/lib/ruby_llm/providers/gemini/tools.rb +88 -0
- data/lib/ruby_llm/providers/gemini.rb +10 -4
- data/lib/ruby_llm/providers/openai/images.rb +0 -2
- data/lib/ruby_llm/stream_accumulator.rb +1 -1
- data/lib/ruby_llm/version.rb +1 -1
- metadata +8 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dac5b1b15a5d840d74ac63af791044a26669e0d41b0512d37236530cdd89693
|
4
|
+
data.tar.gz: b737c0061790066680424051afd3b9ea75d9d63f014d1684261dde81c1bedf37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a90362b3d2dbe5b9f5c54851d94646273b343a32eef452528903026ea2e1add335a105273b0efc17a5ebde1da15421d894029ebe401e94c511531a1e8d2f706b
|
7
|
+
data.tar.gz: 504e5dd4e3692db83b6b9589e26e33f553865234b59264d05aec1f495e403e8e28eb2b7dfc2b2258047df07dd04f3740005b44dee8a874927b12a55f045fae6e
|
data/.rspec_status
CHANGED
@@ -7,6 +7,8 @@ example_id | status | run_time |
|
|
7
7
|
./spec/ruby_llm/chat_content_spec.rb[1:1:3] | passed | 2.54 seconds |
|
8
8
|
./spec/ruby_llm/chat_content_spec.rb[1:2:1] | passed | 2.77 seconds |
|
9
9
|
./spec/ruby_llm/chat_content_spec.rb[1:2:2] | passed | 2.1 seconds |
|
10
|
+
./spec/ruby_llm/chat_pdf_spec.rb[1:1:1] | passed | 7.75 seconds |
|
11
|
+
./spec/ruby_llm/chat_pdf_spec.rb[1:1:2] | passed | 13.88 seconds |
|
10
12
|
./spec/ruby_llm/chat_spec.rb[1:1:1:1] | passed | 1.02 seconds |
|
11
13
|
./spec/ruby_llm/chat_spec.rb[1:1:1:2] | passed | 3.95 seconds |
|
12
14
|
./spec/ruby_llm/chat_spec.rb[1:1:2:1] | passed | 0.4854 seconds |
|
@@ -32,7 +34,8 @@ example_id | status | run_time |
|
|
32
34
|
./spec/ruby_llm/embeddings_spec.rb[1:1:1:2] | passed | 0.43632 seconds |
|
33
35
|
./spec/ruby_llm/embeddings_spec.rb[1:1:2:1] | passed | 0.65614 seconds |
|
34
36
|
./spec/ruby_llm/embeddings_spec.rb[1:1:2:2] | passed | 2.16 seconds |
|
35
|
-
./spec/ruby_llm/error_handling_spec.rb[1:1] | passed | 0.
|
36
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:1] | passed |
|
37
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:2] | passed |
|
38
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:3] | passed |
|
37
|
+
./spec/ruby_llm/error_handling_spec.rb[1:1] | passed | 0.29366 seconds |
|
38
|
+
./spec/ruby_llm/image_generation_spec.rb[1:1:1] | passed | 11.61 seconds |
|
39
|
+
./spec/ruby_llm/image_generation_spec.rb[1:1:2] | passed | 17.63 seconds |
|
40
|
+
./spec/ruby_llm/image_generation_spec.rb[1:1:3] | passed | 8.77 seconds |
|
41
|
+
./spec/ruby_llm/image_generation_spec.rb[1:1:4] | passed | 0.00319 seconds |
|
data/README.md
CHANGED
@@ -16,7 +16,6 @@ A delightful Ruby way to work with AI. Chat in text, analyze and generate images
|
|
16
16
|
<a href="https://badge.fury.io/rb/ruby_llm"><img src="https://badge.fury.io/rb/ruby_llm.svg" alt="Gem Version" /></a>
|
17
17
|
<a href="https://github.com/testdouble/standard"><img src="https://img.shields.io/badge/code_style-standard-brightgreen.svg" alt="Ruby Style Guide" /></a>
|
18
18
|
<a href="https://rubygems.org/gems/ruby_llm"><img alt="Gem Total Downloads" src="https://img.shields.io/gem/dt/ruby_llm"></a>
|
19
|
-
<a href="https://github.com/crmne/ruby_llm/actions/workflows/cicd.yml"><img src="https://github.com/crmne/ruby_llm/actions/workflows/cicd.yml/badge.svg" alt="CI" /></a>
|
20
19
|
<a href="https://codecov.io/gh/crmne/ruby_llm"><img src="https://codecov.io/gh/crmne/ruby_llm/branch/main/graph/badge.svg" alt="codecov" /></a>
|
21
20
|
</p>
|
22
21
|
|
@@ -28,6 +27,7 @@ A delightful Ruby way to work with AI. Chat in text, analyze and generate images
|
|
28
27
|
- 🎵 **Audio Analysis** - Get audio transcription and understanding with `chat.ask "what's said here?", with: { audio: "clip.wav" }`
|
29
28
|
- 👁️ **Vision Understanding** - Let AIs analyze images with a simple `chat.ask "what's in this?", with: { image: "photo.jpg" }`
|
30
29
|
- 🌊 **Streaming** - Real-time responses with proper Ruby streaming with `chat.ask "hello" do |chunk| puts chunk.content end`
|
30
|
+
- 📄 **PDF Analysis** - Analyze PDF documents directly with `chat.ask "What's in this?", with: { pdf: "document.pdf" }`
|
31
31
|
- 🚂 **Rails Integration** - Persist chats and messages with ActiveRecord with `acts_as_{chat|message|tool_call}`
|
32
32
|
- 🛠️ **Tool Support** - Give AIs access to your Ruby code with `chat.with_tool(Calculator).ask "what's 2+2?"`
|
33
33
|
- 🎨 **Paint with AI** - Create images as easily as `RubyLLM.paint "a sunset over mountains"`
|
@@ -116,6 +116,14 @@ chat.ask "What's being said in this recording?", with: { audio: "meeting.wav" }
|
|
116
116
|
# Combine multiple pieces of content
|
117
117
|
chat.ask "Compare these diagrams", with: { image: ["diagram1.png", "diagram2.png"] }
|
118
118
|
|
119
|
+
# Ask about PDFs
|
120
|
+
|
121
|
+
chat = RubyLLM.chat(model: 'claude-3-7-sonnet-20250219')
|
122
|
+
chat.ask "Summarize this research paper", with: { pdf: "research.pdf" }
|
123
|
+
|
124
|
+
# Multiple PDFs work too
|
125
|
+
chat.ask "Compare these contracts", with: { pdf: ["contract1.pdf", "contract2.pdf"] }
|
126
|
+
|
119
127
|
# Check token usage
|
120
128
|
last_message = chat.messages.last
|
121
129
|
puts "Conversation used #{last_message.input_tokens} input tokens and #{last_message.output_tokens} output tokens"
|
@@ -440,6 +448,21 @@ pp chat.messages.map(&:role)
|
|
440
448
|
#=> [:user, :assistant, :tool, :assistant]
|
441
449
|
```
|
442
450
|
|
451
|
+
## Provider Comparison
|
452
|
+
|
453
|
+
| Feature | OpenAI | Anthropic | Google | DeepSeek |
|
454
|
+
|---------|--------|-----------|--------|----------|
|
455
|
+
| Chat | ✅ GPT-4o, GPT-3.5 | ✅ Claude 3.7, 3.5, 3 | ✅ Gemini 2.0, 1.5 | ✅ DeepSeek Chat, Reasoner |
|
456
|
+
| Vision | ✅ GPT-4o, GPT-4 | ✅ All Claude 3 models | ✅ Gemini 2.0, 1.5 | ❌ |
|
457
|
+
| Audio | ✅ GPT-4o-audio, Whisper | ❌ | ✅ Gemini models | ❌ |
|
458
|
+
| PDF Analysis | ❌ | ✅ All Claude 3 models | ✅ Gemini models | ❌ |
|
459
|
+
| Function Calling | ✅ Most models | ✅ Claude 3 models | ✅ Gemini models (except Lite) | ✅ |
|
460
|
+
| JSON Mode | ✅ Most recent models | ✅ Claude 3 models | ✅ Gemini models | ❌ |
|
461
|
+
| Image Generation | ✅ DALL-E 3 | ❌ | ✅ Imagen | ❌ |
|
462
|
+
| Embeddings | ✅ text-embedding-3 | ❌ | ✅ text-embedding-004 | ❌ |
|
463
|
+
| Context Size | ⭐ Up to 200K (o1) | ⭐ 200K tokens | ⭐ Up to 2M tokens | 64K tokens |
|
464
|
+
| Streaming | ✅ | ✅ | ✅ | ✅ |
|
465
|
+
|
443
466
|
## Development
|
444
467
|
|
445
468
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt.
|
data/lib/ruby_llm/content.rb
CHANGED
@@ -5,7 +5,7 @@ module RubyLLM
|
|
5
5
|
# Stores data in a standard internal format, letting providers
|
6
6
|
# handle their own formatting needs.
|
7
7
|
class Content
|
8
|
-
def initialize(text = nil, attachments = {})
|
8
|
+
def initialize(text = nil, attachments = {}) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
9
9
|
@parts = []
|
10
10
|
@parts << { type: 'text', text: text } unless text.nil? || text.empty?
|
11
11
|
|
@@ -16,6 +16,10 @@ module RubyLLM
|
|
16
16
|
Array(attachments[:audio]).each do |source|
|
17
17
|
@parts << attach_audio(source)
|
18
18
|
end
|
19
|
+
|
20
|
+
Array(attachments[:pdf]).each do |source|
|
21
|
+
@parts << attach_pdf(source)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
def to_a
|
@@ -64,6 +68,25 @@ module RubyLLM
|
|
64
68
|
}
|
65
69
|
end
|
66
70
|
|
71
|
+
def attach_pdf(source)
|
72
|
+
source = File.expand_path(source) unless source.start_with?('http')
|
73
|
+
|
74
|
+
pdf_data = {
|
75
|
+
type: 'pdf',
|
76
|
+
source: source
|
77
|
+
}
|
78
|
+
|
79
|
+
# For local files, validate they exist
|
80
|
+
unless source.start_with?('http')
|
81
|
+
raise Error, "PDF file not found: #{source}" unless File.exist?(source)
|
82
|
+
|
83
|
+
# Preload file content for providers that need it
|
84
|
+
pdf_data[:content] = File.read(source)
|
85
|
+
end
|
86
|
+
|
87
|
+
pdf_data
|
88
|
+
end
|
89
|
+
|
67
90
|
def encode_file(source)
|
68
91
|
if source.start_with?('http')
|
69
92
|
response = Faraday.get(source)
|