ruby_llm_community 0.0.6 → 1.1.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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -3
  3. data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +127 -0
  4. data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +39 -0
  5. data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +24 -0
  6. data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +14 -0
  7. data/lib/generators/ruby_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +12 -0
  8. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +16 -0
  9. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +29 -0
  10. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +16 -0
  11. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/new.html.erb.tt +11 -0
  12. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +23 -0
  13. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_form.html.erb.tt +21 -0
  14. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_message.html.erb.tt +10 -0
  15. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +9 -0
  16. data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +16 -0
  17. data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +30 -0
  18. data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +18 -0
  19. data/lib/generators/ruby_llm/install/install_generator.rb +227 -0
  20. data/lib/generators/ruby_llm/install/templates/chat_model.rb.tt +2 -2
  21. data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +4 -4
  22. data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +8 -7
  23. data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +43 -0
  24. data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +6 -5
  25. data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +10 -4
  26. data/lib/generators/ruby_llm/install/templates/message_model.rb.tt +4 -3
  27. data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +3 -0
  28. data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +2 -2
  29. data/lib/generators/ruby_llm/upgrade_to_v1_7/templates/migration.rb.tt +137 -0
  30. data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +170 -0
  31. data/lib/ruby_llm/active_record/acts_as.rb +112 -332
  32. data/lib/ruby_llm/active_record/acts_as_legacy.rb +403 -0
  33. data/lib/ruby_llm/active_record/chat_methods.rb +336 -0
  34. data/lib/ruby_llm/active_record/message_methods.rb +72 -0
  35. data/lib/ruby_llm/active_record/model_methods.rb +84 -0
  36. data/lib/ruby_llm/aliases.json +130 -11
  37. data/lib/ruby_llm/aliases.rb +7 -25
  38. data/lib/ruby_llm/attachment.rb +22 -0
  39. data/lib/ruby_llm/chat.rb +10 -17
  40. data/lib/ruby_llm/configuration.rb +11 -12
  41. data/lib/ruby_llm/connection.rb +4 -4
  42. data/lib/ruby_llm/connection_multipart.rb +19 -0
  43. data/lib/ruby_llm/content.rb +5 -2
  44. data/lib/ruby_llm/embedding.rb +1 -2
  45. data/lib/ruby_llm/error.rb +0 -8
  46. data/lib/ruby_llm/image.rb +23 -8
  47. data/lib/ruby_llm/image_attachment.rb +30 -0
  48. data/lib/ruby_llm/message.rb +7 -7
  49. data/lib/ruby_llm/model/info.rb +12 -10
  50. data/lib/ruby_llm/model/pricing.rb +0 -3
  51. data/lib/ruby_llm/model/pricing_category.rb +0 -2
  52. data/lib/ruby_llm/model/pricing_tier.rb +0 -1
  53. data/lib/ruby_llm/models.json +4705 -2144
  54. data/lib/ruby_llm/models.rb +56 -35
  55. data/lib/ruby_llm/provider.rb +14 -12
  56. data/lib/ruby_llm/providers/anthropic/capabilities.rb +1 -46
  57. data/lib/ruby_llm/providers/anthropic/chat.rb +2 -2
  58. data/lib/ruby_llm/providers/anthropic/media.rb +1 -2
  59. data/lib/ruby_llm/providers/anthropic/tools.rb +1 -2
  60. data/lib/ruby_llm/providers/anthropic.rb +1 -2
  61. data/lib/ruby_llm/providers/bedrock/chat.rb +2 -4
  62. data/lib/ruby_llm/providers/bedrock/media.rb +0 -1
  63. data/lib/ruby_llm/providers/bedrock/models.rb +19 -3
  64. data/lib/ruby_llm/providers/bedrock/streaming/base.rb +0 -12
  65. data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +0 -7
  66. data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +0 -12
  67. data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +0 -12
  68. data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +0 -13
  69. data/lib/ruby_llm/providers/bedrock/streaming.rb +0 -18
  70. data/lib/ruby_llm/providers/bedrock.rb +1 -2
  71. data/lib/ruby_llm/providers/deepseek/capabilities.rb +1 -2
  72. data/lib/ruby_llm/providers/deepseek/chat.rb +0 -1
  73. data/lib/ruby_llm/providers/gemini/capabilities.rb +28 -100
  74. data/lib/ruby_llm/providers/gemini/chat.rb +57 -29
  75. data/lib/ruby_llm/providers/gemini/embeddings.rb +0 -2
  76. data/lib/ruby_llm/providers/gemini/images.rb +1 -2
  77. data/lib/ruby_llm/providers/gemini/media.rb +1 -2
  78. data/lib/ruby_llm/providers/gemini/models.rb +1 -2
  79. data/lib/ruby_llm/providers/gemini/streaming.rb +15 -1
  80. data/lib/ruby_llm/providers/gemini/tools.rb +0 -5
  81. data/lib/ruby_llm/providers/gpustack/chat.rb +11 -1
  82. data/lib/ruby_llm/providers/gpustack/media.rb +45 -0
  83. data/lib/ruby_llm/providers/gpustack/models.rb +44 -9
  84. data/lib/ruby_llm/providers/gpustack.rb +1 -0
  85. data/lib/ruby_llm/providers/mistral/capabilities.rb +2 -10
  86. data/lib/ruby_llm/providers/mistral/chat.rb +0 -2
  87. data/lib/ruby_llm/providers/mistral/embeddings.rb +0 -3
  88. data/lib/ruby_llm/providers/mistral/models.rb +0 -1
  89. data/lib/ruby_llm/providers/ollama/chat.rb +0 -1
  90. data/lib/ruby_llm/providers/ollama/media.rb +2 -7
  91. data/lib/ruby_llm/providers/ollama/models.rb +36 -0
  92. data/lib/ruby_llm/providers/ollama.rb +1 -0
  93. data/lib/ruby_llm/providers/openai/capabilities.rb +3 -16
  94. data/lib/ruby_llm/providers/openai/chat.rb +1 -3
  95. data/lib/ruby_llm/providers/openai/embeddings.rb +0 -3
  96. data/lib/ruby_llm/providers/openai/images.rb +73 -3
  97. data/lib/ruby_llm/providers/openai/media.rb +4 -5
  98. data/lib/ruby_llm/providers/openai/response.rb +121 -29
  99. data/lib/ruby_llm/providers/openai/response_media.rb +3 -3
  100. data/lib/ruby_llm/providers/openai/streaming.rb +110 -47
  101. data/lib/ruby_llm/providers/openai/tools.rb +12 -7
  102. data/lib/ruby_llm/providers/openai.rb +1 -3
  103. data/lib/ruby_llm/providers/openai_base.rb +2 -2
  104. data/lib/ruby_llm/providers/openrouter/models.rb +1 -16
  105. data/lib/ruby_llm/providers/perplexity/capabilities.rb +0 -1
  106. data/lib/ruby_llm/providers/perplexity/chat.rb +0 -1
  107. data/lib/ruby_llm/providers/perplexity.rb +1 -5
  108. data/lib/ruby_llm/providers/vertexai/chat.rb +14 -0
  109. data/lib/ruby_llm/providers/vertexai/embeddings.rb +32 -0
  110. data/lib/ruby_llm/providers/vertexai/models.rb +130 -0
  111. data/lib/ruby_llm/providers/vertexai/streaming.rb +14 -0
  112. data/lib/ruby_llm/providers/vertexai.rb +55 -0
  113. data/lib/ruby_llm/providers/xai/capabilities.rb +166 -0
  114. data/lib/ruby_llm/providers/xai/chat.rb +15 -0
  115. data/lib/ruby_llm/providers/xai/models.rb +48 -0
  116. data/lib/ruby_llm/providers/xai.rb +46 -0
  117. data/lib/ruby_llm/railtie.rb +20 -4
  118. data/lib/ruby_llm/stream_accumulator.rb +68 -10
  119. data/lib/ruby_llm/streaming.rb +16 -25
  120. data/lib/ruby_llm/tool.rb +2 -19
  121. data/lib/ruby_llm/tool_call.rb +0 -9
  122. data/lib/ruby_llm/utils.rb +5 -9
  123. data/lib/ruby_llm/version.rb +1 -1
  124. data/lib/ruby_llm_community.rb +8 -5
  125. data/lib/tasks/models.rake +549 -0
  126. data/lib/tasks/release.rake +37 -2
  127. data/lib/tasks/ruby_llm.rake +15 -0
  128. data/lib/tasks/vcr.rake +2 -9
  129. metadata +44 -6
  130. data/lib/generators/ruby_llm/install/templates/INSTALL_INFO.md.tt +0 -108
  131. data/lib/generators/ruby_llm/install_generator.rb +0 -121
  132. data/lib/tasks/aliases.rake +0 -235
  133. data/lib/tasks/models_docs.rake +0 -224
  134. data/lib/tasks/models_update.rake +0 -108
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyLLM
4
- # Handles streaming responses from AI providers. Provides a unified way to process
5
- # chunked responses, accumulate content, and handle provider-specific streaming formats.
6
- # Each provider implements provider-specific parsing while sharing common stream handling
7
- # patterns.
4
+ # Handles streaming responses from AI providers.
8
5
  module Streaming
