dify_llm 1.6.4 → 1.7.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  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/generator_helpers.rb +129 -0
  20. data/lib/generators/ruby_llm/install/install_generator.rb +104 -0
  21. data/lib/generators/ruby_llm/install/templates/chat_model.rb.tt +1 -1
  22. data/lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt +3 -3
  23. data/lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt +6 -6
  24. data/lib/generators/ruby_llm/install/templates/create_models_migration.rb.tt +3 -6
  25. data/lib/generators/ruby_llm/install/templates/create_tool_calls_migration.rb.tt +5 -5
  26. data/lib/generators/ruby_llm/install/templates/initializer.rb.tt +6 -3
  27. data/lib/generators/ruby_llm/install/templates/message_model.rb.tt +1 -1
  28. data/lib/generators/ruby_llm/install/templates/model_model.rb.tt +1 -1
  29. data/lib/generators/ruby_llm/install/templates/tool_call_model.rb.tt +1 -1
  30. data/lib/generators/ruby_llm/{migrate_model_fields → upgrade_to_v1_7}/templates/migration.rb.tt +23 -20
  31. data/lib/generators/ruby_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +121 -0
  32. data/lib/ruby_llm/active_record/acts_as.rb +88 -58
  33. data/lib/ruby_llm/active_record/chat_methods.rb +51 -30
  34. data/lib/ruby_llm/active_record/message_methods.rb +2 -2
  35. data/lib/ruby_llm/aliases.json +0 -8
  36. data/lib/ruby_llm/configuration.rb +5 -0
  37. data/lib/ruby_llm/models.json +1724 -1497
  38. data/lib/ruby_llm/railtie.rb +4 -12
  39. data/lib/ruby_llm/version.rb +1 -1
  40. data/lib/ruby_llm.rb +2 -1
  41. metadata +27 -9
  42. data/lib/generators/ruby_llm/install/templates/create_chats_legacy_migration.rb.tt +0 -8
  43. data/lib/generators/ruby_llm/install/templates/create_messages_legacy_migration.rb.tt +0 -16
  44. data/lib/generators/ruby_llm/install_generator.rb +0 -184
  45. data/lib/generators/ruby_llm/migrate_model_fields_generator.rb +0 -84
@@ -10,15 +10,17 @@ module RubyLLM
10
10
  before_save :resolve_model_from_strings
11
11
  end
12
12
 
13
- class_methods do
14
- attr_reader :tool_call_class, :model_class
15
- end
16
-
17
13
  attr_accessor :assume_model_exists, :context
18
14
 
19
15
  def model=(value)
20
16
  @model_string = value if value.is_a?(String)
21
- super unless value.is_a?(String)
17
+ return if value.is_a?(String)
18
+
19
+ if self.class.model_association_name == :model
20
+ super
21
+ else
22
+ self.model_association = value
23
+ end
22
24
  end
23
25
 
24
26
  def model_id=(value)
@@ -26,7 +28,7 @@ module RubyLLM
26
28
  end
27
29
 
28
30
  def model_id
29
- model&.model_id
31
+ model_association&.model_id
30
32
  end
31
33
 
32
34
  def provider=(value)
@@ -34,19 +36,21 @@ module RubyLLM
34
36
  end
35
37
 
36
38
  def provider
37
- model&.provider
39
+ model_association&.provider
38
40
  end
39
41
 
40
42
  private
41
43
 
42
44
  def resolve_model_from_strings # rubocop:disable Metrics/PerceivedComplexity
45
+ config = context&.config || RubyLLM.config
46
+ @model_string ||= config.default_model unless model_association
43
47
  return unless @model_string
44
48
 
45
49
  model_info, _provider = Models.resolve(
46
50
  @model_string,
47
51
  provider: @provider_string,
48
52
  assume_exists: assume_model_exists || false,
49
- config: context&.config || RubyLLM.config
53
+ config: config
50
54
  )
