ruby_llm-agents 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/ruby_llm/agents/paginatable.rb +9 -3
  3. data/app/controllers/concerns/ruby_llm/agents/sortable.rb +58 -0
  4. data/app/controllers/ruby_llm/agents/agents_controller.rb +59 -16
  5. data/app/controllers/ruby_llm/agents/dashboard_controller.rb +144 -20
  6. data/app/controllers/ruby_llm/agents/executions_controller.rb +13 -16
  7. data/app/controllers/ruby_llm/agents/workflows_controller.rb +279 -90
  8. data/app/helpers/ruby_llm/agents/application_helper.rb +100 -0
  9. data/app/mailers/ruby_llm/agents/alert_mailer.rb +84 -0
  10. data/app/mailers/ruby_llm/agents/application_mailer.rb +28 -0
  11. data/app/models/ruby_llm/agents/execution/analytics.rb +170 -20
  12. data/app/models/ruby_llm/agents/execution/scopes.rb +0 -31
  13. data/app/models/ruby_llm/agents/execution/workflow.rb +0 -129
  14. data/app/models/ruby_llm/agents/execution.rb +50 -14
  15. data/app/models/ruby_llm/agents/tenant/budgetable.rb +277 -0
  16. data/app/models/ruby_llm/agents/tenant/configurable.rb +135 -0
  17. data/app/models/ruby_llm/agents/tenant/trackable.rb +310 -0
  18. data/app/models/ruby_llm/agents/tenant.rb +146 -0
  19. data/app/models/ruby_llm/agents/tenant_budget.rb +12 -253
  20. data/app/services/ruby_llm/agents/agent_registry.rb +18 -12
  21. data/app/views/layouts/ruby_llm/agents/application.html.erb +72 -76
  22. data/app/views/ruby_llm/agents/agents/_agent.html.erb +0 -12
  23. data/app/views/ruby_llm/agents/agents/_sortable_header.html.erb +56 -0
  24. data/app/views/ruby_llm/agents/agents/_workflow.html.erb +5 -15
  25. data/app/views/ruby_llm/agents/agents/index.html.erb +271 -100
  26. data/app/views/ruby_llm/agents/agents/show.html.erb +1 -0
  27. data/app/views/ruby_llm/agents/alert_mailer/alert_notification.html.erb +107 -0
  28. data/app/views/ruby_llm/agents/alert_mailer/alert_notification.text.erb +18 -0
  29. data/app/views/ruby_llm/agents/api_configurations/show.html.erb +4 -1
  30. data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +66 -359
  31. data/app/views/ruby_llm/agents/dashboard/_model_comparison.html.erb +56 -0
  32. data/app/views/ruby_llm/agents/dashboard/_model_cost_breakdown.html.erb +115 -0
  33. data/app/views/ruby_llm/agents/dashboard/_now_strip.html.erb +35 -60
  34. data/app/views/ruby_llm/agents/dashboard/_top_errors.html.erb +17 -6
  35. data/app/views/ruby_llm/agents/dashboard/index.html.erb +373 -72
  36. data/app/views/ruby_llm/agents/executions/_execution.html.erb +0 -1
  37. data/app/views/ruby_llm/agents/executions/_filters.html.erb +51 -39
  38. data/app/views/ruby_llm/agents/executions/_list.html.erb +53 -195
  39. data/app/views/ruby_llm/agents/executions/_workflow_summary.html.erb +5 -20
  40. data/app/views/ruby_llm/agents/executions/index.html.erb +7 -83
  41. data/app/views/ruby_llm/agents/executions/show.html.erb +10 -20
  42. data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +2 -1
  43. data/app/views/ruby_llm/agents/shared/_doc_link.html.erb +12 -0
  44. data/app/views/ruby_llm/agents/shared/_executions_table.html.erb +3 -15
  45. data/app/views/ruby_llm/agents/shared/_filter_dropdown.html.erb +1 -1
  46. data/app/views/ruby_llm/agents/shared/_select_dropdown.html.erb +1 -1
  47. data/app/views/ruby_llm/agents/shared/_sortable_header.html.erb +53 -0
  48. data/app/views/ruby_llm/agents/shared/_status_badge.html.erb +7 -0
  49. data/app/views/ruby_llm/agents/shared/_status_dot.html.erb +1 -1
  50. data/app/views/ruby_llm/agents/shared/_workflow_type_badge.html.erb +9 -35
  51. data/app/views/ruby_llm/agents/system_config/show.html.erb +4 -1
  52. data/app/views/ruby_llm/agents/tenants/index.html.erb +4 -1
  53. data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +7 -15
  54. data/app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb +539 -0
  55. data/app/views/ruby_llm/agents/workflows/_workflow_diagram.html.erb +920 -0
  56. data/app/views/ruby_llm/agents/workflows/index.html.erb +179 -0
  57. data/app/views/ruby_llm/agents/workflows/show.html.erb +164 -139
  58. data/config/routes.rb +1 -1
  59. data/lib/generators/ruby_llm_agents/agent_generator.rb +6 -36
  60. data/lib/generators/ruby_llm_agents/background_remover_generator.rb +7 -37
  61. data/lib/generators/ruby_llm_agents/embedder_generator.rb +5 -38
  62. data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +7 -37
  63. data/lib/generators/ruby_llm_agents/image_editor_generator.rb +7 -37
  64. data/lib/generators/ruby_llm_agents/image_generator_generator.rb +8 -41
  65. data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +18 -46
  66. data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +7 -37
  67. data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +7 -37
  68. data/lib/generators/ruby_llm_agents/image_variator_generator.rb +7 -37
  69. data/lib/generators/ruby_llm_agents/install_generator.rb +33 -56
  70. data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +480 -0
  71. data/lib/generators/ruby_llm_agents/multi_tenancy_generator.rb +42 -22
  72. data/lib/generators/ruby_llm_agents/restructure_generator.rb +2 -2
  73. data/lib/generators/ruby_llm_agents/speaker_generator.rb +8 -39
  74. data/lib/generators/ruby_llm_agents/templates/add_tenant_to_executions_migration.rb.tt +13 -2
  75. data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +5 -8
  76. data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +40 -42
  77. data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +20 -22
  78. data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +24 -26
  79. data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +20 -22
  80. data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +19 -17
  81. data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +31 -33
  82. data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +125 -127
  83. data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +20 -18
  84. data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +19 -17
  85. data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +19 -17
  86. data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +38 -40
  87. data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +42 -44
  88. data/lib/generators/ruby_llm_agents/templates/application_workflow.rb.tt +48 -0
  89. data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +19 -21
  90. data/lib/generators/ruby_llm_agents/templates/create_tenant_budgets_migration.rb.tt +11 -0
  91. data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +72 -0
  92. data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +19 -21
  93. data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +20 -22
  94. data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +15 -17
  95. data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +25 -27
  96. data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +19 -21
  97. data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +20 -22
  98. data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +17 -19
  99. data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +15 -17
  100. data/lib/generators/ruby_llm_agents/templates/rename_tenant_budgets_to_tenants_migration.rb.tt +34 -0
  101. data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +87 -24
  102. data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +21 -27
  103. data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +46 -54
  104. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +31 -39
  105. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +22 -28
  106. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +53 -63
  107. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +46 -56
  108. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +23 -31
  109. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +22 -30
  110. data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +23 -31
  111. data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +38 -46
  112. data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +7 -7
  113. data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +59 -71
  114. data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +274 -23
  115. data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +29 -31
  116. data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +28 -30
  117. data/lib/generators/ruby_llm_agents/transcriber_generator.rb +10 -43
  118. data/lib/generators/ruby_llm_agents/upgrade_generator.rb +26 -0
  119. data/lib/ruby_llm/agents/core/configuration.rb +55 -43
  120. data/lib/ruby_llm/agents/core/llm_tenant.rb +60 -60
  121. data/lib/ruby_llm/agents/core/version.rb +1 -1
  122. data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +26 -0
  123. data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +4 -2
  124. data/lib/ruby_llm/agents/pipeline.rb +69 -0
  125. data/lib/ruby_llm/agents/workflow/approval.rb +205 -0
  126. data/lib/ruby_llm/agents/workflow/approval_store.rb +179 -0
  127. data/lib/ruby_llm/agents/workflow/dsl/executor.rb +467 -0
  128. data/lib/ruby_llm/agents/workflow/dsl/input_schema.rb +244 -0
  129. data/lib/ruby_llm/agents/workflow/dsl/iteration_executor.rb +289 -0
  130. data/lib/ruby_llm/agents/workflow/dsl/parallel_group.rb +107 -0
  131. data/lib/ruby_llm/agents/workflow/dsl/route_builder.rb +150 -0
  132. data/lib/ruby_llm/agents/workflow/dsl/schedule_helpers.rb +187 -0
  133. data/lib/ruby_llm/agents/workflow/dsl/step_config.rb +352 -0
  134. data/lib/ruby_llm/agents/workflow/dsl/step_executor.rb +415 -0
  135. data/lib/ruby_llm/agents/workflow/dsl/wait_config.rb +257 -0
  136. data/lib/ruby_llm/agents/workflow/dsl/wait_executor.rb +317 -0
  137. data/lib/ruby_llm/agents/workflow/dsl.rb +576 -0
  138. data/lib/ruby_llm/agents/workflow/instrumentation.rb +2 -7
  139. data/lib/ruby_llm/agents/workflow/notifiers/base.rb +117 -0
  140. data/lib/ruby_llm/agents/workflow/notifiers/email.rb +117 -0
  141. data/lib/ruby_llm/agents/workflow/notifiers/slack.rb +180 -0
  142. data/lib/ruby_llm/agents/workflow/notifiers/webhook.rb +121 -0
  143. data/lib/ruby_llm/agents/workflow/notifiers.rb +70 -0
  144. data/lib/ruby_llm/agents/workflow/orchestrator.rb +190 -23
  145. data/lib/ruby_llm/agents/workflow/result.rb +202 -0
  146. data/lib/ruby_llm/agents/workflow/throttle_manager.rb +206 -0
  147. data/lib/ruby_llm/agents/workflow/wait_result.rb +213 -0
  148. metadata +43 -6
  149. data/app/views/ruby_llm/agents/dashboard/_execution_item.html.erb +0 -66
  150. data/lib/ruby_llm/agents/workflow/parallel.rb +0 -299
  151. data/lib/ruby_llm/agents/workflow/pipeline.rb +0 -306
  152. data/lib/ruby_llm/agents/workflow/router.rb +0 -429
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Migration to rename tenant_budgets table to tenants
4
+ #
5
+ # This migration is for users upgrading from an older version of the gem
6
+ # where the table was called 'ruby_llm_agents_tenant_budgets'.
7
+ #
8
+ # If you're doing a fresh install, use the create_tenants_migration instead.
9
+ #
10
+ # Run with: rails db:migrate
11
+ class RenameTenantBudgetsToTenants < ActiveRecord::Migration<%= migration_version %>
12
+ def change
13
+ # Rename the table
14
+ rename_table :ruby_llm_agents_tenant_budgets, :ruby_llm_agents_tenants
15
+
16
+ # Add new columns for Tenant model
17
+ add_column :ruby_llm_agents_tenants, :active, :boolean, default: true
18
+ add_column :ruby_llm_agents_tenants, :metadata, :json, null: false, default: {}
19
+
20
+ # Add index for active status
21
+ add_index :ruby_llm_agents_tenants, :active
22
+
23
+ # Rename indexes to match new table name
24
+ # Note: Some databases handle this automatically when renaming tables
25
+ # If you get an error about missing indexes, you may need to adjust this
26
+
27
+ # The polymorphic index needs to be renamed if it exists
28
+ if index_exists?(:ruby_llm_agents_tenants, [:tenant_record_type, :tenant_record_id], name: "index_tenant_budgets_on_tenant_record")
29
+ rename_index :ruby_llm_agents_tenants,
30
+ "index_tenant_budgets_on_tenant_record",
31
+ "index_tenants_on_tenant_record"
32
+ end
33
+ end
34
+ end
@@ -1,4 +1,4 @@
1
- # <%= @root_namespace %> Agents
1
+ # Agents
2
2
 
