Class: Legion::Extensions::Agentic::Learning::MetaLearning::Helpers::MetaLearningEngine

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb

Constant Summary

Constants included from Constants

Constants::DEFAULT_LEARNING_RATE, Constants::EFFICIENCY_LABELS, Constants::MAX_DOMAINS, Constants::MAX_EPISODES, Constants::MAX_STRATEGIES, Constants::PROFICIENCY_LABELS, Constants::RATE_BOOST, Constants::RATE_DECAY, Constants::STRATEGY_TYPES, Constants::TRANSFER_BONUS

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMetaLearningEngine

Returns a new instance of MetaLearningEngine.



14
15
16
17
18
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 14

def initialize
  @domains    = {}
  @strategies = {}
  @episodes   = []
end

Instance Attribute Details

#domainsObject (readonly)

Returns the value of attribute domains.



12
13
14
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 12

def domains
  @domains
end

#episodesObject (readonly)

Returns the value of attribute episodes.



12
13
14
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 12

def episodes
  @episodes
end

#strategiesObject (readonly)

Returns the value of attribute strategies.



12
13
14
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 12

def strategies
  @strategies
end

Instance Method Details

#adapt_ratesObject



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 120

def adapt_rates
  adapted = []
  @domains.each_value do |domain|
    next if domain.episodes_count.zero?

    if domain.efficiency >= 0.8
      domain.adapt_rate!(delta: RATE_BOOST)
      adapted << { domain: domain.name, direction: :boost, new_rate: domain.learning_rate }
    elsif domain.efficiency < 0.2
      domain.adapt_rate!(delta: -RATE_DECAY)
      adapted << { domain: domain.name, direction: :decay, new_rate: domain.learning_rate }
    end
  end
  { adapted: adapted, count: adapted.size }
end

#apply_transfer(source_domain_id:, target_domain_id:) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 79

def apply_transfer(source_domain_id:, target_domain_id:)
  source = @domains[source_domain_id]
  target = @domains[target_domain_id]
  return { error: :domain_not_found } unless source && target

  check = transfer_check(source_domain_id: source_domain_id, target_domain_id: target_domain_id)
  return { applied: false, reason: :not_eligible } unless check[:eligible]

  target.adapt_rate!(delta: TRANSFER_BONUS)
  { applied: true, target_domain: target.name, new_learning_rate: target.learning_rate }
end

#create_domain(name:, learning_rate: DEFAULT_LEARNING_RATE, related_domains: []) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 20

def create_domain(name:, learning_rate: DEFAULT_LEARNING_RATE, related_domains: [])
  return { error: :limit_reached } if @domains.size >= MAX_DOMAINS

  domain = LearningDomain.new(name: name, learning_rate: learning_rate, related_domains: related_domains)
  @domains[domain.id] = domain
  domain
end

#create_strategy(name:, strategy_type:) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 28

def create_strategy(name:, strategy_type:)
  return { error: :limit_reached } if @strategies.size >= MAX_STRATEGIES
  return { error: :invalid_strategy_type } unless STRATEGY_TYPES.include?(strategy_type)

  strategy = Strategy.new(name: name, strategy_type: strategy_type)
  @strategies[strategy.id] = strategy
  strategy
end

#domain_ranking(limit: 10) ⇒ Object



91
92
93
94
95
96
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 91

def domain_ranking(limit: 10)
  @domains.values
          .sort_by { |d| -d.proficiency }
          .first(limit)
          .map(&:to_h)
end

#learning_curve(domain_id:) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 112

def learning_curve(domain_id:)
  domain = @domains[domain_id]
  return { error: :domain_not_found } unless domain

  domain_episodes = @episodes.select { |e| e[:domain_id] == domain_id }
  { domain: domain.name, curve: domain_episodes }
end

#overall_efficiencyObject



105
106
107
108
109
110
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 105

def overall_efficiency
  return 0.0 if @domains.empty?

  total = @domains.values.sum(&:efficiency)
  (total / @domains.size).round(10)
end

#prune_stale_domains(min_episodes: 1) ⇒ Object



136
137
138
139
140
141
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 136

def prune_stale_domains(min_episodes: 1)
  before = @domains.size
  @domains.reject! { |_, d| d.episodes_count < min_episodes }
  pruned = before - @domains.size
  { pruned: pruned, remaining: @domains.size }
end

#recommend_strategy(domain_id:) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 60

def recommend_strategy(domain_id:)
  domain = @domains[domain_id]
  return { error: :domain_not_found } unless domain

  candidate = best_strategy_for_domain(domain)
  return { recommendation: nil, reason: :no_data } if candidate.nil?

  { recommendation: candidate.name, strategy_id: candidate.id, success_rate: candidate.success_rate }
end

#record_episode(domain_id:, success:, strategy_id: nil) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 37

def record_episode(domain_id:, success:, strategy_id: nil)
  domain = @domains[domain_id]
  return { error: :domain_not_found } unless domain

  success ? domain.record_success! : domain.record_failure!

  strategy = @strategies[strategy_id] if strategy_id
  strategy&.use!(success: success, domain_name: domain.name)

  if strategy && success
    current_preferred_rate = preferred_strategy_rate_for(domain)
    domain.preferred_strategy = strategy.name if strategy.success_rate > current_preferred_rate
  end

  episode = build_episode(domain, strategy_id, success)
  @episodes << episode
  @episodes.shift while @episodes.size > MAX_EPISODES

  check_transfer_opportunities(domain)

  episode
end

#strategy_ranking(limit: 10) ⇒ Object



98
99
100
101
102
103
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 98

def strategy_ranking(limit: 10)
  @strategies.values
             .sort_by { |s| -s.success_rate }
             .first(limit)
             .map(&:to_h)
end

#to_hObject



143
144
145
146
147
148
149
150
151
152
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 143

def to_h
  {
    domain_count:       @domains.size,
    strategy_count:     @strategies.size,
    episode_count:      @episodes.size,
    overall_efficiency: overall_efficiency,
    top_domain:         @domains.values.max_by(&:proficiency)&.name,
    top_strategy:       @strategies.values.max_by(&:success_rate)&.name
  }
end

#transfer_check(source_domain_id:, target_domain_id:) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb', line 70

def transfer_check(source_domain_id:, target_domain_id:)
  source = @domains[source_domain_id]
  target = @domains[target_domain_id]
  return { error: :domain_not_found } unless source && target

  eligible = source.proficiency >= 0.6 && target.related_domains.include?(source.name)
  { eligible: eligible, source_proficiency: source.proficiency, target_domain: target.name }
end