51
55
 
52
56
  model_class = self.class.model_class.constantize
@@ -64,7 +68,7 @@ module RubyLLM
64
68
  m.metadata = model_info.metadata || {}
65
69
  end
66
70
 
67
- self.model = model_record
71
+ self.model_association = model_record
68
72
  @model_string = nil
69
73
  @provider_string = nil
70
74
  end
@@ -72,15 +76,14 @@ module RubyLLM
72
76
  public
73
77
 
74
78
  def to_llm
75
- raise 'No model specified' unless model
76
-
79
+ model_record = model_association
77
80
  @chat ||= (context || RubyLLM).chat(
78
- model: model.model_id,
79
- provider: model.provider.to_sym
81
+ model: model_record.model_id,
82
+ provider: model_record.provider.to_sym
80
83
  )
81
84
  @chat.reset_messages!
82
85
 
83
- messages.each do |msg|
86
+ messages_association.each do |msg|
84
87
  @chat.add_message(msg.to_llm)
85
88
  end
86
89
 
@@ -89,8 +92,8 @@ module RubyLLM
89
92
 
90
93
  def with_instructions(instructions, replace: false)
91
94
  transaction do
92
- messages.where(role: :system).destroy_all if replace
93
- messages.create!(role: :system, content: instructions)
95
+ messages_association.where(role: :system).destroy_all if replace
96
+ messages_association.create!(role: :system, content: instructions)
94
97
  end
95
98
  to_llm.with_instructions(instructions)
96
99
  self
@@ -106,12 +109,13 @@ module RubyLLM
106
109
  self
107
110
  end
108
111
 
109
- def with_model(model_name, provider: nil)
110
- self.provider = provider if provider
112
+ def with_model(model_name, provider: nil, assume_exists: false)
111
113
  self.model = model_name
114
+ self.provider = provider if provider
115
+ self.assume_model_exists = assume_exists
112
116
  resolve_model_from_strings
113
117
  save!
114
- to_llm.with_model(model.model_id, provider: model.provider.to_sym)
118
+ to_llm.with_model(model.model_id, provider: model.provider.to_sym, assume_exists:)
115
119
  self
116
120
  end
117
121
 
@@ -170,7 +174,7 @@ module RubyLLM
170
174
  end
171
175
 
172
176
  def create_user_message(content, with: nil)
173
- message_record = messages.create!(role: :user, content: content)
177
+ message_record = messages_association.create!(role: :user, content: content)
174
178
  persist_content(message_record, with) if with.present?
175
179
  message_record
176
180
  end
@@ -198,8 +202,8 @@ module RubyLLM
198
202
  end
199
203
 
200
204
  def cleanup_orphaned_tool_results # rubocop:disable Metrics/PerceivedComplexity
201
- messages.reload
202
- last = messages.order(:id).last
205
+ messages_association.reload
206
+ last = messages_association.order(:id).last
203
207
 
204
208
  return unless last&.tool_call? || last&.tool_result?
205
209
 
@@ -228,7 +232,7 @@ module RubyLLM
228
232
  end
229
233
 
230
234
  def persist_new_message
231
- @message = messages.create!(role: :assistant, content: '')
235
+ @message = messages_association.create!(role: :assistant, content: '')
232
236
  end
233
237
 
234
238
  def persist_message_completion(message) # rubocop:disable Metrics/PerceivedComplexity
@@ -247,15 +251,22 @@ module RubyLLM
247
251
  content = content.to_json
248
252
  end
249
253
 
250
- @message.update!(
254
+ attrs = {
251
255
  role: message.role,
252
256
  content: content,
253
- model: model,
254
257
  input_tokens: message.input_tokens,
255
258
  output_tokens: message.output_tokens
256
- )
257
- @message.write_attribute(@message.class.tool_call_foreign_key, tool_call_id) if tool_call_id
258
- @message.save!
259
+ }
260
+
261
+ # Add model association dynamically
262
+ attrs[self.class.model_association_name] = model_association
263
+
264
+ if tool_call_id
265
+ parent_tool_call_assoc = @message.class.reflect_on_association(:parent_tool_call)
266
+ attrs[parent_tool_call_assoc.foreign_key] = tool_call_id
267
+ end
268
+
269
+ @message.update!(attrs)
259
270
 