9
6
  module_function
10
7
 
@@ -12,17 +9,14 @@ module RubyLLM
12
9
  accumulator = StreamAccumulator.new
13
10
 
14
11
  response = connection.post stream_url, payload do |req|
15
- # Merge additional headers, with existing headers taking precedence
16
12
  req.headers = additional_headers.merge(req.headers) unless additional_headers.empty?
17
- if req.options.respond_to?(:on_data)
18
- # Handle Faraday 2.x streaming with on_data method
19
- req.options.on_data = handle_stream do |chunk|
13
+ if faraday_1?
14
+ req.options[:on_data] = handle_stream do |chunk|
20
15
  accumulator.add chunk
21
16
  block.call chunk
22
17
  end
23
18
  else
24
- # Handle Faraday 1.x streaming with :on_data key
25
- req.options[:on_data] = handle_stream do |chunk|
19
+ req.options.on_data = handle_stream do |chunk|
26
20
  accumulator.add chunk
27
21
  block.call chunk
28
22
  end
@@ -30,7 +24,7 @@ module RubyLLM
30
24
  end
31
25
 
32
26
  message = accumulator.to_message(response)
33
- RubyLLM.logger.debug "Stream completed: #{message.inspect}"
27
+ RubyLLM.logger.debug "Stream completed: #{message.content}"
34
28
  message
