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.
- checksums.yaml +4 -4
- data/README.md +225 -34
- data/app/controllers/ruby_llm/agents/agents_controller.rb +136 -16
- data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +214 -0
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +29 -9
- data/app/controllers/ruby_llm/agents/{settings_controller.rb → system_config_controller.rb} +3 -3
- data/app/controllers/ruby_llm/agents/tenants_controller.rb +109 -0
- 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/api_configuration.rb +386 -0
- data/app/models/ruby_llm/agents/execution.rb +3 -0
- data/app/models/ruby_llm/agents/tenant_budget.rb +112 -14
- data/app/services/ruby_llm/agents/agent_registry.rb +51 -12
- data/app/views/layouts/ruby_llm/agents/application.html.erb +5 -30
- 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/api_configurations/_api_key_field.html.erb +34 -0
- data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +288 -0
- data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +95 -0
- data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +97 -0
- data/app/views/ruby_llm/agents/api_configurations/show.html.erb +211 -0
- data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +179 -0
- data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +1 -1
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +269 -15
- data/app/views/ruby_llm/agents/executions/show.html.erb +98 -0
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +93 -0
- data/app/views/ruby_llm/agents/{settings → system_config}/show.html.erb +1 -1
- data/app/views/ruby_llm/agents/tenants/_form.html.erb +150 -0
- data/app/views/ruby_llm/agents/tenants/edit.html.erb +13 -0
- data/app/views/ruby_llm/agents/tenants/index.html.erb +129 -0
- data/app/views/ruby_llm/agents/tenants/show.html.erb +374 -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 +13 -1
- data/lib/generators/ruby_llm_agents/agent_generator.rb +56 -7
- data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +100 -0
- 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/create_api_configurations_migration.rb.tt +90 -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} +93 -4
- data/lib/ruby_llm/agents/core/llm_tenant.rb +358 -0
- data/lib/ruby_llm/agents/core/resolved_config.rb +348 -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 -10
- 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 +189 -35
- 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 -283
- 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 -209
- data/lib/ruby_llm/agents/budget_tracker.rb +0 -471
- data/lib/ruby_llm/agents/configuration.rb +0 -357
- /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/{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,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration to create the api_configurations table
|
|
4
|
+
#
|
|
5
|
+
# This table stores API key configurations that can be managed via the dashboard.
|
|
6
|
+
# Supports both global settings and per-tenant overrides.
|
|
7
|
+
#
|
|
8
|
+
# Resolution priority: per-tenant DB > global DB > config file (RubyLLM.configure)
|
|
9
|
+
#
|
|
10
|
+
# Features:
|
|
11
|
+
# - Encrypted storage for all API keys (using Rails encrypted attributes)
|
|
12
|
+
# - Support for all major LLM providers
|
|
13
|
+
# - Custom endpoint configuration
|
|
14
|
+
# - Connection settings
|
|
15
|
+
# - Default model configuration
|
|
16
|
+
#
|
|
17
|
+
# Run with: rails db:migrate
|
|
18
|
+
class CreateRubyLLMAgentsApiConfigurations < ActiveRecord::Migration<%= migration_version %>
|
|
19
|
+
def change
|
|
20
|
+
create_table :ruby_llm_agents_api_configurations do |t|
|
|
21
|
+
# Scope type: 'global' or 'tenant'
|
|
22
|
+
t.string :scope_type, null: false, default: 'global'
|
|
23
|
+
# Tenant ID when scope_type='tenant'
|
|
24
|
+
t.string :scope_id
|
|
25
|
+
|
|
26
|
+
# === Encrypted API Keys ===
|
|
27
|
+
# Rails encrypts stores encrypted data in the same-named column
|
|
28
|
+
# Primary providers
|
|
29
|
+
t.text :openai_api_key
|
|
30
|
+
t.text :anthropic_api_key
|
|
31
|
+
t.text :gemini_api_key
|
|
32
|
+
|
|
33
|
+
# Additional providers
|
|
34
|
+
t.text :deepseek_api_key
|
|
35
|
+
t.text :mistral_api_key
|
|
36
|
+
t.text :perplexity_api_key
|
|
37
|
+
t.text :openrouter_api_key
|
|
38
|
+
t.text :gpustack_api_key
|
|
39
|
+
t.text :xai_api_key
|
|
40
|
+
t.text :ollama_api_key
|
|
41
|
+
|
|
42
|
+
# AWS Bedrock
|
|
43
|
+
t.text :bedrock_api_key
|
|
44
|
+
t.text :bedrock_secret_key
|
|
45
|
+
t.text :bedrock_session_token
|
|
46
|
+
t.string :bedrock_region
|
|
47
|
+
|
|
48
|
+
# Google Vertex AI
|
|
49
|
+
t.text :vertexai_credentials
|
|
50
|
+
t.string :vertexai_project_id
|
|
51
|
+
t.string :vertexai_location
|
|
52
|
+
|
|
53
|
+
# === Custom Endpoints ===
|
|
54
|
+
t.string :openai_api_base
|
|
55
|
+
t.string :gemini_api_base
|
|
56
|
+
t.string :ollama_api_base
|
|
57
|
+
t.string :gpustack_api_base
|
|
58
|
+
t.string :xai_api_base
|
|
59
|
+
|
|
60
|
+
# === OpenAI Options ===
|
|
61
|
+
t.string :openai_organization_id
|
|
62
|
+
t.string :openai_project_id
|
|
63
|
+
|
|
64
|
+
# === Default Models ===
|
|
65
|
+
t.string :default_model
|
|
66
|
+
t.string :default_embedding_model
|
|
67
|
+
t.string :default_image_model
|
|
68
|
+
t.string :default_moderation_model
|
|
69
|
+
|
|
70
|
+
# === Connection Settings ===
|
|
71
|
+
t.integer :request_timeout
|
|
72
|
+
t.integer :max_retries
|
|
73
|
+
t.decimal :retry_interval, precision: 5, scale: 2
|
|
74
|
+
t.decimal :retry_backoff_factor, precision: 5, scale: 2
|
|
75
|
+
t.decimal :retry_interval_randomness, precision: 5, scale: 2
|
|
76
|
+
t.string :http_proxy
|
|
77
|
+
|
|
78
|
+
# Whether to inherit from global config for unset values
|
|
79
|
+
t.boolean :inherit_global_defaults, default: true
|
|
80
|
+
|
|
81
|
+
t.timestamps
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Ensure unique scope_type + scope_id combinations
|
|
85
|
+
add_index :ruby_llm_agents_api_configurations, [:scope_type, :scope_id], unique: true, name: 'idx_api_configs_scope'
|
|
86
|
+
|
|
87
|
+
# Index for faster tenant lookups
|
|
88
|
+
add_index :ruby_llm_agents_api_configurations, :scope_id, name: 'idx_api_configs_scope_id'
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Text
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Embedder < ApplicationEmbedder
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Embedder < ApplicationEmbedder
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
<% if options[:dimensions] -%>
|
|
16
|
+
dimensions <%= options[:dimensions] %>
|
|
17
|
+
<% end -%>
|
|
18
|
+
<% if options[:batch_size] != 100 -%>
|
|
19
|
+
batch_size <%= options[:batch_size] %>
|
|
20
|
+
<% end -%>
|
|
21
|
+
<% if options[:cache] -%>
|
|
22
|
+
|
|
23
|
+
# Caching
|
|
24
|
+
cache_for <%= options[:cache] %>
|
|
25
|
+
<% end -%>
|
|
26
|
+
|
|
27
|
+
# Optional: Custom preprocessing
|
|
28
|
+
# Override this method to normalize/clean text before embedding
|
|
29
|
+
#
|
|
30
|
+
# def preprocess(text)
|
|
31
|
+
# text.strip.downcase.gsub(/\s+/, ' ')
|
|
32
|
+
# end
|
|
33
|
+
<%- if class_name.include?("::") -%>
|
|
34
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
35
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
36
|
+
<%- end -%>
|
|
37
|
+
<%- else -%>
|
|
38
|
+
end
|
|
39
|
+
<%- end -%>
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Analyzer < ApplicationImageAnalyzer
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Analyzer < ApplicationImageAnalyzer
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
analysis_type :<%= options[:analysis_type] %>
|
|
16
|
+
<% if options[:extract_colors] -%>
|
|
17
|
+
extract_colors true
|
|
18
|
+
<% end -%>
|
|
19
|
+
<% if options[:detect_objects] -%>
|
|
20
|
+
detect_objects true
|
|
21
|
+
<% end -%>
|
|
22
|
+
<% if options[:extract_text] -%>
|
|
23
|
+
extract_text true
|
|
24
|
+
<% end -%>
|
|
25
|
+
max_tags <%= options[:max_tags] %>
|
|
26
|
+
<% if options[:cache] -%>
|
|
27
|
+
|
|
28
|
+
# Caching
|
|
29
|
+
cache_for <%= options[:cache] %>
|
|
30
|
+
<% end -%>
|
|
31
|
+
|
|
32
|
+
# Optional: Custom analysis prompt
|
|
33
|
+
# prompt "Analyze this image and describe..."
|
|
34
|
+
|
|
35
|
+
# Optional: Description
|
|
36
|
+
# description "Analyzes <%= class_name.downcase %> images"
|
|
37
|
+
<%- if class_name.include?("::") -%>
|
|
38
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
39
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
40
|
+
<%- end -%>
|
|
41
|
+
<%- else -%>
|
|
42
|
+
end
|
|
43
|
+
<%- end -%>
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Editor < ApplicationImageEditor
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Editor < ApplicationImageEditor
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
size "<%= options[:size] %>"
|
|
16
|
+
<% if options[:content_policy] != "standard" -%>
|
|
17
|
+
content_policy :<%= options[:content_policy] %>
|
|
18
|
+
<% end -%>
|
|
19
|
+
<% if options[:cache] -%>
|
|
20
|
+
|
|
21
|
+
# Caching
|
|
22
|
+
cache_for <%= options[:cache] %>
|
|
23
|
+
<% end -%>
|
|
24
|
+
|
|
25
|
+
# Optional: Description
|
|
26
|
+
# description "Edits <%= class_name.downcase %> images"
|
|
27
|
+
<%- if class_name.include?("::") -%>
|
|
28
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
29
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
30
|
+
<%- end -%>
|
|
31
|
+
<%- else -%>
|
|
32
|
+
end
|
|
33
|
+
<%- end -%>
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Generator < ApplicationImageGenerator
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Generator < ApplicationImageGenerator
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
size "<%= options[:size] %>"
|
|
16
|
+
quality "<%= options[:quality] %>"
|
|
17
|
+
style "<%= options[:style] %>"
|
|
18
|
+
<% if options[:content_policy] != "standard" -%>
|
|
19
|
+
content_policy :<%= options[:content_policy] %>
|
|
20
|
+
<% end -%>
|
|
21
|
+
<% if options[:cache] -%>
|
|
22
|
+
|
|
23
|
+
# Caching
|
|
24
|
+
cache_for <%= options[:cache] %>
|
|
25
|
+
<% end -%>
|
|
26
|
+
|
|
27
|
+
# Optional: Add a prompt template
|
|
28
|
+
# template "Professional {prompt}, high quality, detailed"
|
|
29
|
+
|
|
30
|
+
# Optional: Add negative prompts (for models that support it)
|
|
31
|
+
# negative_prompt "blurry, low quality, distorted"
|
|
32
|
+
|
|
33
|
+
# Optional: Custom preprocessing
|
|
34
|
+
# Override this method to modify prompts before generation
|
|
35
|
+
#
|
|
36
|
+
# def preprocess_prompt(prompt)
|
|
37
|
+
# "#{prompt}, professional quality"
|
|
38
|
+
# end
|
|
39
|
+
<%- if class_name.include?("::") -%>
|
|
40
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
41
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
42
|
+
<%- end -%>
|
|
43
|
+
<%- else -%>
|
|
44
|
+
end
|
|
45
|
+
<%- end -%>
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Pipeline < ApplicationImagePipeline
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Pipeline < ApplicationImagePipeline
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Pipeline steps
|
|
14
|
+
<%- parsed_steps.each do |step| -%>
|
|
15
|
+
<%- case step -%>
|
|
16
|
+
<%- when :generate -%>
|
|
17
|
+
step :<%= step %>, generator: <%= class_name %>Generator
|
|
18
|
+
<%- when :upscale -%>
|
|
19
|
+
step :<%= step %>, upscaler: <%= class_name %>Upscaler
|
|
20
|
+
<%- when :transform -%>
|
|
21
|
+
step :<%= step %>, transformer: <%= class_name %>Transformer
|
|
22
|
+
<%- when :analyze -%>
|
|
23
|
+
step :<%= step %>, analyzer: <%= class_name %>Analyzer
|
|
24
|
+
<%- when :remove_background -%>
|
|
25
|
+
step :<%= step %>, remover: <%= class_name %>BackgroundRemover
|
|
26
|
+
<%- else -%>
|
|
27
|
+
# step :<%= step %>, ...: <%= class_name %><%= step.to_s.camelize %>
|
|
28
|
+
<%- end -%>
|
|
29
|
+
<%- end -%>
|
|
30
|
+
<%- if options[:stop_on_error] == false -%>
|
|
31
|
+
|
|
32
|
+
stop_on_error false
|
|
33
|
+
<%- end -%>
|
|
34
|
+
<% if options[:cache] -%>
|
|
35
|
+
|
|
36
|
+
# Caching
|
|
37
|
+
cache_for <%= options[:cache] %>
|
|
38
|
+
<% end -%>
|
|
39
|
+
|
|
40
|
+
description "<%= class_name %> image processing pipeline"
|
|
41
|
+
version "1.0"
|
|
42
|
+
<%- if class_name.include?("::") -%>
|
|
43
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
44
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
45
|
+
<%- end -%>
|
|
46
|
+
<%- else -%>
|
|
47
|
+
end
|
|
48
|
+
<%- end -%>
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Transformer < ApplicationImageTransformer
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Transformer < ApplicationImageTransformer
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
size "<%= options[:size] %>"
|
|
16
|
+
strength <%= options[:strength] %>
|
|
17
|
+
<% if options[:content_policy] != "standard" -%>
|
|
18
|
+
content_policy :<%= options[:content_policy] %>
|
|
19
|
+
<% end -%>
|
|
20
|
+
<% if options[:template] -%>
|
|
21
|
+
|
|
22
|
+
# Prompt template
|
|
23
|
+
template "<%= options[:template] %>"
|
|
24
|
+
<% end -%>
|
|
25
|
+
<% if options[:cache] -%>
|
|
26
|
+
|
|
27
|
+
# Caching
|
|
28
|
+
cache_for <%= options[:cache] %>
|
|
29
|
+
<% end -%>
|
|
30
|
+
|
|
31
|
+
# Optional: Negative prompts
|
|
32
|
+
# negative_prompt "blurry, low quality, distorted"
|
|
33
|
+
|
|
34
|
+
# Optional: Description
|
|
35
|
+
# description "Transforms images into <%= class_name.downcase %> style"
|
|
36
|
+
<%- if class_name.include?("::") -%>
|
|
37
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
38
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
39
|
+
<%- end -%>
|
|
40
|
+
<%- else -%>
|
|
41
|
+
end
|
|
42
|
+
<%- end -%>
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Upscaler < ApplicationImageUpscaler
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Upscaler < ApplicationImageUpscaler
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
scale <%= options[:scale] %>
|
|
16
|
+
<% if options[:face_enhance] -%>
|
|
17
|
+
face_enhance true
|
|
18
|
+
<% end -%>
|
|
19
|
+
<% if options[:cache] -%>
|
|
20
|
+
|
|
21
|
+
# Caching
|
|
22
|
+
cache_for <%= options[:cache] %>
|
|
23
|
+
<% end -%>
|
|
24
|
+
|
|
25
|
+
# Optional: Denoise strength (0.0-1.0)
|
|
26
|
+
# denoise_strength 0.5
|
|
27
|
+
|
|
28
|
+
# Optional: Description
|
|
29
|
+
# description "Upscales <%= class_name.downcase %> images"
|
|
30
|
+
<%- if class_name.include?("::") -%>
|
|
31
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
32
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
33
|
+
<%- end -%>
|
|
34
|
+
<%- else -%>
|
|
35
|
+
end
|
|
36
|
+
<%- end -%>
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module <%= @root_namespace %>
|
|
4
|
+
module Image
|
|
5
|
+
<%- if class_name.include?("::") -%>
|
|
6
|
+
<%- class_name.split("::")[0..-2].each_with_index do |mod, i| -%>
|
|
7
|
+
<%= " " * (i + 2) %>module <%= mod %>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<%= " " * (class_name.split("::").length + 1) %>class <%= class_name.split("::").last %>Variator < ApplicationImageVariator
|
|
10
|
+
<%- else -%>
|
|
11
|
+
class <%= class_name %>Variator < ApplicationImageVariator
|
|
12
|
+
<%- end -%>
|
|
13
|
+
# Model configuration
|
|
14
|
+
model "<%= options[:model] %>"
|
|
15
|
+
size "<%= options[:size] %>"
|
|
16
|
+
variation_strength <%= options[:variation_strength] %>
|
|
17
|
+
<% if options[:cache] -%>
|
|
18
|
+
|
|
19
|
+
# Caching
|
|
20
|
+
cache_for <%= options[:cache] %>
|
|
21
|
+
<% end -%>
|
|
22
|
+
|
|
23
|
+
# Optional: Description
|
|
24
|
+
# description "Creates variations of <%= class_name.downcase %> images"
|
|
25
|
+
<%- if class_name.include?("::") -%>
|
|
26
|
+
<%- (class_name.split("::").length + 1).times do |i| -%>
|
|
27
|
+
<%= " " * (class_name.split("::").length + 1 - i) %>end
|
|
28
|
+
<%- end -%>
|
|
29
|
+
<%- else -%>
|
|
30
|
+
end
|
|
31
|
+
<%- end -%>
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# <%= @root_namespace %> Agents
|
|
2
|
+
|
|
3
|
+
This directory contains LLM-powered agents for the application. All agents inherit from `ApplicationAgent`.
|
|
4
|
+
|
|
5
|
+
## Creating a New Agent
|
|
6
|
+
|
|
7
|
+
Use the generator:
|
|
8
|
+
```bash
|
|
9
|
+
rails generate ruby_llm_agents:agent AgentName param1:required param2:default_value
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or create manually by extending `ApplicationAgent`:
|
|
13
|
+
```ruby
|
|
14
|
+
module <%= @root_namespace %>
|
|
15
|
+
class MyAgent < ApplicationAgent
|
|
16
|
+
# Configuration
|
|
17
|
+
model "gpt-4o"
|
|
18
|
+
temperature 0.0
|
|
19
|
+
version "1.0"
|
|
20
|
+
|
|
21
|
+
# Parameters
|
|
22
|
+
param :query, required: true
|
|
23
|
+
param :limit, default: 10
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def system_prompt
|
|
28
|
+
"You are a helpful assistant."
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def user_prompt
|
|
32
|
+
query
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## DSL Reference
|
|
39
|
+
|
|
40
|
+
### Model Configuration
|
|
41
|
+
|
|
42
|
+
| Method | Description | Example |
|
|
43
|
+
|--------|-------------|---------|
|
|
44
|
+
| `model` | LLM model to use | `model "gpt-4o"` |
|
|
45
|
+
| `temperature` | Response randomness (0.0-2.0) | `temperature 0.7` |
|
|
46
|
+
| `version` | Cache invalidation version | `version "2.0"` |
|
|
47
|
+
| `timeout` | Request timeout in seconds | `timeout 30` |
|
|
48
|
+
| `description` | Human-readable description | `description "Searches documents"` |
|
|
49
|
+
|
|
50
|
+
### Parameters
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
param :name # Optional parameter
|
|
54
|
+
param :query, required: true # Required parameter
|
|
55
|
+
param :limit, default: 10 # With default value
|
|
56
|
+
param :count, type: Integer # With type validation
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Access parameters as methods: `query`, `limit`, etc.
|
|
60
|
+
|
|
61
|
+
### Caching
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
cache 1.hour # Enable with TTL
|
|
65
|
+
cache_for 30.minutes # Alias for cache
|
|
66
|
+
|
|
67
|
+
cache_key_includes :user_id, :query # Only these params in cache key
|
|
68
|
+
cache_key_excludes :timestamp # Exclude from cache key
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Reliability (Retries & Fallbacks)
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
# Individual settings
|
|
75
|
+
retries max: 3, backoff: :exponential, base: 0.4, max_delay: 3.0
|
|
76
|
+
fallback_models "gpt-4o-mini", "claude-3-haiku"
|
|
77
|
+
total_timeout 30
|
|
78
|
+
circuit_breaker errors: 5, within: 60, cooldown: 300
|
|
79
|
+
|
|
80
|
+
# Or grouped in a block
|
|
81
|
+
reliability do
|
|
82
|
+
retries max: 3, backoff: :exponential
|
|
83
|
+
fallback_models "gpt-4o-mini"
|
|
84
|
+
total_timeout 30
|
|
85
|
+
circuit_breaker errors: 5, within: 60
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Streaming
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
streaming true # Enable streaming by default
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Tools
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
tools [SearchTool, CalculatorTool] # Make tools available to agent
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Extended Thinking
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
thinking effort: :high # Enable extended thinking
|
|
105
|
+
thinking budget: 10000 # With token budget
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Moderation
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
moderation :input # Check input before LLM call
|
|
112
|
+
moderation :output # Check output after LLM call
|
|
113
|
+
moderation :both # Check both
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Required Methods
|
|
117
|
+
|
|
118
|
+
### `user_prompt` (required)
|
|
119
|
+
The prompt sent to the LLM. Must return a String.
|
|
120
|
+
|
|
121
|
+
### `system_prompt` (optional)
|
|
122
|
+
Instructions for the LLM. Return nil for no system prompt.
|
|
123
|
+
|
|
124
|
+
## Optional Overrides
|
|
125
|
+
|
|
126
|
+
### `schema`
|
|
127
|
+
Return a `RubyLLM::Schema` for structured JSON output:
|
|
128
|
+
```ruby
|
|
129
|
+
def schema
|
|
130
|
+
@schema ||= RubyLLM::Schema.create do
|
|
131
|
+
string :result, description: "The result"
|
|
132
|
+
integer :confidence, description: "Confidence 1-100"
|
|
133
|
+
array :tags do
|
|
134
|
+
string
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `process_response(response)`
|
|
141
|
+
Transform the LLM response before returning:
|
|
142
|
+
```ruby
|
|
143
|
+
def process_response(response)
|
|
144
|
+
content = response.content
|
|
145
|
+
# Custom processing
|
|
146
|
+
content
|
|
147
|
+
end
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### `messages`
|
|
151
|
+
Provide conversation history for multi-turn:
|
|
152
|
+
```ruby
|
|
153
|
+
def messages
|
|
154
|
+
[
|
|
155
|
+
{ role: :user, content: "Previous question" },
|
|
156
|
+
{ role: :assistant, content: "Previous answer" }
|
|
157
|
+
]
|
|
158
|
+
end
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `cache_key_data`
|
|
162
|
+
Customize what goes into the cache key:
|
|
163
|
+
```ruby
|
|
164
|
+
def cache_key_data
|
|
165
|
+
{ query: query, locale: I18n.locale }
|
|
166
|
+
end
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `execution_metadata`
|
|
170
|
+
Add custom data to execution logs:
|
|
171
|
+
```ruby
|
|
172
|
+
def execution_metadata
|
|
173
|
+
{ request_id: params[:request_id] }
|
|
174
|
+
end
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Calling Agents
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
# Basic call
|
|
181
|
+
result = <%= @root_namespace %>::MyAgent.call(query: "hello")
|
|
182
|
+
|
|
183
|
+
# Access result
|
|
184
|
+
result.content # The response content
|
|
185
|
+
result.input_tokens # Tokens used in prompt
|
|
186
|
+
result.output_tokens # Tokens in response
|
|
187
|
+
result.total_cost # Cost in USD
|
|
188
|
+
|
|
189
|
+
# Debug mode (no API call)
|
|
190
|
+
result = <%= @root_namespace %>::MyAgent.call(query: "hello", dry_run: true)
|
|
191
|
+
|
|
192
|
+
# Skip cache
|
|
193
|
+
result = <%= @root_namespace %>::MyAgent.call(query: "hello", skip_cache: true)
|
|
194
|
+
|
|
195
|
+
# With attachments
|
|
196
|
+
result = <%= @root_namespace %>::MyAgent.call(query: "describe this", with: "image.png")
|
|
197
|
+
|
|
198
|
+
# Streaming
|
|
199
|
+
<%= @root_namespace %>::MyAgent.stream(query: "hello") do |chunk|
|
|
200
|
+
print chunk.content
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Multi-tenancy
|
|
204
|
+
result = <%= @root_namespace %>::MyAgent.call(query: "hello", tenant: current_user)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Testing Agents
|
|
208
|
+
|
|
209
|
+
```ruby
|
|
210
|
+
RSpec.describe <%= @root_namespace %>::MyAgent do
|
|
211
|
+
describe ".call" do
|
|
212
|
+
it "returns expected result" do
|
|
213
|
+
# Use dry_run for unit tests
|
|
214
|
+
result = described_class.call(query: "test", dry_run: true)
|
|
215
|
+
expect(result.content[:user_prompt]).to eq("test")
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Best Practices
|
|
222
|
+
|
|
223
|
+
1. **Keep prompts focused** - One agent, one task
|
|
224
|
+
2. **Use structured output** - Define schemas for predictable responses
|
|
225
|
+
3. **Enable caching** - For deterministic queries
|
|
226
|
+
4. **Set appropriate temperatures** - 0.0 for deterministic, higher for creative
|
|
227
|
+
5. **Configure retries** - For production reliability
|
|
228
|
+
6. **Version your agents** - Bump version when changing prompts
|