ruby_llm-agents 3.1.0 → 3.2.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 +1 -0
- data/app/controllers/ruby_llm/agents/agents_controller.rb +16 -14
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +20 -20
- data/app/controllers/ruby_llm/agents/executions_controller.rb +5 -7
- data/app/helpers/ruby_llm/agents/application_helper.rb +57 -58
- data/app/models/ruby_llm/agents/execution/analytics.rb +27 -27
- data/app/models/ruby_llm/agents/execution/scopes.rb +4 -6
- data/app/models/ruby_llm/agents/execution.rb +25 -25
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +16 -10
- data/app/models/ruby_llm/agents/tenant/resettable.rb +12 -12
- data/app/models/ruby_llm/agents/tenant/trackable.rb +7 -7
- data/app/services/ruby_llm/agents/agent_registry.rb +6 -6
- data/lib/generators/ruby_llm_agents/agent_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/background_remover_generator.rb +6 -6
- data/lib/generators/ruby_llm_agents/embedder_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +7 -7
- data/lib/generators/ruby_llm_agents/image_editor_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/image_generator_generator.rb +6 -6
- data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +9 -9
- data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +6 -6
- data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/image_variator_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/install_generator.rb +3 -3
- data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/multi_tenancy_generator.rb +2 -2
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +13 -13
- data/lib/generators/ruby_llm_agents/speaker_generator.rb +6 -6
- data/lib/generators/ruby_llm_agents/transcriber_generator.rb +4 -4
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +2 -2
- data/lib/ruby_llm/agents/audio/speaker.rb +40 -31
- data/lib/ruby_llm/agents/audio/speech_client.rb +328 -0
- data/lib/ruby_llm/agents/audio/speech_pricing.rb +273 -0
- data/lib/ruby_llm/agents/audio/transcriber.rb +33 -33
- data/lib/ruby_llm/agents/base_agent.rb +14 -14
- data/lib/ruby_llm/agents/core/base/callbacks.rb +3 -3
- data/lib/ruby_llm/agents/core/configuration.rb +86 -73
- data/lib/ruby_llm/agents/core/errors.rb +27 -2
- data/lib/ruby_llm/agents/core/instrumentation.rb +64 -66
- data/lib/ruby_llm/agents/core/llm_tenant.rb +7 -7
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +3 -3
- data/lib/ruby_llm/agents/dsl/reliability.rb +9 -9
- data/lib/ruby_llm/agents/image/analyzer/dsl.rb +1 -1
- data/lib/ruby_llm/agents/image/analyzer/execution.rb +4 -4
- data/lib/ruby_llm/agents/image/background_remover/dsl.rb +1 -1
- data/lib/ruby_llm/agents/image/background_remover/execution.rb +3 -3
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +8 -8
- data/lib/ruby_llm/agents/image/editor/execution.rb +1 -1
- data/lib/ruby_llm/agents/image/generator/pricing.rb +9 -10
- data/lib/ruby_llm/agents/image/generator.rb +6 -6
- data/lib/ruby_llm/agents/image/pipeline/dsl.rb +6 -6
- data/lib/ruby_llm/agents/image/pipeline/execution.rb +9 -9
- data/lib/ruby_llm/agents/image/pipeline.rb +1 -1
- data/lib/ruby_llm/agents/image/transformer/execution.rb +1 -1
- data/lib/ruby_llm/agents/image/upscaler/dsl.rb +1 -1
- data/lib/ruby_llm/agents/image/upscaler/execution.rb +3 -5
- data/lib/ruby_llm/agents/image/variator/execution.rb +1 -1
- data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +4 -4
- data/lib/ruby_llm/agents/infrastructure/attempt_tracker.rb +4 -4
- data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +9 -9
- data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +3 -3
- data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +1 -1
- data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +17 -17
- data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +1 -0
- data/lib/ruby_llm/agents/infrastructure/execution_logger_job.rb +1 -1
- data/lib/ruby_llm/agents/infrastructure/reliability.rb +6 -6
- data/lib/ruby_llm/agents/pipeline/builder.rb +11 -11
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +3 -3
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +4 -4
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +34 -22
- data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +2 -3
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +7 -7
- data/lib/ruby_llm/agents/results/background_removal_result.rb +6 -6
- data/lib/ruby_llm/agents/results/embedding_result.rb +15 -15
- data/lib/ruby_llm/agents/results/image_analysis_result.rb +7 -7
- data/lib/ruby_llm/agents/results/image_edit_result.rb +4 -4
- data/lib/ruby_llm/agents/results/image_generation_result.rb +5 -5
- data/lib/ruby_llm/agents/results/image_pipeline_result.rb +4 -4
- data/lib/ruby_llm/agents/results/image_transform_result.rb +4 -4
- data/lib/ruby_llm/agents/results/image_upscale_result.rb +5 -5
- data/lib/ruby_llm/agents/results/image_variation_result.rb +4 -4
- data/lib/ruby_llm/agents/results/transcription_result.rb +1 -1
- data/lib/ruby_llm/agents/text/embedder.rb +13 -13
- metadata +3 -1
|
@@ -67,27 +67,27 @@ module RubyLLM
|
|
|
67
67
|
belongs_to :parent_execution, class_name: "RubyLLM::Agents::Execution", optional: true
|
|
68
68
|
belongs_to :root_execution, class_name: "RubyLLM::Agents::Execution", optional: true
|
|
69
69
|
has_many :child_executions, class_name: "RubyLLM::Agents::Execution",
|
|
70
|
-
|
|
70
|
+
foreign_key: :parent_execution_id, dependent: :nullify, inverse_of: :parent_execution
|
|
71
71
|
|
|
72
72
|
# Detail record for large payloads (prompts, responses, tool calls, etc.)
|
|
73
73
|
has_one :detail, class_name: "RubyLLM::Agents::ExecutionDetail",
|
|
74
|
-
|
|
74
|
+
foreign_key: :execution_id, dependent: :destroy
|
|
75
75
|
|
|
76
76
|
# Delegations so existing code keeps working transparently
|
|
77
77
|
delegate :system_prompt, :user_prompt, :assistant_prompt, :response, :error_message,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
:messages_summary, :tool_calls, :attempts, :fallback_chain,
|
|
79
|
+
:parameters, :routed_to, :classification_result,
|
|
80
|
+
:cached_at, :cache_creation_tokens,
|
|
81
|
+
to: :detail, prefix: false, allow_nil: true
|
|
82
82
|
|
|
83
83
|
# Validations
|
|
84
84
|
validates :agent_type, :model_id, :started_at, presence: true
|
|
85
|
-
validates :status, inclusion: {
|
|
86
|
-
validates :temperature, numericality: {
|
|
87
|
-
validates :input_tokens, :output_tokens, numericality: {
|
|
88
|
-
validates :duration_ms, numericality: {
|
|
89
|
-
validates :input_cost, :output_cost, :total_cost, numericality: {
|
|
90
|
-
validates :finish_reason, inclusion: {
|
|
85
|
+
validates :status, inclusion: {in: statuses.keys}
|
|
86
|
+
validates :temperature, numericality: {greater_than_or_equal_to: 0, less_than_or_equal_to: 2}, allow_nil: true
|
|
87
|
+
validates :input_tokens, :output_tokens, numericality: {greater_than_or_equal_to: 0}, allow_nil: true
|
|
88
|
+
validates :duration_ms, numericality: {greater_than_or_equal_to: 0}, allow_nil: true
|
|
89
|
+
validates :input_cost, :output_cost, :total_cost, numericality: {greater_than_or_equal_to: 0}, allow_nil: true
|
|
90
|
+
validates :finish_reason, inclusion: {in: FINISH_REASONS}, allow_nil: true
|
|
91
91
|
|
|
92
92
|
before_save :calculate_total_tokens, if: -> { input_tokens_changed? || output_tokens_changed? }
|
|
93
93
|
before_save :calculate_total_cost, if: -> { input_cost_changed? || output_cost_changed? }
|
|
@@ -130,10 +130,10 @@ module RubyLLM
|
|
|
130
130
|
# @return [Boolean] true if more than one attempt was made
|
|
131
131
|
def has_retries?
|
|
132
132
|
count = if self.class.column_names.include?("attempts_count")
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
attempts_count
|
|
134
|
+
elsif self.class.column_names.include?("attempts")
|
|
135
|
+
attempts&.size
|
|
136
|
+
end
|
|
137
137
|
(count || 0) > 1
|
|
138
138
|
end
|
|
139
139
|
|
|
@@ -278,16 +278,16 @@ module RubyLLM
|
|
|
278
278
|
# @return [Hash] Now strip metrics with period-over-period comparisons
|
|
279
279
|
def self.now_strip_data(range: "today")
|
|
280
280
|
current_scope = case range
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
281
|
+
when "7d" then last_n_days(7)
|
|
282
|
+
when "30d" then last_n_days(30)
|
|
283
|
+
else today
|
|
284
|
+
end
|
|
285
285
|
|
|
286
286
|
previous_scope = case range
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
287
|
+
when "7d" then where(created_at: 14.days.ago.beginning_of_day..7.days.ago.beginning_of_day)
|
|
288
|
+
when "30d" then where(created_at: 60.days.ago.beginning_of_day..30.days.ago.beginning_of_day)
|
|
289
|
+
else yesterday
|
|
290
|
+
end
|
|
291
291
|
|
|
292
292
|
current = {
|
|
293
293
|
running: running.count,
|
|
@@ -371,7 +371,7 @@ module RubyLLM
|
|
|
371
371
|
return nil unless lookup_model_id
|
|
372
372
|
|
|
373
373
|
RubyLLM::Models.find(lookup_model_id)
|
|
374
|
-
rescue
|
|
374
|
+
rescue
|
|
375
375
|
nil
|
|
376
376
|
end
|
|
377
377
|
end
|
|
@@ -35,13 +35,13 @@ module RubyLLM
|
|
|
35
35
|
|
|
36
36
|
included do
|
|
37
37
|
# Validations
|
|
38
|
-
validates :enforcement, inclusion: {
|
|
38
|
+
validates :enforcement, inclusion: {in: ENFORCEMENT_MODES}, allow_nil: true
|
|
39
39
|
validates :daily_limit, :monthly_limit,
|
|
40
|
-
|
|
40
|
+
numericality: {greater_than_or_equal_to: 0}, allow_nil: true
|
|
41
41
|
validates :daily_token_limit, :monthly_token_limit,
|
|
42
|
-
|
|
42
|
+
numericality: {greater_than_or_equal_to: 0, only_integer: true}, allow_nil: true
|
|
43
43
|
validates :daily_execution_limit, :monthly_execution_limit,
|
|
44
|
-
|
|
44
|
+
numericality: {greater_than_or_equal_to: 0, only_integer: true}, allow_nil: true
|
|
45
45
|
|
|
46
46
|
# Scopes
|
|
47
47
|
scope :with_budgets, -> { where.not(daily_limit: nil).or(where.not(monthly_limit: nil)) }
|
|
@@ -203,17 +203,23 @@ module RubyLLM
|
|
|
203
203
|
def remaining_budget(type: :daily_cost)
|
|
204
204
|
case type
|
|
205
205
|
when :daily_cost
|
|
206
|
-
effective_daily_limit && (ensure_daily_reset
|
|
206
|
+
effective_daily_limit && (ensure_daily_reset!
|
|
207
|
+
effective_daily_limit - daily_cost_spent)
|
|
207
208
|
when :monthly_cost
|
|
208
|
-
effective_monthly_limit && (ensure_monthly_reset
|
|
209
|
+
effective_monthly_limit && (ensure_monthly_reset!
|
|
210
|
+
effective_monthly_limit - monthly_cost_spent)
|
|
209
211
|
when :daily_tokens
|
|
210
|
-
effective_daily_token_limit && (ensure_daily_reset
|
|
212
|
+
effective_daily_token_limit && (ensure_daily_reset!
|
|
213
|
+
effective_daily_token_limit - daily_tokens_used)
|
|
211
214
|
when :monthly_tokens
|
|
212
|
-
effective_monthly_token_limit && (ensure_monthly_reset
|
|
215
|
+
effective_monthly_token_limit && (ensure_monthly_reset!
|
|
216
|
+
effective_monthly_token_limit - monthly_tokens_used)
|
|
213
217
|
when :daily_executions
|
|
214
|
-
effective_daily_execution_limit && (ensure_daily_reset
|
|
218
|
+
effective_daily_execution_limit && (ensure_daily_reset!
|
|
219
|
+
effective_daily_execution_limit - daily_executions_count)
|
|
215
220
|
when :monthly_executions
|
|
216
|
-
effective_monthly_execution_limit && (ensure_monthly_reset
|
|
221
|
+
effective_monthly_execution_limit && (ensure_monthly_reset!
|
|
222
|
+
effective_monthly_execution_limit - monthly_executions_count)
|
|
217
223
|
end
|
|
218
224
|
end
|
|
219
225
|
|
|
@@ -71,19 +71,19 @@ module RubyLLM
|
|
|
71
71
|
last_exec = executions.order(created_at: :desc).pick(:created_at, :status)
|
|
72
72
|
|
|
73
73
|
update_columns(
|
|
74
|
-
daily_cost_spent:
|
|
75
|
-
daily_tokens_used:
|
|
76
|
-
daily_executions_count:
|
|
77
|
-
daily_error_count:
|
|
78
|
-
daily_reset_date:
|
|
79
|
-
|
|
80
|
-
monthly_cost_spent:
|
|
81
|
-
monthly_tokens_used:
|
|
74
|
+
daily_cost_spent: daily_stats[:cost],
|
|
75
|
+
daily_tokens_used: daily_stats[:tokens],
|
|
76
|
+
daily_executions_count: daily_stats[:count],
|
|
77
|
+
daily_error_count: daily_stats[:errors],
|
|
78
|
+
daily_reset_date: today,
|
|
79
|
+
|
|
80
|
+
monthly_cost_spent: monthly_stats[:cost],
|
|
81
|
+
monthly_tokens_used: monthly_stats[:tokens],
|
|
82
82
|
monthly_executions_count: monthly_stats[:count],
|
|
83
|
-
monthly_error_count:
|
|
84
|
-
monthly_reset_date:
|
|
83
|
+
monthly_error_count: monthly_stats[:errors],
|
|
84
|
+
monthly_reset_date: bom,
|
|
85
85
|
|
|
86
|
-
last_execution_at:
|
|
86
|
+
last_execution_at: last_exec&.first,
|
|
87
87
|
last_execution_status: last_exec&.last
|
|
88
88
|
)
|
|
89
89
|
|
|
@@ -120,7 +120,7 @@ module RubyLLM
|
|
|
120
120
|
Arel.sql("COALESCE(SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END), 0)")
|
|
121
121
|
)
|
|
122
122
|
|
|
123
|
-
{
|
|
123
|
+
{cost: agg[0], tokens: agg[1], count: agg[2], errors: agg[3]}
|
|
124
124
|
end
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -32,10 +32,10 @@ module RubyLLM
|
|
|
32
32
|
included do
|
|
33
33
|
# Association to executions via tenant_id
|
|
34
34
|
has_many :executions,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
class_name: "RubyLLM::Agents::Execution",
|
|
36
|
+
primary_key: :tenant_id,
|
|
37
|
+
foreign_key: :tenant_id,
|
|
38
|
+
inverse_of: false
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# Cost queries
|
|
@@ -251,7 +251,7 @@ module RubyLLM
|
|
|
251
251
|
Arel.sql("SUM(total_tokens)"),
|
|
252
252
|
Arel.sql("COUNT(*)")
|
|
253
253
|
).to_h do |agent_type, total_cost, total_tokens, count|
|
|
254
|
-
[agent_type, {
|
|
254
|
+
[agent_type, {cost: total_cost || 0, tokens: total_tokens || 0, count: count}]
|
|
255
255
|
end
|
|
256
256
|
end
|
|
257
257
|
|
|
@@ -269,7 +269,7 @@ module RubyLLM
|
|
|
269
269
|
Arel.sql("SUM(total_tokens)"),
|
|
270
270
|
Arel.sql("COUNT(*)")
|
|
271
271
|
).to_h do |model_id, total_cost, total_tokens, count|
|
|
272
|
-
[model_id, {
|
|
272
|
+
[model_id, {cost: total_cost || 0, tokens: total_tokens || 0, count: count}]
|
|
273
273
|
end
|
|
274
274
|
end
|
|
275
275
|
|
|
@@ -287,7 +287,7 @@ module RubyLLM
|
|
|
287
287
|
Arel.sql("SUM(total_tokens)"),
|
|
288
288
|
Arel.sql("COUNT(*)")
|
|
289
289
|
).to_h do |date, total_cost, total_tokens, count|
|
|
290
|
-
[date.to_date, {
|
|
290
|
+
[date.to_date, {cost: total_cost || 0, tokens: total_tokens || 0, count: count}]
|
|
291
291
|
end
|
|
292
292
|
end
|
|
293
293
|
|
|
@@ -71,7 +71,7 @@ module RubyLLM
|
|
|
71
71
|
image_generators = RubyLLM::Agents::ImageGenerator.descendants.map(&:name).compact
|
|
72
72
|
|
|
73
73
|
(agents + embedders + speakers + transcribers + image_generators).uniq
|
|
74
|
-
rescue
|
|
74
|
+
rescue => e
|
|
75
75
|
Rails.logger.error("[RubyLLM::Agents] Error loading agents from file system: #{e.message}")
|
|
76
76
|
[]
|
|
77
77
|
end
|
|
@@ -81,7 +81,7 @@ module RubyLLM
|
|
|
81
81
|
# @return [Array<String>] Agent class names with execution records
|
|
82
82
|
def execution_agents
|
|
83
83
|
Execution.distinct.pluck(:agent_type).compact
|
|
84
|
-
rescue
|
|
84
|
+
rescue => e
|
|
85
85
|
Rails.logger.error("[RubyLLM::Agents] Error loading agents from executions: #{e.message}")
|
|
86
86
|
[]
|
|
87
87
|
end
|
|
@@ -149,7 +149,7 @@ module RubyLLM
|
|
|
149
149
|
return nil unless klass.respond_to?(method_name)
|
|
150
150
|
|
|
151
151
|
klass.public_send(method_name)
|
|
152
|
-
rescue
|
|
152
|
+
rescue
|
|
153
153
|
nil
|
|
154
154
|
end
|
|
155
155
|
|
|
@@ -159,8 +159,8 @@ module RubyLLM
|
|
|
159
159
|
# @return [Hash] Statistics hash
|
|
160
160
|
def fetch_stats(agent_type)
|
|
161
161
|
Execution.stats_for(agent_type, period: :all_time)
|
|
162
|
-
rescue
|
|
163
|
-
{
|
|
162
|
+
rescue
|
|
163
|
+
{count: 0, total_cost: 0, total_tokens: 0, avg_duration_ms: 0, success_rate: 0, error_rate: 0}
|
|
164
164
|
end
|
|
165
165
|
|
|
166
166
|
# Gets the timestamp of the last execution for an agent
|
|
@@ -169,7 +169,7 @@ module RubyLLM
|
|
|
169
169
|
# @return [Time, nil] Last execution time or nil
|
|
170
170
|
def last_execution_time(agent_type)
|
|
171
171
|
Execution.by_agent(agent_type).order(created_at: :desc).first&.created_at
|
|
172
|
-
rescue
|
|
172
|
+
rescue
|
|
173
173
|
nil
|
|
174
174
|
end
|
|
175
175
|
|
|
@@ -22,11 +22,11 @@ module RubyLlmAgents
|
|
|
22
22
|
argument :params, type: :array, default: [], banner: "param[:required|:default] param[:required|:default]"
|
|
23
23
|
|
|
24
24
|
class_option :model, type: :string, default: "gemini-2.0-flash",
|
|
25
|
-
|
|
25
|
+
desc: "The LLM model to use"
|
|
26
26
|
class_option :temperature, type: :numeric, default: 0.0,
|
|
27
|
-
|
|
27
|
+
desc: "The temperature setting (0.0-1.0)"
|
|
28
28
|
class_option :cache, type: :string, default: nil,
|
|
29
|
-
|
|
29
|
+
desc: "Cache TTL (e.g., '1.hour', '30.minutes')"
|
|
30
30
|
|
|
31
31
|
def ensure_base_class_and_skill_file
|
|
32
32
|
agents_dir = "app/agents"
|
|
@@ -80,7 +80,7 @@ module RubyLlmAgents
|
|
|
80
80
|
if p.required?
|
|
81
81
|
"#{p.name}: value"
|
|
82
82
|
else
|
|
83
|
-
"#{p.name}: #{p.default ||
|
|
83
|
+
"#{p.name}: #{p.default || "value"}"
|
|
84
84
|
end
|
|
85
85
|
end.join(", ")
|
|
86
86
|
end
|
|
@@ -17,17 +17,17 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "rembg",
|
|
20
|
-
|
|
20
|
+
desc: "The segmentation model to use"
|
|
21
21
|
class_option :output_format, type: :string, default: "png",
|
|
22
|
-
|
|
22
|
+
desc: "Output format (png, webp)"
|
|
23
23
|
class_option :refine_edges, type: :boolean, default: false,
|
|
24
|
-
|
|
24
|
+
desc: "Enable edge refinement"
|
|
25
25
|
class_option :alpha_matting, type: :boolean, default: false,
|
|
26
|
-
|
|
26
|
+
desc: "Enable alpha matting for better edges"
|
|
27
27
|
class_option :return_mask, type: :boolean, default: false,
|
|
28
|
-
|
|
28
|
+
desc: "Also return the segmentation mask"
|
|
29
29
|
class_option :cache, type: :string, default: nil,
|
|
30
|
-
|
|
30
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
31
31
|
|
|
32
32
|
def ensure_base_class_and_skill_file
|
|
33
33
|
images_dir = "app/agents/images"
|
|
@@ -17,13 +17,13 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "text-embedding-3-small",
|
|
20
|
-
|
|
20
|
+
desc: "The embedding model to use"
|
|
21
21
|
class_option :dimensions, type: :numeric, default: nil,
|
|
22
|
-
|
|
22
|
+
desc: "Vector dimensions (nil for model default)"
|
|
23
23
|
class_option :batch_size, type: :numeric, default: 100,
|
|
24
|
-
|
|
24
|
+
desc: "Texts per API call for batch processing"
|
|
25
25
|
class_option :cache, type: :string, default: nil,
|
|
26
|
-
|
|
26
|
+
desc: "Cache TTL (e.g., '1.week', '1.day')"
|
|
27
27
|
|
|
28
28
|
def ensure_base_class_and_skill_file
|
|
29
29
|
embedders_dir = "app/agents/embedders"
|
|
@@ -17,19 +17,19 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "gpt-4o",
|
|
20
|
-
|
|
20
|
+
desc: "The vision model to use"
|
|
21
21
|
class_option :analysis_type, type: :string, default: "detailed",
|
|
22
|
-
|
|
22
|
+
desc: "Analysis type (caption, detailed, tags, objects, colors, all)"
|
|
23
23
|
class_option :extract_colors, type: :boolean, default: false,
|
|
24
|
-
|
|
24
|
+
desc: "Enable color extraction"
|
|
25
25
|
class_option :detect_objects, type: :boolean, default: false,
|
|
26
|
-
|
|
26
|
+
desc: "Enable object detection"
|
|
27
27
|
class_option :extract_text, type: :boolean, default: false,
|
|
28
|
-
|
|
28
|
+
desc: "Enable text extraction (OCR)"
|
|
29
29
|
class_option :max_tags, type: :string, default: "10",
|
|
30
|
-
|
|
30
|
+
desc: "Maximum number of tags to return"
|
|
31
31
|
class_option :cache, type: :string, default: nil,
|
|
32
|
-
|
|
32
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
33
33
|
|
|
34
34
|
def ensure_base_class_and_skill_file
|
|
35
35
|
images_dir = "app/agents/images"
|
|
@@ -17,13 +17,13 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "gpt-image-1",
|
|
20
|
-
|
|
20
|
+
desc: "The image model to use"
|
|
21
21
|
class_option :size, type: :string, default: "1024x1024",
|
|
22
|
-
|
|
22
|
+
desc: "Output image size (e.g., 1024x1024)"
|
|
23
23
|
class_option :content_policy, type: :string, default: "standard",
|
|
24
|
-
|
|
24
|
+
desc: "Content policy level (none, standard, moderate, strict)"
|
|
25
25
|
class_option :cache, type: :string, default: nil,
|
|
26
|
-
|
|
26
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
27
27
|
|
|
28
28
|
def ensure_base_class_and_skill_file
|
|
29
29
|
images_dir = "app/agents/images"
|
|
@@ -17,17 +17,17 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "gpt-image-1",
|
|
20
|
-
|
|
20
|
+
desc: "The image generation model to use"
|
|
21
21
|
class_option :size, type: :string, default: "1024x1024",
|
|
22
|
-
|
|
22
|
+
desc: "Image size (e.g., 1024x1024, 1792x1024)"
|
|
23
23
|
class_option :quality, type: :string, default: "standard",
|
|
24
|
-
|
|
24
|
+
desc: "Image quality (standard, hd)"
|
|
25
25
|
class_option :style, type: :string, default: "vivid",
|
|
26
|
-
|
|
26
|
+
desc: "Image style (vivid, natural)"
|
|
27
27
|
class_option :content_policy, type: :string, default: "standard",
|
|
28
|
-
|
|
28
|
+
desc: "Content policy level (none, standard, moderate, strict)"
|
|
29
29
|
class_option :cache, type: :string, default: nil,
|
|
30
|
-
|
|
30
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
31
31
|
|
|
32
32
|
def ensure_base_class_and_skill_file
|
|
33
33
|
images_dir = "app/agents/images"
|
|
@@ -17,11 +17,11 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :steps, type: :string, default: "generate,upscale",
|
|
20
|
-
|
|
20
|
+
desc: "Pipeline steps (comma-separated: generate,upscale,transform,analyze,remove_background)"
|
|
21
21
|
class_option :stop_on_error, type: :boolean, default: true,
|
|
22
|
-
|
|
22
|
+
desc: "Stop pipeline on first error"
|
|
23
23
|
class_option :cache, type: :string, default: nil,
|
|
24
|
-
|
|
24
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
25
25
|
|
|
26
26
|
def ensure_base_class_and_skill_file
|
|
27
27
|
images_dir = "app/agents/images"
|
|
@@ -132,17 +132,17 @@ module RubyLlmAgents
|
|
|
132
132
|
class_base = name.split("/").map(&:camelize).join("::")
|
|
133
133
|
case step
|
|
134
134
|
when :generate
|
|
135
|
-
{
|
|
135
|
+
{step: step, type: :generator, class_name: "Images::#{class_base}Generator"}
|
|
136
136
|
when :upscale
|
|
137
|
-
{
|
|
137
|
+
{step: step, type: :upscaler, class_name: "Images::#{class_base}Upscaler"}
|
|
138
138
|
when :transform
|
|
139
|
-
{
|
|
139
|
+
{step: step, type: :transformer, class_name: "Images::#{class_base}Transformer"}
|
|
140
140
|
when :analyze
|
|
141
|
-
{
|
|
141
|
+
{step: step, type: :analyzer, class_name: "Images::#{class_base}Analyzer"}
|
|
142
142
|
when :remove_background
|
|
143
|
-
{
|
|
143
|
+
{step: step, type: :remover, class_name: "Images::#{class_base}BackgroundRemover"}
|
|
144
144
|
else
|
|
145
|
-
{
|
|
145
|
+
{step: step, type: step, class_name: "Images::#{class_base}#{step.to_s.camelize}"}
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
end
|
|
@@ -17,17 +17,17 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "sdxl",
|
|
20
|
-
|
|
20
|
+
desc: "The image model to use"
|
|
21
21
|
class_option :size, type: :string, default: "1024x1024",
|
|
22
|
-
|
|
22
|
+
desc: "Output image size (e.g., 1024x1024)"
|
|
23
23
|
class_option :strength, type: :string, default: "0.75",
|
|
24
|
-
|
|
24
|
+
desc: "Transformation strength (0.0-1.0)"
|
|
25
25
|
class_option :template, type: :string, default: nil,
|
|
26
|
-
|
|
26
|
+
desc: "Prompt template (use {prompt} as placeholder)"
|
|
27
27
|
class_option :content_policy, type: :string, default: "standard",
|
|
28
|
-
|
|
28
|
+
desc: "Content policy level (none, standard, moderate, strict)"
|
|
29
29
|
class_option :cache, type: :string, default: nil,
|
|
30
|
-
|
|
30
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
31
31
|
|
|
32
32
|
def ensure_base_class_and_skill_file
|
|
33
33
|
images_dir = "app/agents/images"
|
|
@@ -17,13 +17,13 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "real-esrgan",
|
|
20
|
-
|
|
20
|
+
desc: "The upscaling model to use"
|
|
21
21
|
class_option :scale, type: :string, default: "4",
|
|
22
|
-
|
|
22
|
+
desc: "Upscale factor (2, 4, or 8)"
|
|
23
23
|
class_option :face_enhance, type: :boolean, default: false,
|
|
24
|
-
|
|
24
|
+
desc: "Enable face enhancement"
|
|
25
25
|
class_option :cache, type: :string, default: nil,
|
|
26
|
-
|
|
26
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
27
27
|
|
|
28
28
|
def ensure_base_class_and_skill_file
|
|
29
29
|
images_dir = "app/agents/images"
|
|
@@ -17,13 +17,13 @@ module RubyLlmAgents
|
|
|
17
17
|
source_root File.expand_path("templates", __dir__)
|
|
18
18
|
|
|
19
19
|
class_option :model, type: :string, default: "gpt-image-1",
|
|
20
|
-
|
|
20
|
+
desc: "The image model to use"
|
|
21
21
|
class_option :size, type: :string, default: "1024x1024",
|
|
22
|
-
|
|
22
|
+
desc: "Output image size (e.g., 1024x1024)"
|
|
23
23
|
class_option :variation_strength, type: :string, default: "0.5",
|
|
24
|
-
|
|
24
|
+
desc: "Variation strength (0.0-1.0)"
|
|
25
25
|
class_option :cache, type: :string, default: nil,
|
|
26
|
-
|
|
26
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
27
27
|
|
|
28
28
|
def ensure_base_class_and_skill_file
|
|
29
29
|
images_dir = "app/agents/images"
|
|
@@ -22,11 +22,11 @@ module RubyLlmAgents
|
|
|
22
22
|
source_root File.expand_path("templates", __dir__)
|
|
23
23
|
|
|
24
24
|
class_option :skip_migration, type: :boolean, default: false,
|
|
25
|
-
|
|
25
|
+
desc: "Skip generating the migration file"
|
|
26
26
|
class_option :skip_initializer, type: :boolean, default: false,
|
|
27
|
-
|
|
27
|
+
desc: "Skip generating the initializer file"
|
|
28
28
|
class_option :mount_dashboard, type: :boolean, default: true,
|
|
29
|
-
|
|
29
|
+
desc: "Mount the dashboard engine in routes"
|
|
30
30
|
|
|
31
31
|
def create_migration_file
|
|
32
32
|
return if options[:skip_migration]
|
|
@@ -158,7 +158,7 @@ module RubyLlmAgents
|
|
|
158
158
|
|
|
159
159
|
directories.each do |dir|
|
|
160
160
|
if options[:dry_run]
|
|
161
|
-
say_status :dry_run, "Would create #{dir.sub(Rails.root.to_s +
|
|
161
|
+
say_status :dry_run, "Would create #{dir.sub(Rails.root.to_s + "/", "")}", :yellow
|
|
162
162
|
else
|
|
163
163
|
FileUtils.mkdir_p(dir)
|
|
164
164
|
say_status :mkdir, dir.sub(Rails.root.to_s + "/", ""), :green
|
|
@@ -393,7 +393,7 @@ module RubyLlmAgents
|
|
|
393
393
|
|
|
394
394
|
if content != original_content
|
|
395
395
|
File.write(file_path, content)
|
|
396
|
-
say_status :updated, "base classes in #{file_path.sub(Rails.root.to_s +
|
|
396
|
+
say_status :updated, "base classes in #{file_path.sub(Rails.root.to_s + "/", "")}", :blue
|
|
397
397
|
end
|
|
398
398
|
end
|
|
399
399
|
|
|
@@ -441,7 +441,7 @@ module RubyLlmAgents
|
|
|
441
441
|
next unless File.directory?(subdir) && Dir.empty?(subdir)
|
|
442
442
|
|
|
443
443
|
if options[:dry_run]
|
|
444
|
-
say_status :dry_run, "Would remove empty #{subdir.sub(Rails.root.to_s +
|
|
444
|
+
say_status :dry_run, "Would remove empty #{subdir.sub(Rails.root.to_s + "/", "")}", :yellow
|
|
445
445
|
else
|
|
446
446
|
FileUtils.rmdir(subdir)
|
|
447
447
|
say_status :removed, subdir.sub(Rails.root.to_s + "/", ""), :red
|
|
@@ -452,7 +452,7 @@ module RubyLlmAgents
|
|
|
452
452
|
return unless File.directory?(dir) && Dir.empty?(dir)
|
|
453
453
|
|
|
454
454
|
if options[:dry_run]
|
|
455
|
-
say_status :dry_run, "Would remove empty #{dir.sub(Rails.root.to_s +
|
|
455
|
+
say_status :dry_run, "Would remove empty #{dir.sub(Rails.root.to_s + "/", "")}", :yellow
|
|
456
456
|
else
|
|
457
457
|
FileUtils.rmdir(dir)
|
|
458
458
|
say_status :removed, dir.sub(Rails.root.to_s + "/", ""), :red
|
|
@@ -102,7 +102,7 @@ module RubyLlmAgents
|
|
|
102
102
|
|
|
103
103
|
def table_exists?(table)
|
|
104
104
|
ActiveRecord::Base.connection.table_exists?(table)
|
|
105
|
-
rescue
|
|
105
|
+
rescue
|
|
106
106
|
false
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -110,7 +110,7 @@ module RubyLlmAgents
|
|
|
110
110
|
return false unless ActiveRecord::Base.connection.table_exists?(table)
|
|
111
111
|
|
|
112
112
|
ActiveRecord::Base.connection.column_exists?(table, column)
|
|
113
|
-
rescue
|
|
113
|
+
rescue
|
|
114
114
|
false
|
|
115
115
|
end
|
|
116
116
|
end
|
|
@@ -37,25 +37,25 @@ module RubyLlmAgents
|
|
|
37
37
|
# Maps old directory -> { category:, type: }
|
|
38
38
|
DIRECTORY_MAPPING = {
|
|
39
39
|
# Top-level under llm/
|
|
40
|
-
"agents" => {
|
|
41
|
-
"tools" => {
|
|
40
|
+
"agents" => {category: nil, type: "agents"},
|
|
41
|
+
"tools" => {category: nil, type: "tools"},
|
|
42
42
|
|
|
43
43
|
# Audio group
|
|
44
|
-
"speakers" => {
|
|
45
|
-
"transcribers" => {
|
|
44
|
+
"speakers" => {category: :audio, type: "speakers"},
|
|
45
|
+
"transcribers" => {category: :audio, type: "transcribers"},
|
|
46
46
|
|
|
47
47
|
# Image group
|
|
48
|
-
"image_generators" => {
|
|
49
|
-
"image_editors" => {
|
|
50
|
-
"image_analyzers" => {
|
|
51
|
-
"image_transformers" => {
|
|
52
|
-
"image_upscalers" => {
|
|
53
|
-
"image_variators" => {
|
|
54
|
-
"background_removers" => {
|
|
48
|
+
"image_generators" => {category: :image, type: "generators"},
|
|
49
|
+
"image_editors" => {category: :image, type: "editors"},
|
|
50
|
+
"image_analyzers" => {category: :image, type: "analyzers"},
|
|
51
|
+
"image_transformers" => {category: :image, type: "transformers"},
|
|
52
|
+
"image_upscalers" => {category: :image, type: "upscalers"},
|
|
53
|
+
"image_variators" => {category: :image, type: "variators"},
|
|
54
|
+
"background_removers" => {category: :image, type: "background_removers"},
|
|
55
55
|
|
|
56
56
|
# Text group
|
|
57
|
-
"embedders" => {
|
|
58
|
-
"moderators" => {
|
|
57
|
+
"embedders" => {category: :text, type: "embedders"},
|
|
58
|
+
"moderators" => {category: :text, type: "moderators"}
|
|
59
59
|
}.freeze
|
|
60
60
|
|
|
61
61
|
def validate_root_directory
|