ruby_llm-agents 0.4.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.
Files changed (208) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +225 -34
  3. data/app/controllers/ruby_llm/agents/agents_controller.rb +136 -16
  4. data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +214 -0
  5. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +29 -9
  6. data/app/controllers/ruby_llm/agents/{settings_controller.rb → system_config_controller.rb} +3 -3
  7. data/app/controllers/ruby_llm/agents/tenants_controller.rb +109 -0
  8. data/app/controllers/ruby_llm/agents/workflows_controller.rb +355 -0
  9. data/app/helpers/ruby_llm/agents/application_helper.rb +25 -0
  10. data/app/models/ruby_llm/agents/api_configuration.rb +386 -0
  11. data/app/models/ruby_llm/agents/execution.rb +3 -0
  12. data/app/models/ruby_llm/agents/tenant_budget.rb +112 -14
  13. data/app/services/ruby_llm/agents/agent_registry.rb +51 -12
  14. data/app/views/layouts/ruby_llm/agents/application.html.erb +5 -30
  15. data/app/views/ruby_llm/agents/agents/_agent.html.erb +13 -1
  16. data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +235 -0
  17. data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +70 -0
  18. data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +152 -0
  19. data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +63 -0
  20. data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +108 -0
  21. data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +91 -0
  22. data/app/views/ruby_llm/agents/agents/_workflow.html.erb +1 -1
  23. data/app/views/ruby_llm/agents/agents/index.html.erb +74 -9
  24. data/app/views/ruby_llm/agents/agents/show.html.erb +18 -378
  25. data/app/views/ruby_llm/agents/api_configurations/_api_key_field.html.erb +34 -0
  26. data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +288 -0
  27. data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +95 -0
  28. data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +97 -0
  29. data/app/views/ruby_llm/agents/api_configurations/show.html.erb +211 -0
  30. data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +179 -0
  31. data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +1 -1
  32. data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +269 -15
  33. data/app/views/ruby_llm/agents/executions/show.html.erb +98 -0
  34. data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +93 -0
  35. data/app/views/ruby_llm/agents/{settings → system_config}/show.html.erb +1 -1
  36. data/app/views/ruby_llm/agents/tenants/_form.html.erb +150 -0
  37. data/app/views/ruby_llm/agents/tenants/edit.html.erb +13 -0
  38. data/app/views/ruby_llm/agents/tenants/index.html.erb +129 -0
  39. data/app/views/ruby_llm/agents/tenants/show.html.erb +374 -0
  40. data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +236 -0
  41. data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +76 -0
  42. data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +74 -0
  43. data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +108 -0
  44. data/app/views/ruby_llm/agents/workflows/show.html.erb +442 -0
  45. data/config/routes.rb +13 -1
  46. data/lib/generators/ruby_llm_agents/agent_generator.rb +56 -7
  47. data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +100 -0
  48. data/lib/generators/ruby_llm_agents/background_remover_generator.rb +110 -0
  49. data/lib/generators/ruby_llm_agents/embedder_generator.rb +107 -0
  50. data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +115 -0
  51. data/lib/generators/ruby_llm_agents/image_editor_generator.rb +108 -0
  52. data/lib/generators/ruby_llm_agents/image_generator_generator.rb +116 -0
  53. data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +178 -0
  54. data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +109 -0
  55. data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +103 -0
  56. data/lib/generators/ruby_llm_agents/image_variator_generator.rb +102 -0
  57. data/lib/generators/ruby_llm_agents/install_generator.rb +76 -4
  58. data/lib/generators/ruby_llm_agents/restructure_generator.rb +292 -0
  59. data/lib/generators/ruby_llm_agents/speaker_generator.rb +121 -0
  60. data/lib/generators/ruby_llm_agents/templates/add_execution_type_migration.rb.tt +8 -0
  61. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +99 -84
  62. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +42 -40
  63. data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +26 -0
  64. data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +50 -0
  65. data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +26 -0
  66. data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +20 -0
  67. data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +38 -0
  68. data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +139 -0
  69. data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +21 -0
  70. data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +20 -0
  71. data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +20 -0
  72. data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +49 -0
  73. data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +53 -0
  74. data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +44 -0
  75. data/lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt +90 -0
  76. data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +41 -0
  77. data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +45 -0
  78. data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +35 -0
  79. data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +47 -0
  80. data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +50 -0
  81. data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +44 -0
  82. data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +38 -0
  83. data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +33 -0
  84. data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +228 -0
  85. data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +131 -0
  86. data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +255 -0
  87. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +120 -0
  88. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +102 -0
  89. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +282 -0
  90. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +228 -0
  91. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +120 -0
  92. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +110 -0
  93. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +120 -0
  94. data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +212 -0
  95. data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +227 -0
  96. data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +251 -0
  97. data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +300 -0
  98. data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +56 -0
  99. data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +51 -0
  100. data/lib/generators/ruby_llm_agents/transcriber_generator.rb +107 -0
  101. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +152 -1
  102. data/lib/ruby_llm/agents/audio/speaker.rb +553 -0
  103. data/lib/ruby_llm/agents/audio/transcriber.rb +669 -0
  104. data/lib/ruby_llm/agents/base_agent.rb +675 -0
  105. data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +181 -0
  106. data/lib/ruby_llm/agents/core/base/moderation_execution.rb +274 -0
  107. data/lib/ruby_llm/agents/core/base.rb +135 -0
  108. data/lib/ruby_llm/agents/core/configuration.rb +981 -0
  109. data/lib/ruby_llm/agents/core/errors.rb +150 -0
  110. data/lib/ruby_llm/agents/{instrumentation.rb → core/instrumentation.rb} +93 -4
  111. data/lib/ruby_llm/agents/core/llm_tenant.rb +358 -0
  112. data/lib/ruby_llm/agents/core/resolved_config.rb +348 -0
  113. data/lib/ruby_llm/agents/{version.rb → core/version.rb} +1 -1
  114. data/lib/ruby_llm/agents/dsl/base.rb +110 -0
  115. data/lib/ruby_llm/agents/dsl/caching.rb +142 -0
  116. data/lib/ruby_llm/agents/dsl/reliability.rb +307 -0
  117. data/lib/ruby_llm/agents/dsl.rb +41 -0
  118. data/lib/ruby_llm/agents/image/analyzer/dsl.rb +130 -0
  119. data/lib/ruby_llm/agents/image/analyzer/execution.rb +402 -0
  120. data/lib/ruby_llm/agents/image/analyzer.rb +90 -0
  121. data/lib/ruby_llm/agents/image/background_remover/dsl.rb +154 -0
  122. data/lib/ruby_llm/agents/image/background_remover/execution.rb +240 -0
  123. data/lib/ruby_llm/agents/image/background_remover.rb +89 -0
  124. data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +91 -0
  125. data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +165 -0
  126. data/lib/ruby_llm/agents/image/editor/dsl.rb +56 -0
  127. data/lib/ruby_llm/agents/image/editor/execution.rb +207 -0
  128. data/lib/ruby_llm/agents/image/editor.rb +92 -0
  129. data/lib/ruby_llm/agents/image/generator/active_storage_support.rb +127 -0
  130. data/lib/ruby_llm/agents/image/generator/content_policy.rb +95 -0
  131. data/lib/ruby_llm/agents/image/generator/pricing.rb +353 -0
  132. data/lib/ruby_llm/agents/image/generator/templates.rb +124 -0
  133. data/lib/ruby_llm/agents/image/generator.rb +455 -0
  134. data/lib/ruby_llm/agents/image/pipeline/dsl.rb +213 -0
  135. data/lib/ruby_llm/agents/image/pipeline/execution.rb +382 -0
  136. data/lib/ruby_llm/agents/image/pipeline.rb +97 -0
  137. data/lib/ruby_llm/agents/image/transformer/dsl.rb +148 -0
  138. data/lib/ruby_llm/agents/image/transformer/execution.rb +223 -0
  139. data/lib/ruby_llm/agents/image/transformer.rb +95 -0
  140. data/lib/ruby_llm/agents/image/upscaler/dsl.rb +83 -0
  141. data/lib/ruby_llm/agents/image/upscaler/execution.rb +219 -0
  142. data/lib/ruby_llm/agents/image/upscaler.rb +81 -0
  143. data/lib/ruby_llm/agents/image/variator/dsl.rb +62 -0
  144. data/lib/ruby_llm/agents/image/variator/execution.rb +189 -0
  145. data/lib/ruby_llm/agents/image/variator.rb +80 -0
  146. data/lib/ruby_llm/agents/{alert_manager.rb → infrastructure/alert_manager.rb} +17 -22
  147. data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +145 -0
  148. data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +149 -0
  149. data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +68 -0
  150. data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +279 -0
  151. data/lib/ruby_llm/agents/infrastructure/budget_tracker.rb +275 -0
  152. data/lib/ruby_llm/agents/{execution_logger_job.rb → infrastructure/execution_logger_job.rb} +17 -1
  153. data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/executor.rb +2 -1
  154. data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/retry_strategy.rb +9 -3
  155. data/lib/ruby_llm/agents/{reliability.rb → infrastructure/reliability.rb} +11 -21
  156. data/lib/ruby_llm/agents/pipeline/builder.rb +215 -0
  157. data/lib/ruby_llm/agents/pipeline/context.rb +255 -0
  158. data/lib/ruby_llm/agents/pipeline/executor.rb +86 -0
  159. data/lib/ruby_llm/agents/pipeline/middleware/base.rb +124 -0
  160. data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +95 -0
  161. data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +171 -0
  162. data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +415 -0
  163. data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +276 -0
  164. data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +196 -0
  165. data/lib/ruby_llm/agents/pipeline.rb +68 -0
  166. data/lib/ruby_llm/agents/{engine.rb → rails/engine.rb} +79 -10
  167. data/lib/ruby_llm/agents/results/background_removal_result.rb +286 -0
  168. data/lib/ruby_llm/agents/{result.rb → results/base.rb} +73 -1
  169. data/lib/ruby_llm/agents/results/embedding_result.rb +243 -0
  170. data/lib/ruby_llm/agents/results/image_analysis_result.rb +314 -0
  171. data/lib/ruby_llm/agents/results/image_edit_result.rb +250 -0
  172. data/lib/ruby_llm/agents/results/image_generation_result.rb +346 -0
  173. data/lib/ruby_llm/agents/results/image_pipeline_result.rb +399 -0
  174. data/lib/ruby_llm/agents/results/image_transform_result.rb +251 -0
  175. data/lib/ruby_llm/agents/results/image_upscale_result.rb +255 -0
  176. data/lib/ruby_llm/agents/results/image_variation_result.rb +237 -0
  177. data/lib/ruby_llm/agents/results/moderation_result.rb +158 -0
  178. data/lib/ruby_llm/agents/results/speech_result.rb +338 -0
  179. data/lib/ruby_llm/agents/results/transcription_result.rb +408 -0
  180. data/lib/ruby_llm/agents/text/embedder.rb +444 -0
  181. data/lib/ruby_llm/agents/text/moderator.rb +237 -0
  182. data/lib/ruby_llm/agents/workflow/async.rb +220 -0
  183. data/lib/ruby_llm/agents/workflow/async_executor.rb +156 -0
  184. data/lib/ruby_llm/agents/{workflow.rb → workflow/orchestrator.rb} +6 -5
  185. data/lib/ruby_llm/agents/workflow/parallel.rb +34 -17
  186. data/lib/ruby_llm/agents/workflow/thread_pool.rb +185 -0
  187. data/lib/ruby_llm/agents.rb +86 -20
  188. metadata +189 -35
  189. data/lib/ruby_llm/agents/base/caching.rb +0 -40
  190. data/lib/ruby_llm/agents/base/cost_calculation.rb +0 -105
  191. data/lib/ruby_llm/agents/base/dsl.rb +0 -324
  192. data/lib/ruby_llm/agents/base/execution.rb +0 -283
  193. data/lib/ruby_llm/agents/base/reliability_dsl.rb +0 -82
  194. data/lib/ruby_llm/agents/base/reliability_execution.rb +0 -136
  195. data/lib/ruby_llm/agents/base/response_building.rb +0 -86
  196. data/lib/ruby_llm/agents/base/tool_tracking.rb +0 -57
  197. data/lib/ruby_llm/agents/base.rb +0 -209
  198. data/lib/ruby_llm/agents/budget_tracker.rb +0 -471
  199. data/lib/ruby_llm/agents/configuration.rb +0 -357
  200. /data/lib/ruby_llm/agents/{deprecations.rb → core/deprecations.rb} +0 -0
  201. /data/lib/ruby_llm/agents/{inflections.rb → core/inflections.rb} +0 -0
  202. /data/lib/ruby_llm/agents/{attempt_tracker.rb → infrastructure/attempt_tracker.rb} +0 -0
  203. /data/lib/ruby_llm/agents/{cache_helper.rb → infrastructure/cache_helper.rb} +0 -0
  204. /data/lib/ruby_llm/agents/{circuit_breaker.rb → infrastructure/circuit_breaker.rb} +0 -0
  205. /data/lib/ruby_llm/agents/{redactor.rb → infrastructure/redactor.rb} +0 -0
  206. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/breaker_manager.rb +0 -0
  207. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/execution_constraints.rb +0 -0
  208. /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/fallback_routing.rb +0 -0
