ruby_llm 1.12.1 → 1.13.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 +2 -0
- data/lib/generators/ruby_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +1 -1
- data/lib/generators/ruby_llm/generator_helpers.rb +4 -0
- data/lib/generators/ruby_llm/install/install_generator.rb +5 -4
- data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +1 -1
- data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +1 -1
- data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +1 -6
- data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +1 -1
- data/lib/ruby_llm/active_record/acts_as.rb +8 -2
- data/lib/ruby_llm/active_record/acts_as_legacy.rb +29 -0
- data/lib/ruby_llm/active_record/chat_methods.rb +35 -4
- data/lib/ruby_llm/agent.rb +33 -5
- data/lib/ruby_llm/aliases.json +19 -9
- data/lib/ruby_llm/chat.rb +107 -11
- data/lib/ruby_llm/configuration.rb +18 -0
- data/lib/ruby_llm/connection.rb +10 -4
- data/lib/ruby_llm/content.rb +0 -2
- data/lib/ruby_llm/error.rb +32 -1
- data/lib/ruby_llm/message.rb +5 -3
- data/lib/ruby_llm/model/info.rb +1 -1
- data/lib/ruby_llm/models.json +3535 -2894
- data/lib/ruby_llm/models.rb +5 -3
- data/lib/ruby_llm/provider.rb +5 -1
- data/lib/ruby_llm/providers/anthropic/capabilities.rb +22 -4
- data/lib/ruby_llm/providers/anthropic/chat.rb +22 -5
- data/lib/ruby_llm/providers/anthropic/models.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/tools.rb +20 -0
- data/lib/ruby_llm/providers/anthropic.rb +1 -1
- data/lib/ruby_llm/providers/azure/chat.rb +1 -1
- data/lib/ruby_llm/providers/azure/embeddings.rb +1 -1
- data/lib/ruby_llm/providers/azure/models.rb +1 -1
- data/lib/ruby_llm/providers/azure.rb +88 -0
- data/lib/ruby_llm/providers/bedrock/chat.rb +50 -5
- data/lib/ruby_llm/providers/bedrock/models.rb +17 -1
- data/lib/ruby_llm/providers/bedrock/streaming.rb +8 -4
- data/lib/ruby_llm/providers/bedrock.rb +5 -1
- data/lib/ruby_llm/providers/deepseek/capabilities.rb +8 -0
- data/lib/ruby_llm/providers/deepseek.rb +1 -1
- data/lib/ruby_llm/providers/gemini/capabilities.rb +8 -0
- data/lib/ruby_llm/providers/gemini/chat.rb +19 -4
- data/lib/ruby_llm/providers/gemini/images.rb +1 -1
- data/lib/ruby_llm/providers/gemini/streaming.rb +1 -1
- data/lib/ruby_llm/providers/gemini/tools.rb +19 -0
- data/lib/ruby_llm/providers/gpustack/capabilities.rb +20 -0
- data/lib/ruby_llm/providers/gpustack.rb +4 -0
- data/lib/ruby_llm/providers/mistral/capabilities.rb +8 -0
- data/lib/ruby_llm/providers/mistral/chat.rb +2 -1
- data/lib/ruby_llm/providers/ollama/capabilities.rb +20 -0
- data/lib/ruby_llm/providers/ollama.rb +7 -1
- data/lib/ruby_llm/providers/openai/capabilities.rb +10 -2
- data/lib/ruby_llm/providers/openai/chat.rb +15 -5
- data/lib/ruby_llm/providers/openai/media.rb +4 -1
- data/lib/ruby_llm/providers/openai/temperature.rb +2 -2
- data/lib/ruby_llm/providers/openai/tools.rb +27 -2
- data/lib/ruby_llm/providers/openrouter/chat.rb +19 -5
- data/lib/ruby_llm/providers/openrouter/images.rb +69 -0
- data/lib/ruby_llm/providers/openrouter.rb +31 -1
- data/lib/ruby_llm/providers/vertexai/models.rb +1 -1
- data/lib/ruby_llm/providers/vertexai.rb +14 -6
- data/lib/ruby_llm/stream_accumulator.rb +10 -5
- data/lib/ruby_llm/streaming.rb +6 -6
- data/lib/ruby_llm/tool.rb +48 -3
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/tasks/models.rake +33 -7
- data/lib/tasks/release.rake +1 -1
- data/lib/tasks/ruby_llm.rake +7 -0
- data/lib/tasks/vcr.rake +1 -1
- metadata +4 -1
data/lib/ruby_llm/error.rb
CHANGED
|
@@ -14,13 +14,16 @@ module RubyLLM
|
|
|
14
14
|
|
|
15
15
|
# Error classes for non-HTTP errors
|
|
16
16
|
class ConfigurationError < StandardError; end
|
|
17
|
+
class PromptNotFoundError < StandardError; end
|
|
17
18
|
class InvalidRoleError < StandardError; end
|
|
19
|
+
class InvalidToolChoiceError < StandardError; end
|
|
18
20
|
class ModelNotFoundError < StandardError; end
|
|
19
21
|
class UnsupportedAttachmentError < StandardError; end
|
|
20
22
|
|
|
21
23
|
# Error classes for different HTTP status codes
|
|
22
24
|
class BadRequestError < Error; end
|
|
23
25
|
class ForbiddenError < Error; end
|
|
26
|
+
class ContextLengthExceededError < Error; end
|
|
24
27
|
class OverloadedError < Error; end
|
|
25
28
|
class PaymentRequiredError < Error; end
|
|
26
29
|
class RateLimitError < Error; end
|
|
@@ -42,6 +45,18 @@ module RubyLLM
|
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
class << self
|
|
48
|
+
CONTEXT_LENGTH_PATTERNS = [
|
|
49
|
+
/context length/i,
|
|
50
|
+
/context window/i,
|
|
51
|
+
/maximum context/i,
|
|
52
|
+
/request too large/i,
|
|
53
|
+
/too many tokens/i,
|
|
54
|
+
/token count exceeds/i,
|
|
55
|
+
/input[_\s-]?token/i,
|
|
56
|
+
/input or output tokens? must be reduced/i,
|
|
57
|
+
/reduce the length of messages/i
|
|
58
|
+
].freeze
|
|
59
|
+
|
|
45
60
|
def parse_error(provider:, response:) # rubocop:disable Metrics/PerceivedComplexity
|
|
46
61
|
message = provider&.parse_error(response)
|
|
47
62
|
|
|
@@ -49,6 +64,10 @@ module RubyLLM
|
|
|
49
64
|
when 200..399
|
|
50
65
|
message
|
|
51
66
|
when 400
|
|
67
|
+
if context_length_exceeded?(message)
|
|
68
|
+
raise ContextLengthExceededError.new(response, message || 'Context length exceeded')
|
|
69
|
+
end
|
|
70
|
+
|
|
52
71
|
raise BadRequestError.new(response, message || 'Invalid request - please check your input')
|
|
53
72
|
when 401
|
|
54
73
|
raise UnauthorizedError.new(response, message || 'Invalid API key - check your credentials')
|
|
@@ -58,10 +77,14 @@ module RubyLLM
|
|
|
58
77
|
raise ForbiddenError.new(response,
|
|
59
78
|
message || 'Forbidden - you do not have permission to access this resource')
|
|
60
79
|
when 429
|
|
80
|
+
if context_length_exceeded?(message)
|
|
81
|
+
raise ContextLengthExceededError.new(response, message || 'Context length exceeded')
|
|
82
|
+
end
|
|
83
|
+
|
|
61
84
|
raise RateLimitError.new(response, message || 'Rate limit exceeded - please wait a moment')
|
|
62
85
|
when 500
|
|
63
86
|
raise ServerError.new(response, message || 'API server error - please try again')
|
|
64
|
-
when 502..
|
|
87
|
+
when 502..504
|
|
65
88
|
raise ServiceUnavailableError.new(response, message || 'API server unavailable - please try again later')
|
|
66
89
|
when 529
|
|
67
90
|
raise OverloadedError.new(response, message || 'Service overloaded - please try again later')
|
|
@@ -69,6 +92,14 @@ module RubyLLM
|
|
|
69
92
|
raise Error.new(response, message || 'An unknown error occurred')
|
|
70
93
|
end
|
|
71
94
|
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def context_length_exceeded?(message)
|
|
99
|
+
return false if message.to_s.empty?
|
|
100
|
+
|
|
101
|
+
CONTEXT_LENGTH_PATTERNS.any? { |pattern| message.match?(pattern) }
|
|
102
|
+
end
|
|
72
103
|
end
|
|
73
104
|
end
|
|
74
105
|
end
|
data/lib/ruby_llm/message.rb
CHANGED
|
@@ -10,9 +10,9 @@ module RubyLLM
|
|
|
10
10
|
|
|
11
11
|
def initialize(options = {})
|
|
12
12
|
@role = options.fetch(:role).to_sym
|
|
13
|
-
@content = normalize_content(options.fetch(:content))
|
|
14
|
-
@model_id = options[:model_id]
|
|
15
13
|
@tool_calls = options[:tool_calls]
|
|
14
|
+
@content = normalize_content(options.fetch(:content), role: @role, tool_calls: @tool_calls)
|
|
15
|
+
@model_id = options[:model_id]
|
|
16
16
|
@tool_call_id = options[:tool_call_id]
|
|
17
17
|
@tokens = options[:tokens] || Tokens.build(
|
|
18
18
|
input: options[:input_tokens],
|
|
@@ -90,7 +90,9 @@ module RubyLLM
|
|
|
90
90
|
|
|
91
91
|
private
|
|
92
92
|
|
|
93
|
-
def normalize_content(content)
|
|
93
|
+
def normalize_content(content, role:, tool_calls:)
|
|
94
|
+
return '' if role == :assistant && content.nil? && tool_calls && !tool_calls.empty?
|
|
95
|
+
|
|
94
96
|
case content
|
|
95
97
|
when String then Content.new(content)
|
|
96
98
|
when Hash then Content.new(content[:text], content)
|
data/lib/ruby_llm/model/info.rb
CHANGED
|
@@ -24,7 +24,7 @@ module RubyLLM
|
|
|
24
24
|
@name = data[:name]
|
|
25
25
|
@provider = data[:provider]
|
|
26
26
|
@family = data[:family]
|
|
27
|
-
@created_at = Utils.to_time(data[:created_at])
|
|
27
|
+
@created_at = Utils.to_time(data[:created_at])&.utc
|
|
28
28
|
@context_window = data[:context_window]
|
|
29
29
|
@max_output_tokens = data[:max_output_tokens]
|
|
30
30
|
@knowledge_cutoff = Utils.to_date(data[:knowledge_cutoff])
|