ruby_llm-agents 0.5.0 → 1.0.0.beta.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.
- checksums.yaml +4 -4
- data/README.md +189 -31
- data/app/controllers/ruby_llm/agents/agents_controller.rb +136 -16
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +29 -9
- data/app/controllers/ruby_llm/agents/workflows_controller.rb +355 -0
- data/app/helpers/ruby_llm/agents/application_helper.rb +25 -0
- data/app/models/ruby_llm/agents/execution.rb +3 -0
- data/app/models/ruby_llm/agents/tenant_budget.rb +58 -15
- data/app/services/ruby_llm/agents/agent_registry.rb +51 -12
- data/app/views/layouts/ruby_llm/agents/application.html.erb +2 -29
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +13 -1
- data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +235 -0
- data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +70 -0
- data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +152 -0
- data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +63 -0
- data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +108 -0
- data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +91 -0
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +1 -1
- data/app/views/ruby_llm/agents/agents/index.html.erb +74 -9
- data/app/views/ruby_llm/agents/agents/show.html.erb +18 -378
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +269 -15
- data/app/views/ruby_llm/agents/executions/show.html.erb +16 -0
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +93 -0
- data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +236 -0
- data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +76 -0
- data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +74 -0
- data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +108 -0
- data/app/views/ruby_llm/agents/workflows/show.html.erb +442 -0
- data/config/routes.rb +1 -0
- data/lib/generators/ruby_llm_agents/agent_generator.rb +56 -7
- data/lib/generators/ruby_llm_agents/background_remover_generator.rb +110 -0
- data/lib/generators/ruby_llm_agents/embedder_generator.rb +107 -0
- data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +115 -0
- data/lib/generators/ruby_llm_agents/image_editor_generator.rb +108 -0
- data/lib/generators/ruby_llm_agents/image_generator_generator.rb +116 -0
- data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +178 -0
- data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +109 -0
- data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +103 -0
- data/lib/generators/ruby_llm_agents/image_variator_generator.rb +102 -0
- data/lib/generators/ruby_llm_agents/install_generator.rb +76 -4
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +292 -0
- data/lib/generators/ruby_llm_agents/speaker_generator.rb +121 -0
- data/lib/generators/ruby_llm_agents/templates/add_execution_type_migration.rb.tt +8 -0
- data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +99 -84
- data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +42 -40
- data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +26 -0
- data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +50 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +26 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +20 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +38 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +139 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +21 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +20 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +20 -0
- data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +49 -0
- data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +53 -0
- data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +44 -0
- data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +41 -0
- data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +45 -0
- data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +35 -0
- data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +47 -0
- data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +50 -0
- data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +44 -0
- data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +38 -0
- data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +33 -0
- data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +228 -0
- data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +131 -0
- data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +255 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +120 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +102 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +282 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +228 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +120 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +110 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +120 -0
- data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +212 -0
- data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +227 -0
- data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +251 -0
- data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +300 -0
- data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +56 -0
- data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +51 -0
- data/lib/generators/ruby_llm_agents/transcriber_generator.rb +107 -0
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +152 -1
- data/lib/ruby_llm/agents/audio/speaker.rb +553 -0
- data/lib/ruby_llm/agents/audio/transcriber.rb +669 -0
- data/lib/ruby_llm/agents/base_agent.rb +675 -0
- data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +181 -0
- data/lib/ruby_llm/agents/core/base/moderation_execution.rb +274 -0
- data/lib/ruby_llm/agents/core/base.rb +135 -0
- data/lib/ruby_llm/agents/core/configuration.rb +981 -0
- data/lib/ruby_llm/agents/core/errors.rb +150 -0
- data/lib/ruby_llm/agents/{instrumentation.rb → core/instrumentation.rb} +22 -1
- data/lib/ruby_llm/agents/core/llm_tenant.rb +358 -0
- data/lib/ruby_llm/agents/{version.rb → core/version.rb} +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +110 -0
- data/lib/ruby_llm/agents/dsl/caching.rb +142 -0
- data/lib/ruby_llm/agents/dsl/reliability.rb +307 -0
- data/lib/ruby_llm/agents/dsl.rb +41 -0
- data/lib/ruby_llm/agents/image/analyzer/dsl.rb +130 -0
- data/lib/ruby_llm/agents/image/analyzer/execution.rb +402 -0
- data/lib/ruby_llm/agents/image/analyzer.rb +90 -0
- data/lib/ruby_llm/agents/image/background_remover/dsl.rb +154 -0
- data/lib/ruby_llm/agents/image/background_remover/execution.rb +240 -0
- data/lib/ruby_llm/agents/image/background_remover.rb +89 -0
- data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +91 -0
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +165 -0
- data/lib/ruby_llm/agents/image/editor/dsl.rb +56 -0
- data/lib/ruby_llm/agents/image/editor/execution.rb +207 -0
- data/lib/ruby_llm/agents/image/editor.rb +92 -0
- data/lib/ruby_llm/agents/image/generator/active_storage_support.rb +127 -0
- data/lib/ruby_llm/agents/image/generator/content_policy.rb +95 -0
- data/lib/ruby_llm/agents/image/generator/pricing.rb +353 -0
- data/lib/ruby_llm/agents/image/generator/templates.rb +124 -0
- data/lib/ruby_llm/agents/image/generator.rb +455 -0
- data/lib/ruby_llm/agents/image/pipeline/dsl.rb +213 -0
- data/lib/ruby_llm/agents/image/pipeline/execution.rb +382 -0
- data/lib/ruby_llm/agents/image/pipeline.rb +97 -0
- data/lib/ruby_llm/agents/image/transformer/dsl.rb +148 -0
- data/lib/ruby_llm/agents/image/transformer/execution.rb +223 -0
- data/lib/ruby_llm/agents/image/transformer.rb +95 -0
- data/lib/ruby_llm/agents/image/upscaler/dsl.rb +83 -0
- data/lib/ruby_llm/agents/image/upscaler/execution.rb +219 -0
- data/lib/ruby_llm/agents/image/upscaler.rb +81 -0
- data/lib/ruby_llm/agents/image/variator/dsl.rb +62 -0
- data/lib/ruby_llm/agents/image/variator/execution.rb +189 -0
- data/lib/ruby_llm/agents/image/variator.rb +80 -0
- data/lib/ruby_llm/agents/{alert_manager.rb → infrastructure/alert_manager.rb} +17 -22
- data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +145 -0
- data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +149 -0
- data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +68 -0
- data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +279 -0
- data/lib/ruby_llm/agents/infrastructure/budget_tracker.rb +275 -0
- data/lib/ruby_llm/agents/{execution_logger_job.rb → infrastructure/execution_logger_job.rb} +17 -1
- data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/executor.rb +2 -1
- data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/retry_strategy.rb +9 -3
- data/lib/ruby_llm/agents/{reliability.rb → infrastructure/reliability.rb} +11 -21
- data/lib/ruby_llm/agents/pipeline/builder.rb +215 -0
- data/lib/ruby_llm/agents/pipeline/context.rb +255 -0
- data/lib/ruby_llm/agents/pipeline/executor.rb +86 -0
- data/lib/ruby_llm/agents/pipeline/middleware/base.rb +124 -0
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +95 -0
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +171 -0
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +415 -0
- data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +276 -0
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +196 -0
- data/lib/ruby_llm/agents/pipeline.rb +68 -0
- data/lib/ruby_llm/agents/{engine.rb → rails/engine.rb} +79 -11
- data/lib/ruby_llm/agents/results/background_removal_result.rb +286 -0
- data/lib/ruby_llm/agents/{result.rb → results/base.rb} +73 -1
- data/lib/ruby_llm/agents/results/embedding_result.rb +243 -0
- data/lib/ruby_llm/agents/results/image_analysis_result.rb +314 -0
- data/lib/ruby_llm/agents/results/image_edit_result.rb +250 -0
- data/lib/ruby_llm/agents/results/image_generation_result.rb +346 -0
- data/lib/ruby_llm/agents/results/image_pipeline_result.rb +399 -0
- data/lib/ruby_llm/agents/results/image_transform_result.rb +251 -0
- data/lib/ruby_llm/agents/results/image_upscale_result.rb +255 -0
- data/lib/ruby_llm/agents/results/image_variation_result.rb +237 -0
- data/lib/ruby_llm/agents/results/moderation_result.rb +158 -0
- data/lib/ruby_llm/agents/results/speech_result.rb +338 -0
- data/lib/ruby_llm/agents/results/transcription_result.rb +408 -0
- data/lib/ruby_llm/agents/text/embedder.rb +444 -0
- data/lib/ruby_llm/agents/text/moderator.rb +237 -0
- data/lib/ruby_llm/agents/workflow/async.rb +220 -0
- data/lib/ruby_llm/agents/workflow/async_executor.rb +156 -0
- data/lib/ruby_llm/agents/{workflow.rb → workflow/orchestrator.rb} +6 -5
- data/lib/ruby_llm/agents/workflow/parallel.rb +34 -17
- data/lib/ruby_llm/agents/workflow/thread_pool.rb +185 -0
- data/lib/ruby_llm/agents.rb +86 -20
- metadata +172 -34
- data/lib/ruby_llm/agents/base/caching.rb +0 -40
- data/lib/ruby_llm/agents/base/cost_calculation.rb +0 -105
- data/lib/ruby_llm/agents/base/dsl.rb +0 -324
- data/lib/ruby_llm/agents/base/execution.rb +0 -366
- data/lib/ruby_llm/agents/base/reliability_dsl.rb +0 -82
- data/lib/ruby_llm/agents/base/reliability_execution.rb +0 -136
- data/lib/ruby_llm/agents/base/response_building.rb +0 -86
- data/lib/ruby_llm/agents/base/tool_tracking.rb +0 -57
- data/lib/ruby_llm/agents/base.rb +0 -210
- data/lib/ruby_llm/agents/budget_tracker.rb +0 -733
- data/lib/ruby_llm/agents/configuration.rb +0 -394
- /data/lib/ruby_llm/agents/{deprecations.rb → core/deprecations.rb} +0 -0
- /data/lib/ruby_llm/agents/{inflections.rb → core/inflections.rb} +0 -0
- /data/lib/ruby_llm/agents/{resolved_config.rb → core/resolved_config.rb} +0 -0
- /data/lib/ruby_llm/agents/{attempt_tracker.rb → infrastructure/attempt_tracker.rb} +0 -0
- /data/lib/ruby_llm/agents/{cache_helper.rb → infrastructure/cache_helper.rb} +0 -0
- /data/lib/ruby_llm/agents/{circuit_breaker.rb → infrastructure/circuit_breaker.rb} +0 -0
- /data/lib/ruby_llm/agents/{redactor.rb → infrastructure/redactor.rb} +0 -0
- /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/breaker_manager.rb +0 -0
- /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/execution_constraints.rb +0 -0
- /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/fallback_routing.rb +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RubyLlmAgents
|
|
6
|
+
# Embedder generator for creating new embedders
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# rails generate ruby_llm_agents:embedder Document
|
|
10
|
+
# rails generate ruby_llm_agents:embedder Document --model text-embedding-3-large
|
|
11
|
+
# rails generate ruby_llm_agents:embedder Document --dimensions 512
|
|
12
|
+
# rails generate ruby_llm_agents:embedder Document --root=ai
|
|
13
|
+
#
|
|
14
|
+
# This will create:
|
|
15
|
+
# - app/{root}/text/embedders/document_embedder.rb
|
|
16
|
+
#
|
|
17
|
+
class EmbedderGenerator < ::Rails::Generators::NamedBase
|
|
18
|
+
source_root File.expand_path("templates", __dir__)
|
|
19
|
+
|
|
20
|
+
class_option :model, type: :string, default: "text-embedding-3-small",
|
|
21
|
+
desc: "The embedding model to use"
|
|
22
|
+
class_option :dimensions, type: :numeric, default: nil,
|
|
23
|
+
desc: "Vector dimensions (nil for model default)"
|
|
24
|
+
class_option :batch_size, type: :numeric, default: 100,
|
|
25
|
+
desc: "Texts per API call for batch processing"
|
|
26
|
+
class_option :cache, type: :string, default: nil,
|
|
27
|
+
desc: "Cache TTL (e.g., '1.week', '1.day')"
|
|
28
|
+
class_option :root,
|
|
29
|
+
type: :string,
|
|
30
|
+
default: nil,
|
|
31
|
+
desc: "Root directory name (default: uses config or 'llm')"
|
|
32
|
+
class_option :namespace,
|
|
33
|
+
type: :string,
|
|
34
|
+
default: nil,
|
|
35
|
+
desc: "Root namespace (default: camelized root or config)"
|
|
36
|
+
|
|
37
|
+
def ensure_base_class_and_skill_file
|
|
38
|
+
@root_namespace = root_namespace
|
|
39
|
+
@text_namespace = "#{root_namespace}::Text"
|
|
40
|
+
embedders_dir = "app/#{root_directory}/text/embedders"
|
|
41
|
+
|
|
42
|
+
# Create directory if needed
|
|
43
|
+
empty_directory embedders_dir
|
|
44
|
+
|
|
45
|
+
# Create base class if it doesn't exist
|
|
46
|
+
base_class_path = "#{embedders_dir}/application_embedder.rb"
|
|
47
|
+
unless File.exist?(File.join(destination_root, base_class_path))
|
|
48
|
+
template "application_embedder.rb.tt", base_class_path
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Create skill file if it doesn't exist
|
|
52
|
+
skill_file_path = "#{embedders_dir}/EMBEDDERS.md"
|
|
53
|
+
unless File.exist?(File.join(destination_root, skill_file_path))
|
|
54
|
+
template "skills/EMBEDDERS.md.tt", skill_file_path
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def create_embedder_file
|
|
59
|
+
# Support nested paths: "search/document" -> "app/{root}/text/embedders/search/document_embedder.rb"
|
|
60
|
+
@root_namespace = root_namespace
|
|
61
|
+
@text_namespace = "#{root_namespace}::Text"
|
|
62
|
+
embedder_path = name.underscore
|
|
63
|
+
template "embedder.rb.tt", "app/#{root_directory}/text/embedders/#{embedder_path}_embedder.rb"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def show_usage
|
|
67
|
+
# Build full class name from path
|
|
68
|
+
embedder_class_name = name.split("/").map(&:camelize).join("::")
|
|
69
|
+
full_class_name = "#{root_namespace}::Text::#{embedder_class_name}Embedder"
|
|
70
|
+
say ""
|
|
71
|
+
say "Embedder #{full_class_name} created!", :green
|
|
72
|
+
say ""
|
|
73
|
+
say "Usage:"
|
|
74
|
+
say " # Single text"
|
|
75
|
+
say " #{full_class_name}.call(text: \"Hello world\")"
|
|
76
|
+
say ""
|
|
77
|
+
say " # Multiple texts (batch)"
|
|
78
|
+
say " #{full_class_name}.call(texts: [\"Hello\", \"World\"])"
|
|
79
|
+
say ""
|
|
80
|
+
say " # With progress tracking"
|
|
81
|
+
say " #{full_class_name}.call(texts: large_array) do |batch, idx|"
|
|
82
|
+
say " puts \"Processed batch \#{idx}\""
|
|
83
|
+
say " end"
|
|
84
|
+
say ""
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def root_directory
|
|
90
|
+
@root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def root_namespace
|
|
94
|
+
@root_namespace ||= options[:namespace] || camelize(root_directory)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def camelize(str)
|
|
98
|
+
# Handle special cases for common abbreviations
|
|
99
|
+
return "AI" if str.downcase == "ai"
|
|
100
|
+
return "ML" if str.downcase == "ml"
|
|
101
|
+
return "LLM" if str.downcase == "llm"
|
|
102
|
+
|
|
103
|
+
# Standard camelization
|
|
104
|
+
str.split(/[-_]/).map(&:capitalize).join
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RubyLlmAgents
|
|
6
|
+
# ImageAnalyzer generator for creating new image analyzers
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# rails generate ruby_llm_agents:image_analyzer Product
|
|
10
|
+
# rails generate ruby_llm_agents:image_analyzer Content --model gpt-4o --analysis_type detailed
|
|
11
|
+
# rails generate ruby_llm_agents:image_analyzer Photo --extract_colors --detect_objects
|
|
12
|
+
# rails generate ruby_llm_agents:image_analyzer Product --root=ai
|
|
13
|
+
#
|
|
14
|
+
# This will create:
|
|
15
|
+
# - app/{root}/image/analyzers/product_analyzer.rb
|
|
16
|
+
#
|
|
17
|
+
class ImageAnalyzerGenerator < ::Rails::Generators::NamedBase
|
|
18
|
+
source_root File.expand_path("templates", __dir__)
|
|
19
|
+
|
|
20
|
+
class_option :model, type: :string, default: "gpt-4o",
|
|
21
|
+
desc: "The vision model to use"
|
|
22
|
+
class_option :analysis_type, type: :string, default: "detailed",
|
|
23
|
+
desc: "Analysis type (caption, detailed, tags, objects, colors, all)"
|
|
24
|
+
class_option :extract_colors, type: :boolean, default: false,
|
|
25
|
+
desc: "Enable color extraction"
|
|
26
|
+
class_option :detect_objects, type: :boolean, default: false,
|
|
27
|
+
desc: "Enable object detection"
|
|
28
|
+
class_option :extract_text, type: :boolean, default: false,
|
|
29
|
+
desc: "Enable text extraction (OCR)"
|
|
30
|
+
class_option :max_tags, type: :string, default: "10",
|
|
31
|
+
desc: "Maximum number of tags to return"
|
|
32
|
+
class_option :cache, type: :string, default: nil,
|
|
33
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
34
|
+
class_option :root,
|
|
35
|
+
type: :string,
|
|
36
|
+
default: nil,
|
|
37
|
+
desc: "Root directory name (default: uses config or 'llm')"
|
|
38
|
+
class_option :namespace,
|
|
39
|
+
type: :string,
|
|
40
|
+
default: nil,
|
|
41
|
+
desc: "Root namespace (default: camelized root or config)"
|
|
42
|
+
|
|
43
|
+
def ensure_base_class_and_skill_file
|
|
44
|
+
@root_namespace = root_namespace
|
|
45
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
46
|
+
analyzers_dir = "app/#{root_directory}/image/analyzers"
|
|
47
|
+
|
|
48
|
+
# Create directory if needed
|
|
49
|
+
empty_directory analyzers_dir
|
|
50
|
+
|
|
51
|
+
# Create base class if it doesn't exist
|
|
52
|
+
base_class_path = "#{analyzers_dir}/application_image_analyzer.rb"
|
|
53
|
+
unless File.exist?(File.join(destination_root, base_class_path))
|
|
54
|
+
template "application_image_analyzer.rb.tt", base_class_path
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Create skill file if it doesn't exist
|
|
58
|
+
skill_file_path = "#{analyzers_dir}/IMAGE_ANALYZERS.md"
|
|
59
|
+
unless File.exist?(File.join(destination_root, skill_file_path))
|
|
60
|
+
template "skills/IMAGE_ANALYZERS.md.tt", skill_file_path
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def create_image_analyzer_file
|
|
65
|
+
@root_namespace = root_namespace
|
|
66
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
67
|
+
analyzer_path = name.underscore
|
|
68
|
+
template "image_analyzer.rb.tt", "app/#{root_directory}/image/analyzers/#{analyzer_path}_analyzer.rb"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def show_usage
|
|
72
|
+
analyzer_class_name = name.split("/").map(&:camelize).join("::")
|
|
73
|
+
full_class_name = "#{root_namespace}::Image::#{analyzer_class_name}Analyzer"
|
|
74
|
+
say ""
|
|
75
|
+
say "Image analyzer #{full_class_name} created!", :green
|
|
76
|
+
say ""
|
|
77
|
+
say "Usage:"
|
|
78
|
+
say " # Analyze an image"
|
|
79
|
+
say " result = #{full_class_name}.call(image: 'photo.jpg')"
|
|
80
|
+
say " result.caption # => 'A sunset over mountains'"
|
|
81
|
+
say " result.tags # => ['sunset', 'mountains', 'nature']"
|
|
82
|
+
say " result.description # => 'Detailed description...'"
|
|
83
|
+
say ""
|
|
84
|
+
say " # Override settings at runtime"
|
|
85
|
+
say " result = #{full_class_name}.call("
|
|
86
|
+
say " image: 'product.jpg',"
|
|
87
|
+
say " analysis_type: :all,"
|
|
88
|
+
say " extract_colors: true,"
|
|
89
|
+
say " detect_objects: true"
|
|
90
|
+
say " )"
|
|
91
|
+
say ""
|
|
92
|
+
say " # Access detected objects and colors"
|
|
93
|
+
say " result.objects # => [{name: 'laptop', location: 'center', confidence: 'high'}]"
|
|
94
|
+
say " result.colors # => [{hex: '#C0C0C0', name: 'silver', percentage: 45}]"
|
|
95
|
+
say ""
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def root_directory
|
|
101
|
+
@root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def root_namespace
|
|
105
|
+
@root_namespace ||= options[:namespace] || camelize(root_directory)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def camelize(str)
|
|
109
|
+
return "AI" if str.downcase == "ai"
|
|
110
|
+
return "ML" if str.downcase == "ml"
|
|
111
|
+
return "LLM" if str.downcase == "llm"
|
|
112
|
+
str.split(/[-_]/).map(&:capitalize).join
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RubyLlmAgents
|
|
6
|
+
# ImageEditor generator for creating new image editors
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# rails generate ruby_llm_agents:image_editor Product
|
|
10
|
+
# rails generate ruby_llm_agents:image_editor Background --model gpt-image-1 --size 1024x1024
|
|
11
|
+
# rails generate ruby_llm_agents:image_editor Photo --content_policy strict
|
|
12
|
+
# rails generate ruby_llm_agents:image_editor Product --root=ai
|
|
13
|
+
#
|
|
14
|
+
# This will create:
|
|
15
|
+
# - app/{root}/image/editors/product_editor.rb
|
|
16
|
+
#
|
|
17
|
+
class ImageEditorGenerator < ::Rails::Generators::NamedBase
|
|
18
|
+
source_root File.expand_path("templates", __dir__)
|
|
19
|
+
|
|
20
|
+
class_option :model, type: :string, default: "gpt-image-1",
|
|
21
|
+
desc: "The image model to use"
|
|
22
|
+
class_option :size, type: :string, default: "1024x1024",
|
|
23
|
+
desc: "Output image size (e.g., 1024x1024)"
|
|
24
|
+
class_option :content_policy, type: :string, default: "standard",
|
|
25
|
+
desc: "Content policy level (none, standard, moderate, strict)"
|
|
26
|
+
class_option :cache, type: :string, default: nil,
|
|
27
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
28
|
+
class_option :root,
|
|
29
|
+
type: :string,
|
|
30
|
+
default: nil,
|
|
31
|
+
desc: "Root directory name (default: uses config or 'llm')"
|
|
32
|
+
class_option :namespace,
|
|
33
|
+
type: :string,
|
|
34
|
+
default: nil,
|
|
35
|
+
desc: "Root namespace (default: camelized root or config)"
|
|
36
|
+
|
|
37
|
+
def ensure_base_class_and_skill_file
|
|
38
|
+
@root_namespace = root_namespace
|
|
39
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
40
|
+
editors_dir = "app/#{root_directory}/image/editors"
|
|
41
|
+
|
|
42
|
+
# Create directory if needed
|
|
43
|
+
empty_directory editors_dir
|
|
44
|
+
|
|
45
|
+
# Create base class if it doesn't exist
|
|
46
|
+
base_class_path = "#{editors_dir}/application_image_editor.rb"
|
|
47
|
+
unless File.exist?(File.join(destination_root, base_class_path))
|
|
48
|
+
template "application_image_editor.rb.tt", base_class_path
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Create skill file if it doesn't exist
|
|
52
|
+
skill_file_path = "#{editors_dir}/IMAGE_EDITORS.md"
|
|
53
|
+
unless File.exist?(File.join(destination_root, skill_file_path))
|
|
54
|
+
template "skills/IMAGE_EDITORS.md.tt", skill_file_path
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def create_image_editor_file
|
|
59
|
+
@root_namespace = root_namespace
|
|
60
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
61
|
+
editor_path = name.underscore
|
|
62
|
+
template "image_editor.rb.tt", "app/#{root_directory}/image/editors/#{editor_path}_editor.rb"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def show_usage
|
|
66
|
+
editor_class_name = name.split("/").map(&:camelize).join("::")
|
|
67
|
+
full_class_name = "#{root_namespace}::Image::#{editor_class_name}Editor"
|
|
68
|
+
say ""
|
|
69
|
+
say "Image editor #{full_class_name} created!", :green
|
|
70
|
+
say ""
|
|
71
|
+
say "Usage:"
|
|
72
|
+
say " # Edit an image with a mask"
|
|
73
|
+
say " result = #{full_class_name}.call("
|
|
74
|
+
say " image: 'photo.png',"
|
|
75
|
+
say " mask: 'mask.png',"
|
|
76
|
+
say " prompt: 'Replace the background with a beach scene'"
|
|
77
|
+
say " )"
|
|
78
|
+
say " result.url # => 'https://...'"
|
|
79
|
+
say ""
|
|
80
|
+
say " # Generate multiple edit variations"
|
|
81
|
+
say " result = #{full_class_name}.call("
|
|
82
|
+
say " image: 'photo.png',"
|
|
83
|
+
say " mask: 'mask.png',"
|
|
84
|
+
say " prompt: 'Add a sunset',"
|
|
85
|
+
say " count: 3"
|
|
86
|
+
say " )"
|
|
87
|
+
say " result.urls # => ['https://...', ...]"
|
|
88
|
+
say ""
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def root_directory
|
|
94
|
+
@root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def root_namespace
|
|
98
|
+
@root_namespace ||= options[:namespace] || camelize(root_directory)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def camelize(str)
|
|
102
|
+
return "AI" if str.downcase == "ai"
|
|
103
|
+
return "ML" if str.downcase == "ml"
|
|
104
|
+
return "LLM" if str.downcase == "llm"
|
|
105
|
+
str.split(/[-_]/).map(&:capitalize).join
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RubyLlmAgents
|
|
6
|
+
# ImageGenerator generator for creating new image generators
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# rails generate ruby_llm_agents:image_generator Logo
|
|
10
|
+
# rails generate ruby_llm_agents:image_generator Product --model gpt-image-1 --size 1024x1024
|
|
11
|
+
# rails generate ruby_llm_agents:image_generator Avatar --quality hd --style vivid
|
|
12
|
+
# rails generate ruby_llm_agents:image_generator Logo --root=ai
|
|
13
|
+
#
|
|
14
|
+
# This will create:
|
|
15
|
+
# - app/{root}/image/generators/logo_generator.rb
|
|
16
|
+
#
|
|
17
|
+
class ImageGeneratorGenerator < ::Rails::Generators::NamedBase
|
|
18
|
+
source_root File.expand_path("templates", __dir__)
|
|
19
|
+
|
|
20
|
+
class_option :model, type: :string, default: "gpt-image-1",
|
|
21
|
+
desc: "The image generation model to use"
|
|
22
|
+
class_option :size, type: :string, default: "1024x1024",
|
|
23
|
+
desc: "Image size (e.g., 1024x1024, 1792x1024)"
|
|
24
|
+
class_option :quality, type: :string, default: "standard",
|
|
25
|
+
desc: "Image quality (standard, hd)"
|
|
26
|
+
class_option :style, type: :string, default: "vivid",
|
|
27
|
+
desc: "Image style (vivid, natural)"
|
|
28
|
+
class_option :content_policy, type: :string, default: "standard",
|
|
29
|
+
desc: "Content policy level (none, standard, moderate, strict)"
|
|
30
|
+
class_option :cache, type: :string, default: nil,
|
|
31
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
32
|
+
class_option :root,
|
|
33
|
+
type: :string,
|
|
34
|
+
default: nil,
|
|
35
|
+
desc: "Root directory name (default: uses config or 'llm')"
|
|
36
|
+
class_option :namespace,
|
|
37
|
+
type: :string,
|
|
38
|
+
default: nil,
|
|
39
|
+
desc: "Root namespace (default: camelized root or config)"
|
|
40
|
+
|
|
41
|
+
def ensure_base_class_and_skill_file
|
|
42
|
+
@root_namespace = root_namespace
|
|
43
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
44
|
+
generators_dir = "app/#{root_directory}/image/generators"
|
|
45
|
+
|
|
46
|
+
# Create directory if needed
|
|
47
|
+
empty_directory generators_dir
|
|
48
|
+
|
|
49
|
+
# Create base class if it doesn't exist
|
|
50
|
+
base_class_path = "#{generators_dir}/application_image_generator.rb"
|
|
51
|
+
unless File.exist?(File.join(destination_root, base_class_path))
|
|
52
|
+
template "application_image_generator.rb.tt", base_class_path
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Create skill file if it doesn't exist
|
|
56
|
+
skill_file_path = "#{generators_dir}/IMAGE_GENERATORS.md"
|
|
57
|
+
unless File.exist?(File.join(destination_root, skill_file_path))
|
|
58
|
+
template "skills/IMAGE_GENERATORS.md.tt", skill_file_path
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def create_image_generator_file
|
|
63
|
+
# Support nested paths: "product/hero" -> "app/{root}/image/generators/product/hero_generator.rb"
|
|
64
|
+
@root_namespace = root_namespace
|
|
65
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
66
|
+
generator_path = name.underscore
|
|
67
|
+
template "image_generator.rb.tt", "app/#{root_directory}/image/generators/#{generator_path}_generator.rb"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def show_usage
|
|
71
|
+
# Build full class name from path
|
|
72
|
+
generator_class_name = name.split("/").map(&:camelize).join("::")
|
|
73
|
+
full_class_name = "#{root_namespace}::Image::#{generator_class_name}Generator"
|
|
74
|
+
say ""
|
|
75
|
+
say "Image generator #{full_class_name} created!", :green
|
|
76
|
+
say ""
|
|
77
|
+
say "Usage:"
|
|
78
|
+
say " # Generate a single image"
|
|
79
|
+
say " result = #{full_class_name}.call(prompt: \"A beautiful sunset\")"
|
|
80
|
+
say " result.url # => \"https://...\""
|
|
81
|
+
say " result.save(\"sunset.png\")"
|
|
82
|
+
say ""
|
|
83
|
+
say " # Generate multiple images"
|
|
84
|
+
say " result = #{full_class_name}.call(prompt: \"Logos\", count: 4)"
|
|
85
|
+
say " result.urls # => [\"https://...\", ...]"
|
|
86
|
+
say ""
|
|
87
|
+
say " # Override settings at runtime"
|
|
88
|
+
say " result = #{full_class_name}.call("
|
|
89
|
+
say " prompt: \"High quality portrait\","
|
|
90
|
+
say " quality: \"hd\","
|
|
91
|
+
say " size: \"1792x1024\""
|
|
92
|
+
say " )"
|
|
93
|
+
say ""
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def root_directory
|
|
99
|
+
@root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def root_namespace
|
|
103
|
+
@root_namespace ||= options[:namespace] || camelize(root_directory)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def camelize(str)
|
|
107
|
+
# Handle special cases for common abbreviations
|
|
108
|
+
return "AI" if str.downcase == "ai"
|
|
109
|
+
return "ML" if str.downcase == "ml"
|
|
110
|
+
return "LLM" if str.downcase == "llm"
|
|
111
|
+
|
|
112
|
+
# Standard camelization
|
|
113
|
+
str.split(/[-_]/).map(&:capitalize).join
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RubyLlmAgents
|
|
6
|
+
# ImagePipeline generator for creating new image pipelines
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# rails generate ruby_llm_agents:image_pipeline Product
|
|
10
|
+
# rails generate ruby_llm_agents:image_pipeline Ecommerce --steps generate,upscale,remove_background
|
|
11
|
+
# rails generate ruby_llm_agents:image_pipeline Content --steps generate,analyze
|
|
12
|
+
# rails generate ruby_llm_agents:image_pipeline Product --root=ai
|
|
13
|
+
#
|
|
14
|
+
# This will create:
|
|
15
|
+
# - app/{root}/image/pipelines/product_pipeline.rb
|
|
16
|
+
#
|
|
17
|
+
class ImagePipelineGenerator < ::Rails::Generators::NamedBase
|
|
18
|
+
source_root File.expand_path("templates", __dir__)
|
|
19
|
+
|
|
20
|
+
class_option :steps, type: :string, default: "generate,upscale",
|
|
21
|
+
desc: "Pipeline steps (comma-separated: generate,upscale,transform,analyze,remove_background)"
|
|
22
|
+
class_option :stop_on_error, type: :boolean, default: true,
|
|
23
|
+
desc: "Stop pipeline on first error"
|
|
24
|
+
class_option :cache, type: :string, default: nil,
|
|
25
|
+
desc: "Cache TTL (e.g., '1.hour', '1.day')"
|
|
26
|
+
class_option :root,
|
|
27
|
+
type: :string,
|
|
28
|
+
default: nil,
|
|
29
|
+
desc: "Root directory name (default: uses config or 'llm')"
|
|
30
|
+
class_option :namespace,
|
|
31
|
+
type: :string,
|
|
32
|
+
default: nil,
|
|
33
|
+
desc: "Root namespace (default: camelized root or config)"
|
|
34
|
+
|
|
35
|
+
def ensure_base_class_and_skill_file
|
|
36
|
+
@root_namespace = root_namespace
|
|
37
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
38
|
+
pipelines_dir = "app/#{root_directory}/image/pipelines"
|
|
39
|
+
|
|
40
|
+
# Create directory if needed
|
|
41
|
+
empty_directory pipelines_dir
|
|
42
|
+
|
|
43
|
+
# Create base class if it doesn't exist
|
|
44
|
+
base_class_path = "#{pipelines_dir}/application_image_pipeline.rb"
|
|
45
|
+
unless File.exist?(File.join(destination_root, base_class_path))
|
|
46
|
+
template "application_image_pipeline.rb.tt", base_class_path
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Create skill file if it doesn't exist
|
|
50
|
+
skill_file_path = "#{pipelines_dir}/IMAGE_PIPELINES.md"
|
|
51
|
+
unless File.exist?(File.join(destination_root, skill_file_path))
|
|
52
|
+
template "skills/IMAGE_PIPELINES.md.tt", skill_file_path
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def create_image_pipeline_file
|
|
57
|
+
@root_namespace = root_namespace
|
|
58
|
+
@image_namespace = "#{root_namespace}::Image"
|
|
59
|
+
pipeline_path = name.underscore
|
|
60
|
+
template "image_pipeline.rb.tt", "app/#{root_directory}/image/pipelines/#{pipeline_path}_pipeline.rb"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def create_step_classes
|
|
64
|
+
# Create stub classes for referenced steps if they don't exist
|
|
65
|
+
parsed_steps.each do |step|
|
|
66
|
+
create_step_stub(step) if should_create_stub?(step)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def show_usage
|
|
71
|
+
pipeline_class_name = name.split("/").map(&:camelize).join("::")
|
|
72
|
+
full_class_name = "#{root_namespace}::Image::#{pipeline_class_name}Pipeline"
|
|
73
|
+
say ""
|
|
74
|
+
say "Image pipeline #{full_class_name} created!", :green
|
|
75
|
+
say ""
|
|
76
|
+
say "Usage:"
|
|
77
|
+
say " # Run the pipeline"
|
|
78
|
+
say " result = #{full_class_name}.call(prompt: 'Product photo')"
|
|
79
|
+
say " result.final_image # => The processed image"
|
|
80
|
+
say " result.total_cost # => Combined cost of all steps"
|
|
81
|
+
say " result.step_count # => Number of steps executed"
|
|
82
|
+
say ""
|
|
83
|
+
say " # Access individual step results"
|
|
84
|
+
say " result.step(:generate) # => ImageGenerationResult"
|
|
85
|
+
say " result.step(:upscale) # => ImageUpscaleResult"
|
|
86
|
+
say " result.analysis # => ImageAnalysisResult (if analyzer step)"
|
|
87
|
+
say ""
|
|
88
|
+
say " # Save the final image"
|
|
89
|
+
say " result.save('output.png')"
|
|
90
|
+
say ""
|
|
91
|
+
say " # With tenant tracking"
|
|
92
|
+
say " result = #{full_class_name}.call("
|
|
93
|
+
say " prompt: 'Product photo',"
|
|
94
|
+
say " tenant: current_organization"
|
|
95
|
+
say " )"
|
|
96
|
+
say ""
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def root_directory
|
|
102
|
+
@root_directory ||= options[:root] || RubyLLM::Agents.configuration.root_directory
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def root_namespace
|
|
106
|
+
@root_namespace ||= options[:namespace] || camelize(root_directory)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def camelize(str)
|
|
110
|
+
return "AI" if str.downcase == "ai"
|
|
111
|
+
return "ML" if str.downcase == "ml"
|
|
112
|
+
return "LLM" if str.downcase == "llm"
|
|
113
|
+
str.split(/[-_]/).map(&:capitalize).join
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def parsed_steps
|
|
117
|
+
options[:steps].to_s.split(",").map(&:strip).map(&:to_sym)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def should_create_stub?(step)
|
|
121
|
+
case step
|
|
122
|
+
when :generate
|
|
123
|
+
!File.exist?("app/#{root_directory}/image/generators/#{name.underscore}_generator.rb")
|
|
124
|
+
when :upscale
|
|
125
|
+
!File.exist?("app/#{root_directory}/image/upscalers/#{name.underscore}_upscaler.rb")
|
|
126
|
+
when :transform
|
|
127
|
+
!File.exist?("app/#{root_directory}/image/transformers/#{name.underscore}_transformer.rb")
|
|
128
|
+
when :analyze
|
|
129
|
+
!File.exist?("app/#{root_directory}/image/analyzers/#{name.underscore}_analyzer.rb")
|
|
130
|
+
when :remove_background
|
|
131
|
+
!File.exist?("app/#{root_directory}/image/background_removers/#{name.underscore}_background_remover.rb")
|
|
132
|
+
else
|
|
133
|
+
false
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def create_step_stub(step)
|
|
138
|
+
# Just show a note - don't auto-create stubs
|
|
139
|
+
case step
|
|
140
|
+
when :generate
|
|
141
|
+
say " Note: You may want to create #{name}Generator with:", :yellow
|
|
142
|
+
say " rails generate ruby_llm_agents:image_generator #{name}"
|
|
143
|
+
when :upscale
|
|
144
|
+
say " Note: You may want to create #{name}Upscaler with:", :yellow
|
|
145
|
+
say " rails generate ruby_llm_agents:image_upscaler #{name}"
|
|
146
|
+
when :transform
|
|
147
|
+
say " Note: You may want to create #{name}Transformer with:", :yellow
|
|
148
|
+
say " rails generate ruby_llm_agents:image_transformer #{name}"
|
|
149
|
+
when :analyze
|
|
150
|
+
say " Note: You may want to create #{name}Analyzer with:", :yellow
|
|
151
|
+
say " rails generate ruby_llm_agents:image_analyzer #{name}"
|
|
152
|
+
when :remove_background
|
|
153
|
+
say " Note: You may want to create #{name}BackgroundRemover with:", :yellow
|
|
154
|
+
say " rails generate ruby_llm_agents:background_remover #{name}"
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def step_classes
|
|
159
|
+
@step_classes ||= parsed_steps.map do |step|
|
|
160
|
+
class_base = name.split("/").map(&:camelize).join("::")
|
|
161
|
+
case step
|
|
162
|
+
when :generate
|
|
163
|
+
{ step: step, type: :generator, class_name: "#{@image_namespace}::#{class_base}Generator" }
|
|
164
|
+
when :upscale
|
|
165
|
+
{ step: step, type: :upscaler, class_name: "#{@image_namespace}::#{class_base}Upscaler" }
|
|
166
|
+
when :transform
|
|
167
|
+
{ step: step, type: :transformer, class_name: "#{@image_namespace}::#{class_base}Transformer" }
|
|
168
|
+
when :analyze
|
|
169
|
+
{ step: step, type: :analyzer, class_name: "#{@image_namespace}::#{class_base}Analyzer" }
|
|
170
|
+
when :remove_background
|
|
171
|
+
{ step: step, type: :remover, class_name: "#{@image_namespace}::#{class_base}BackgroundRemover" }
|
|
172
|
+
else
|
|
173
|
+
{ step: step, type: step, class_name: "#{@image_namespace}::#{class_base}#{step.to_s.camelize}" }
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|