3
3
  This directory contains LLM-powered agents for the application. All agents inherit from `ApplicationAgent`.
4
4
 
@@ -11,30 +11,47 @@ rails generate ruby_llm_agents:agent AgentName param1:required param2:default_va
11
11
 
12
12
  Or create manually by extending `ApplicationAgent`:
13
13
  ```ruby
14
- module <%= @root_namespace %>
15
- class MyAgent < ApplicationAgent
16
- # Configuration
17
- model "gpt-4o"
18
- temperature 0.0
19
- version "1.0"
14
+ class MyAgent < ApplicationAgent
15
+ # Configuration
16
+ model "gpt-4o"
17
+ temperature 0.0
18
+ version "1.0"
20
19
 
21
- # Parameters
22
- param :query, required: true
23
- param :limit, default: 10
20
+ # Parameters
21
+ param :query, required: true
22
+ param :limit, default: 10
24
23
 
25
- private
24
+ private
26
25
 
27
- def system_prompt
28
- "You are a helpful assistant."
29
- end
26
+ def system_prompt
27
+ "You are a helpful assistant."
28
+ end
30
29
 
31
- def user_prompt
32
- query
33
- end
30
+ def user_prompt
31
+ query
34
32
  end
35
33
  end
36
34
  ```
37
35
 