260
271
  persist_content(@message, attachments_to_persist) if attachments_to_persist
261
272
  persist_tool_calls(message.tool_calls) if message.tool_calls.present?
@@ -266,12 +277,22 @@ module RubyLLM
266
277
  tool_calls.each_value do |tool_call|
267
278
  attributes = tool_call.to_h
268
279
  attributes[:tool_call_id] = attributes.delete(:id)
269
- @message.tool_calls.create!(**attributes)
280
+ @message.tool_calls_association.create!(**attributes)
270
281
  end
271
282
  end
272
283
 
273
284
  def find_tool_call_id(tool_call_id)
274
- self.class.tool_call_class.constantize.find_by(tool_call_id: tool_call_id)&.id
285
+ messages = messages_association
286
+ message_class = messages.klass
287
+ tool_calls_assoc = message_class.tool_calls_association_name
288
+ tool_call_table_name = message_class.reflect_on_association(tool_calls_assoc).table_name
289
+
290
+ message_with_tool_call = messages.joins(tool_calls_assoc)
291
+ .find_by(tool_call_table_name => { tool_call_id: tool_call_id })
292
+ return nil unless message_with_tool_call
293
+
294
+ tool_call = message_with_tool_call.tool_calls_association.find_by(tool_call_id: tool_call_id)
295
+ tool_call&.id
275
296
  end
276
297
 
277
298
  def persist_content(message_record, attachments)
@@ -18,14 +18,14 @@ module RubyLLM
18
18
  tool_call_id: extract_tool_call_id,
19
19
  input_tokens: input_tokens,
20
20
  output_tokens: output_tokens,
21
- model_id: model_id
21
+ model_id: model_association&.model_id
22
22
  )
23
23
  end
24
24
 
25
25
  private
26
26
 
27
27
  def extract_tool_calls
28
- tool_calls.to_h do |tool_call|
28
+ tool_calls_association.to_h do |tool_call|
29
29
  [
30
30
  tool_call.tool_call_id,
31
31
  RubyLLM::ToolCall.new(
@@ -227,14 +227,6 @@
227
227
  "openai": "gpt-5-nano",
228
228
  "openrouter": "openai/gpt-5-nano"
229
229
  },
230
- "gpt-oss-120b": {
231
- "openai": "gpt-oss-120b",
232
- "openrouter": "openai/gpt-oss-120b"
233
- },
234
- "gpt-oss-20b": {
235
- "openai": "gpt-oss-20b",
236
- "openrouter": "openai/gpt-oss-20b"
237
- },
238
230
  "o1": {
239
231
  "openai": "o1",
240
232
  "openrouter": "openai/o1"
@@ -32,6 +32,8 @@ module RubyLLM
32
32
  :default_image_model,
33
33
  # Model registry
34
34
  :model_registry_class,
35
+ # Rails integration
36
+ :use_new_acts_as,
35
37
  # Connection configuration
36
38
  :request_timeout,
37
39
  :max_retries,
@@ -57,6 +59,9 @@ module RubyLLM
57
59
  @default_embedding_model = 'text-embedding-3-small'
58
60
  @default_image_model = 'gpt-image-1'
59
61
 
62
+ @model_registry_class = 'Model'
63
+ @use_new_acts_as = false
64
+
60
65
  @log_file = $stdout
61
66
  @log_level = ENV['RUBYLLM_DEBUG'] ? Logger::DEBUG : Logger::INFO
62
67
  @log_stream_debug = ENV['RUBYLLM_STREAM_DEBUG'] == 'true'