dify_llm 1.7.1 → 1.8.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.
@@ -194,15 +194,15 @@ module RubyLLM
194
194
  end
195
195
 
196
196
  def embedding_models
197
- self.class.new(all.select { |m| m.type == 'embedding' })
197
+ self.class.new(all.select { |m| m.type == 'embedding' || m.modalities.output.include?('embeddings') })
198
198
  end
199
199
 
200
200
  def audio_models
201
- self.class.new(all.select { |m| m.type == 'audio' })
201
+ self.class.new(all.select { |m| m.type == 'audio' || m.modalities.output.include?('audio') })
202
202
  end
203
203
 
204
204
  def image_models
205
- self.class.new(all.select { |m| m.type == 'image' })
205
+ self.class.new(all.select { |m| m.type == 'image' || m.modalities.output.include?('image') })
206
206
  end
207
207
 
208
208
  def by_family(family)
@@ -217,6 +217,10 @@ module RubyLLM
217
217
  self.class.refresh!(remote_only: remote_only)
218
218
  end
219
219
 
220
+ def resolve(model_id, provider: nil, assume_exists: false, config: nil)
221
+ self.class.resolve(model_id, provider: provider, assume_exists: assume_exists, config: config)
222
+ end
223
+
220
224
  private
221
225
 
222
226
  def find_with_provider(model_id, provider)
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ # Identify potentially harmful content in text.
5
+ # https://platform.openai.com/docs/guides/moderation
6
+ class Moderation
7
+ attr_reader :id, :model, :results
8
+
9
+ def initialize(id:, model:, results:)
10
+ @id = id
11
+ @model = model
12
+ @results = results
13
+ end
14
+
15
+ def self.moderate(input,
16
+ model: nil,
17
+ provider: nil,
18
+ assume_model_exists: false,
19
+ context: nil)
20
+ config = context&.config || RubyLLM.config
21
+ model ||= config.default_moderation_model || 'omni-moderation-latest'
22
+ model, provider_instance = Models.resolve(model, provider: provider, assume_exists: assume_model_exists,
23
+ config: config)
24
+ model_id = model.id
25
+
26
+ provider_instance.moderate(input, model: model_id)
27
+ end
28
+
29
+ # Convenience method to get content from moderation result
30
+ def content
31
+ results
32
+ end
33
+
34
+ # Check if any content was flagged
35
+ def flagged?
36
+ results.any? { |result| result['flagged'] }
37
+ end
38
+
39
+ # Get all flagged categories across all results
40
+ def flagged_categories
41
+ results.flat_map do |result|
42
+ result['categories']&.select { |_category, flagged| flagged }&.keys || []
43
+ end.uniq
44
+ end
45
+
46
+ # Get category scores for the first result (most common case)
47
+ def category_scores
48
+ results.first&.dig('category_scores') || {}
49
+ end
50
+
51
+ # Get categories for the first result (most common case)
52
+ def categories
53
+ results.first&.dig('categories') || {}
54
+ end
55
+ end
56
+ end
@@ -70,6 +70,12 @@ module RubyLLM
70
70
  parse_embedding_response(response, model:, text:)
71
71
  end
72
72
 
73
+ def moderate(input, model:)
74
+ payload = render_moderation_payload(input, model:)
75
+ response = @connection.post moderation_url, payload
76
+ parse_moderation_response(response, model:)
77
+ end
78
+
73
79
  def paint(prompt, model:, size:)
74
80
  payload = render_image_payload(prompt, model:, size:)
75
81
  response = @connection.post images_url, payload
@@ -52,6 +52,10 @@ module RubyLLM
52
52
  model_id.match?(/gemini|flash|pro|imagen/)
53
53
  end
54
54
 
55
+ def supports_video?(model_id)
56
+ model_id.match?(/gemini/)
57
+ end
58
+
55
59
  def supports_functions?(model_id)
56
60
  return false if model_id.match?(/text-embedding|embedding-001|aqa|flash-lite|imagen|gemini-2\.0-flash-lite/)
57
61
 