@@ -0,0 +1,110 @@
1
+ # <%= @root_namespace %>::Image Upscalers
2
+
3
+ This directory contains image upscaling services. All upscalers inherit from `ApplicationImageUpscaler`.
4
+
5
+ ## Creating a New Upscaler
6
+
7
+ Use the generator:
8
+ ```bash
9
+ rails generate ruby_llm_agents:image_upscaler UpscalerName
10
+ rails generate ruby_llm_agents:image_upscaler Photo --scale 4
11
+ ```
12
+
13
+ Or create manually:
14
+ ```ruby
15
+ module <%= @root_namespace %>
16
+ module Image
17
+ class PhotoUpscaler < ApplicationImageUpscaler
18
+ model "esrgan"
19
+ scale 4
20
+ denoise true
21
+ end
22
+ end
23
+ end
24
+ ```
25
+
26
+ ## DSL Reference
27
+
28
+ | Method | Description | Example |
29
+ |--------|-------------|---------|
30
+ | `model` | Upscaling model | `model "esrgan"` |
31
+ | `scale` | Scale factor (2, 4, 8) | `scale 4` |
32
+ | `denoise` | Apply noise reduction | `denoise true` |
33
+ | `sharpen` | Apply sharpening | `sharpen true` |
34
+
35
+ ### Scale Factors
36
+ - `2` - Double resolution (512x512 -> 1024x1024)
37
+ - `4` - Quadruple resolution (512x512 -> 2048x2048)
38
+ - `8` - 8x resolution (may be slow)
39
+
40
+ ## Using Upscalers
41
+
42
+ ```ruby
43
+ result = <%= @root_namespace %>::Image::PhotoUpscaler.call(image: "small.jpg")
44
+
45
+ result.url # Upscaled image URL
46
+ result.image_data # Binary data
47
+ result.original_size # "512x512"
48
+ result.upscaled_size # "2048x2048"
49
+ result.save("large.png")
50
+ ```
51
+
52
+ ### Override Scale
53
+
54
+ ```ruby
55
+ result = <%= @root_namespace %>::Image::PhotoUpscaler.call(
56
+ image: "thumbnail.jpg",
57
+ scale: 2 # Just double it
58
+ )
59
+ ```
60
+
61
+ ## Use Cases
62
+
63
+ ### Thumbnail Enhancement
64
+
65
+ ```ruby
66
+ module <%= @root_namespace %>
67
+ module Image
68
+ class ThumbnailUpscaler < ApplicationImageUpscaler
69
+ scale 4
70
+ denoise true
71
+ sharpen true
72
+ end
73
+ end
74
+ end
75
+ ```
76
+
77
+ ### Print Preparation
78
+
79
+ ```ruby
80
+ module <%= @root_namespace %>
81
+ module Image
82
+ class PrintUpscaler < ApplicationImageUpscaler
83
+ scale 4
84
+ denoise false # Preserve original detail
85
+ end
86
+ end
87
+ end
88
+ ```
89
+
90
+ ### Avatar Enhancement
91
+
92
+ ```ruby
93
+ module <%= @root_namespace %>
94
+ module Image
95
+ class AvatarUpscaler < ApplicationImageUpscaler
96
+ scale 2 # Modest upscale
97
+ denoise true
98
+ sharpen true
99
+ end
100
+ end
101
+ end
102
+ ```
103
+
104
+ ## Best Practices
105
+
106
+ 1. **Choose appropriate scale** - Don't over-upscale
107
+ 2. **Enable denoise for low-quality sources** - Helps with compression artifacts
108
+ 3. **Sharpen selectively** - Can introduce artifacts
109
+ 4. **Consider file size** - Larger images = larger files
110
+ 5. **Test with similar images** - Results vary by content type
@@ -0,0 +1,120 @@
1
+ # <%= @root_namespace %>::Image Variators
2
+
3
+ This directory contains image variation services. All variators inherit from `ApplicationImageVariator`.
4
+
5
+ ## Creating a New Variator
6
+
7
+ Use the generator:
8
+ ```bash
9
+ rails generate ruby_llm_agents:image_variator VariatorName
10
+ rails generate ruby_llm_agents:image_variator Product --count 4
11
+ ```
12
+
13
+ Or create manually:
14
+ ```ruby
15
+ module <%= @root_namespace %>
16
+ module Image
17
+ class ProductVariator < ApplicationImageVariator
18
+ model "gpt-image-1"
19
+ count 4
20
+ size "1024x1024"
21
+ end
22
+ end
23
+ end
24
+ ```
25
+
26
+ ## DSL Reference
27
+
28
+ | Method | Description | Example |
29
+ |--------|-------------|---------|
30
+ | `model` | Variation model | `model "gpt-image-1"` |
31
+ | `count` | Number of variations | `count 4` |
32
+ | `size` | Output size | `size "1024x1024"` |
33
+ | `variation_strength` | How different from original | `variation_strength 0.5` |
34
+
35
+ ### Variation Strength
36
+ - `0.1-0.3` - Very similar to original
37
+ - `0.4-0.6` - Moderate differences
38
+ - `0.7-1.0` - Significant variations
39
+
40
+ ## Using Variators
41
+
42
+ ```ruby
43
+ result = <%= @root_namespace %>::Image::ProductVariator.call(image: "product.png")
44
+
45
+ result.urls # Array of variation URLs
46
+ result.images # Array of image data
47
+ result.count # Number of variations
48
+ result.total_cost # Combined cost
49
+ ```
50
+
51
+ ### Override Count
52
+
53
+ ```ruby
54
+ result = <%= @root_namespace %>::Image::ProductVariator.call(
55
+ image: "logo.png",
56
+ count: 8 # Generate 8 variations
57
+ )
58
+ ```
59
+
60
+ ### Save All Variations
61
+
62
+ ```ruby
63
+ result = <%= @root_namespace %>::Image::ProductVariator.call(image: "design.png")
64
+
65
+ result.images.each_with_index do |image_data, i|
66
+ File.write("variation_#{i}.png", image_data)
67
+ end
68
+ ```
69
+
70
+ ## Use Cases
71
+
72
+ ### Design Exploration
73
+
74
+ ```ruby
75
+ module <%= @root_namespace %>
76
+ module Image
77
+ class DesignVariator < ApplicationImageVariator
78
+ count 6
79
+ variation_strength 0.5 # Moderate differences
80
+ end
81
+ end
82
+ end
83
+
84
+ # Generate design alternatives
85
+ result = <%= @root_namespace %>::Image::DesignVariator.call(image: "concept.png")
86
+ ```
87
+
88
+ ### A/B Testing Assets
89
+
90
+ ```ruby
91
+ module <%= @root_namespace %>
92
+ module Image
93
+ class MarketingVariator < ApplicationImageVariator
94
+ count 4
95
+ variation_strength 0.3 # Similar but different
96
+ end
97
+ end
98
+ end
99
+ ```
100
+
101
+ ### Avatar Options
102
+
103
+ ```ruby
104
+ module <%= @root_namespace %>
105
+ module Image
106
+ class AvatarVariator < ApplicationImageVariator
107
+ count 8
108
+ size "512x512"
109
+ variation_strength 0.4
110
+ end
111
+ end
112
+ end
113
+ ```
114
+
115
+ ## Best Practices
116
+
117
+ 1. **Start with fewer variations** - Generate more if needed
118
+ 2. **Adjust strength for use case** - Subtle for refinement, strong for exploration
119
+ 3. **Use high-quality source** - Better input = better variations
120
+ 4. **Consider cost** - Each variation costs separately
@@ -0,0 +1,212 @@
1
+ # <%= @root_namespace %>::Audio Speakers
2
+
3
+ This directory contains text-to-speech (TTS) speakers. All speakers inherit from `ApplicationSpeaker`.
4
+
5
+ ## Creating a New Speaker
6
+
7
+ Use the generator:
8
+ ```bash
9
+ rails generate ruby_llm_agents:speaker SpeakerName
10
+ rails generate ruby_llm_agents:speaker Narrator --provider openai --voice nova
11
+ rails generate ruby_llm_agents:speaker Podcast --provider elevenlabs --voice Rachel
12
+ ```
13
+
14
+ Or create manually:
15
+ ```ruby
16
+ module <%= @root_namespace %>
17
+ module Audio
18
+ class NarratorSpeaker < ApplicationSpeaker
19
+ provider :openai
20
+ model "tts-1"
21
+ voice "nova"
22
+ speed 1.0
23
+ output_format :mp3
24
+ end
25
+ end
26
+ end
27
+ ```
28
+
29
+ ## DSL Reference
30
+
31
+ ### Provider Configuration
32
+
33
+ | Method | Description | Example |
34
+ |--------|-------------|---------|
35
+ | `provider` | TTS provider | `provider :openai` or `provider :elevenlabs` |
36
+ | `model` | TTS model | `model "tts-1"` or `model "tts-1-hd"` |
37
+ | `voice` | Voice to use | `voice "nova"` |
38
+ | `speed` | Speech speed (0.25-4.0) | `speed 1.25` |
39
+ | `output_format` | Audio format | `output_format :mp3` |
40
+
41
+ ### OpenAI Voices
42
+ - `alloy` - Neutral, balanced
43
+ - `echo` - Male, warm
44
+ - `fable` - British, storytelling
45
+ - `onyx` - Male, deep
46
+ - `nova` - Female, friendly
47
+ - `shimmer` - Female, soft
48
+
49
+ ### OpenAI Models
50
+ - `tts-1` - Standard quality, faster
51
+ - `tts-1-hd` - High definition, slower
52
+
53
+ ### ElevenLabs Configuration
54
+
55
+ ```ruby
56
+ class PodcastSpeaker < ApplicationSpeaker
57
+ provider :elevenlabs
58
+ model "eleven_multilingual_v2"
59
+ voice "Rachel"
60
+
61
+ voice_settings do
62
+ stability 0.5
63
+ similarity_boost 0.75
64
+ style 0.5
65
+ speaker_boost true
66
+ end
67
+ end
68
+ ```
69
+
70
+ ### Caching
71
+
72
+ ```ruby
73
+ cache_for 7.days # Cache audio output
74
+ ```
75
+
76
+ ### Custom Pronunciation
77
+
78
+ ```ruby
79
+ lexicon do
80
+ pronounce 'API', 'A P I'
81
+ pronounce 'SQL', 'sequel'
82
+ pronounce 'PostgreSQL', 'post-gres-Q-L'
83
+ pronounce 'RubyLLM', 'ruby L L M'
84
+ end
85
+ ```
86
+
87
+ ## Using Speakers
88
+
89
+ ### Generate Speech
90
+
91
+ ```ruby
92
+ result = <%= @root_namespace %>::Audio::NarratorSpeaker.call(text: "Hello world")
93
+
94
+ result.audio # Binary audio data
95
+ result.format # :mp3
96
+ result.duration # Duration in seconds (if available)
97
+ result.total_cost # Cost in USD
98
+ ```
99
+
100
+ ### Save to File
101
+
102
+ ```ruby
103
+ result = <%= @root_namespace %>::Audio::NarratorSpeaker.call(text: "Hello world")
104
+ result.save_to("output.mp3")
105
+ ```
106
+
107
+ ### Stream Audio
108
+
109
+ For long text, stream chunks as they're generated:
110
+
111
+ ```ruby
112
+ <%= @root_namespace %>::Audio::NarratorSpeaker.stream(text: long_article) do |chunk|
113
+ audio_player.play(chunk.audio)
114
+ end
115
+ ```
116
+
117
+ ### Override Settings at Runtime
118
+
119
+ ```ruby
120
+ result = <%= @root_namespace %>::Audio::NarratorSpeaker.call(
121
+ text: "Speak slowly and clearly",
122
+ voice: "onyx",
123
+ speed: 0.8
124
+ )
125
+ ```
126
+
127
+ ## Use Cases
128
+
129
+ ### Article Narration
130
+
131
+ ```ruby
132
+ module <%= @root_namespace %>
133
+ module Audio
134
+ class ArticleNarratorSpeaker < ApplicationSpeaker
135
+ provider :openai
136
+ model "tts-1-hd"
137
+ voice "fable"
138
+ speed 0.9
139
+
140
+ cache_for 30.days
141
+
142
+ lexicon do
143
+ pronounce 'JavaScript', 'java-script'
144
+ pronounce 'TypeScript', 'type-script'
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ # Usage
151
+ article = Article.find(params[:id])
152
+ result = <%= @root_namespace %>::Audio::ArticleNarratorSpeaker.call(text: article.body)
153
+ result.save_to("public/audio/articles/#{article.id}.mp3")
154
+ ```
155
+
156
+ ### Voice Announcements
157
+
158
+ ```ruby
159
+ module <%= @root_namespace %>
160
+ module Audio
161
+ class AnnouncementSpeaker < ApplicationSpeaker
162
+ provider :openai
163
+ voice "nova"
164
+ speed 1.1
165
+ output_format :mp3
166
+ end
167
+ end
168
+ end
169
+
170
+ # Usage
171
+ <%= @root_namespace %>::Audio::AnnouncementSpeaker.call(
172
+ text: "Your order has been shipped!"
173
+ )
174
+ ```
175
+
176
+ ### Multilingual TTS
177
+
178
+ ```ruby
179
+ module <%= @root_namespace %>
180
+ module Audio
181
+ class MultilingualSpeaker < ApplicationSpeaker
182
+ provider :elevenlabs
183
+ model "eleven_multilingual_v2"
184
+ voice "Rachel"
185
+ end
186
+ end
187
+ end
188
+ ```
189
+
190
+ ## Testing Speakers
191
+
192
+ ```ruby
193
+ RSpec.describe <%= @root_namespace %>::Audio::NarratorSpeaker do
194
+ describe ".call" do
195
+ it "generates audio from text" do
196
+ result = described_class.call(text: "Hello world")
197
+
198
+ expect(result.audio).to be_present
199
+ expect(result.format).to eq(:mp3)
200
+ end
201
+ end
202
+ end
203
+ ```
204
+
205
+ ## Best Practices
206
+
207
+ 1. **Use caching** - Same text produces same audio
208
+ 2. **Choose appropriate voices** - Match voice to content type
209
+ 3. **Add pronunciation lexicon** - For technical terms and acronyms
210
+ 4. **Use HD models for quality** - When audio quality matters
211
+ 5. **Stream long content** - Don't wait for entire audio to generate
212
+ 6. **Consider file sizes** - MP3 is smaller, WAV is lossless
@@ -0,0 +1,227 @@
1
+ # <%= @root_namespace %> Tools
2
+
3
+ This directory contains tools that agents can use to perform actions. Tools allow LLM agents to interact with external systems, APIs, databases, and more.
4
+
5
+ ## Creating a Tool
6
+
7
+ Tools use the RubyLLM tool interface. Create a class that includes `RubyLLM::Tool`:
8
+
9
+ ```ruby
10
+ module <%= @root_namespace %>
11
+ class SearchTool
12
+ include RubyLLM::Tool
13
+
14
+ description "Searches the knowledge base for relevant documents"
15
+
16
+ param :query, type: :string, description: "The search query", required: true
17
+ param :limit, type: :integer, description: "Maximum results to return", default: 10
18
+
19
+ def execute(query:, limit: 10)
20
+ # Implement your tool logic here
21
+ results = Document.search(query).limit(limit)
22
+
23
+ results.map do |doc|
24
+ { title: doc.title, content: doc.content, score: doc.score }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ ```
30
+
31
+ ## Tool DSL Reference
32
+
33
+ ### `description`
34
+ Human-readable description of what the tool does. The LLM uses this to decide when to call the tool.
35
+
36
+ ```ruby
37
+ description "Fetches current weather data for a given location"
38
+ ```
39
+
40
+ ### `param`
41
+ Define parameters the tool accepts:
42
+
43
+ ```ruby
44
+ param :name, type: :string, description: "Parameter description", required: true
45
+ param :count, type: :integer, description: "Optional count", default: 5
46
+ ```
47
+
48
+ **Supported types:**
49
+ - `:string` - Text values
50
+ - `:integer` - Whole numbers
51
+ - `:number` - Decimal numbers
52
+ - `:boolean` - true/false
53
+ - `:array` - Lists of values
54
+ - `:object` - Nested objects
55
+
56
+ ### `execute`
57
+ The method that runs when the tool is called. Receives keyword arguments matching the defined params.
58
+
59
+ ```ruby
60
+ def execute(query:, limit: 10)
61
+ # Tool implementation
62
+ # Return value is passed back to the LLM
63
+ end
64
+ ```
65
+
66
+ ## Using Tools with Agents
67
+
68
+ Register tools in your agent:
69
+
70
+ ```ruby
71
+ module <%= @root_namespace %>
72
+ class ResearchAgent < ApplicationAgent
73
+ model "gpt-4o"
74
+
75
+ tools [SearchTool, CalculatorTool, WebFetchTool]
76
+
77
+ param :question, required: true
78
+
79
+ private
80
+
81
+ def system_prompt
82
+ <<~PROMPT
83
+ You are a research assistant. Use the available tools to answer questions.
84
+ Always cite your sources.
85
+ PROMPT
86
+ end
87
+
88
+ def user_prompt
89
+ question
90
+ end
91
+ end
92
+ end
93
+ ```
94
+
95
+ ## Tool Patterns
96
+
97
+ ### Database Query Tool
98
+
99
+ ```ruby
100
+ module <%= @root_namespace %>
101
+ class CustomerLookupTool
102
+ include RubyLLM::Tool
103
+
104
+ description "Looks up customer information by email or ID"
105
+
106
+ param :email, type: :string, description: "Customer email address"
107
+ param :id, type: :integer, description: "Customer ID"
108
+
109
+ def execute(email: nil, id: nil)
110
+ customer = if id
111
+ Customer.find_by(id: id)
112
+ elsif email
113
+ Customer.find_by(email: email)
114
+ end
115
+
116
+ return { error: "Customer not found" } unless customer
117
+
118
+ {
119
+ id: customer.id,
120
+ name: customer.name,
121
+ email: customer.email,
122
+ plan: customer.subscription_plan
123
+ }
124
+ end
125
+ end
126
+ end
127
+ ```
128
+
129
+ ### API Integration Tool
130
+
131
+ ```ruby
132
+ module <%= @root_namespace %>
133
+ class WeatherTool
134
+ include RubyLLM::Tool
135
+
136
+ description "Gets current weather for a location"
137
+
138
+ param :city, type: :string, description: "City name", required: true
139
+ param :units, type: :string, description: "Temperature units (celsius/fahrenheit)", default: "celsius"
140
+
141
+ def execute(city:, units: "celsius")
142
+ response = HTTP.get("https://api.weather.com/current", params: {
143
+ q: city,
144
+ units: units == "celsius" ? "metric" : "imperial"
145
+ })
146
+
147
+ data = JSON.parse(response.body)
148
+
149
+ {
150
+ temperature: data["temp"],
151
+ conditions: data["conditions"],
152
+ humidity: data["humidity"]
153
+ }
154
+ rescue HTTP::Error => e
155
+ { error: "Failed to fetch weather: #{e.message}" }
156
+ end
157
+ end
158
+ end
159
+ ```
160
+
161
+ ### Action Tool
162
+
163
+ ```ruby
164
+ module <%= @root_namespace %>
165
+ class SendEmailTool
166
+ include RubyLLM::Tool
167
+
168
+ description "Sends an email to a recipient"
169
+
170
+ param :to, type: :string, description: "Recipient email", required: true
171
+ param :subject, type: :string, description: "Email subject", required: true
172
+ param :body, type: :string, description: "Email body content", required: true
173
+
174
+ def execute(to:, subject:, body:)
175
+ # Validate email format
176
+ unless to.match?(URI::MailTo::EMAIL_REGEXP)
177
+ return { error: "Invalid email address" }
178
+ end
179
+
180
+ UserMailer.custom_email(to: to, subject: subject, body: body).deliver_later
181
+
182
+ { success: true, message: "Email queued for delivery to #{to}" }
183
+ end
184
+ end
185
+ end
186
+ ```
187
+
188
+ ## Best Practices
189
+
190
+ 1. **Clear descriptions** - Write descriptions that help the LLM understand when to use the tool
191
+ 2. **Validate inputs** - Check parameters before executing
192
+ 3. **Handle errors gracefully** - Return error objects instead of raising exceptions
193
+ 4. **Keep tools focused** - One tool, one purpose
194
+ 5. **Return structured data** - Return hashes that the LLM can interpret
195
+ 6. **Consider rate limits** - Add throttling for API-calling tools
196
+ 7. **Log tool usage** - Track which tools are called and how often
197
+
198
+ ## Testing Tools
199
+
200
+ ```ruby
201
+ RSpec.describe <%= @root_namespace %>::SearchTool do
202
+ describe "#execute" do
203
+ it "returns search results" do
204
+ tool = described_class.new
205
+ results = tool.execute(query: "ruby programming", limit: 5)
206
+
207
+ expect(results).to be_an(Array)
208
+ expect(results.length).to be <= 5
209
+ end
210
+
211
+ it "handles empty results" do
212
+ tool = described_class.new
213
+ results = tool.execute(query: "xyznonexistent123", limit: 5)
214
+
215
+ expect(results).to eq([])
216
+ end
217
+ end
218
+ end
219
+ ```
220
+
221
+ ## Security Considerations
222
+
223
+ - **Sanitize inputs** - Never trust LLM-provided parameters directly
224
+ - **Limit scope** - Tools should only access what they need
225
+ - **Audit actions** - Log destructive operations
226
+ - **Rate limit** - Prevent abuse of expensive operations
227
+ - **Validate permissions** - Check user authorization before actions