35
29
  end
36
30
 
@@ -42,6 +36,10 @@ module RubyLLM
42
36
 
43
37
  private
44
38
 
39
+ def faraday_1?
40
+ Faraday::VERSION.start_with?('1')
41
+ end
42
+
45
43
  def to_json_stream(&)
46
44
  buffer = +''
47
45
  parser = EventStreamParser::Parser.new
@@ -50,11 +48,9 @@ module RubyLLM
50
48
  end
51
49
 
52
50
  def create_stream_processor(parser, buffer, &)
53
- if Faraday::VERSION.start_with?('1')
54
- # Faraday 1.x: on_data receives (chunk, size)
51
+ if faraday_1?
55
52
  legacy_stream_processor(parser, &)
56
53
  else
57
- # Faraday 2.x: on_data receives (chunk, bytes, env)
58
54
  stream_processor(parser, buffer, &)
59
55
  end
60
56
  end
@@ -94,12 +90,10 @@ module RubyLLM
94
90
  status, _message = parse_streaming_error(error_data)
95
91
  parsed_data = JSON.parse(error_data)
96
92
 
97
- # Create a response-like object that works for both Faraday v1 and v2
98
- error_response = if env
99
- env.merge(body: parsed_data, status: status)
100
- else
101
- # For Faraday v1, create a simple object that responds to .status and .body
93
+ error_response = if faraday_1?
102
94
  Struct.new(:body, :status).new(parsed_data, status)
95
+ else
96
+ env.merge(body: parsed_data, status: status)
103
97
  end
104
98
 
105
99
  ErrorMiddleware.parse_error(provider: self, response: error_response)
@@ -137,12 +131,10 @@ module RubyLLM
137
131
  status, _message = parse_streaming_error(data)
138
132
  parsed_data = JSON.parse(data)
139
133
 
140
- # Create a response-like object that works for both Faraday v1 and v2
141
- error_response = if env
142
- env.merge(body: parsed_data, status: status)
143
- else
144
- # For Faraday v1, create a simple object that responds to .status and .body
134
+ error_response = if faraday_1?
145
135
  Struct.new(:body, :status).new(parsed_data, status)
136
+ else
137
+ env.merge(body: parsed_data, status: status)
146
138
  end
147
139
 
148
140
  ErrorMiddleware.parse_error(provider: self, response: error_response)
@@ -150,7 +142,6 @@ module RubyLLM
150
142
  RubyLLM.logger.debug "Failed to parse error event: #{e.message}"
151
143
  end
152
144
 
153
- # Default implementation - providers should override this method
154
145
  def parse_streaming_error(data)
155
146
  error_data = JSON.parse(data)
156
147
  [500, error_data['message'] || 'Unknown streaming error']
data/lib/ruby_llm/tool.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyLLM
4
- # Parameter definition for Tool methods. Specifies type constraints,
5
- # descriptions, and whether parameters are required.
4
+ # Parameter definition for Tool methods.
6
5
  class Parameter
7
6
  attr_reader :name, :type, :description, :required
8
7
 
@@ -14,23 +13,7 @@ module RubyLLM
14
13
  end
15
14
  end
16
15
 