36
+ ## Directory Structure
37
+
38
+ ```
39
+ app/agents/
40
+ ├── application_agent.rb # Base class for all agents
41
+ ├── concerns/ # Shared agent mixins
42
+ ├── my_agent.rb # Task agents at root
43
+ ├── images/ # Image operation agents
44
+ │ ├── product_generator.rb
45
+ │ └── content_analyzer.rb
46
+ ├── audio/ # Audio operation agents
47
+ │ ├── meeting_transcriber.rb
48
+ │ └── voice_narrator.rb
49
+ ├── embedders/ # Embedding agents
50
+ │ └── semantic_embedder.rb
51
+ └── moderators/ # Moderation agents
52
+ └── content_moderator.rb
53
+ ```
54
+
38
55
  ## DSL Reference
39
56
 
40
57
  ### Model Configuration
@@ -178,7 +195,7 @@ end
178
195
 
179
196
  ```ruby
180
197
  # Basic call
181
- result = <%= @root_namespace %>::MyAgent.call(query: "hello")
198
+ result = MyAgent.call(query: "hello")
182
199
 
183
200
  # Access result
184
201
  result.content # The response content
@@ -187,27 +204,73 @@ result.output_tokens # Tokens in response
187
204
  result.total_cost # Cost in USD
188
205
 
189
206
  # Debug mode (no API call)
190
- result = <%= @root_namespace %>::MyAgent.call(query: "hello", dry_run: true)
207
+ result = MyAgent.call(query: "hello", dry_run: true)
191
208
 
192
209
  # Skip cache
193
- result = <%= @root_namespace %>::MyAgent.call(query: "hello", skip_cache: true)
210
+ result = MyAgent.call(query: "hello", skip_cache: true)
194
211
 
195
212
  # With attachments
196
- result = <%= @root_namespace %>::MyAgent.call(query: "describe this", with: "image.png")
213
+ result = MyAgent.call(query: "describe this", with: "image.png")
197
214
 
198
215
  # Streaming
199
- <%= @root_namespace %>::MyAgent.stream(query: "hello") do |chunk|
216
+ MyAgent.stream(query: "hello") do |chunk|
200
217
  print chunk.content
201
218
  end
202
219
 
203
220
  # Multi-tenancy
204
- result = <%= @root_namespace %>::MyAgent.call(query: "hello", tenant: current_user)
221
+ result = MyAgent.call(query: "hello", tenant: current_user)
222
+ ```
223
+
224
+ ## Specialized Agents
225
+
226
+ ### Image Agents
227
+ ```ruby
228
+ # app/agents/images/product_generator.rb
229
+ module Images
230
+ class ProductGenerator < RubyLLM::Agents::Image::Generator
231
+ model "dall-e-3"
232
+ size "1024x1024"
233
+ quality "hd"
234
+ end
235
+ end
236
+
237
+ # Usage
238
+ result = Images::ProductGenerator.call(prompt: "A product photo")
239
+ result.url # Image URL
240
+ ```
241
+
242
+ ### Audio Agents
243
+ ```ruby
244
+ # app/agents/audio/meeting_transcriber.rb
245
+ module Audio
246
+ class MeetingTranscriber < RubyLLM::Agents::Audio::Transcriber
247
+ model "whisper-1"
248
+ end
249
+ end
250
+
251
+ # Usage
252
+ result = Audio::MeetingTranscriber.call(audio: "meeting.mp3")
253
+ result.text # Transcribed text
254
+ ```
255
+
256
+ ### Embedding Agents
257
+ ```ruby
258
+ # app/agents/embedders/semantic_embedder.rb
259
+ module Embedders
260
+ class SemanticEmbedder < RubyLLM::Agents::Embedder
261
+ model "text-embedding-3-large"
262
+ end
263
+ end
264
+
265
+ # Usage
266
+ result = Embedders::SemanticEmbedder.call(text: "Hello world")
267
+ result.embedding # Vector array
205
268
  ```
