ruby_llm 1.13.2 → 1.14.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/lib/generators/ruby_llm/agent/agent_generator.rb +36 -0
  4. data/lib/generators/ruby_llm/agent/templates/agent.rb.tt +6 -0
  5. data/lib/generators/ruby_llm/agent/templates/instructions.txt.erb.tt +0 -0
  6. data/lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb +110 -41
  7. data/lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt +14 -15
  8. data/lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt +8 -11
  9. data/lib/generators/ruby_llm/chat_ui/templates/controllers/models_controller.rb.tt +2 -2
  10. data/lib/generators/ruby_llm/chat_ui/templates/helpers/messages_helper.rb.tt +25 -0
  11. data/lib/generators/ruby_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +1 -1
  12. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_chat.html.erb.tt +16 -0
  13. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/_form.html.erb.tt +31 -0
  14. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/index.html.erb.tt +31 -0
  15. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/new.html.erb.tt +9 -0
  16. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/chats/show.html.erb.tt +27 -0
  17. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt +14 -0
  18. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_content.html.erb.tt +1 -0
  19. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_error.html.erb.tt +13 -0
  20. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_form.html.erb.tt +23 -0
  21. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_system.html.erb.tt +10 -0
  22. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool.html.erb.tt +2 -0
  23. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt +4 -0
  24. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/_user.html.erb.tt +14 -0
  25. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/tool_calls/_default.html.erb.tt +13 -0
  26. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/messages/tool_results/_default.html.erb.tt +21 -0
  27. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/_model.html.erb.tt +17 -0
  28. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/index.html.erb.tt +40 -0
  29. data/lib/generators/ruby_llm/chat_ui/templates/tailwind/views/models/show.html.erb.tt +27 -0
  30. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +2 -2
  31. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/_form.html.erb.tt +2 -2
  32. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt +19 -7
  33. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/new.html.erb.tt +1 -1
  34. data/lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt +5 -3
  35. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_assistant.html.erb.tt +9 -0
  36. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_content.html.erb.tt +1 -1
  37. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_error.html.erb.tt +8 -0
  38. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_form.html.erb.tt +1 -1
  39. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_system.html.erb.tt +6 -0
  40. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool.html.erb.tt +2 -0
  41. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +4 -7
  42. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_user.html.erb.tt +9 -0
  43. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +5 -7
  44. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_calls/_default.html.erb.tt +8 -0
  45. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/tool_results/_default.html.erb.tt +16 -0
  46. data/lib/generators/ruby_llm/chat_ui/templates/views/models/_model.html.erb.tt +11 -12
  47. data/lib/generators/ruby_llm/chat_ui/templates/views/models/index.html.erb.tt +27 -17
  48. data/lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt +3 -4
  49. data/lib/generators/ruby_llm/generator_helpers.rb +33 -17
  50. data/lib/generators/ruby_llm/install/install_generator.rb +21 -18
  51. data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +3 -4
  52. data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +1 -1
  53. data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +2 -2
  54. data/lib/generators/ruby_llm/schema/schema_generator.rb +26 -0
  55. data/lib/generators/ruby_llm/schema/templates/schema.rb.tt +2 -0
  56. data/lib/generators/ruby_llm/tool/templates/tool.rb.tt +9 -0
  57. data/lib/generators/ruby_llm/tool/templates/tool_call.html.erb.tt +13 -0
  58. data/lib/generators/ruby_llm/tool/templates/tool_result.html.erb.tt +13 -0
  59. data/lib/generators/ruby_llm/tool/tool_generator.rb +96 -0
  60. data/lib/generators/ruby_llm/upgrade_to_v1_10/upgrade_to_v1_10_generator.rb +1 -1
  61. data/lib/generators/ruby_llm/upgrade_to_v1_14/templates/add_v1_14_tool_call_columns.rb.tt +7 -0
  62. data/lib/generators/ruby_llm/upgrade_to_v1_14/upgrade_to_v1_14_generator.rb +49 -0
  63. data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +2 -4
  64. data/lib/generators/ruby_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +1 -1
  65. data/lib/ruby_llm/active_record/acts_as.rb +2 -0
  66. data/lib/ruby_llm/active_record/acts_as_legacy.rb +2 -0
  67. data/lib/ruby_llm/active_record/chat_methods.rb +1 -1
  68. data/lib/ruby_llm/active_record/message_methods.rb +28 -0
  69. data/lib/ruby_llm/active_record/model_methods.rb +1 -1
  70. data/lib/ruby_llm/active_record/tool_call_methods.rb +28 -0
  71. data/lib/ruby_llm/agent.rb +11 -0
  72. data/lib/ruby_llm/aliases.json +15 -5
  73. data/lib/ruby_llm/attachment.rb +3 -0
  74. data/lib/ruby_llm/configuration.rb +54 -73
  75. data/lib/ruby_llm/connection.rb +1 -3
  76. data/lib/ruby_llm/error.rb +5 -0
  77. data/lib/ruby_llm/model/info.rb +14 -12
  78. data/lib/ruby_llm/models.json +2693 -2160
  79. data/lib/ruby_llm/models.rb +10 -3
  80. data/lib/ruby_llm/provider.rb +5 -0
  81. data/lib/ruby_llm/providers/anthropic.rb +4 -0
  82. data/lib/ruby_llm/providers/azure.rb +4 -0
  83. data/lib/ruby_llm/providers/bedrock.rb +4 -0
  84. data/lib/ruby_llm/providers/deepseek.rb +4 -0
  85. data/lib/ruby_llm/providers/gemini.rb +4 -0
  86. data/lib/ruby_llm/providers/gpustack.rb +4 -0
  87. data/lib/ruby_llm/providers/mistral.rb +4 -0
  88. data/lib/ruby_llm/providers/ollama.rb +4 -0
  89. data/lib/ruby_llm/providers/openai.rb +10 -0
  90. data/lib/ruby_llm/providers/openrouter/images.rb +1 -1
  91. data/lib/ruby_llm/providers/openrouter.rb +4 -0
  92. data/lib/ruby_llm/providers/perplexity.rb +4 -0
  93. data/lib/ruby_llm/providers/vertexai.rb +4 -0
  94. data/lib/ruby_llm/providers/xai.rb +4 -0
  95. data/lib/ruby_llm/version.rb +1 -1
  96. data/lib/tasks/release.rake +1 -1
  97. data/lib/tasks/ruby_llm.rake +6 -5
  98. data/lib/tasks/vcr.rake +1 -1
  99. metadata +47 -10
  100. data/lib/generators/ruby_llm/chat_ui/templates/views/messages/_message.html.erb.tt +0 -13