17
- # Base class for creating tools that AI models can use. Provides a simple
18
- # interface for defining parameters and implementing tool behavior.
19
- #
20
- # Example:
21
- # require 'tzinfo'
22
- #
23
- # class TimeInfo < RubyLLM::Tool
24
- # description 'Gets the current time in various timezones'
25
- # param :timezone, desc: "Timezone name (e.g., 'UTC', 'America/New_York')"
26
- #
27
- # def execute(timezone:)
28
- # time = TZInfo::Timezone.get(timezone).now.strftime('%Y-%m-%d %H:%M:%S')
29
- # "Current time in #{timezone}: #{time}"
30
- # rescue StandardError => e
31
- # { error: e.message }
32
- # end
33
- # end
16
+ # Base class for creating tools that AI models can use
34
17
  class Tool
35
18
  # Stops conversation continuation after tool execution
36
19
  class Halt
@@ -2,15 +2,6 @@
2
2
 
3
3
  module RubyLLM
4
4
  # Represents a function call from an AI model to a Tool.
5
- # Encapsulates the function name, arguments, and execution results
6
- # in a clean Ruby interface.
7
- #
8
- # Example:
9
- # tool_call = ToolCall.new(
10
- # id: "call_123",
11
- # name: "calculator",
12
- # arguments: { expression: "2 + 2" }
13
- # )
14
5
  class ToolCall
15
6
  attr_reader :id, :name, :arguments
16
7
 
@@ -5,10 +5,6 @@ module RubyLLM
5
5
  module Utils
6
6
  module_function
7
7
 
8
- def format_text_file_for_llm(text_file)
9
- "<file name='#{text_file.filename}' mime_type='#{text_file.mime_type}'>#{text_file.content}</file>"
10
- end
11
-
12
8
  def hash_get(hash, key)
13
9
  hash[key.to_sym] || hash[key.to_s]
14
10
  end
@@ -36,12 +32,12 @@ module RubyLLM
36
32
  value.is_a?(Date) ? value : Date.parse(value.to_s)
37
33
  end
38
34
 
39
- def deep_merge(params, payload)
40
- params.merge(payload) do |_key, params_value, payload_value|
41
- if params_value.is_a?(Hash) && payload_value.is_a?(Hash)
42
- deep_merge(params_value, payload_value)
35
+ def deep_merge(original, overrides)
36
+ original.merge(overrides) do |_key, original_value, overrides_value|
37
+ if original_value.is_a?(Hash) && overrides_value.is_a?(Hash)
38
+ deep_merge(original_value, overrides_value)
43
39
  else
44
- payload_value
40
+ overrides_value
45
41
  end
46
42
  end
47
43
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyLLM
4
- VERSION = '0.0.6'
4
+ VERSION = '1.1.0'
5
5
  end
@@ -4,6 +4,8 @@ require 'base64'
4
4
  require 'event_stream_parser'
5
5
  require 'faraday'
6
6
  require 'faraday/retry'
7
+ require 'faraday/multipart'
8
+
7
9
  require 'json'
8
10
  require 'logger'
9
11
  require 'securerandom'
@@ -23,12 +25,13 @@ loader.inflector.inflect(
23
25
  'gpustack' => 'GPUStack',
24
26
  'mistral' => 'Mistral',
25
27
  'pdf' => 'PDF',
26
- 'version' => 'VERSION'
28
+ 'version' => 'VERSION',
29
+ 'vertexai' => 'VertexAI',
30
+ 'xai' => 'XAI',
31
+ 'UI' => 'UI'
27
32
  )
28
33
  loader.ignore("#{__dir__}/shims")
29
34
  loader.ignore("#{__dir__}/tasks")
30
- loader.ignore("#{__dir__}/ruby_llm/railtie")
31
- loader.ignore("#{__dir__}/ruby_llm/active_record")
32
35
  loader.ignore("#{__dir__}/generators")
33
36
  loader.setup
34
37
 
@@ -37,8 +40,6 @@ module RubyLlmCommunity
37
40
  end
38
41
 
39
42
  # A delightful Ruby interface to modern AI language models.
40
- # Provides a unified way to interact with models from OpenAI, Anthropic and others
41
- # with a focus on developer happiness and convention over configuration.
42
43
  module RubyLLM
43
44
  class Error < StandardError; end
44
45
 
@@ -97,6 +98,8 @@ RubyLLM::Provider.register :ollama, RubyLLM::Providers::Ollama
97
98
  RubyLLM::Provider.register :openai, RubyLLM::Providers::OpenAI
98
99
  RubyLLM::Provider.register :openrouter, RubyLLM::Providers::OpenRouter
99
100
  RubyLLM::Provider.register :perplexity, RubyLLM::Providers::Perplexity
101
+ RubyLLM::Provider.register :vertexai, RubyLLM::Providers::VertexAI
102
+ RubyLLM::Provider.register :xai, RubyLLM::Providers::XAI
100
103
 
101
104
  if defined?(Rails::Railtie)
102
105
  require 'ruby_llm/railtie'