206
269
 
207
270
  ## Testing Agents
208
271
 
209
272
  ```ruby
210
- RSpec.describe <%= @root_namespace %>::MyAgent do
273
+ RSpec.describe MyAgent do
211
274
  describe ".call" do
212
275
  it "returns expected result" do
213
276
  # Use dry_run for unit tests
@@ -1,4 +1,4 @@
1
- # <%= @root_namespace %>::Image Background Removers
1
+ # Images Background Removers
2
2
 
3
3
  This directory contains background removal services. All removers inherit from `ApplicationBackgroundRemover`.
4
4
 
@@ -12,13 +12,11 @@ rails generate ruby_llm_agents:background_remover Product --edge_refinement high
12
12
 
13
13
  Or create manually:
14
14
  ```ruby
15
- module <%= @root_namespace %>
16
- module Image
17
- class ProductRemover < ApplicationBackgroundRemover
18
- model "remove-bg"
19
- edge_refinement :high
20
- output_format :png
21
- end
15
+ module Images
16
+ class ProductRemover < ApplicationBackgroundRemover
17
+ model "remove-bg"
18
+ edge_refinement :high
19
+ output_format :png
22
20
  end
23
21
  end
24
22
  ```
@@ -45,7 +43,7 @@ end
45
43
  ## Using Removers
46
44
 
47
45
  ```ruby
