ruby_llm-agents 1.3.3 → 2.0.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 +101 -334
- data/app/controllers/concerns/ruby_llm/agents/sortable.rb +0 -1
- data/app/controllers/ruby_llm/agents/agents_controller.rb +5 -56
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +22 -106
- data/app/controllers/ruby_llm/agents/executions_controller.rb +4 -114
- data/app/controllers/ruby_llm/agents/tenants_controller.rb +30 -2
- data/app/helpers/ruby_llm/agents/application_helper.rb +19 -53
- data/app/models/ruby_llm/agents/execution/analytics.rb +13 -54
- data/app/models/ruby_llm/agents/execution/scopes.rb +61 -14
- data/app/models/ruby_llm/agents/execution.rb +46 -10
- data/app/models/ruby_llm/agents/execution_detail.rb +18 -0
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +132 -24
- data/app/models/ruby_llm/agents/tenant/incrementable.rb +117 -0
- data/app/models/ruby_llm/agents/tenant/resettable.rb +128 -0
- data/app/models/ruby_llm/agents/tenant/trackable.rb +46 -12
- data/app/models/ruby_llm/agents/tenant.rb +2 -3
- data/app/models/ruby_llm/agents/tenant_budget.rb +6 -3
- data/app/services/ruby_llm/agents/agent_registry.rb +6 -112
- data/app/views/layouts/ruby_llm/agents/application.html.erb +87 -252
- data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +71 -218
- data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +20 -63
- data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +44 -131
- data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +16 -57
- data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +39 -104
- data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +29 -82
- data/app/views/ruby_llm/agents/agents/_empty_state.html.erb +4 -14
- data/app/views/ruby_llm/agents/agents/index.html.erb +105 -274
- data/app/views/ruby_llm/agents/agents/show.html.erb +248 -378
- data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +29 -52
- data/app/views/ruby_llm/agents/dashboard/_tenant_budget.html.erb +73 -99
- data/app/views/ruby_llm/agents/dashboard/index.html.erb +228 -433
- data/app/views/ruby_llm/agents/executions/_execution.html.erb +1 -1
- data/app/views/ruby_llm/agents/executions/_filters.html.erb +4 -25
- data/app/views/ruby_llm/agents/executions/_list.html.erb +111 -152
- data/app/views/ruby_llm/agents/executions/index.html.erb +5 -7
- data/app/views/ruby_llm/agents/executions/show.html.erb +528 -989
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +5 -21
- data/app/views/ruby_llm/agents/shared/_executions_table.html.erb +70 -191
- data/app/views/ruby_llm/agents/shared/_filter_dropdown.html.erb +16 -44
- data/app/views/ruby_llm/agents/shared/_select_dropdown.html.erb +12 -41
- data/app/views/ruby_llm/agents/shared/_status_badge.html.erb +11 -65
- data/app/views/ruby_llm/agents/shared/_tenant_filter.html.erb +6 -5
- data/app/views/ruby_llm/agents/system_config/show.html.erb +240 -351
- data/app/views/ruby_llm/agents/tenants/_form.html.erb +67 -77
- data/app/views/ruby_llm/agents/tenants/edit.html.erb +7 -9
- data/app/views/ruby_llm/agents/tenants/index.html.erb +100 -122
- data/app/views/ruby_llm/agents/tenants/show.html.erb +146 -336
- data/config/routes.rb +0 -13
- data/lib/generators/ruby_llm_agents/install_generator.rb +9 -14
- data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +2 -12
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +0 -2
- data/lib/generators/ruby_llm_agents/templates/add_usage_counters_to_tenants_migration.rb.tt +37 -0
- data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +1 -2
- data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +1 -1
- data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/create_execution_details_migration.rb.tt +27 -0
- data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +25 -0
- data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/initializer.rb.tt +9 -12
- data/lib/generators/ruby_llm_agents/templates/migration.rb.tt +40 -71
- data/lib/generators/ruby_llm_agents/templates/remove_agent_version_migration.rb.tt +13 -0
- data/lib/generators/ruby_llm_agents/templates/remove_workflow_columns_migration.rb.tt +19 -0
- data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +2 -4
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/split_execution_details_migration.rb.tt +232 -0
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +58 -262
- data/lib/ruby_llm/agents/audio/speaker.rb +0 -1
- data/lib/ruby_llm/agents/audio/transcriber.rb +0 -1
- data/lib/ruby_llm/agents/base_agent.rb +52 -6
- data/lib/ruby_llm/agents/core/base/callbacks.rb +142 -0
- data/lib/ruby_llm/agents/core/base.rb +23 -55
- data/lib/ruby_llm/agents/core/configuration.rb +58 -117
- data/lib/ruby_llm/agents/core/errors.rb +0 -58
- data/lib/ruby_llm/agents/core/instrumentation.rb +157 -110
- data/lib/ruby_llm/agents/core/llm_tenant.rb +8 -7
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +157 -17
- data/lib/ruby_llm/agents/dsl/caching.rb +33 -2
- data/lib/ruby_llm/agents/dsl/reliability.rb +148 -0
- data/lib/ruby_llm/agents/dsl.rb +1 -2
- data/lib/ruby_llm/agents/image/analyzer/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/background_remover/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +1 -13
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +2 -2
- data/lib/ruby_llm/agents/image/editor/dsl.rb +0 -14
- data/lib/ruby_llm/agents/image/editor/execution.rb +1 -10
- data/lib/ruby_llm/agents/image/editor.rb +0 -1
- data/lib/ruby_llm/agents/image/generator.rb +0 -21
- data/lib/ruby_llm/agents/image/pipeline/dsl.rb +0 -13
- data/lib/ruby_llm/agents/image/pipeline/execution.rb +0 -1
- data/lib/ruby_llm/agents/image/transformer/dsl.rb +0 -13
- data/lib/ruby_llm/agents/image/transformer/execution.rb +1 -10
- data/lib/ruby_llm/agents/image/transformer.rb +0 -1
- data/lib/ruby_llm/agents/image/upscaler/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/variator/execution.rb +1 -2
- data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +78 -173
- data/lib/ruby_llm/agents/infrastructure/attempt_tracker.rb +1 -0
- data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +66 -2
- data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +0 -12
- data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +10 -13
- data/lib/ruby_llm/agents/infrastructure/reliability.rb +37 -2
- data/lib/ruby_llm/agents/pipeline/context.rb +0 -1
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +28 -4
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +3 -10
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +88 -55
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +5 -41
- data/lib/ruby_llm/agents/rails/engine.rb +6 -6
- data/lib/ruby_llm/agents/results/base.rb +1 -49
- data/lib/ruby_llm/agents/text/embedder.rb +0 -1
- data/lib/ruby_llm/agents.rb +1 -9
- data/lib/tasks/ruby_llm_agents.rake +34 -0
- metadata +12 -81
- data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +0 -214
- data/app/controllers/ruby_llm/agents/workflows_controller.rb +0 -544
- data/app/mailers/ruby_llm/agents/alert_mailer.rb +0 -84
- data/app/mailers/ruby_llm/agents/application_mailer.rb +0 -28
- data/app/models/ruby_llm/agents/api_configuration.rb +0 -386
- data/app/models/ruby_llm/agents/execution/workflow.rb +0 -170
- data/app/models/ruby_llm/agents/tenant/configurable.rb +0 -135
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +0 -98
- data/app/views/ruby_llm/agents/agents/_version_comparison.html.erb +0 -186
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +0 -126
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.html.erb +0 -107
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.text.erb +0 -18
- data/app/views/ruby_llm/agents/api_configurations/_api_key_field.html.erb +0 -34
- data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +0 -288
- data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +0 -95
- data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +0 -97
- data/app/views/ruby_llm/agents/api_configurations/show.html.erb +0 -214
- data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +0 -179
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +0 -73
- data/app/views/ruby_llm/agents/dashboard/_alerts_feed.html.erb +0 -62
- data/app/views/ruby_llm/agents/dashboard/_breaker_strip.html.erb +0 -47
- data/app/views/ruby_llm/agents/dashboard/_budgets_bar.html.erb +0 -75
- data/app/views/ruby_llm/agents/dashboard/_model_comparison.html.erb +0 -56
- data/app/views/ruby_llm/agents/dashboard/_model_cost_breakdown.html.erb +0 -115
- data/app/views/ruby_llm/agents/dashboard/_now_strip.html.erb +0 -59
- data/app/views/ruby_llm/agents/dashboard/_top_errors.html.erb +0 -60
- data/app/views/ruby_llm/agents/executions/_workflow_summary.html.erb +0 -86
- data/app/views/ruby_llm/agents/executions/dry_run.html.erb +0 -149
- data/app/views/ruby_llm/agents/shared/_breadcrumbs.html.erb +0 -48
- data/app/views/ruby_llm/agents/shared/_nav_link.html.erb +0 -27
- data/app/views/ruby_llm/agents/shared/_stat_card.html.erb +0 -14
- data/app/views/ruby_llm/agents/shared/_workflow_type_badge.html.erb +0 -35
- data/app/views/ruby_llm/agents/workflows/_empty_state.html.erb +0 -22
- data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +0 -228
- data/app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb +0 -539
- data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +0 -76
- data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +0 -74
- data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +0 -108
- data/app/views/ruby_llm/agents/workflows/_workflow_diagram.html.erb +0 -920
- data/app/views/ruby_llm/agents/workflows/index.html.erb +0 -179
- data/app/views/ruby_llm/agents/workflows/show.html.erb +0 -467
- data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +0 -100
- data/lib/generators/ruby_llm_agents/templates/add_workflow_migration.rb.tt +0 -38
- data/lib/generators/ruby_llm_agents/templates/application_workflow.rb.tt +0 -48
- data/lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt +0 -90
- data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +0 -551
- data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +0 -181
- data/lib/ruby_llm/agents/core/base/moderation_execution.rb +0 -274
- data/lib/ruby_llm/agents/core/resolved_config.rb +0 -348
- data/lib/ruby_llm/agents/image/generator/content_policy.rb +0 -95
- data/lib/ruby_llm/agents/infrastructure/redactor.rb +0 -130
- data/lib/ruby_llm/agents/results/moderation_result.rb +0 -158
- data/lib/ruby_llm/agents/text/moderator.rb +0 -237
- data/lib/ruby_llm/agents/workflow/approval.rb +0 -205
- data/lib/ruby_llm/agents/workflow/approval_store.rb +0 -179
- data/lib/ruby_llm/agents/workflow/async.rb +0 -220
- data/lib/ruby_llm/agents/workflow/async_executor.rb +0 -156
- data/lib/ruby_llm/agents/workflow/dsl/executor.rb +0 -467
- data/lib/ruby_llm/agents/workflow/dsl/input_schema.rb +0 -244
- data/lib/ruby_llm/agents/workflow/dsl/iteration_executor.rb +0 -289
- data/lib/ruby_llm/agents/workflow/dsl/parallel_group.rb +0 -107
- data/lib/ruby_llm/agents/workflow/dsl/route_builder.rb +0 -150
- data/lib/ruby_llm/agents/workflow/dsl/schedule_helpers.rb +0 -187
- data/lib/ruby_llm/agents/workflow/dsl/step_config.rb +0 -352
- data/lib/ruby_llm/agents/workflow/dsl/step_executor.rb +0 -415
- data/lib/ruby_llm/agents/workflow/dsl/wait_config.rb +0 -257
- data/lib/ruby_llm/agents/workflow/dsl/wait_executor.rb +0 -317
- data/lib/ruby_llm/agents/workflow/dsl.rb +0 -576
- data/lib/ruby_llm/agents/workflow/instrumentation.rb +0 -249
- data/lib/ruby_llm/agents/workflow/notifiers/base.rb +0 -117
- data/lib/ruby_llm/agents/workflow/notifiers/email.rb +0 -117
- data/lib/ruby_llm/agents/workflow/notifiers/slack.rb +0 -180
- data/lib/ruby_llm/agents/workflow/notifiers/webhook.rb +0 -121
- data/lib/ruby_llm/agents/workflow/notifiers.rb +0 -70
- data/lib/ruby_llm/agents/workflow/orchestrator.rb +0 -416
- data/lib/ruby_llm/agents/workflow/result.rb +0 -592
- data/lib/ruby_llm/agents/workflow/thread_pool.rb +0 -185
- data/lib/ruby_llm/agents/workflow/throttle_manager.rb +0 -206
- data/lib/ruby_llm/agents/workflow/wait_result.rb +0 -213
|
@@ -7,20 +7,39 @@ module RubyLLM
|
|
|
7
7
|
#
|
|
8
8
|
# Provides common configuration methods that every agent type needs:
|
|
9
9
|
# - model: The LLM model to use
|
|
10
|
-
# -
|
|
10
|
+
# - prompt: The user prompt (string with {placeholders} or block)
|
|
11
|
+
# - system: System instructions
|
|
11
12
|
# - description: Human-readable description
|
|
12
13
|
# - timeout: Request timeout
|
|
14
|
+
# - returns: Structured output schema
|
|
13
15
|
#
|
|
14
|
-
# @example
|
|
15
|
-
# class
|
|
16
|
-
# extend DSL::Base
|
|
17
|
-
#
|
|
16
|
+
# @example Simplified DSL
|
|
17
|
+
# class SearchAgent < RubyLLM::Agents::BaseAgent
|
|
18
18
|
# model "gpt-4o"
|
|
19
|
-
#
|
|
20
|
-
#
|
|
19
|
+
# system "You are a helpful search assistant."
|
|
20
|
+
# prompt "Search for: {query} (limit: {limit})"
|
|
21
|
+
#
|
|
22
|
+
# param :limit, default: 10 # Override auto-detected param
|
|
23
|
+
#
|
|
24
|
+
# returns do
|
|
25
|
+
# array :results do
|
|
26
|
+
# string :title
|
|
27
|
+
# string :url
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# @example Dynamic prompt with block
|
|
33
|
+
# class SummaryAgent < RubyLLM::Agents::BaseAgent
|
|
34
|
+
# prompt do
|
|
35
|
+
# "Summarize in #{word_count} words: #{text}"
|
|
36
|
+
# end
|
|
21
37
|
# end
|
|
22
38
|
#
|
|
23
39
|
module Base
|
|
40
|
+
# Regex pattern to extract {placeholder} parameters from prompt strings
|
|
41
|
+
PLACEHOLDER_PATTERN = /\{(\w+)\}/.freeze
|
|
42
|
+
|
|
24
43
|
# @!group Configuration DSL
|
|
25
44
|
|
|
26
45
|
# Sets or returns the LLM model for this agent class
|
|
@@ -34,18 +53,75 @@ module RubyLLM
|
|
|
34
53
|
@model || inherited_or_default(:model, default_model)
|
|
35
54
|
end
|
|
36
55
|
|
|
37
|
-
# Sets
|
|
56
|
+
# Sets the user prompt template or block
|
|
38
57
|
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
58
|
+
# When a string is provided, {placeholder} syntax is used to interpolate
|
|
59
|
+
# parameters. Parameters are automatically registered (as required) unless
|
|
60
|
+
# already defined with `param`.
|
|
41
61
|
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
# When a block is provided, it's evaluated in the instance context at
|
|
63
|
+
# execution time, allowing access to all instance methods and parameters.
|
|
64
|
+
#
|
|
65
|
+
# @param template [String, nil] Prompt template with {placeholder} syntax
|
|
66
|
+
# @yield Block that returns the prompt string (evaluated at execution time)
|
|
67
|
+
# @return [String, Proc, nil] The current prompt configuration
|
|
68
|
+
#
|
|
69
|
+
# @example With template string (parameters auto-detected)
|
|
70
|
+
# prompt "Search for: {query} in {category}"
|
|
71
|
+
# # Automatically registers :query and :category as required params
|
|
72
|
+
#
|
|
73
|
+
# @example With block for dynamic prompts
|
|
74
|
+
# prompt do
|
|
75
|
+
# base = "Analyze the following"
|
|
76
|
+
# base += " in #{language}" if language != "en"
|
|
77
|
+
# "#{base}: #{text}"
|
|
78
|
+
# end
|
|
79
|
+
#
|
|
80
|
+
def prompt(template = nil, &block)
|
|
81
|
+
if template
|
|
82
|
+
@prompt_template = template
|
|
83
|
+
auto_register_params_from_template(template)
|
|
84
|
+
elsif block
|
|
85
|
+
@prompt_block = block
|
|
86
|
+
end
|
|
87
|
+
@prompt_template || @prompt_block || inherited_or_default(:prompt_config, nil)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns the prompt configuration (template or block)
|
|
91
|
+
#
|
|
92
|
+
# @return [String, Proc, nil] The prompt template, block, or nil
|
|
93
|
+
def prompt_config
|
|
94
|
+
@prompt_template || @prompt_block || inherited_or_default(:prompt_config, nil)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Sets the system prompt/instructions
|
|
98
|
+
#
|
|
99
|
+
# @param text [String, nil] System instructions for the LLM
|
|
100
|
+
# @yield Block that returns the system prompt (evaluated at execution time)
|
|
101
|
+
# @return [String, Proc, nil] The current system prompt
|
|
102
|
+
#
|
|
103
|
+
# @example Static system prompt
|
|
104
|
+
# system "You are a helpful assistant. Be concise and accurate."
|
|
105
|
+
#
|
|
106
|
+
# @example Dynamic system prompt
|
|
107
|
+
# system do
|
|
108
|
+
# "You are helping #{user_name}. Their preferences: #{preferences}"
|
|
109
|
+
# end
|
|
110
|
+
#
|
|
111
|
+
def system(text = nil, &block)
|
|
112
|
+
if text
|
|
113
|
+
@system_template = text
|
|
114
|
+
elsif block
|
|
115
|
+
@system_block = block
|
|
116
|
+
end
|
|
117
|
+
@system_template || @system_block || inherited_or_default(:system_config, nil)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Returns the system prompt configuration
|
|
121
|
+
#
|
|
122
|
+
# @return [String, Proc, nil] The system template, block, or nil
|
|
123
|
+
def system_config
|
|
124
|
+
@system_template || @system_block || inherited_or_default(:system_config, nil)
|
|
49
125
|
end
|
|
50
126
|
|
|
51
127
|
# Sets or returns the description for this agent class
|
|
@@ -72,10 +148,74 @@ module RubyLLM
|
|
|
72
148
|
@timeout || inherited_or_default(:timeout, default_timeout)
|
|
73
149
|
end
|
|
74
150
|
|
|
151
|
+
# Sets or returns the response schema for structured output
|
|
152
|
+
#
|
|
153
|
+
# Accepts a hash (JSON Schema), a block (passed to RubyLLM::Schema.create),
|
|
154
|
+
# or any object that responds to `to_json_schema`.
|
|
155
|
+
#
|
|
156
|
+
# @param value [Hash, Object, nil] The schema to set
|
|
157
|
+
# @param block [Proc, nil] Block passed to RubyLLM::Schema.create
|
|
158
|
+
# @return [Hash, RubyLLM::Schema, nil] The current schema setting
|
|
159
|
+
# @example With a block (recommended)
|
|
160
|
+
# schema do
|
|
161
|
+
# string :name, description: "The user's name"
|
|
162
|
+
# integer :age, description: "The user's age"
|
|
163
|
+
# end
|
|
164
|
+
# @example With a hash
|
|
165
|
+
# schema type: "object", properties: { name: { type: "string" } }
|
|
166
|
+
def schema(value = nil, &block)
|
|
167
|
+
if value
|
|
168
|
+
@schema = value
|
|
169
|
+
elsif block
|
|
170
|
+
@schema = RubyLLM::Schema.create(&block)
|
|
171
|
+
end
|
|
172
|
+
@schema || inherited_or_default(:schema, nil)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Alias for schema with a clearer name
|
|
176
|
+
#
|
|
177
|
+
# Defines the structured output schema for this agent.
|
|
178
|
+
# This is the preferred method for defining schemas in the simplified DSL.
|
|
179
|
+
#
|
|
180
|
+
# @param block [Proc] Block passed to RubyLLM::Schema.create
|
|
181
|
+
# @return [RubyLLM::Schema, nil] The current schema setting
|
|
182
|
+
#
|
|
183
|
+
# @example
|
|
184
|
+
# returns do
|
|
185
|
+
# string :summary, "A brief summary"
|
|
186
|
+
# array :insights, of: :string, description: "Key insights"
|
|
187
|
+
# number :confidence, "Confidence score from 0 to 1"
|
|
188
|
+
# end
|
|
189
|
+
#
|
|
190
|
+
def returns(&block)
|
|
191
|
+
schema(&block)
|
|
192
|
+
end
|
|
193
|
+
|
|
75
194
|
# @!endgroup
|
|
76
195
|
|
|
77
196
|
private
|
|
78
197
|
|
|
198
|
+
# Auto-registers parameters found in prompt template placeholders
|
|
199
|
+
#
|
|
200
|
+
# Extracts {placeholder} patterns from the template and registers
|
|
201
|
+
# each as a required parameter (unless already defined).
|
|
202
|
+
#
|
|
203
|
+
# @param template [String] The prompt template
|
|
204
|
+
# @return [void]
|
|
205
|
+
def auto_register_params_from_template(template)
|
|
206
|
+
return unless respond_to?(:param)
|
|
207
|
+
|
|
208
|
+
placeholders = template.scan(PLACEHOLDER_PATTERN).flatten.map(&:to_sym)
|
|
209
|
+
existing_params = respond_to?(:params) ? params.keys : []
|
|
210
|
+
|
|
211
|
+
placeholders.each do |placeholder|
|
|
212
|
+
next if existing_params.include?(placeholder)
|
|
213
|
+
|
|
214
|
+
# Auto-register as required parameter
|
|
215
|
+
param(placeholder, required: true)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
79
219
|
# Looks up setting from superclass or uses default
|
|
80
220
|
#
|
|
81
221
|
# @param method [Symbol] The method to call on superclass
|
|
@@ -43,8 +43,39 @@ module RubyLLM
|
|
|
43
43
|
@cache_ttl = ttl
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
#
|
|
47
|
-
|
|
46
|
+
# Unified cache configuration method (simplified DSL)
|
|
47
|
+
#
|
|
48
|
+
# Configures caching with a cleaner syntax using keyword arguments.
|
|
49
|
+
#
|
|
50
|
+
# @param ttl_or_options [ActiveSupport::Duration, Hash] TTL or options hash
|
|
51
|
+
# @param for_duration [ActiveSupport::Duration] TTL for cached responses
|
|
52
|
+
# @param key [Array<Symbol>] Parameters to include in cache key
|
|
53
|
+
# @return [void]
|
|
54
|
+
#
|
|
55
|
+
# @example Simple TTL (positional argument for backward compatibility)
|
|
56
|
+
# cache 1.hour
|
|
57
|
+
#
|
|
58
|
+
# @example With keyword arguments (preferred)
|
|
59
|
+
# cache for: 1.hour
|
|
60
|
+
# cache for: 30.minutes, key: [:query, :user_id]
|
|
61
|
+
#
|
|
62
|
+
def cache(ttl_or_options = nil, for: nil, key: nil)
|
|
63
|
+
# Handle positional argument (backward compatibility)
|
|
64
|
+
if ttl_or_options && !ttl_or_options.is_a?(Hash)
|
|
65
|
+
@cache_enabled = true
|
|
66
|
+
@cache_ttl = ttl_or_options
|
|
67
|
+
return
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Handle keyword arguments
|
|
71
|
+
for_duration = binding.local_variable_get(:for)
|
|
72
|
+
if for_duration
|
|
73
|
+
@cache_enabled = true
|
|
74
|
+
@cache_ttl = for_duration
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@cache_key_includes = Array(key) if key
|
|
78
|
+
end
|
|
48
79
|
|
|
49
80
|
# Returns whether caching is enabled for this agent
|
|
50
81
|
#
|
|
@@ -57,6 +57,35 @@ module RubyLLM
|
|
|
57
57
|
@non_fallback_errors = builder.non_fallback_errors_list if builder.non_fallback_errors_list
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# Alias for reliability with clearer intent-revealing name
|
|
61
|
+
#
|
|
62
|
+
# Configures what happens when an LLM call fails.
|
|
63
|
+
# This is the preferred method in the simplified DSL.
|
|
64
|
+
#
|
|
65
|
+
# @yield Block containing failure handling configuration
|
|
66
|
+
# @return [void]
|
|
67
|
+
#
|
|
68
|
+
# @example
|
|
69
|
+
# on_failure do
|
|
70
|
+
# retry times: 3, backoff: :exponential
|
|
71
|
+
# fallback to: ["gpt-4o-mini", "gpt-3.5-turbo"]
|
|
72
|
+
# circuit_breaker after: 5, cooldown: 5.minutes
|
|
73
|
+
# timeout 30.seconds
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
def on_failure(&block)
|
|
77
|
+
builder = OnFailureBuilder.new
|
|
78
|
+
builder.instance_eval(&block)
|
|
79
|
+
|
|
80
|
+
@retries_config = builder.retries_config if builder.retries_config
|
|
81
|
+
@fallback_models = builder.fallback_models_list if builder.fallback_models_list.any?
|
|
82
|
+
@fallback_providers = builder.fallback_providers_list if builder.fallback_providers_list.any?
|
|
83
|
+
@total_timeout = builder.total_timeout_value if builder.total_timeout_value
|
|
84
|
+
@circuit_breaker_config = builder.circuit_breaker_config if builder.circuit_breaker_config
|
|
85
|
+
@retryable_patterns = builder.retryable_patterns_list if builder.retryable_patterns_list
|
|
86
|
+
@non_fallback_errors = builder.non_fallback_errors_list if builder.non_fallback_errors_list
|
|
87
|
+
end
|
|
88
|
+
|
|
60
89
|
# Returns the complete reliability configuration hash
|
|
61
90
|
#
|
|
62
91
|
# Used by the Reliability middleware to get all settings.
|
|
@@ -326,6 +355,125 @@ module RubyLLM
|
|
|
326
355
|
@non_fallback_errors_list = error_classes.flatten
|
|
327
356
|
end
|
|
328
357
|
end
|
|
358
|
+
|
|
359
|
+
# Builder class for on_failure block with simplified syntax
|
|
360
|
+
#
|
|
361
|
+
# Uses more intuitive method names:
|
|
362
|
+
# - `retry times:` instead of `retries max:`
|
|
363
|
+
# - `fallback to:` instead of `fallback_models`
|
|
364
|
+
# - `circuit_breaker after:` instead of `circuit_breaker errors:`
|
|
365
|
+
# - `timeout` instead of `total_timeout`
|
|
366
|
+
#
|
|
367
|
+
class OnFailureBuilder
|
|
368
|
+
attr_reader :retries_config, :fallback_models_list, :total_timeout_value,
|
|
369
|
+
:circuit_breaker_config, :retryable_patterns_list, :fallback_providers_list,
|
|
370
|
+
:non_fallback_errors_list
|
|
371
|
+
|
|
372
|
+
def initialize
|
|
373
|
+
@retries_config = nil
|
|
374
|
+
@fallback_models_list = []
|
|
375
|
+
@total_timeout_value = nil
|
|
376
|
+
@circuit_breaker_config = nil
|
|
377
|
+
@retryable_patterns_list = nil
|
|
378
|
+
@fallback_providers_list = []
|
|
379
|
+
@non_fallback_errors_list = nil
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# Configure retry behavior
|
|
383
|
+
#
|
|
384
|
+
# @param times [Integer] Number of retry attempts
|
|
385
|
+
# @param backoff [Symbol] Backoff strategy (:constant or :exponential)
|
|
386
|
+
# @param base [Float] Base delay in seconds
|
|
387
|
+
# @param max_delay [Float] Maximum delay between retries
|
|
388
|
+
# @param on [Array<Class>] Error classes to retry on
|
|
389
|
+
#
|
|
390
|
+
# @example
|
|
391
|
+
# retries times: 3, backoff: :exponential
|
|
392
|
+
#
|
|
393
|
+
def retries(times: 0, backoff: :exponential, base: 0.4, max_delay: 3.0, on: [])
|
|
394
|
+
@retries_config = {
|
|
395
|
+
max: times,
|
|
396
|
+
backoff: backoff,
|
|
397
|
+
base: base,
|
|
398
|
+
max_delay: max_delay,
|
|
399
|
+
on: on
|
|
400
|
+
}
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Configure fallback models
|
|
404
|
+
#
|
|
405
|
+
# @param to [String, Array<String>] Model(s) to fall back to
|
|
406
|
+
#
|
|
407
|
+
# @example
|
|
408
|
+
# fallback to: "gpt-4o-mini"
|
|
409
|
+
# fallback to: ["gpt-4o-mini", "gpt-3.5-turbo"]
|
|
410
|
+
#
|
|
411
|
+
def fallback(to:)
|
|
412
|
+
@fallback_models_list = Array(to)
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# Also support fallback_models for compatibility
|
|
416
|
+
def fallback_models(*models)
|
|
417
|
+
@fallback_models_list = models.flatten
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# Configure a fallback provider (for audio agents)
|
|
421
|
+
#
|
|
422
|
+
# @param provider [Symbol] The provider to fall back to
|
|
423
|
+
# @param options [Hash] Provider-specific options
|
|
424
|
+
#
|
|
425
|
+
def fallback_provider(provider, **options)
|
|
426
|
+
@fallback_providers_list << { provider: provider, **options }
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Configure timeout for all retry/fallback attempts
|
|
430
|
+
#
|
|
431
|
+
# @param duration [Integer, ActiveSupport::Duration] Timeout duration
|
|
432
|
+
#
|
|
433
|
+
# @example
|
|
434
|
+
# timeout 30
|
|
435
|
+
# timeout 30.seconds
|
|
436
|
+
#
|
|
437
|
+
def timeout(duration)
|
|
438
|
+
# Handle ActiveSupport::Duration
|
|
439
|
+
@total_timeout_value = duration.respond_to?(:to_i) ? duration.to_i : duration
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
# Also support total_timeout for compatibility
|
|
443
|
+
alias total_timeout timeout
|
|
444
|
+
|
|
445
|
+
# Configure circuit breaker
|
|
446
|
+
#
|
|
447
|
+
# @param after [Integer] Number of errors to trigger open state
|
|
448
|
+
# @param errors [Integer] Alias for after (compatibility)
|
|
449
|
+
# @param within [Integer] Rolling window in seconds
|
|
450
|
+
# @param cooldown [Integer, ActiveSupport::Duration] Cooldown period
|
|
451
|
+
#
|
|
452
|
+
# @example
|
|
453
|
+
# circuit_breaker after: 5, cooldown: 5.minutes
|
|
454
|
+
# circuit_breaker errors: 10, within: 60, cooldown: 300
|
|
455
|
+
#
|
|
456
|
+
def circuit_breaker(after: nil, errors: nil, within: 60, cooldown: 300)
|
|
457
|
+
error_threshold = after || errors || 10
|
|
458
|
+
cooldown_seconds = cooldown.respond_to?(:to_i) ? cooldown.to_i : cooldown
|
|
459
|
+
|
|
460
|
+
@circuit_breaker_config = {
|
|
461
|
+
errors: error_threshold,
|
|
462
|
+
within: within,
|
|
463
|
+
cooldown: cooldown_seconds
|
|
464
|
+
}
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
# Configure additional retryable patterns
|
|
468
|
+
def retryable_patterns(*patterns)
|
|
469
|
+
@retryable_patterns_list = patterns.flatten
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
# Configure errors that should never trigger fallback
|
|
473
|
+
def non_fallback_errors(*error_classes)
|
|
474
|
+
@non_fallback_errors_list = error_classes.flatten
|
|
475
|
+
end
|
|
476
|
+
end
|
|
329
477
|
end
|
|
330
478
|
end
|
|
331
479
|
end
|
data/lib/ruby_llm/agents/dsl.rb
CHANGED
|
@@ -11,7 +11,7 @@ module RubyLLM
|
|
|
11
11
|
# The DSL modules provide a clean, declarative way to configure agents
|
|
12
12
|
# at the class level. Each module focuses on a specific concern:
|
|
13
13
|
#
|
|
14
|
-
# - {DSL::Base} - Core settings (model,
|
|
14
|
+
# - {DSL::Base} - Core settings (model, description, timeout)
|
|
15
15
|
# - {DSL::Reliability} - Retries, fallbacks, circuit breakers
|
|
16
16
|
# - {DSL::Caching} - Response caching configuration
|
|
17
17
|
#
|
|
@@ -22,7 +22,6 @@ module RubyLLM
|
|
|
22
22
|
# extend DSL::Caching
|
|
23
23
|
#
|
|
24
24
|
# model "gpt-4o"
|
|
25
|
-
# version "2.0"
|
|
26
25
|
# description "A helpful agent"
|
|
27
26
|
# timeout 30
|
|
28
27
|
#
|
|
@@ -365,7 +365,6 @@ module RubyLLM
|
|
|
365
365
|
[
|
|
366
366
|
"image_analyzer",
|
|
367
367
|
self.class.name,
|
|
368
|
-
self.class.version,
|
|
369
368
|
resolve_model,
|
|
370
369
|
resolve_analysis_type.to_s,
|
|
371
370
|
resolve_extract_colors.to_s,
|
|
@@ -387,7 +386,7 @@ module RubyLLM
|
|
|
387
386
|
end
|
|
388
387
|
end
|
|
389
388
|
|
|
390
|
-
def
|
|
389
|
+
def build_metadata(result)
|
|
391
390
|
{
|
|
392
391
|
analysis_type: result.analysis_type,
|
|
393
392
|
tags_count: result.tags.size,
|
|
@@ -203,7 +203,6 @@ module RubyLLM
|
|
|
203
203
|
[
|
|
204
204
|
"background_remover",
|
|
205
205
|
self.class.name,
|
|
206
|
-
self.class.version,
|
|
207
206
|
resolve_model,
|
|
208
207
|
resolve_output_format.to_s,
|
|
209
208
|
resolve_alpha_matting.to_s,
|
|
@@ -226,7 +225,7 @@ module RubyLLM
|
|
|
226
225
|
end
|
|
227
226
|
end
|
|
228
227
|
|
|
229
|
-
def
|
|
228
|
+
def build_metadata(result)
|
|
230
229
|
{
|
|
231
230
|
output_format: result.output_format,
|
|
232
231
|
alpha_matting: result.alpha_matting,
|
|
@@ -5,7 +5,7 @@ module RubyLLM
|
|
|
5
5
|
module Concerns
|
|
6
6
|
# Shared DSL methods for all image operation classes
|
|
7
7
|
#
|
|
8
|
-
# Provides common configuration options like model,
|
|
8
|
+
# Provides common configuration options like model,
|
|
9
9
|
# description, and caching that are shared across ImageVariator,
|
|
10
10
|
# ImageEditor, ImageTransformer, and ImageUpscaler.
|
|
11
11
|
#
|
|
@@ -22,18 +22,6 @@ module RubyLLM
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
# Set or get the version
|
|
26
|
-
#
|
|
27
|
-
# @param value [String, nil] Version identifier
|
|
28
|
-
# @return [String] The version
|
|
29
|
-
def version(value = nil)
|
|
30
|
-
if value
|
|
31
|
-
@version = value
|
|
32
|
-
else
|
|
33
|
-
@version || inherited_or_default(:version, "v1")
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
25
|
# Set or get the description
|
|
38
26
|
#
|
|
39
27
|
# @param value [String, nil] Description
|
|
@@ -118,7 +118,7 @@ module RubyLLM
|
|
|
118
118
|
duration_ms: result.duration_ms,
|
|
119
119
|
started_at: result.started_at,
|
|
120
120
|
completed_at: result.completed_at,
|
|
121
|
-
metadata:
|
|
121
|
+
metadata: build_metadata(result)
|
|
122
122
|
}
|
|
123
123
|
end
|
|
124
124
|
|
|
@@ -141,7 +141,7 @@ module RubyLLM
|
|
|
141
141
|
}
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
-
def
|
|
144
|
+
def build_metadata(result)
|
|
145
145
|
{ count: result.count }
|
|
146
146
|
end
|
|
147
147
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "../concerns/image_operation_dsl"
|
|
4
|
-
require_relative "../generator/content_policy"
|
|
5
4
|
|
|
6
5
|
module RubyLLM
|
|
7
6
|
module Agents
|
|
@@ -15,7 +14,6 @@ module RubyLLM
|
|
|
15
14
|
# class ProductEditor < RubyLLM::Agents::ImageEditor
|
|
16
15
|
# model "gpt-image-1"
|
|
17
16
|
# size "1024x1024"
|
|
18
|
-
# content_policy :strict
|
|
19
17
|
# end
|
|
20
18
|
#
|
|
21
19
|
module DSL
|
|
@@ -33,18 +31,6 @@ module RubyLLM
|
|
|
33
31
|
end
|
|
34
32
|
end
|
|
35
33
|
|
|
36
|
-
# Set or get the content policy level
|
|
37
|
-
#
|
|
38
|
-
# @param level [Symbol, nil] Policy level (:none, :standard, :moderate, :strict)
|
|
39
|
-
# @return [Symbol] The content policy level
|
|
40
|
-
def content_policy(level = nil)
|
|
41
|
-
if level
|
|
42
|
-
@content_policy = level
|
|
43
|
-
else
|
|
44
|
-
@content_policy || inherited_or_default(:content_policy, :standard)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
34
|
private
|
|
49
35
|
|
|
50
36
|
def default_model
|
|
@@ -23,7 +23,6 @@ module RubyLLM
|
|
|
23
23
|
resolve_tenant_context!
|
|
24
24
|
check_budget! if budget_tracking_enabled?
|
|
25
25
|
validate_inputs!
|
|
26
|
-
validate_content_policy!
|
|
27
26
|
|
|
28
27
|
# Check cache
|
|
29
28
|
cached = check_cache(ImageEditResult) if cache_enabled?
|
|
@@ -81,13 +80,6 @@ module RubyLLM
|
|
|
81
80
|
end
|
|
82
81
|
end
|
|
83
82
|
|
|
84
|
-
def validate_content_policy!
|
|
85
|
-
policy = self.class.content_policy
|
|
86
|
-
return if policy == :none || policy == :standard
|
|
87
|
-
|
|
88
|
-
ImageGenerator::ContentPolicy.validate!(prompt, policy)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
83
|
def edit_images
|
|
92
84
|
count = resolve_count
|
|
93
85
|
|
|
@@ -173,7 +165,6 @@ module RubyLLM
|
|
|
173
165
|
[
|
|
174
166
|
"image_editor",
|
|
175
167
|
self.class.name,
|
|
176
|
-
self.class.version,
|
|
177
168
|
resolve_model,
|
|
178
169
|
resolve_size,
|
|
179
170
|
Digest::SHA256.hexdigest(prompt),
|
|
@@ -194,7 +185,7 @@ module RubyLLM
|
|
|
194
185
|
end
|
|
195
186
|
end
|
|
196
187
|
|
|
197
|
-
def
|
|
188
|
+
def build_metadata(result)
|
|
198
189
|
{
|
|
199
190
|
count: result.count,
|
|
200
191
|
size: result.size,
|
|
@@ -57,7 +57,6 @@ module RubyLLM
|
|
|
57
57
|
subclass.instance_variable_set(:@version, @version)
|
|
58
58
|
subclass.instance_variable_set(:@description, @description)
|
|
59
59
|
subclass.instance_variable_set(:@cache_ttl, @cache_ttl)
|
|
60
|
-
subclass.instance_variable_set(:@content_policy, @content_policy)
|
|
61
60
|
end
|
|
62
61
|
end
|
|
63
62
|
|
|
@@ -80,15 +80,6 @@ module RubyLLM
|
|
|
80
80
|
@style || inherited_or_default(:style, default_image_style)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
# Sets or returns the content policy level
|
|
84
|
-
#
|
|
85
|
-
# @param level [Symbol, nil] Policy level (:none, :standard, :moderate, :strict)
|
|
86
|
-
# @return [Symbol] The content policy level
|
|
87
|
-
def content_policy(level = nil)
|
|
88
|
-
@content_policy = level if level
|
|
89
|
-
@content_policy || inherited_or_default(:content_policy, :standard)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
83
|
# Sets or returns negative prompt (things to avoid in generation)
|
|
93
84
|
#
|
|
94
85
|
# @param value [String, nil] Negative prompt text
|
|
@@ -162,7 +153,6 @@ module RubyLLM
|
|
|
162
153
|
subclass.instance_variable_set(:@version, @version)
|
|
163
154
|
subclass.instance_variable_set(:@description, @description)
|
|
164
155
|
subclass.instance_variable_set(:@cache_ttl, @cache_ttl)
|
|
165
|
-
subclass.instance_variable_set(:@content_policy, @content_policy)
|
|
166
156
|
subclass.instance_variable_set(:@negative_prompt, @negative_prompt)
|
|
167
157
|
subclass.instance_variable_set(:@seed, @seed)
|
|
168
158
|
subclass.instance_variable_set(:@guidance_scale, @guidance_scale)
|
|
@@ -246,7 +236,6 @@ module RubyLLM
|
|
|
246
236
|
execution_started_at = Time.current
|
|
247
237
|
|
|
248
238
|
validate_prompt!
|
|
249
|
-
validate_content_policy!
|
|
250
239
|
|
|
251
240
|
# Generate image(s)
|
|
252
241
|
images = generate_images
|
|
@@ -286,7 +275,6 @@ module RubyLLM
|
|
|
286
275
|
"ruby_llm_agents",
|
|
287
276
|
"image_generator",
|
|
288
277
|
self.class.name,
|
|
289
|
-
self.class.version,
|
|
290
278
|
resolved_model,
|
|
291
279
|
resolved_size,
|
|
292
280
|
resolved_quality,
|
|
@@ -323,14 +311,6 @@ module RubyLLM
|
|
|
323
311
|
end
|
|
324
312
|
end
|
|
325
313
|
|
|
326
|
-
# Validates prompt against content policy
|
|
327
|
-
def validate_content_policy!
|
|
328
|
-
policy = self.class.content_policy
|
|
329
|
-
return if policy == :none || policy == :standard
|
|
330
|
-
|
|
331
|
-
ContentPolicy.validate!(prompt, policy)
|
|
332
|
-
end
|
|
333
|
-
|
|
334
314
|
# Generate images using RubyLLM.paint
|
|
335
315
|
def generate_images
|
|
336
316
|
count = @runtime_count
|
|
@@ -450,6 +430,5 @@ end
|
|
|
450
430
|
|
|
451
431
|
# Load supporting modules after class is defined (they reopen the class)
|
|
452
432
|
require_relative "generator/pricing"
|
|
453
|
-
require_relative "generator/content_policy"
|
|
454
433
|
require_relative "generator/templates"
|
|
455
434
|
require_relative "generator/active_storage_support"
|
|
@@ -14,7 +14,6 @@ module RubyLLM
|
|
|
14
14
|
# step :upscale, upscaler: PhotoUpscaler, scale: 4
|
|
15
15
|
# step :analyze, analyzer: ProductAnalyzer
|
|
16
16
|
#
|
|
17
|
-
# version "1.0"
|
|
18
17
|
# description "Complete product image pipeline"
|
|
19
18
|
# stop_on_error true
|
|
20
19
|
# end
|
|
@@ -103,18 +102,6 @@ module RubyLLM
|
|
|
103
102
|
@callbacks ||= { before: [], after: [] }
|
|
104
103
|
end
|
|
105
104
|
|
|
106
|
-
# Set or get the version
|
|
107
|
-
#
|
|
108
|
-
# @param value [String, nil] Version identifier
|
|
109
|
-
# @return [String] The version
|
|
110
|
-
def version(value = nil)
|
|
111
|
-
if value
|
|
112
|
-
@version = value
|
|
113
|
-
else
|
|
114
|
-
@version || inherited_or_default(:version, "v1")
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
105
|
# Set or get the description
|
|
119
106
|
#
|
|
120
107
|
# @param value [String, nil] Description
|