@@ -3,83 +3,64 @@
3
3
  module RubyLLM
4
4
  # Global configuration for RubyLLM
5
5
  class Configuration
6
- attr_accessor :openai_api_key,
7
- :openai_api_base,
8
- :openai_organization_id,
9
- :openai_project_id,
10
- :openai_use_system_role,
11
- :azure_api_base,
12
- :azure_api_key,
13
- :azure_ai_auth_token,
14
- :anthropic_api_base,
15
- :anthropic_api_key,
16
- :gemini_api_key,
17
- :gemini_api_base,
18
- :vertexai_project_id,
19
- :vertexai_location,
20
- :vertexai_service_account_key,
21
- :deepseek_api_key,
22
- :deepseek_api_base,
23
- :perplexity_api_key,
24
- :bedrock_api_key,
25
- :bedrock_secret_key,
26
- :bedrock_region,
27
- :bedrock_session_token,
28
- :openrouter_api_base,
29
- :openrouter_api_key,
30
- :xai_api_key,
31
- :ollama_api_base,
32
- :ollama_api_key,
33
- :gpustack_api_base,
34
- :gpustack_api_key,
35
- :mistral_api_key,
36
- # Default models
37
- :default_model,
38
- :default_embedding_model,
39
- :default_moderation_model,
40
- :default_image_model,
41
- :default_transcription_model,
42
- # Model registry
43
- :model_registry_file,
44
- :model_registry_class,
45
- # Rails integration
46
- :use_new_acts_as,
47
- # Connection configuration
48
- :request_timeout,
49
- :max_retries,
50
- :retry_interval,
51
- :retry_backoff_factor,
52
- :retry_interval_randomness,
53
- :http_proxy,
54
- # Logging configuration
55
- :logger,
56
- :log_file,
57
- :log_level,
58
- :log_stream_debug
59
- attr_reader :log_regexp_timeout
6
+ class << self
7
+ # Declare a single configuration option.
8
+ def option(key, default = nil)
9
+ key = key.to_sym
10
+ return if options.include?(key)
60
11
 
61
- def initialize
62
- @request_timeout = 300
63
- @max_retries = 3
64
- @retry_interval = 0.1
65
- @retry_backoff_factor = 2
66
- @retry_interval_randomness = 0.5
67
- @http_proxy = nil
12
+ send(:attr_accessor, key)
13
+ option_keys << key
14
+ defaults[key] = default
15
+ end
16
+
17
+ def register_provider_options(options)
18
+ Array(options).each { |key| option(key, nil) }
19
+ end
20
+
21
+ def options
22
+ option_keys.dup
23
+ end
24
+
25
+ private
68
26
 