@@ -217,6 +221,7 @@ module RubyLLM
217
221
  modalities[:input] << 'pdf'
218
222
  end
219
223
 
224
+ modalities[:input] << 'video' if supports_video?(model_id)
220
225
  modalities[:input] << 'audio' if model_id.match?(/audio/)
221
226
  modalities[:output] << 'embeddings' if model_id.match?(/embedding|gemini-embedding/)
222
227
  modalities[:output] = ['image'] if model_id.match?(/imagen/)
@@ -26,6 +26,9 @@ module RubyLLM
26
26
  gpt4o_realtime: /^gpt-4o-realtime/,
27
27
  gpt4o_search: /^gpt-4o-search/,
28
28
  gpt4o_transcribe: /^gpt-4o-transcribe/,
29
+ gpt5: /^gpt-5/,
30
+ gpt5_mini: /^gpt-5-mini/,
31
+ gpt5_nano: /^gpt-5-nano/,
29
32
  o1: /^o1(?!-(?:mini|pro))/,
30
33
  o1_mini: /^o1-mini/,
31
34
  o1_pro: /^o1-pro/,
@@ -44,7 +47,7 @@ module RubyLLM
44
47
  def context_window_for(model_id)
45
48
  case model_family(model_id)
46
49
  when 'gpt41', 'gpt41_mini', 'gpt41_nano' then 1_047_576
47
- when 'chatgpt4o', 'gpt4_turbo', 'gpt4o', 'gpt4o_audio', 'gpt4o_mini',
50
+ when 'gpt5', 'gpt5_mini', 'gpt5_nano', 'chatgpt4o', 'gpt4_turbo', 'gpt4o', 'gpt4o_audio', 'gpt4o_mini',
48
51
  'gpt4o_mini_audio', 'gpt4o_mini_realtime', 'gpt4o_realtime',
49
52
  'gpt4o_search', 'gpt4o_transcribe', 'gpt4o_mini_search', 'o1_mini' then 128_000
50
53
  when 'gpt4' then 8_192
@@ -59,6 +62,7 @@ module RubyLLM
59
62
 
60
63
  def max_tokens_for(model_id)
61
64
  case model_family(model_id)
65
+ when 'gpt5', 'gpt5_mini', 'gpt5_nano' then 400_000
62
66
  when 'gpt41', 'gpt41_mini', 'gpt41_nano' then 32_768
63
67
  when 'chatgpt4o', 'gpt4o', 'gpt4o_mini', 'gpt4o_mini_search' then 16_384
64
68
  when 'babbage', 'davinci' then 16_384 # rubocop:disable Lint/DuplicateBranch
@@ -76,16 +80,17 @@ module RubyLLM
76
80
 
77
81
  def supports_vision?(model_id)
78
82
  case model_family(model_id)
79
- when 'gpt41', 'gpt41_mini', 'gpt41_nano', 'chatgpt4o', 'gpt4', 'gpt4_turbo', 'gpt4o', 'gpt4o_mini', 'o1',
80
- 'o1_pro', 'moderation', 'gpt4o_search', 'gpt4o_mini_search' then true
83
+ when 'gpt5', 'gpt5_mini', 'gpt5_nano', 'gpt41', 'gpt41_mini', 'gpt41_nano', 'chatgpt4o', 'gpt4',
84
+ 'gpt4_turbo', 'gpt4o', 'gpt4o_mini', 'o1', 'o1_pro', 'moderation', 'gpt4o_search',
85
+ 'gpt4o_mini_search' then true
81
86
  else false
82
87
  end
83
88
  end
84
89
 
85
90
  def supports_functions?(model_id)
86
91
  case model_family(model_id)
87
- when 'gpt41', 'gpt41_mini', 'gpt41_nano', 'gpt4', 'gpt4_turbo', 'gpt4o', 'gpt4o_mini', 'o1', 'o1_pro',
88
- 'o3_mini' then true
92
+ when 'gpt5', 'gpt5_mini', 'gpt5_nano', 'gpt41', 'gpt41_mini', 'gpt41_nano', 'gpt4', 'gpt4_turbo', 'gpt4o',
93
+ 'gpt4o_mini', 'o1', 'o1_pro', 'o3_mini' then true
89
94
  when 'chatgpt4o', 'gpt35_turbo', 'o1_mini', 'gpt4o_mini_tts',
