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,282 @@
|
|
|
1
|
+
# <%= @root_namespace %>::Image Generators
|
|
2
|
+
|
|
3
|
+
This directory contains image generation services. All generators inherit from `ApplicationImageGenerator`.
|
|
4
|
+
|
|
5
|
+
## Creating a New Generator
|
|
6
|
+
|
|
7
|
+
Use the generator:
|
|
8
|
+
```bash
|
|
9
|
+
rails generate ruby_llm_agents:image_generator GeneratorName
|
|
10
|
+
rails generate ruby_llm_agents:image_generator Logo --model gpt-image-1 --size 1024x1024
|
|
11
|
+
rails generate ruby_llm_agents:image_generator Product --quality hd --style vivid
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or create manually:
|
|
15
|
+
```ruby
|
|
16
|
+
module <%= @root_namespace %>
|
|
17
|
+
module Image
|
|
18
|
+
class LogoGenerator < ApplicationImageGenerator
|
|
19
|
+
model "gpt-image-1"
|
|
20
|
+
size "1024x1024"
|
|
21
|
+
quality "hd"
|
|
22
|
+
style "vivid"
|
|
23
|
+
content_policy :standard
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## DSL Reference
|
|
30
|
+
|
|
31
|
+
### Model Configuration
|
|
32
|
+
|
|
33
|
+
| Method | Description | Example |
|
|
34
|
+
|--------|-------------|---------|
|
|
35
|
+
| `model` | Image generation model | `model "gpt-image-1"` |
|
|
36
|
+
| `size` | Output image size | `size "1024x1024"` |
|
|
37
|
+
| `quality` | Image quality | `quality "hd"` |
|
|
38
|
+
| `style` | Generation style | `style "vivid"` |
|
|
39
|
+
| `content_policy` | Content filtering level | `content_policy :strict` |
|
|
40
|
+
|
|
41
|
+
### Available Sizes
|
|
42
|
+
|
|
43
|
+
- `1024x1024` - Square (default)
|
|
44
|
+
- `1792x1024` - Landscape
|
|
45
|
+
- `1024x1792` - Portrait
|
|
46
|
+
- `512x512` - Small square
|
|
47
|
+
- `256x256` - Thumbnail
|
|
48
|
+
|
|
49
|
+
### Quality Options
|
|
50
|
+
|
|
51
|
+
- `standard` - Faster generation, good quality
|
|
52
|
+
- `hd` - Higher detail, slower generation
|
|
53
|
+
|
|
54
|
+
### Style Options
|
|
55
|
+
|
|
56
|
+
- `vivid` - Hyper-real, dramatic (default)
|
|
57
|
+
- `natural` - More natural, less extreme
|
|
58
|
+
|
|
59
|
+
### Content Policy Levels
|
|
60
|
+
|
|
61
|
+
- `:none` - No filtering
|
|
62
|
+
- `:standard` - Default content filtering
|
|
63
|
+
- `:moderate` - Stricter filtering
|
|
64
|
+
- `:strict` - Maximum filtering
|
|
65
|
+
|
|
66
|
+
### Caching
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
cache_for 1.day # Cache generated images
|
|
70
|
+
cache_for 1.week # Long-term caching
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Optional Methods & DSL
|
|
74
|
+
|
|
75
|
+
### `template`
|
|
76
|
+
Define a prompt template:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
template "Professional {prompt}, minimalist design, vector art style"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `negative_prompt`
|
|
83
|
+
Specify what to avoid (for supported models):
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
negative_prompt "blurry, low quality, distorted, watermark"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### `preprocess_prompt(prompt)`
|
|
90
|
+
Transform prompt before generation:
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
def preprocess_prompt(prompt)
|
|
94
|
+
"#{prompt}, professional quality, 8k resolution"
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Using Generators
|
|
99
|
+
|
|
100
|
+
### Basic Generation
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
result = <%= @root_namespace %>::Image::LogoGenerator.call(prompt: "Tech startup logo")
|
|
104
|
+
|
|
105
|
+
result.url # Temporary URL to generated image
|
|
106
|
+
result.image_data # Binary image data
|
|
107
|
+
result.size # "1024x1024"
|
|
108
|
+
result.total_cost # Cost in USD
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Save to File
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
result = <%= @root_namespace %>::Image::LogoGenerator.call(prompt: "Company logo")
|
|
115
|
+
result.save("logo.png")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Generate Multiple Images
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
result = <%= @root_namespace %>::Image::LogoGenerator.call(
|
|
122
|
+
prompt: "Product photography",
|
|
123
|
+
count: 4
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
result.urls # Array of image URLs
|
|
127
|
+
result.images # Array of image data
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Override Settings at Runtime
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
result = <%= @root_namespace %>::Image::LogoGenerator.call(
|
|
134
|
+
prompt: "High quality portrait",
|
|
135
|
+
quality: "hd",
|
|
136
|
+
size: "1792x1024",
|
|
137
|
+
style: "natural"
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### With ActiveStorage
|
|
142
|
+
|
|
143
|
+
If ActiveStorage is available:
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
result = <%= @root_namespace %>::Image::ProductGenerator.call(prompt: "Product shot")
|
|
147
|
+
|
|
148
|
+
# Attach to a model
|
|
149
|
+
product.images.attach(
|
|
150
|
+
io: StringIO.new(result.image_data),
|
|
151
|
+
filename: "product_image.png",
|
|
152
|
+
content_type: "image/png"
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Use Cases
|
|
157
|
+
|
|
158
|
+
### Product Photography
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
module <%= @root_namespace %>
|
|
162
|
+
module Image
|
|
163
|
+
class ProductGenerator < ApplicationImageGenerator
|
|
164
|
+
model "gpt-image-1"
|
|
165
|
+
size "1024x1024"
|
|
166
|
+
quality "hd"
|
|
167
|
+
style "natural"
|
|
168
|
+
|
|
169
|
+
template "Professional product photography of {prompt}, " \
|
|
170
|
+
"white background, studio lighting, e-commerce style"
|
|
171
|
+
|
|
172
|
+
negative_prompt "text, watermark, blurry, low quality"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Marketing Banners
|
|
179
|
+
|
|
180
|
+
```ruby
|
|
181
|
+
module <%= @root_namespace %>
|
|
182
|
+
module Image
|
|
183
|
+
class BannerGenerator < ApplicationImageGenerator
|
|
184
|
+
model "gpt-image-1"
|
|
185
|
+
size "1792x1024" # Landscape
|
|
186
|
+
quality "hd"
|
|
187
|
+
style "vivid"
|
|
188
|
+
|
|
189
|
+
template "Marketing banner for {prompt}, bold colors, " \
|
|
190
|
+
"eye-catching design, professional"
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Avatar Generation
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
module <%= @root_namespace %>
|
|
200
|
+
module Image
|
|
201
|
+
class AvatarGenerator < ApplicationImageGenerator
|
|
202
|
+
model "gpt-image-1"
|
|
203
|
+
size "512x512"
|
|
204
|
+
quality "standard"
|
|
205
|
+
style "vivid"
|
|
206
|
+
content_policy :strict
|
|
207
|
+
|
|
208
|
+
template "Friendly cartoon avatar of {prompt}, " \
|
|
209
|
+
"professional, approachable, colorful"
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Social Media Graphics
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
module <%= @root_namespace %>
|
|
219
|
+
module Image
|
|
220
|
+
class SocialGenerator < ApplicationImageGenerator
|
|
221
|
+
model "gpt-image-1"
|
|
222
|
+
quality "standard"
|
|
223
|
+
|
|
224
|
+
def preprocess_prompt(prompt)
|
|
225
|
+
"#{prompt}, social media post, engaging, modern design"
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Usage with different sizes
|
|
232
|
+
<%= @root_namespace %>::Image::SocialGenerator.call(
|
|
233
|
+
prompt: "Tech announcement",
|
|
234
|
+
size: "1024x1024" # Instagram
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
<%= @root_namespace %>::Image::SocialGenerator.call(
|
|
238
|
+
prompt: "Tech announcement",
|
|
239
|
+
size: "1792x1024" # Twitter/LinkedIn
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Testing Generators
|
|
244
|
+
|
|
245
|
+
```ruby
|
|
246
|
+
RSpec.describe <%= @root_namespace %>::Image::LogoGenerator do
|
|
247
|
+
describe ".call" do
|
|
248
|
+
it "generates an image" do
|
|
249
|
+
result = described_class.call(prompt: "Test logo")
|
|
250
|
+
|
|
251
|
+
expect(result.url).to be_present
|
|
252
|
+
expect(result.size).to eq("1024x1024")
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "respects quality setting" do
|
|
256
|
+
result = described_class.call(prompt: "Test", quality: "hd")
|
|
257
|
+
|
|
258
|
+
expect(result.quality).to eq("hd")
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
describe "#preprocess_prompt" do
|
|
263
|
+
it "enhances the prompt" do
|
|
264
|
+
generator = described_class.new(prompt: "simple logo")
|
|
265
|
+
|
|
266
|
+
result = generator.preprocess_prompt("simple logo")
|
|
267
|
+
|
|
268
|
+
expect(result).to include("simple logo")
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Best Practices
|
|
275
|
+
|
|
276
|
+
1. **Use templates** - Ensure consistent style across generations
|
|
277
|
+
2. **Set appropriate quality** - HD for final assets, standard for drafts
|
|
278
|
+
3. **Use caching** - Same prompt produces same image
|
|
279
|
+
4. **Add negative prompts** - Exclude unwanted elements
|
|
280
|
+
5. **Match size to use case** - Don't generate larger than needed
|
|
281
|
+
6. **Consider content policy** - Use strict for user-facing content
|
|
282
|
+
7. **Handle errors gracefully** - Content policy rejections, rate limits
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# <%= @root_namespace %>::Image Pipelines
|
|
2
|
+
|
|
3
|
+
This directory contains multi-step image processing pipelines. All pipelines inherit from `ApplicationImagePipeline`.
|
|
4
|
+
|
|
5
|
+
## Creating a New Pipeline
|
|
6
|
+
|
|
7
|
+
Use the generator:
|
|
8
|
+
```bash
|
|
9
|
+
rails generate ruby_llm_agents:image_pipeline PipelineName
|
|
10
|
+
rails generate ruby_llm_agents:image_pipeline Product --steps generate,upscale,remove_background
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or create manually:
|
|
14
|
+
```ruby
|
|
15
|
+
module <%= @root_namespace %>
|
|
16
|
+
module Image
|
|
17
|
+
class ProductPipeline < ApplicationImagePipeline
|
|
18
|
+
step :generate, generator: ProductGenerator
|
|
19
|
+
step :upscale, upscaler: PhotoUpscaler, scale: 2
|
|
20
|
+
step :remove_bg, remover: BackgroundRemover
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## DSL Reference
|
|
27
|
+
|
|
28
|
+
### Step Definition
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
step :name, generator: MyGenerator # Text-to-image generation
|
|
32
|
+
step :name, upscaler: MyUpscaler # Resolution enhancement
|
|
33
|
+
step :name, transformer: MyTransformer # Style transfer / img2img
|
|
34
|
+
step :name, editor: MyEditor # Inpainting / editing
|
|
35
|
+
step :name, variator: MyVariator # Generate variations
|
|
36
|
+
step :name, analyzer: MyAnalyzer # Image analysis
|
|
37
|
+
step :name, remover: MyRemover # Background removal
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Conditional Steps
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
step :upscale, upscaler: Upscaler, if: ->(ctx) { ctx[:high_quality] }
|
|
44
|
+
step :remove_bg, remover: Remover, unless: ->(ctx) { ctx[:keep_background] }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step Options
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
step :upscale, upscaler: PhotoUpscaler, scale: 4
|
|
51
|
+
step :transform, transformer: StyleTransformer, strength: 0.8
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Callbacks
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
before_pipeline :validate_inputs
|
|
58
|
+
after_pipeline :add_watermark
|
|
59
|
+
after_pipeline { |result| notify_completion(result) }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Error Handling
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
stop_on_error true # Stop pipeline on first error (default)
|
|
66
|
+
stop_on_error false # Continue even if a step fails
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Caching
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
cache_for 1.hour # Cache pipeline results
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Using Pipelines
|
|
76
|
+
|
|
77
|
+
### Basic Execution
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
result = <%= @root_namespace %>::Image::ProductPipeline.call(prompt: "Laptop on desk")
|
|
81
|
+
|
|
82
|
+
result.success? # All steps succeeded
|
|
83
|
+
result.final_image # Final processed image
|
|
84
|
+
result.url # Final image URL
|
|
85
|
+
result.total_cost # Combined cost of all steps
|
|
86
|
+
result.duration_ms # Total pipeline duration
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Access Individual Steps
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
result = <%= @root_namespace %>::Image::ProductPipeline.call(prompt: "Product photo")
|
|
93
|
+
|
|
94
|
+
result.step(:generate) # Generation step result
|
|
95
|
+
result.step(:upscale) # Upscale step result
|
|
96
|
+
result.steps # Array of all step results
|
|
97
|
+
result.step_count # Total number of steps
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Save Result
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
result = <%= @root_namespace %>::Image::ProductPipeline.call(prompt: "...")
|
|
104
|
+
result.save("final_output.png")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Conditional Execution
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
module <%= @root_namespace %>
|
|
111
|
+
module Image
|
|
112
|
+
class SmartPipeline < ApplicationImagePipeline
|
|
113
|
+
step :generate, generator: ProductGenerator
|
|
114
|
+
step :upscale, upscaler: PhotoUpscaler, if: ->(ctx) { ctx[:hd] }
|
|
115
|
+
step :remove_bg, remover: BackgroundRemover, if: ->(ctx) { ctx[:transparent] }
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Call with options
|
|
121
|
+
result = <%= @root_namespace %>::Image::SmartPipeline.call(
|
|
122
|
+
prompt: "Product photo",
|
|
123
|
+
hd: true,
|
|
124
|
+
transparent: false
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Use Cases
|
|
129
|
+
|
|
130
|
+
### E-commerce Product Pipeline
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
module <%= @root_namespace %>
|
|
134
|
+
module Image
|
|
135
|
+
class EcommercePipeline < ApplicationImagePipeline
|
|
136
|
+
description "Generate and process product images"
|
|
137
|
+
version "1.0"
|
|
138
|
+
|
|
139
|
+
step :generate, generator: ProductGenerator
|
|
140
|
+
step :upscale, upscaler: PhotoUpscaler, scale: 2
|
|
141
|
+
step :remove_bg, remover: BackgroundRemover
|
|
142
|
+
step :analyze, analyzer: ProductAnalyzer
|
|
143
|
+
|
|
144
|
+
cache_for 1.day
|
|
145
|
+
|
|
146
|
+
after_pipeline :log_completion
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def log_completion(result)
|
|
151
|
+
Rails.logger.info("Pipeline completed: cost=#{result.total_cost}")
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Marketing Asset Pipeline
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
module <%= @root_namespace %>
|
|
162
|
+
module Image
|
|
163
|
+
class MarketingPipeline < ApplicationImagePipeline
|
|
164
|
+
step :generate, generator: MarketingGenerator, quality: "hd"
|
|
165
|
+
step :transform, transformer: BrandStyleTransformer, strength: 0.3
|
|
166
|
+
step :variations, variator: DesignVariator, count: 4
|
|
167
|
+
|
|
168
|
+
stop_on_error false # Continue even if transform fails
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
result = <%= @root_namespace %>::Image::MarketingPipeline.call(prompt: "Sale banner")
|
|
174
|
+
result.step(:variations).images # Get all variations
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Photo Enhancement Pipeline
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
module <%= @root_namespace %>
|
|
181
|
+
module Image
|
|
182
|
+
class EnhancementPipeline < ApplicationImagePipeline
|
|
183
|
+
step :upscale, upscaler: PhotoUpscaler, scale: 2
|
|
184
|
+
step :enhance, transformer: EnhancementTransformer, strength: 0.2
|
|
185
|
+
step :analyze, analyzer: QualityAnalyzer
|
|
186
|
+
|
|
187
|
+
before_pipeline :validate_image_format
|
|
188
|
+
|
|
189
|
+
private
|
|
190
|
+
|
|
191
|
+
def validate_image_format
|
|
192
|
+
raise ArgumentError, "Image required" unless context[:image]
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Process existing image
|
|
199
|
+
result = <%= @root_namespace %>::Image::EnhancementPipeline.call(image: "photo.jpg")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Result Methods
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
result.success? # All steps succeeded
|
|
206
|
+
result.partial? # Some steps succeeded
|
|
207
|
+
result.error? # Pipeline failed
|
|
208
|
+
|
|
209
|
+
result.final_image # Final processed image
|
|
210
|
+
result.url # Final image URL
|
|
211
|
+
result.to_blob # Binary data
|
|
212
|
+
result.save("output.png") # Save to file
|
|
213
|
+
|
|
214
|
+
result.total_cost # Combined cost
|
|
215
|
+
result.duration_ms # Total duration
|
|
216
|
+
result.steps # All step results
|
|
217
|
+
result.step(:name) # Specific step result
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Best Practices
|
|
221
|
+
|
|
222
|
+
1. **Order steps logically** - Generate before transform, upscale before final
|
|
223
|
+
2. **Use conditional steps** - Skip unnecessary processing
|
|
224
|
+
3. **Enable caching** - Especially for expensive pipelines
|
|
225
|
+
4. **Add callbacks for monitoring** - Log completions, costs
|
|
226
|
+
5. **Set appropriate stop_on_error** - Usually true for production
|
|
227
|
+
6. **Version your pipelines** - Invalidate cache when steps change
|
|
228
|
+
7. **Use analysis steps** - For quality assurance
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# <%= @root_namespace %>::Image Transformers
|
|
2
|
+
|
|
3
|
+
This directory contains image transformation services (style transfer, img2img). All transformers inherit from `ApplicationImageTransformer`.
|
|
4
|
+
|
|
5
|
+
## Creating a New Transformer
|
|
6
|
+
|
|
7
|
+
Use the generator:
|
|
8
|
+
```bash
|
|
9
|
+
rails generate ruby_llm_agents:image_transformer TransformerName
|
|
10
|
+
rails generate ruby_llm_agents:image_transformer Style --strength 0.8
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or create manually:
|
|
14
|
+
```ruby
|
|
15
|
+
module <%= @root_namespace %>
|
|
16
|
+
module Image
|
|
17
|
+
class StyleTransformer < ApplicationImageTransformer
|
|
18
|
+
model "gpt-image-1"
|
|
19
|
+
strength 0.7
|
|
20
|
+
size "1024x1024"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## DSL Reference
|
|
27
|
+
|
|
28
|
+
| Method | Description | Example |
|
|
29
|
+
|--------|-------------|---------|
|
|
30
|
+
| `model` | Transformation model | `model "gpt-image-1"` |
|
|
31
|
+
| `strength` | Transformation intensity (0.0-1.0) | `strength 0.7` |
|
|
32
|
+
| `size` | Output size | `size "1024x1024"` |
|
|
33
|
+
|
|
34
|
+
### Strength Values
|
|
35
|
+
- `0.1-0.3` - Subtle changes, preserve original
|
|
36
|
+
- `0.4-0.6` - Moderate transformation
|
|
37
|
+
- `0.7-0.9` - Strong style transfer
|
|
38
|
+
- `1.0` - Maximum transformation
|
|
39
|
+
|
|
40
|
+
## Using Transformers
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
result = <%= @root_namespace %>::Image::StyleTransformer.call(
|
|
44
|
+
image: "photo.jpg",
|
|
45
|
+
prompt: "Oil painting style, impressionist"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
result.url # Transformed image URL
|
|
49
|
+
result.image_data # Binary data
|
|
50
|
+
result.save("transformed.png")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Override Strength
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
result = <%= @root_namespace %>::Image::StyleTransformer.call(
|
|
57
|
+
image: "photo.jpg",
|
|
58
|
+
prompt: "Watercolor painting",
|
|
59
|
+
strength: 0.5 # More subtle
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Use Cases
|
|
64
|
+
|
|
65
|
+
### Artistic Style Transfer
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
module <%= @root_namespace %>
|
|
69
|
+
module Image
|
|
70
|
+
class ArtisticTransformer < ApplicationImageTransformer
|
|
71
|
+
strength 0.8
|
|
72
|
+
|
|
73
|
+
template "{prompt} style, artistic rendering, high quality"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Usage
|
|
79
|
+
<%= @root_namespace %>::Image::ArtisticTransformer.call(
|
|
80
|
+
image: "photo.jpg",
|
|
81
|
+
prompt: "Van Gogh starry night"
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Photo Enhancement
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
module <%= @root_namespace %>
|
|
89
|
+
module Image
|
|
90
|
+
class EnhancementTransformer < ApplicationImageTransformer
|
|
91
|
+
strength 0.3 # Subtle enhancement
|
|
92
|
+
|
|
93
|
+
def default_prompt
|
|
94
|
+
"Enhanced lighting, improved colors, professional photography"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Sketch to Photo
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
module <%= @root_namespace %>
|
|
105
|
+
module Image
|
|
106
|
+
class SketchToPhotoTransformer < ApplicationImageTransformer
|
|
107
|
+
strength 0.9
|
|
108
|
+
|
|
109
|
+
template "Photorealistic version of this sketch: {prompt}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Best Practices
|
|
116
|
+
|
|
117
|
+
1. **Adjust strength carefully** - Start low, increase as needed
|
|
118
|
+
2. **Match styles to content** - Some styles work better with certain images
|
|
119
|
+
3. **Use descriptive prompts** - Specify the desired artistic style
|
|
120
|
+
4. **Consider original quality** - Higher quality inputs produce better results
|