69
- @default_model = 'gpt-5-nano'
70
- @default_embedding_model = 'text-embedding-3-small'
71
- @default_moderation_model = 'omni-moderation-latest'
72
- @default_image_model = 'gpt-image-1'
73
- @default_transcription_model = 'whisper-1'
27
+ def option_keys = @option_keys ||= []
28
+ def defaults = @defaults ||= {}
29
+ private :option
30
+ end
31
+
32
+ # System-level options are declared here.
33
+ # Provider-specific options are declared in each provider class via
34
+ # `self.configuration_options` and registered through Provider.register.
35
+ option :default_model, 'gpt-5.4'
36
+ option :default_embedding_model, 'text-embedding-3-small'
37
+ option :default_moderation_model, 'omni-moderation-latest'
38
+ option :default_image_model, 'gpt-image-1.5'
39
+ option :default_transcription_model, 'whisper-1'
40
+
41
+ option :model_registry_file, -> { File.expand_path('models.json', __dir__) }
42
+ option :model_registry_class, 'Model'
43
+
44
+ option :use_new_acts_as, false
74
45
 
75
- @model_registry_file = File.expand_path('models.json', __dir__)
76
- @model_registry_class = 'Model'
77
- @use_new_acts_as = false
46
+ option :request_timeout, 300
47
+ option :max_retries, 3
48
+ option :retry_interval, 0.1
49
+ option :retry_backoff_factor, 2
50
+ option :retry_interval_randomness, 0.5
51
+ option :http_proxy, nil
78
52
 
79
- @log_file = $stdout
80
- @log_level = ENV['RUBYLLM_DEBUG'] ? Logger::DEBUG : Logger::INFO
81
- @log_stream_debug = ENV['RUBYLLM_STREAM_DEBUG'] == 'true'
82
- self.log_regexp_timeout = Regexp.respond_to?(:timeout) ? (Regexp.timeout || 1.0) : nil
53
+ option :logger, nil
54
+ option :log_file, -> { $stdout }
55
+ option :log_level, -> { ENV['RUBYLLM_DEBUG'] ? Logger::DEBUG : Logger::INFO }
56
+ option :log_stream_debug, -> { ENV['RUBYLLM_STREAM_DEBUG'] == 'true' }
57
+ option :log_regexp_timeout, -> { Regexp.respond_to?(:timeout) ? (Regexp.timeout || 1.0) : nil }
58
+
59
+ def initialize
60
+ self.class.send(:defaults).each do |key, default|
61
+ value = default.respond_to?(:call) ? instance_exec(&default) : default
62
+ public_send("#{key}=", value)
63
+ end
83
64
  end
84
65
 
85
66
  def instance_variables
@@ -10,7 +10,6 @@ module RubyLLM
10
10
  f.response :logger,
11
11
  RubyLLM.logger,
12
12
  bodies: false,
13
- response: false,
14
13
  errors: true,
15
14
  headers: false,
16
15
  log_level: :debug
@@ -60,8 +59,7 @@ module RubyLLM
60
59
  def setup_logging(faraday)
61
60
  faraday.response :logger,
62
61
  RubyLLM.logger,
63
- bodies: true,
64
- response: true,
62
+ bodies: RubyLLM.logger.debug?,
65
63
  errors: true,
66
64
  headers: false,
67
65
  log_level: :debug do |logger|
@@ -7,6 +7,11 @@ module RubyLLM
7
7
  attr_reader :response
8
8
 
9
9
  def initialize(response = nil, message = nil)
10
+ if response.is_a?(String)
11
+ message = response
12
+ response = nil
13
+ end
14
+
10
15
  @response = response
11
16
  super(message || response&.body)
12
17
  end
@@ -48,6 +48,11 @@ module RubyLLM
48
48
  name
49
49
  end
50
50
 
51
+ def label
52
+ provider_name = provider_class&.name || provider
53
+ "#{provider_name} - #{display_name}"
54
+ end
55
+
51
56
  def max_tokens
52
57
  max_output_tokens
53
58
  end
@@ -76,18 +81,15 @@ module RubyLLM
76
81
  RubyLLM::Provider.resolve provider
77
82
  end
78
83
 
79
- def type # rubocop:disable Metrics/PerceivedComplexity
80
- if modalities.output.include?('embeddings') && !modalities.output.include?('text')
81
- 'embedding'
82
- elsif modalities.output.include?('image') && !modalities.output.include?('text')
83
- 'image'
84
- elsif modalities.output.include?('audio') && !modalities.output.include?('text')
85
- 'audio'
86
- elsif modalities.output.include?('moderation')
87
- 'moderation'
88
- else
89
- 'chat'
90
- end
84
+ def type
85
+ output = modalities.output
86
+ return 'embedding' if output.include?('embeddings')
87
+ return 'moderation' if output.include?('moderation')
88
+ return 'image' if output.include?('image')
89
+ return 'audio' if output.include?('audio')
90
+ return 'video' if output.include?('video')
91
+
92
+ 'chat'
91
93
  end
92
94
 
93
95
  def to_h