90
95
  'gpt4o_transcribe', 'gpt4o_search', 'gpt4o_mini_search' then false
91
96
  else false # rubocop:disable Lint/DuplicateBranch
@@ -94,8 +99,8 @@ module RubyLLM
94
99
 
95
100
  def supports_structured_output?(model_id)
96
101
  case model_family(model_id)
97
- when 'gpt41', 'gpt41_mini', 'gpt41_nano', 'chatgpt4o', 'gpt4o', 'gpt4o_mini', 'o1', 'o1_pro',
98
- 'o3_mini' then true
102
+ when 'gpt5', 'gpt5_mini', 'gpt5_nano', 'gpt41', 'gpt41_mini', 'gpt41_nano', 'chatgpt4o', 'gpt4o',
103
+ 'gpt4o_mini', 'o1', 'o1_pro', 'o3_mini' then true
99
104
  else false
100
105
  end
101
106
  end
@@ -105,6 +110,9 @@ module RubyLLM
105
110
  end
106
111
 
107
112
  PRICES = {
113
+ gpt5: { input: 1.25, output: 10.0, cached_input: 0.125 },
114
+ gpt5_mini: { input: 0.25, output: 2.0, cached_input: 0.025 },
115
+ gpt5_nano: { input: 0.05, output: 0.4, cached_input: 0.005 },
108
116
  gpt41: { input: 2.0, output: 8.0, cached_input: 0.5 },
109
117
  gpt41_mini: { input: 0.4, output: 1.6, cached_input: 0.1 },
110
118
  gpt41_nano: { input: 0.1, output: 0.4 },
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Providers
5
+ class OpenAI
6
+ # Moderation methods of the OpenAI API integration
7
+ module Moderation
8
+ module_function
9
+
10
+ def moderation_url
11
+ 'moderations'
12
+ end
13
+
14
+ def render_moderation_payload(input, model:)
15
+ {
16
+ model: model,
17
+ input: input
18
+ }
19
+ end
20
+
21
+ def parse_moderation_response(response, model:)
22
+ data = response.body
23
+ raise Error.new(response, data.dig('error', 'message')) if data.dig('error', 'message')
24
+
25
+ RubyLLM::Moderation.new(
26
+ id: data['id'],
27
+ model: model,
28
+ results: data['results'] || []
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -7,6 +7,7 @@ module RubyLLM
7
7
  include OpenAI::Chat
8
8
  include OpenAI::Embeddings
9
9
  include OpenAI::Models
10
+ include OpenAI::Moderation
10
11
  include OpenAI::Streaming
11
12
  include OpenAI::Tools
12
13
  include OpenAI::Images
@@ -5,7 +5,7 @@ module RubyLLM
5
5
  class Railtie < Rails::Railtie
6
6
  initializer 'ruby_llm.inflections' do
7
7
  ActiveSupport::Inflector.inflections(:en) do |inflect|
8
- inflect.acronym 'LLM'
8
+ inflect.acronym 'RubyLLM'
9
9
  end
10
10
  end
11
11
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyLLM
4
- VERSION = '1.7.1'
4
+ VERSION = '1.8.1'
5
5
  end
data/lib/ruby_llm.rb CHANGED
@@ -28,6 +28,7 @@ loader.inflector.inflect(
28
28
  )
29
29
  loader.ignore("#{__dir__}/tasks")
30
30
  loader.ignore("#{__dir__}/generators")
31
+ loader.ignore("#{__dir__}/dify_llm.rb")
31
32
  loader.setup
32
33
 
33
34
  # A delightful Ruby interface to modern AI language models.
@@ -49,6 +50,10 @@ module RubyLLM
49
50
  Embedding.embed(...)
50
51
  end
51
52
 
53
+ def moderate(...)
54
+ Moderation.moderate(...)
55
+ end
56
+
52
57
  def paint(...)
53
58
  Image.paint(...)
54
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dify_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
@@ -136,6 +136,7 @@ extra_rdoc_files: []
136
136
  files:
137
137
  - LICENSE
138
138
  - README.md
139
+ - lib/dify_llm.rb
139
140
  - lib/generators/ruby_llm/chat_ui/chat_ui_generator.rb
140
141
  - lib/generators/ruby_llm/chat_ui/templates/controllers/chats_controller.rb.tt
141
142
  - lib/generators/ruby_llm/chat_ui/templates/controllers/messages_controller.rb.tt
@@ -146,6 +147,7 @@ files:
146
147
  - lib/generators/ruby_llm/chat_ui/templates/views/chats/index.html.erb.tt
147
148
  - lib/generators/ruby_llm/chat_ui/templates/views/chats/new.html.erb.tt
148
149
  - lib/generators/ruby_llm/chat_ui/templates/views/chats/show.html.erb.tt
150
+ - lib/generators/ruby_llm/chat_ui/templates/views/messages/_content.html.erb.tt
149
151
  - lib/generators/ruby_llm/chat_ui/templates/views/messages/_form.html.erb.tt
150
152
  - lib/generators/ruby_llm/chat_ui/templates/views/messages/_message.html.erb.tt
151
153
  - lib/generators/ruby_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt
@@ -154,6 +156,7 @@ files:
154
156
  - lib/generators/ruby_llm/chat_ui/templates/views/models/show.html.erb.tt
155
157
  - lib/generators/ruby_llm/generator_helpers.rb
156
158
  - lib/generators/ruby_llm/install/install_generator.rb
159
+ - lib/generators/ruby_llm/install/templates/add_references_to_chats_tool_calls_and_messages_migration.rb.tt
157
160
  - lib/generators/ruby_llm/install/templates/chat_model.rb.tt
158
161
  - lib/generators/ruby_llm/install/templates/create_chats_migration.rb.tt
159
162
  - lib/generators/ruby_llm/install/templates/create_messages_migration.rb.tt
@@ -194,6 +197,7 @@ files:
194
197
  - lib/ruby_llm/models.json
195
198
  - lib/ruby_llm/models.rb
196
199
  - lib/ruby_llm/models_schema.json
200
+ - lib/ruby_llm/moderation.rb
197
201
  - lib/ruby_llm/provider.rb
198
202
  - lib/ruby_llm/providers/anthropic.rb
199
203
  - lib/ruby_llm/providers/anthropic/capabilities.rb
@@ -252,6 +256,7 @@ files:
252
256
  - lib/ruby_llm/providers/openai/images.rb
253
257
  - lib/ruby_llm/providers/openai/media.rb
254
258
  - lib/ruby_llm/providers/openai/models.rb
259
+ - lib/ruby_llm/providers/openai/moderation.rb
255
260
  - lib/ruby_llm/providers/openai/streaming.rb
256
261
  - lib/ruby_llm/providers/openai/tools.rb
257
262
  - lib/ruby_llm/providers/openrouter.rb
@@ -281,10 +286,11 @@ licenses:
281
286
  - MIT
282
287
  metadata:
283
288
  homepage_uri: https://github.com/crmne/ruby_llm/pull/168
284
- source_code_uri: https://github.com/crmne/ruby_llm
285
- changelog_uri: https://github.com/crmne/ruby_llm/commits/main
289
+ source_code_uri: https://github.com/crmne/ruby_llm/pull/168
290
+ changelog_uri: https://github.com/crmne/ruby_llm/pull/168/commits/main
286
291
  documentation_uri: https://github.com/crmne/ruby_llm/pull/168
287
- bug_tracker_uri: https://github.com/crmne/ruby_llm/issues
292
+ bug_tracker_uri: https://github.com/crmne/ruby_llm/pull/168/issues
293
+ funding_uri: https://github.com/sponsors/crmne
288
294
  rubygems_mfa_required: 'true'
289
295
  post_install_message: |
290
296
  Upgrading from RubyLLM <= 1.6.x? Check the upgrade guide for new features and migration instructions