Class: Agentic::Learning::StrategyOptimizer

Inherits:
Object
  • Object
show all
Defined in:
lib/agentic/learning/strategy_optimizer.rb

Overview

StrategyOptimizer improves execution strategies based on historical performance data. It uses insights from the PatternRecognizer to automatically generate optimized strategies for tasks, agents, and plans.

Examples:

Optimizing a prompt template

history_store = Agentic::Learning::ExecutionHistoryStore.new
recognizer = Agentic::Learning::PatternRecognizer.new(history_store: history_store)
optimizer = Agentic::Learning::StrategyOptimizer.new(
  pattern_recognizer: recognizer,
  history_store: history_store
)

improved_prompt = optimizer.optimize_prompt_template(
  original_template: "Please research the following topic: {topic}",
  agent_type: "research_agent"
)

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ StrategyOptimizer

Initialize a new StrategyOptimizer

Parameters:

  • options (Hash) (defaults to: {})

    Configuration options

Options Hash (options):

  • :logger (Logger)

    Custom logger (defaults to Agentic.logger)

  • :pattern_recognizer (PatternRecognizer)

    Pattern recognizer for insights

  • :history_store (ExecutionHistoryStore)

    History store for performance data

  • :llm_client (LlmClient)

    LLM client for generating optimizations (optional)

  • :optimization_interval_hours (Integer)

    Hours between optimization attempts (defaults to 24)

  • :auto_apply_optimizations (Boolean)

    Whether to automatically apply optimizations (defaults to false)



32
33
34
35
36
37
38
39
40
41
# File 'lib/agentic/learning/strategy_optimizer.rb', line 32

def initialize(options = {})
  @logger = options[:logger] || Agentic.logger
  @pattern_recognizer = options[:pattern_recognizer] || raise(ArgumentError, "pattern_recognizer is required")
  @history_store = options[:history_store] || raise(ArgumentError, "history_store is required")
  @llm_client = options[:llm_client]
  @optimization_interval_hours = options[:optimization_interval_hours] || 24
  @auto_apply_optimizations = options.fetch(:auto_apply_optimizations, false)
  @optimization_cache = {}
  @last_optimization = {}
end

Instance Method Details

#apply_optimizations(target, registry) ⇒ Hash

Apply learned optimizations to existing configurations

Parameters:

  • target (Symbol)

    Type of target to optimize (:prompts, :parameters, :sequences)

  • registry (Hash)

    Registry of current configurations

Returns:

  • (Hash)

    Results of optimization applications



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/agentic/learning/strategy_optimizer.rb', line 188

def apply_optimizations(target, registry)
  results = {}

  case target
  when :prompts
    registry.each do |key, template|
      agent_type = extract_agent_type_from_key(key)
      next unless agent_type

      result = optimize_prompt_template(template, agent_type)
      results[key] = result

      if result[:optimized] && @auto_apply_optimizations
        # Logic to apply optimization to registry would go here
        @logger.info("Auto-applied optimized prompt for #{key}")
      end
    end

  when :parameters
    registry.each do |key, params|
      agent_type = extract_agent_type_from_key(key)
      next unless agent_type

      result = optimize_llm_parameters(params, agent_type)
      results[key] = result

      if result[:optimized] && @auto_apply_optimizations
        # Logic to apply optimization to registry would go here
        @logger.info("Auto-applied optimized parameters for #{key}")
      end
    end

  when :sequences
    registry.each do |key, sequence|
      plan_type = key.to_s

      result = optimize_task_sequence(sequence, plan_type)
      results[key] = result

      if result[:optimized] && @auto_apply_optimizations
        # Logic to apply optimization to registry would go here
        @logger.info("Auto-applied optimized sequence for #{key}")
      end
    end
  end

  results
end

#generate_performance_report(agent_type) ⇒ Hash

Generate a performance report for a specific agent type

Parameters:

  • agent_type (String)

    The agent type to report on

Returns:

  • (Hash)

    Performance report with metrics and optimization suggestions



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/agentic/learning/strategy_optimizer.rb', line 241

def generate_performance_report(agent_type)
  performance = @pattern_recognizer.analyze_agent_performance(agent_type)

  if performance[:insufficient_data]
    return {
      agent_type: agent_type,
      status: :insufficient_data,
      message: "Not enough execution data to generate a meaningful report"
    }
  end

  # Get recommendations
  recommendations = @pattern_recognizer.recommend_optimizations(agent_type)

  {
    agent_type: agent_type,
    status: :complete,
    timestamp: Time.now.iso8601,
    metrics: {
      success_rate: performance[:success_rate][:overall],
      trend: performance[:success_rate][:trend],
      sample_size: performance[:success_rate][:sample_size]
    },
    performance_trends: performance[:performance_trends],
    failure_patterns: performance[:failure_patterns],
    recommendations: recommendations
  }
end

#optimize_llm_parameters(original_params, agent_type, options = {}) ⇒ Hash

Optimize LLM parameters based on historical performance