48
- result = <%= @root_namespace %>::Image::ProductRemover.call(image: "product.jpg")
46
+ result = Images::ProductRemover.call(image: "product.jpg")
49
47
 
50
48
  result.url # Image URL with transparent background
51
49
  result.image_data # PNG binary data
@@ -56,7 +54,7 @@ result.save("product_nobg.png")
56
54
  ### With Background Color
57
55
 
58
56
  ```ruby
59
- result = <%= @root_namespace %>::Image::ProductRemover.call(
57
+ result = Images::ProductRemover.call(
60
58
  image: "product.jpg",
61
59
  background_color: "#FFFFFF" # White background
62
60
  )
@@ -65,7 +63,7 @@ result = <%= @root_namespace %>::Image::ProductRemover.call(
65
63
  ### Override Settings
66
64
 
67
65
  ```ruby
68
- result = <%= @root_namespace %>::Image::ProductRemover.call(
66
+ result = Images::ProductRemover.call(
69
67
  image: "complex_photo.jpg",
70
68
  edge_refinement: :high,
71
69
  output_format: :webp
@@ -77,14 +75,12 @@ result = <%= @root_namespace %>::Image::ProductRemover.call(
77
75
  ### E-commerce Product Photos
78
76
 
79
77
  ```ruby
80
- module <%= @root_namespace %>
81
- module Image
82
- class ProductBackgroundRemover < ApplicationBackgroundRemover
83
- edge_refinement :high
84
- output_format :png
85
-
86
- cache_for 30.days # Product images don't change often
87
- end
78
+ module Images
79
+ class ProductBackgroundRemover < ApplicationBackgroundRemover
80
+ edge_refinement :high
81
+ output_format :png
82
+
83
+ cache_for 30.days # Product images don't change often
88
84
  end
89
85
  end
90
86
  ```
@@ -92,24 +88,22 @@ end
92
88
  ### Profile Photo Processing
93
89
 
94
90
  ```ruby
95
- module <%= @root_namespace %>
96
- module Image
97
- class AvatarBackgroundRemover < ApplicationBackgroundRemover
98
- edge_refinement :high
99
- output_format :png
100
- end
91
+ module Images
92
+ class AvatarBackgroundRemover < ApplicationBackgroundRemover
93
+ edge_refinement :high
94
+ output_format :png
101
95
  end
102
96
  end
103
97
 
104
98
  # Remove background and resize
105
- result = <%= @root_namespace %>::Image::AvatarBackgroundRemover.call(image: uploaded_photo)
99
+ result = Images::AvatarBackgroundRemover.call(image: uploaded_photo)
106
100
  ```
107
101
 
108
102
  ### Batch Processing
109
103
 
110
104
  ```ruby
111
105
  Product.where(background_removed: false).find_each do |product|
112
- result = <%= @root_namespace %>::Image::ProductBackgroundRemover.call(
106
+ result = Images::ProductBackgroundRemover.call(
113
107
  image: product.original_image.download
114
108
  )
115
109
 
@@ -1,4 +1,4 @@
1
- # <%= @root_namespace %>::Text Embedders
1
+ # Embedders
2
2
 
3
3
  This directory contains text embedding services for vector search and semantic similarity. All embedders inherit from `ApplicationEmbedder`.
4
4
 
@@ -13,14 +13,12 @@ rails generate ruby_llm_agents:embedder Search --dimensions 512 --batch_size 50
13
13
 
14
14
  Or create manually:
15
15
  ```ruby
16
- module <%= @root_namespace %>
17
- module Text
18
- class DocumentEmbedder < ApplicationEmbedder
19
- model "text-embedding-3-small"
20
- dimensions 1536
21
- batch_size 100
22
- cache_for 1.week
23
- end
16
+ module Embedders
17
+ class DocumentEmbedder < ApplicationEmbedder
18
+ model "text-embedding-3-small"
19
+ dimensions 1536
20
+ batch_size 100
21
+ cache_for 1.week
24
22
  end
25
23
  end
26
24
  ```
@@ -76,7 +74,7 @@ end
76
74
  ### Single Text Embedding
77
75
 
78
76
  ```ruby
79
- result = <%= @root_namespace %>::Text::DocumentEmbedder.call(text: "Hello world")
77
+ result = Embedders::DocumentEmbedder.call(text: "Hello world")
80
78
 
81
79
  result.embedding # [0.123, -0.456, ...] vector array
82
80
  result.dimensions # 1536
@@ -90,7 +88,7 @@ Process multiple texts efficiently:
90
88
 
91
89
  ```ruby
92
90
  texts = ["Hello world", "Goodbye world", "Ruby programming"]
93
- result = <%= @root_namespace %>::Text::DocumentEmbedder.call(texts: texts)
91
+ result = Embedders::DocumentEmbedder.call(texts: texts)
94
92
 
95
93
  result.embeddings # Array of embedding vectors
96
94
  result.count # 3
@@ -112,7 +110,7 @@ end
112
110
 
113
111
  # Generate and store embedding
114
112
  document = Document.find(1)
115
- result = <%= @root_namespace %>::Text::DocumentEmbedder.call(text: document.content)
113
+ result = Embedders::DocumentEmbedder.call(text: document.content)
116
114
  document.update!(embedding: result.embedding)
117
115
  ```
118
116
 
@@ -120,7 +118,7 @@ document.update!(embedding: result.embedding)
120
118
 
121
119
  ```ruby
122
120
  # Embed the query
123
- query_result = <%= @root_namespace %>::Text::SearchEmbedder.call(text: "ruby web framework")
121
+ query_result = Embedders::SearchEmbedder.call(text: "ruby web framework")
124
122
 
125
123
  # Find similar documents
126
124
  similar = Document.nearest_neighbors(:embedding, query_result.embedding, distance: "cosine")
@@ -132,20 +130,18 @@ similar = Document.nearest_neighbors(:embedding, query_result.embedding, distanc
132
130
  ### Document Embedding
133
131
 
134
132
  ```ruby
135
- module <%= @root_namespace %>
136
- module Text
137
- class DocumentEmbedder < ApplicationEmbedder
138
- model "text-embedding-3-large"
139
- dimensions 1024
140
- batch_size 50
141
- cache_for 30.days
142
-
143
- def preprocess(text)
144
- text
145
- .strip
146
- .gsub(/\s+/, ' ')
147
- .truncate(8000)
148
- end
133
+ module Embedders
134
+ class DocumentEmbedder < ApplicationEmbedder
135
+ model "text-embedding-3-large"
136
+ dimensions 1024
137
+ batch_size 50
138
+ cache_for 30.days
139
+
140
+ def preprocess(text)
141
+ text
142
+ .strip
143
+ .gsub(/\s+/, ' ')
144
+ .truncate(8000)
149
145
  end
150
146
  end
151
147
  end
@@ -154,16 +150,14 @@ end
154
150
  ### Search Query Embedding
155
151
 
156
152
  ```ruby
157
- module <%= @root_namespace %>
158
- module Text
159
- class SearchEmbedder < ApplicationEmbedder
160
- model "text-embedding-3-small"
161
- dimensions 512
162
- cache_for 1.hour # Queries may repeat
163
-
164
- def preprocess(text)
165
- text.strip.downcase
166
- end
153
+ module Embedders
154
+ class SearchEmbedder < ApplicationEmbedder
155
+ model "text-embedding-3-small"
156
+ dimensions 512
157
+ cache_for 1.hour # Queries may repeat
158
+
159
+ def preprocess(text)
160
+ text.strip.downcase
167
161
  end
168
162
  end
169
163
  end
@@ -172,20 +166,18 @@ end
172
166
  ### Code Embedding
173
167
 
174
168
  ```ruby
175
- module <%= @root_namespace %>
176
- module Text
177
- class CodeEmbedder < ApplicationEmbedder
178
- model "text-embedding-3-large"
179
- cache_for 7.days
180
-
181
- def preprocess(text)
182
- # Remove comments, normalize whitespace
183
- text
184
- .gsub(/#.*$/, '')
185
- .gsub(/\/\/.*$/, '')
186
- .gsub(/\s+/, ' ')
187
- .strip
188
- end
169
+ module Embedders
170
+ class CodeEmbedder < ApplicationEmbedder
171
+ model "text-embedding-3-large"
172
+ cache_for 7.days
173
+
174
+ def preprocess(text)
175
+ # Remove comments, normalize whitespace
176
+ text
177
+ .gsub(/#.*$/, '')
178
+ .gsub(/\/\/.*$/, '')
179
+ .gsub(/\s+/, ' ')
180
+ .strip
189
181
  end
190
182
  end
191
183
  end
@@ -198,13 +190,13 @@ end
198
190
  Document.find_each(batch_size: 100) do |doc|
199
191
  next if doc.embedding.present?
200
192
 
201
- result = <%= @root_namespace %>::Text::DocumentEmbedder.call(text: doc.content)
193
+ result = Embedders::DocumentEmbedder.call(text: doc.content)
202
194
  doc.update!(embedding: result.embedding)
203
195
  end
204
196
 
205
197
  # Or batch multiple at once
206
198
  texts = Document.where(embedding: nil).limit(100).pluck(:id, :content)
207
- results = <%= @root_namespace %>::Text::DocumentEmbedder.call(texts: texts.map(&:last))
199
+ results = Embedders::DocumentEmbedder.call(texts: texts.map(&:last))
208
200
 
209
201
  texts.each_with_index do |(id, _), index|
210
202
  Document.find(id).update!(embedding: results.embeddings[index])
@@ -214,7 +206,7 @@ end
214
206
  ## Testing Embedders
215
207
 
216
208
  ```ruby
217
- RSpec.describe <%= @root_namespace %>::Text::DocumentEmbedder do
209
+ RSpec.describe Embedders::DocumentEmbedder do
218
210
  describe ".call" do
219
211
  it "returns embedding vector" do
220
212
  result = described_class.call(text: "Hello world")
@@ -1,4 +1,4 @@
1
- # <%= @root_namespace %>::Image Analyzers
1
+ # Images Analyzers
2
2
 
3
3
  This directory contains image analysis services. All analyzers inherit from `ApplicationImageAnalyzer`.
4
4
 
@@ -12,14 +12,12 @@ rails generate ruby_llm_agents:image_analyzer Product --model gpt-4o
12
12
 
13
13
  Or create manually:
14
14
  ```ruby
15
- module <%= @root_namespace %>
16
- module Image
17
- class ProductAnalyzer < ApplicationImageAnalyzer
18
- model "gpt-4o"
19
- analysis_type :detailed
20
- extract_colors true
21
- detect_objects true
22
- end
15
+ module Images
16
+ class ProductAnalyzer < ApplicationImageAnalyzer
17
+ model "gpt-4o"
18
+ analysis_type :detailed
19
+ extract_colors true
20
+ detect_objects true
23
21
  end
24
22
  end
25
23
  ```
@@ -41,7 +39,7 @@ end
41
39
  ## Using Analyzers
42
40
 
43
41
  ```ruby
44
- result = <%= @root_namespace %>::Image::ProductAnalyzer.call(image: "product.jpg")
42
+ result = Images::ProductAnalyzer.call(image: "product.jpg")
45
43
 
46
44
  result.description # Text description
47
45
  result.objects # Detected objects
@@ -53,7 +51,7 @@ result.total_cost # Cost in USD
53
51
  ### Analyze URL
54
52
 
55
53
  ```ruby
56
- result = <%= @root_namespace %>::Image::ProductAnalyzer.call(
54
+ result = Images::ProductAnalyzer.call(
57
55
  image: "https://example.com/photo.jpg"
58
56
  )
59
57
  ```
@@ -61,16 +59,14 @@ result = <%= @root_namespace %>::Image::ProductAnalyzer.call(
61
59
  ### Custom Analysis Prompt
62
60
 
63
61
  ```ruby
64
- module <%= @root_namespace %>
65
- module Image
66
- class CustomAnalyzer < ApplicationImageAnalyzer
67
- model "gpt-4o"
68
- analysis_type :custom
69
-
70
- def analysis_prompt
71
- "Analyze this image for: composition, lighting, color harmony. " \
72
- "Return JSON with scores from 1-10 for each aspect."
73
- end
62
+ module Images
63
+ class CustomAnalyzer < ApplicationImageAnalyzer
64
+ model "gpt-4o"
65
+ analysis_type :custom
66
+
67
+ def analysis_prompt
68
+ "Analyze this image for: composition, lighting, color harmony. " \
69
+ "Return JSON with scores from 1-10 for each aspect."
74
70
  end
75
71
  end
76
72
  end
@@ -81,15 +77,13 @@ end
81
77
  ### Content Moderation
82
78
 
83
79
  ```ruby
84
- module <%= @root_namespace %>
85
- module Image
86
- class ModerationAnalyzer < ApplicationImageAnalyzer
87
- model "gpt-4o"
88
-
89
- def analysis_prompt
90
- "Analyze this image for inappropriate content. " \
91
- "Return JSON with: safe (boolean), reason (string if unsafe)"
92
- end
80
+ module Images
81
+ class ModerationAnalyzer < ApplicationImageAnalyzer
82
+ model "gpt-4o"
83
+
84
+ def analysis_prompt
85
+ "Analyze this image for inappropriate content. " \
86
+ "Return JSON with: safe (boolean), reason (string if unsafe)"
93
87
  end
94
88
  end
95
89
  end
@@ -98,15 +92,13 @@ end
98
92
  ### Product Categorization
99
93
 
100
94
  ```ruby
101
- module <%= @root_namespace %>
102
- module Image
103
- class CategoryAnalyzer < ApplicationImageAnalyzer
104
- model "gpt-4o"
105
- detect_objects true
106
-
107
- def analysis_prompt
108
- "Identify the product category, brand if visible, and condition."
109
- end
95
+ module Images
96
+ class CategoryAnalyzer < ApplicationImageAnalyzer
97
+ model "gpt-4o"
98
+ detect_objects true
99
+
100
+ def analysis_prompt
101
+ "Identify the product category, brand if visible, and condition."
110
102
  end
111
103
  end
112
104
  end
@@ -1,4 +1,4 @@
1
- # <%= @root_namespace %>::Image Editors
1
+ # Images Editors
2
2
 
3
3
  This directory contains image editing services (inpainting, masked edits). All editors inherit from `ApplicationImageEditor`.
4
4
 
@@ -12,13 +12,11 @@ rails generate ruby_llm_agents:image_editor Background --model gpt-image-1
12
12
 
13
13
  Or create manually:
14
14
  ```ruby
15
- module <%= @root_namespace %>
16
- module Image
17
- class BackgroundEditor < ApplicationImageEditor
18
- model "gpt-image-1"
19
- size "1024x1024"
20
- content_policy :standard
21
- end
15
+ module Images
16
+ class BackgroundEditor < ApplicationImageEditor
17
+ model "gpt-image-1"
18
+ size "1024x1024"
19
+ content_policy :standard
22
20
  end
23
21
  end
24
22
  ```
@@ -36,7 +34,7 @@ end
36
34
  ### Basic Edit with Mask
37
35
 
38
36
  ```ruby
39
- result = <%= @root_namespace %>::Image::BackgroundEditor.call(
37
+ result = Images::BackgroundEditor.call(
40
38
  image: "photo.png",
41
39
  mask: "mask.png",
42
40
  prompt: "Beautiful sunset sky background"
@@ -51,7 +49,7 @@ result.save("edited.png")
51
49
 
52
50
  ```ruby
53
51
  # Mask should be PNG with transparent areas indicating regions to edit
54
- result = <%= @root_namespace %>::Image::BackgroundEditor.call(
52
+ result = Images::BackgroundEditor.call(
55
53
  image: original_image,
56
54
  mask: mask_with_transparent_areas,
57
55
  prompt: "Modern city skyline"
@@ -63,15 +61,13 @@ result = <%= @root_namespace %>::Image::BackgroundEditor.call(
63
61
  ### Background Replacement
64
62
 
65
63
  ```ruby
66
- module <%= @root_namespace %>
67
- module Image
68
- class BackgroundReplacer < ApplicationImageEditor
69
- model "gpt-image-1"
70
- size "1024x1024"
71
-
72
- def default_prompt
73
- "Professional studio background, soft lighting"
74
- end
64
+ module Images
65
+ class BackgroundReplacer < ApplicationImageEditor
66
+ model "gpt-image-1"
67
+ size "1024x1024"
68
+
69
+ def default_prompt
70
+ "Professional studio background, soft lighting"
75
71
  end
76
72
  end
77
73
  end
@@ -80,15 +76,13 @@ end
80
76
  ### Object Removal
81
77
 
82
78
  ```ruby
83
- module <%= @root_namespace %>
84
- module Image
85
- class ObjectRemover < ApplicationImageEditor
86
- model "gpt-image-1"
87
-
88
- # Mask covers the object to remove
89
- def default_prompt
90
- "Seamless continuation of the surrounding area"
91
- end
79
+ module Images
80
+ class ObjectRemover < ApplicationImageEditor
81
+ model "gpt-image-1"
82
+
83
+ # Mask covers the object to remove
84
+ def default_prompt
85
+ "Seamless continuation of the surrounding area"
92
86
  end
93
87
  end
94
88
  end