ruby_llm 1.5.0 → 1.6.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/ruby_llm/active_record/acts_as.rb +46 -6
- data/lib/ruby_llm/aliases.json +27 -3
- data/lib/ruby_llm/chat.rb +27 -6
- data/lib/ruby_llm/configuration.rb +7 -18
- data/lib/ruby_llm/connection.rb +11 -6
- data/lib/ruby_llm/context.rb +2 -3
- data/lib/ruby_llm/embedding.rb +3 -4
- data/lib/ruby_llm/error.rb +2 -2
- data/lib/ruby_llm/image.rb +3 -4
- data/lib/ruby_llm/message.rb +4 -0
- data/lib/ruby_llm/model/info.rb +2 -2
- data/lib/ruby_llm/models.json +7692 -7067
- data/lib/ruby_llm/models.rb +22 -31
- data/lib/ruby_llm/models_schema.json +168 -0
- data/lib/ruby_llm/provider.rb +150 -89
- data/lib/ruby_llm/providers/anthropic/capabilities.rb +1 -2
- data/lib/ruby_llm/providers/anthropic/chat.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/media.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/models.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/streaming.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/tools.rb +1 -1
- data/lib/ruby_llm/providers/anthropic.rb +17 -22
- data/lib/ruby_llm/providers/bedrock/capabilities.rb +3 -63
- data/lib/ruby_llm/providers/bedrock/chat.rb +5 -4
- data/lib/ruby_llm/providers/bedrock/media.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/models.rb +5 -6
- data/lib/ruby_llm/providers/bedrock/signing.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/base.rb +5 -4
- data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/streaming.rb +1 -1
- data/lib/ruby_llm/providers/bedrock.rb +26 -31
- data/lib/ruby_llm/providers/deepseek/capabilities.rb +16 -57
- data/lib/ruby_llm/providers/deepseek/chat.rb +1 -1
- data/lib/ruby_llm/providers/deepseek.rb +12 -17
- data/lib/ruby_llm/providers/gemini/capabilities.rb +4 -1
- data/lib/ruby_llm/providers/gemini/chat.rb +1 -1
- data/lib/ruby_llm/providers/gemini/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/gemini/images.rb +1 -1
- data/lib/ruby_llm/providers/gemini/media.rb +1 -1
- data/lib/ruby_llm/providers/gemini/models.rb +1 -1
- data/lib/ruby_llm/providers/gemini/streaming.rb +1 -1
- data/lib/ruby_llm/providers/gemini/tools.rb +1 -7
- data/lib/ruby_llm/providers/gemini.rb +18 -23
- data/lib/ruby_llm/providers/gpustack/chat.rb +1 -1
- data/lib/ruby_llm/providers/gpustack/models.rb +1 -1
- data/lib/ruby_llm/providers/gpustack.rb +16 -19
- data/lib/ruby_llm/providers/mistral/capabilities.rb +31 -19
- data/lib/ruby_llm/providers/mistral/chat.rb +1 -1
- data/lib/ruby_llm/providers/mistral/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/mistral/models.rb +1 -1
- data/lib/ruby_llm/providers/mistral.rb +14 -19
- data/lib/ruby_llm/providers/ollama/chat.rb +1 -1
- data/lib/ruby_llm/providers/ollama/media.rb +1 -1
- data/lib/ruby_llm/providers/ollama.rb +13 -18
- data/lib/ruby_llm/providers/openai/capabilities.rb +2 -2
- data/lib/ruby_llm/providers/openai/chat.rb +2 -2
- data/lib/ruby_llm/providers/openai/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/openai/images.rb +1 -1
- data/lib/ruby_llm/providers/openai/media.rb +1 -1
- data/lib/ruby_llm/providers/openai/models.rb +1 -1
- data/lib/ruby_llm/providers/openai/streaming.rb +1 -1
- data/lib/ruby_llm/providers/openai/tools.rb +1 -1
- data/lib/ruby_llm/providers/openai.rb +24 -36
- data/lib/ruby_llm/providers/openrouter/models.rb +1 -1
- data/lib/ruby_llm/providers/openrouter.rb +9 -14
- data/lib/ruby_llm/providers/perplexity/capabilities.rb +1 -30
- data/lib/ruby_llm/providers/perplexity/chat.rb +1 -1
- data/lib/ruby_llm/providers/perplexity/models.rb +1 -1
- data/lib/ruby_llm/providers/perplexity.rb +13 -18
- data/lib/ruby_llm/stream_accumulator.rb +3 -3
- data/lib/ruby_llm/streaming.rb +16 -3
- data/lib/ruby_llm/tool.rb +19 -0
- data/lib/ruby_llm/utils.rb +12 -0
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/tasks/models_docs.rake +18 -11
- data/lib/tasks/models_update.rake +31 -4
- metadata +2 -1
@@ -3,32 +3,27 @@
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
5
|
# DeepSeek API integration.
|
6
|
-
|
7
|
-
|
8
|
-
extend DeepSeek::Chat
|
6
|
+
class DeepSeek < OpenAI
|
7
|
+
include DeepSeek::Chat
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
def api_base(_config)
|
9
|
+
def api_base
|
13
10
|
'https://api.deepseek.com'
|
14
11
|
end
|
15
12
|
|
16
|
-
def headers
|
13
|
+
def headers
|
17
14
|
{
|
18
|
-
'Authorization' => "Bearer #{config.deepseek_api_key}"
|
15
|
+
'Authorization' => "Bearer #{@config.deepseek_api_key}"
|
19
16
|
}
|
20
17
|
end
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def slug
|
27
|
-
'deepseek'
|
28
|
-
end
|
19
|
+
class << self
|
20
|
+
def capabilities
|
21
|
+
DeepSeek::Capabilities
|
22
|
+
end
|
29
23
|
|
30
|
-
|
31
|
-
|
24
|
+
def configuration_requirements
|
25
|
+
%i[deepseek_api_key]
|
26
|
+
end
|
32
27
|
end
|
33
28
|
end
|
34
29
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Gemini
|
6
6
|
# Determines capabilities and pricing for Google Gemini models
|
7
7
|
module Capabilities
|
8
8
|
module_function
|
@@ -280,6 +280,9 @@ module RubyLLM
|
|
280
280
|
# Embedding output
|
281
281
|
modalities[:output] << 'embeddings' if model_id.match?(/embedding|gemini-embedding/)
|
282
282
|
|
283
|
+
# Image output for imagen models
|
284
|
+
modalities[:output] = ['image'] if model_id.match?(/imagen/)
|
285
|
+
|
283
286
|
modalities
|
284
287
|
end
|
285
288
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Gemini
|
6
6
|
# Tools methods for the Gemini API implementation
|
7
7
|
module Tools
|
8
8
|
# Format tools for Gemini API
|
@@ -18,26 +18,20 @@ module RubyLLM
|
|
18
18
|
def extract_tool_calls(data)
|
19
19
|
return nil unless data
|
20
20
|
|
21
|
-
# Get the first candidate
|
22
21
|
candidate = data.is_a?(Hash) ? data.dig('candidates', 0) : nil
|
23
22
|
return nil unless candidate
|
24
23
|
|
25
|
-
# Get the parts array from content
|
26
24
|
parts = candidate.dig('content', 'parts')
|
27
25
|
return nil unless parts.is_a?(Array)
|
28
26
|
|
29
|
-
# Find the function call part
|
30
27
|
function_call_part = parts.find { |p| p['functionCall'] }
|
31
28
|
return nil unless function_call_part
|
32
29
|
|
33
|
-
# Get the function call data
|
34
30
|
function_data = function_call_part['functionCall']
|
35
31
|
return nil unless function_data
|
36
32
|
|
37
|
-
# Create a unique ID for the tool call
|
38
33
|
id = SecureRandom.uuid
|
39
34
|
|
40
|
-
# Return the tool call in the expected format
|
41
35
|
{
|
42
36
|
id => ToolCall.new(
|
43
37
|
id: id,
|
@@ -3,38 +3,33 @@
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
5
|
# Native Gemini API implementation
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
extend Gemini::Media
|
6
|
+
class Gemini < Provider
|
7
|
+
include Gemini::Chat
|
8
|
+
include Gemini::Embeddings
|
9
|
+
include Gemini::Images
|
10
|
+
include Gemini::Models
|
11
|
+
include Gemini::Streaming
|
12
|
+
include Gemini::Tools
|
13
|
+
include Gemini::Media
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
def api_base(_config)
|
15
|
+
def api_base
|
19
16
|
'https://generativelanguage.googleapis.com/v1beta'
|
20
17
|
end
|
21
18
|
|
22
|
-
def headers
|
19
|
+
def headers
|
23
20
|
{
|
24
|
-
'x-goog-api-key' => config.gemini_api_key
|
21
|
+
'x-goog-api-key' => @config.gemini_api_key
|
25
22
|
}
|
26
23
|
end
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def slug
|
33
|
-
'gemini'
|
34
|
-
end
|
25
|
+
class << self
|
26
|
+
def capabilities
|
27
|
+
Gemini::Capabilities
|
28
|
+
end
|
35
29
|
|
36
|
-
|
37
|
-
|
30
|
+
def configuration_requirements
|
31
|
+
%i[gemini_api_key]
|
32
|
+
end
|
38
33
|
end
|
39
34
|
end
|
40
35
|
end
|
@@ -3,33 +3,30 @@
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
5
|
# GPUStack API integration based on Ollama.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
extend GPUStack::Models
|
6
|
+
class GPUStack < OpenAI
|
7
|
+
include GPUStack::Chat
|
8
|
+
include GPUStack::Models
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
def api_base(config)
|
14
|
-
config.gpustack_api_base
|
10
|
+
def api_base
|
11
|
+
@config.gpustack_api_base
|
15
12
|
end
|
16
13
|
|
17
|
-
def headers
|
14
|
+
def headers
|
15
|
+
return {} unless @config.gpustack_api_key
|
16
|
+
|
18
17
|
{
|
19
|
-
'Authorization' => "Bearer #{config.gpustack_api_key}"
|
18
|
+
'Authorization' => "Bearer #{@config.gpustack_api_key}"
|
20
19
|
}
|
21
20
|
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def local?
|
28
|
-
true
|
29
|
-
end
|
22
|
+
class << self
|
23
|
+
def local?
|
24
|
+
true
|
25
|
+
end
|
30
26
|
|
31
|
-
|
32
|
-
|
27
|
+
def configuration_requirements
|
28
|
+
%i[gpustack_api_base]
|
29
|
+
end
|
33
30
|
end
|
34
31
|
end
|
35
32
|
end
|
@@ -2,25 +2,29 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class Mistral
|
6
6
|
# Determines capabilities for Mistral models
|
7
7
|
module Capabilities
|
8
8
|
module_function
|
9
9
|
|
10
|
-
def supports_streaming?(
|
11
|
-
|
10
|
+
def supports_streaming?(model_id)
|
11
|
+
# All chat models support streaming, but not embedding/moderation/OCR/transcription
|
12
|
+
!model_id.match?(/embed|moderation|ocr|transcriptions/)
|
12
13
|
end
|
13
14
|
|
14
|
-
def supports_tools?(
|
15
|
-
|
15
|
+
def supports_tools?(model_id)
|
16
|
+
# Most chat models support tools except embedding/moderation/OCR/voxtral/transcription
|
17
|
+
!model_id.match?(/embed|moderation|ocr|voxtral|transcriptions|mistral-(tiny|small)-(2312|2402)/)
|
16
18
|
end
|
17
19
|
|
18
20
|
def supports_vision?(model_id)
|
19
|
-
|
21
|
+
# Models with vision capabilities
|
22
|
+
model_id.match?(/pixtral|mistral-small-(2503|2506)|mistral-medium/)
|
20
23
|
end
|
21
24
|
|
22
|
-
def supports_json_mode?(
|
23
|
-
|
25
|
+
def supports_json_mode?(model_id)
|
26
|
+
# Most chat models support JSON mode (structured output)
|
27
|
+
!model_id.match?(/embed|moderation|ocr|voxtral|transcriptions/) && supports_tools?(model_id)
|
24
28
|
end
|
25
29
|
|
26
30
|
def format_display_name(model_id)
|
@@ -71,7 +75,7 @@ module RubyLLM
|
|
71
75
|
when /embed/
|
72
76
|
{
|
73
77
|
input: ['text'],
|
74
|
-
output: ['
|
78
|
+
output: ['embeddings']
|
75
79
|
}
|
76
80
|
else
|
77
81
|
{
|
@@ -81,18 +85,26 @@ module RubyLLM
|
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
84
|
-
def capabilities_for(model_id)
|
88
|
+
def capabilities_for(model_id) # rubocop:disable Metrics/PerceivedComplexity
|
85
89
|
case model_id
|
86
|
-
when /
|
87
|
-
when /
|
90
|
+
when /moderation/ then ['moderation']
|
91
|
+
when /voxtral.*transcribe/ then ['transcription']
|
92
|
+
when /ocr/ then ['vision']
|
88
93
|
else
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
94
|
+
capabilities = []
|
95
|
+
capabilities << 'streaming' if supports_streaming?(model_id)
|
96
|
+
capabilities << 'function_calling' if supports_tools?(model_id)
|
97
|
+
capabilities << 'structured_output' if supports_json_mode?(model_id)
|
98
|
+
capabilities << 'vision' if supports_vision?(model_id)
|
99
|
+
|
100
|
+
# Model-specific capabilities
|
101
|
+
capabilities << 'reasoning' if model_id.match?(/magistral/)
|
102
|
+
capabilities << 'batch' unless model_id.match?(/voxtral|ocr|embed|moderation/)
|
103
|
+
capabilities << 'fine_tuning' if model_id.match?(/mistral-(small|medium|large)|devstral/)
|
104
|
+
capabilities << 'distillation' if model_id.match?(/ministral/)
|
105
|
+
capabilities << 'predicted_outputs' if model_id.match?(/codestral/)
|
106
|
+
|
107
|
+
capabilities.uniq
|
96
108
|
end
|
97
109
|
end
|
98
110
|
|
@@ -3,34 +3,29 @@
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
5
|
# Mistral API integration.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
extend Mistral::Embeddings
|
6
|
+
class Mistral < OpenAI
|
7
|
+
include Mistral::Chat
|
8
|
+
include Mistral::Models
|
9
|
+
include Mistral::Embeddings
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
def api_base(_config)
|
11
|
+
def api_base
|
15
12
|
'https://api.mistral.ai/v1'
|
16
13
|
end
|
17
14
|
|
18
|
-
def headers
|
15
|
+
def headers
|
19
16
|
{
|
20
|
-
'Authorization' => "Bearer #{config.mistral_api_key}"
|
17
|
+
'Authorization' => "Bearer #{@config.mistral_api_key}"
|
21
18
|
}
|
22
19
|
end
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def slug
|
29
|
-
'mistral'
|
30
|
-
end
|
21
|
+
class << self
|
22
|
+
def capabilities
|
23
|
+
Mistral::Capabilities
|
24
|
+
end
|
31
25
|
|
32
|
-
|
33
|
-
|
26
|
+
def configuration_requirements
|
27
|
+
%i[mistral_api_key]
|
28
|
+
end
|
34
29
|
end
|
35
30
|
end
|
36
31
|
end
|
@@ -3,31 +3,26 @@
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
5
|
# Ollama API integration.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
extend Ollama::Media
|
6
|
+
class Ollama < OpenAI
|
7
|
+
include Ollama::Chat
|
8
|
+
include Ollama::Media
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
def api_base(config)
|
14
|
-
config.ollama_api_base
|
10
|
+
def api_base
|
11
|
+
@config.ollama_api_base
|
15
12
|
end
|
16
13
|
|
17
|
-
def headers
|
14
|
+
def headers
|
18
15
|
{}
|
19
16
|
end
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def configuration_requirements
|
26
|
-
%i[ollama_api_base]
|
27
|
-
end
|
18
|
+
class << self
|
19
|
+
def configuration_requirements
|
20
|
+
%i[ollama_api_base]
|
21
|
+
end
|
28
22
|
|
29
|
-
|
30
|
-
|
23
|
+
def local?
|
24
|
+
true
|
25
|
+
end
|
31
26
|
end
|
32
27
|
end
|
33
28
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class OpenAI
|
6
6
|
# Determines capabilities and pricing for OpenAI models
|
7
7
|
module Capabilities
|
8
8
|
module_function
|
@@ -264,7 +264,7 @@ module RubyLLM
|
|
264
264
|
capabilities << 'batch' if model_id.match?(/embedding|batch/)
|
265
265
|
|
266
266
|
# Advanced capabilities
|
267
|
-
capabilities << 'reasoning' if model_id.match?(/
|
267
|
+
capabilities << 'reasoning' if model_id.match?(/o\d|gpt-5|codex/)
|
268
268
|
|
269
269
|
if model_id.match?(/gpt-4-turbo|gpt-4o/)
|
270
270
|
capabilities << 'image_generation' if model_id.match?(/vision/)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RubyLLM
|
4
4
|
module Providers
|
5
|
-
|
5
|
+
class OpenAI
|
6
6
|
# Chat methods of the OpenAI API integration
|
7
7
|
module Chat
|
8
8
|
def completion_url
|
@@ -78,7 +78,7 @@ module RubyLLM
|
|
78
78
|
def format_role(role)
|
79
79
|
case role
|
80
80
|
when :system
|
81
|
-
'developer'
|
81
|
+
@config.openai_use_system_role ? 'system' : 'developer'
|
82
82
|
else
|
83
83
|
role.to_s
|
84
84
|
end
|