Parameters:

  • original_params (Hash)

    The original LLM parameters

  • agent_type (String)

    The agent type using these parameters

  • options (Hash) (defaults to: {})

    Optimization options

Options Hash (options):

  • :force (Boolean)

    Force optimization even if recently optimized

  • :optimization_strategy (Symbol)

    Strategy to use (:conservative, :balanced, :aggressive)

Returns:

  • (Hash)

    Optimization result with improved parameters and explanation



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/agentic/learning/strategy_optimizer.rb', line 99

def optimize_llm_parameters(original_params, agent_type, options = {})
  cache_key = "params:#{agent_type}:#{Digest::MD5.hexdigest(original_params.to_s)}"

  # Check cache and optimization interval
  unless options[:force]
    if @optimization_cache[cache_key] &&
        @last_optimization[cache_key] &&
        @last_optimization[cache_key] > Time.now - (@optimization_interval_hours * 3600)
      return @optimization_cache[cache_key]
    end
  end

  # Get performance data
  performance = @pattern_recognizer.analyze_agent_performance(agent_type)

  if performance[:insufficient_data]
    @logger.info("Insufficient data to optimize LLM parameters for #{agent_type}")
    return {
      optimized: false,
      reason: "Insufficient performance data",
      original_params: original_params,
      improved_params: original_params.dup
    }
  end

  # Generate optimization
  optimization = generate_optimized_parameters(original_params, agent_type, performance, options)

  # Cache result
  @optimization_cache[cache_key] = optimization
  @last_optimization[cache_key] = Time.now

  optimization
end

#optimize_prompt_template(original_template, agent_type, options = {}) ⇒ Hash

Optimize a prompt template based on historical performance

Parameters:

  • original_template (String)

    The original prompt template

  • agent_type (String)

    The agent type using this prompt

  • options (Hash) (defaults to: {})

    Optimization options

Options Hash (options):

  • :force (Boolean)

    Force optimization even if recently optimized

  • :optimization_strategy (Symbol)

    Strategy to use (:conservative, :balanced, :aggressive)

  • :context (Hash)

    Additional context for optimization

Returns:

  • (Hash)

    Optimization result with improved template and explanation



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/agentic/learning/strategy_optimizer.rb', line 52

def optimize_prompt_template(original_template, agent_type, options = {})
  cache_key = "prompt:#{agent_type}:#{Digest::MD5.hexdigest(original_template)}"

  # Check cache and optimization interval
  unless options[:force]
    if @optimization_cache[cache_key] &&
        @last_optimization[cache_key] &&
        @last_optimization[cache_key] > Time.now - (@optimization_interval_hours * 3600)
      return @optimization_cache[cache_key]
    end
  end

  # Get performance data
  performance = @pattern_recognizer.analyze_agent_performance(agent_type)

  if performance[:insufficient_data]
    @logger.info("Insufficient data to optimize prompt for #{agent_type}")
    return {
      optimized: false,
      reason: "Insufficient performance data",
      original_template: original_template,
      improved_template: original_template
    }
  end

  # Generate optimization
  optimization = if @llm_client
    generate_optimized_prompt_with_llm(original_template, agent_type, performance, options)
  else
    generate_optimized_prompt_heuristic(original_template, agent_type, performance, options)
  end

  # Cache result
  @optimization_cache[cache_key] = optimization
  @last_optimization[cache_key] = Time.now

  optimization
end

#optimize_task_sequence(original_sequence, plan_type, options = {}) ⇒ Hash

Optimize task sequence based on historical performance

Parameters:

  • original_sequence (Array<Hash>)

    Original task sequence

  • plan_type (String)

    The type of plan

  • options (Hash) (defaults to: {})

    Optimization options

Options Hash (options):

  • :force (Boolean)

    Force optimization even if recently optimized

Returns:

  • (Hash)

    Optimization result with improved sequence and explanation



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/agentic/learning/strategy_optimizer.rb', line 141

def optimize_task_sequence(original_sequence, plan_type, options = {})
  cache_key = "sequence:#{plan_type}:#{Digest::MD5.hexdigest(original_sequence.to_s)}"

  # Check cache and optimization interval
  unless options[:force]
    if @optimization_cache[cache_key] &&
        @last_optimization[cache_key] &&
        @last_optimization[cache_key] > Time.now - (@optimization_interval_hours * 3600)
      return @optimization_cache[cache_key]
    end
  end

  # Get historical plan executions
  end_time = Time.now
  start_time = end_time - (30 * 24 * 60 * 60) # 30 days

  plan_history = @history_store.get_history(
    plan_id: plan_type,
    start_time: start_time,
    end_time: end_time
  )

  if plan_history.size < 5
    @logger.info("Insufficient data to optimize task sequence for #{plan_type}")
    return {
      optimized: false,
      reason: "Insufficient plan execution data",
      original_sequence: original_sequence,
      improved_sequence: original_sequence.dup
    }
  end

  # Generate optimization
  optimization = generate_optimized_sequence(original_sequence, plan_history, options)

  # Cache result
  @optimization_cache[cache_key] = optimization
  @last_optimization[cache_key] = Time.now

  optimization
end