lex-agentic-learning 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +13 -0
- data/lex-agentic-learning.gemspec +30 -0
- data/lib/legion/extensions/agentic/learning/anchoring/client.rb +26 -0
- data/lib/legion/extensions/agentic/learning/anchoring/helpers/anchor.rb +65 -0
- data/lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb +132 -0
- data/lib/legion/extensions/agentic/learning/anchoring/helpers/constants.rb +31 -0
- data/lib/legion/extensions/agentic/learning/anchoring/runners/anchoring.rb +100 -0
- data/lib/legion/extensions/agentic/learning/anchoring/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/anchoring.rb +19 -0
- data/lib/legion/extensions/agentic/learning/catalyst/client.rb +15 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/catalyst.rb +87 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/catalyst_engine.rb +153 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/constants.rb +55 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/reaction.rb +87 -0
- data/lib/legion/extensions/agentic/learning/catalyst/runners/cognitive_catalyst.rb +103 -0
- data/lib/legion/extensions/agentic/learning/catalyst/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/catalyst.rb +22 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/client.rb +22 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis.rb +137 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/cocoon.rb +89 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/constants.rb +49 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/metamorphosis_engine.rb +157 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/runners/cognitive_chrysalis.rb +129 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/chrysalis.rb +21 -0
- data/lib/legion/extensions/agentic/learning/curiosity/client.rb +28 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/constants.rb +30 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/gap_detector.rb +167 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/wonder.rb +73 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/wonder_store.rb +149 -0
- data/lib/legion/extensions/agentic/learning/curiosity/runners/curiosity.rb +163 -0
- data/lib/legion/extensions/agentic/learning/curiosity/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/curiosity.rb +21 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/client.rb +28 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/constants.rb +31 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/curiosity_engine.rb +122 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/knowledge_gap.rb +70 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/runners/epistemic_curiosity.rb +106 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity.rb +19 -0
- data/lib/legion/extensions/agentic/learning/fermentation/client.rb +19 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/batch.rb +75 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/constants.rb +78 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/fermentation_engine.rb +147 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/substrate.rb +108 -0
- data/lib/legion/extensions/agentic/learning/fermentation/runners/cognitive_fermentation.rb +60 -0
- data/lib/legion/extensions/agentic/learning/fermentation/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/fermentation.rb +22 -0
- data/lib/legion/extensions/agentic/learning/habit/client.rb +26 -0
- data/lib/legion/extensions/agentic/learning/habit/helpers/action_sequence.rb +120 -0
- data/lib/legion/extensions/agentic/learning/habit/helpers/constants.rb +44 -0
- data/lib/legion/extensions/agentic/learning/habit/helpers/habit_store.rb +148 -0
- data/lib/legion/extensions/agentic/learning/habit/runners/habit.rb +86 -0
- data/lib/legion/extensions/agentic/learning/habit/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/habit.rb +19 -0
- data/lib/legion/extensions/agentic/learning/hebbian/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/learning/hebbian/client.rb +29 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/assembly.rb +82 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/assembly_network.rb +190 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/constants.rb +50 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/unit.rb +94 -0
- data/lib/legion/extensions/agentic/learning/hebbian/runners/hebbian_assembly.rb +94 -0
- data/lib/legion/extensions/agentic/learning/hebbian/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/hebbian.rb +20 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/client.rb +25 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/helpers/constants.rb +35 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/helpers/rate_model.rb +133 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/runners/learning_rate.rb +85 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/learning_rate.rb +18 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/client.rb +27 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/constants.rb +46 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/learning_domain.rb +85 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb +202 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/strategy.rb +62 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/runners/meta_learning.rb +118 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/meta_learning.rb +20 -0
- data/lib/legion/extensions/agentic/learning/plasticity/client.rb +15 -0
- data/lib/legion/extensions/agentic/learning/plasticity/helpers/constants.rb +45 -0
- data/lib/legion/extensions/agentic/learning/plasticity/helpers/neural_pathway.rb +85 -0
- data/lib/legion/extensions/agentic/learning/plasticity/helpers/plasticity_engine.rb +130 -0
- data/lib/legion/extensions/agentic/learning/plasticity/runners/cognitive_plasticity.rb +85 -0
- data/lib/legion/extensions/agentic/learning/plasticity/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/plasticity.rb +19 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/client.rb +28 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/helpers/constants.rb +35 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/helpers/option.rb +78 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/helpers/preference_engine.rb +121 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/runners/preference_learning.rb +84 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/preference_learning.rb +19 -0
- data/lib/legion/extensions/agentic/learning/procedural/client.rb +19 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/constants.rb +46 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/learning_engine.rb +160 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/production.rb +66 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/skill.rb +101 -0
- data/lib/legion/extensions/agentic/learning/procedural/runners/procedural_learning.rb +96 -0
- data/lib/legion/extensions/agentic/learning/procedural/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/procedural.rb +20 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/client.rb +26 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/helpers/constants.rb +42 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/helpers/scaffold.rb +136 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine.rb +112 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding.rb +107 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/scaffolding.rb +19 -0
- data/lib/legion/extensions/agentic/learning/version.rb +11 -0
- data/lib/legion/extensions/agentic/learning.rb +31 -0
- data/spec/legion/extensions/agentic/learning/anchoring/client_spec.rb +32 -0
- data/spec/legion/extensions/agentic/learning/anchoring/helpers/anchor_spec.rb +130 -0
- data/spec/legion/extensions/agentic/learning/anchoring/helpers/anchor_store_spec.rb +201 -0
- data/spec/legion/extensions/agentic/learning/anchoring/helpers/constants_spec.rb +63 -0
- data/spec/legion/extensions/agentic/learning/anchoring/runners/anchoring_spec.rb +199 -0
- data/spec/legion/extensions/agentic/learning/catalyst/client_spec.rb +58 -0
- data/spec/legion/extensions/agentic/learning/catalyst/cognitive_catalyst_spec.rb +49 -0
- data/spec/legion/extensions/agentic/learning/catalyst/helpers/catalyst_engine_spec.rb +263 -0
- data/spec/legion/extensions/agentic/learning/catalyst/helpers/catalyst_spec.rb +214 -0
- data/spec/legion/extensions/agentic/learning/catalyst/helpers/reaction_spec.rb +223 -0
- data/spec/legion/extensions/agentic/learning/catalyst/runners/cognitive_catalyst_spec.rb +217 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/client_spec.rb +83 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/cognitive_chrysalis_spec.rb +15 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis_engine_spec.rb +57 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis_spec.rb +305 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/cocoon_spec.rb +206 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/constants_spec.rb +109 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/metamorphic_cycle_spec.rb +76 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/metamorphosis_engine_spec.rb +247 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/transformation_phase_spec.rb +98 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/runners/cognitive_chrysalis_spec.rb +180 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/runners/reporting_spec.rb +81 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/runners/transformation_spec.rb +74 -0
- data/spec/legion/extensions/agentic/learning/curiosity/client_spec.rb +27 -0
- data/spec/legion/extensions/agentic/learning/curiosity/helpers/gap_detector_spec.rb +118 -0
- data/spec/legion/extensions/agentic/learning/curiosity/helpers/wonder_spec.rb +130 -0
- data/spec/legion/extensions/agentic/learning/curiosity/helpers/wonder_store_spec.rb +136 -0
- data/spec/legion/extensions/agentic/learning/curiosity/runners/curiosity_spec.rb +159 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/client_spec.rb +47 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/constants_spec.rb +45 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/curiosity_engine_spec.rb +229 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/knowledge_gap_spec.rb +188 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/runners/epistemic_curiosity_spec.rb +175 -0
- data/spec/legion/extensions/agentic/learning/fermentation/client_spec.rb +36 -0
- data/spec/legion/extensions/agentic/learning/fermentation/helpers/batch_spec.rb +72 -0
- data/spec/legion/extensions/agentic/learning/fermentation/helpers/fermentation_engine_spec.rb +138 -0
- data/spec/legion/extensions/agentic/learning/fermentation/helpers/substrate_spec.rb +146 -0
- data/spec/legion/extensions/agentic/learning/habit/client_spec.rb +50 -0
- data/spec/legion/extensions/agentic/learning/habit/helpers/action_sequence_spec.rb +276 -0
- data/spec/legion/extensions/agentic/learning/habit/helpers/constants_spec.rb +115 -0
- data/spec/legion/extensions/agentic/learning/habit/helpers/habit_store_spec.rb +274 -0
- data/spec/legion/extensions/agentic/learning/habit/runners/habit_spec.rb +228 -0
- data/spec/legion/extensions/agentic/learning/hebbian/client_spec.rb +38 -0
- data/spec/legion/extensions/agentic/learning/hebbian/helpers/assembly_network_spec.rb +142 -0
- data/spec/legion/extensions/agentic/learning/hebbian/helpers/assembly_spec.rb +89 -0
- data/spec/legion/extensions/agentic/learning/hebbian/helpers/unit_spec.rb +119 -0
- data/spec/legion/extensions/agentic/learning/hebbian/runners/hebbian_assembly_spec.rb +109 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/client_spec.rb +51 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/helpers/constants_spec.rb +29 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/helpers/rate_model_spec.rb +151 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/runners/learning_rate_spec.rb +92 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/client_spec.rb +27 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/constants_spec.rb +43 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/learning_domain_spec.rb +146 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine_spec.rb +309 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/strategy_spec.rb +82 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/runners/meta_learning_spec.rb +185 -0
- data/spec/legion/extensions/agentic/learning/plasticity/helpers/constants_spec.rb +54 -0
- data/spec/legion/extensions/agentic/learning/plasticity/helpers/neural_pathway_spec.rb +136 -0
- data/spec/legion/extensions/agentic/learning/plasticity/helpers/plasticity_engine_spec.rb +157 -0
- data/spec/legion/extensions/agentic/learning/plasticity/runners/cognitive_plasticity_spec.rb +83 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/client_spec.rb +17 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/helpers/constants_spec.rb +67 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/helpers/option_spec.rb +104 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/helpers/preference_engine_spec.rb +151 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/runners/preference_learning_spec.rb +86 -0
- data/spec/legion/extensions/agentic/learning/procedural/client_spec.rb +22 -0
- data/spec/legion/extensions/agentic/learning/procedural/helpers/learning_engine_spec.rb +135 -0
- data/spec/legion/extensions/agentic/learning/procedural/helpers/production_spec.rb +66 -0
- data/spec/legion/extensions/agentic/learning/procedural/helpers/skill_spec.rb +102 -0
- data/spec/legion/extensions/agentic/learning/procedural/runners/procedural_learning_spec.rb +94 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/helpers/constants_spec.rb +36 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/helpers/scaffold_spec.rb +187 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine_spec.rb +159 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding_spec.rb +163 -0
- data/spec/spec_helper.rb +46 -0
- metadata +277 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module LearningRate
|
|
8
|
+
module Runners
|
|
9
|
+
module LearningRate
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def record_prediction(correct:, domain: :general, **)
|
|
14
|
+
rate_model.record_prediction(domain: domain, correct: correct)
|
|
15
|
+
rate = rate_model.rate_for(domain)
|
|
16
|
+
accuracy = rate_model.accuracy_for(domain)
|
|
17
|
+
Legion::Logging.debug "[learning_rate] prediction: domain=#{domain} correct=#{correct} rate=#{rate.round(3)} accuracy=#{accuracy.round(3)}"
|
|
18
|
+
{
|
|
19
|
+
success: true,
|
|
20
|
+
domain: domain,
|
|
21
|
+
rate: rate,
|
|
22
|
+
accuracy: accuracy,
|
|
23
|
+
label: rate_model.label_for(domain)
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def record_surprise(magnitude:, domain: :general, **)
|
|
28
|
+
rate_model.record_surprise(domain: domain, magnitude: magnitude)
|
|
29
|
+
rate = rate_model.rate_for(domain)
|
|
30
|
+
Legion::Logging.debug "[learning_rate] surprise: domain=#{domain} magnitude=#{magnitude.round(3)} rate=#{rate.round(3)}"
|
|
31
|
+
{ success: true, domain: domain, rate: rate, label: rate_model.label_for(domain) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def record_error(magnitude:, domain: :general, **)
|
|
35
|
+
rate_model.record_error(domain: domain, magnitude: magnitude)
|
|
36
|
+
rate = rate_model.rate_for(domain)
|
|
37
|
+
Legion::Logging.debug "[learning_rate] error: domain=#{domain} magnitude=#{magnitude.round(3)} rate=#{rate.round(3)}"
|
|
38
|
+
{ success: true, domain: domain, rate: rate, label: rate_model.label_for(domain) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def current_rate(domain: :general, **)
|
|
42
|
+
rate = rate_model.rate_for(domain)
|
|
43
|
+
accuracy = rate_model.accuracy_for(domain)
|
|
44
|
+
{
|
|
45
|
+
success: true,
|
|
46
|
+
domain: domain,
|
|
47
|
+
rate: rate,
|
|
48
|
+
accuracy: accuracy,
|
|
49
|
+
label: rate_model.label_for(domain)
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def fastest_domains(count: 5, **)
|
|
54
|
+
domains = rate_model.fastest_domains(count)
|
|
55
|
+
{ success: true, domains: domains, count: domains.size }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def slowest_domains(count: 5, **)
|
|
59
|
+
domains = rate_model.slowest_domains(count)
|
|
60
|
+
{ success: true, domains: domains, count: domains.size }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def update_learning_rate(**)
|
|
64
|
+
rate_model.decay
|
|
65
|
+
overall = rate_model.overall_rate
|
|
66
|
+
Legion::Logging.debug "[learning_rate] tick: domains=#{rate_model.domain_count} overall=#{overall.round(3)}"
|
|
67
|
+
{ success: true, domain_count: rate_model.domain_count, overall_rate: overall }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def learning_rate_stats(**)
|
|
71
|
+
{ success: true, stats: rate_model.to_h }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def rate_model
|
|
77
|
+
@rate_model ||= Helpers::RateModel.new
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/learning/learning_rate/version'
|
|
4
|
+
require 'legion/extensions/agentic/learning/learning_rate/helpers/constants'
|
|
5
|
+
require 'legion/extensions/agentic/learning/learning_rate/helpers/rate_model'
|
|
6
|
+
require 'legion/extensions/agentic/learning/learning_rate/runners/learning_rate'
|
|
7
|
+
require 'legion/extensions/agentic/learning/learning_rate/client'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module Agentic
|
|
12
|
+
module Learning
|
|
13
|
+
module LearningRate
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/learning/meta_learning/helpers/constants'
|
|
4
|
+
require 'legion/extensions/agentic/learning/meta_learning/helpers/learning_domain'
|
|
5
|
+
require 'legion/extensions/agentic/learning/meta_learning/helpers/strategy'
|
|
6
|
+
require 'legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine'
|
|
7
|
+
require 'legion/extensions/agentic/learning/meta_learning/runners/meta_learning'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module Agentic
|
|
12
|
+
module Learning
|
|
13
|
+
module MetaLearning
|
|
14
|
+
class Client
|
|
15
|
+
include Runners::MetaLearning
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def engine
|
|
20
|
+
@engine ||= Helpers::MetaLearningEngine.new
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module MetaLearning
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
MAX_DOMAINS = 100
|
|
11
|
+
MAX_STRATEGIES = 50
|
|
12
|
+
MAX_EPISODES = 1000
|
|
13
|
+
|
|
14
|
+
DEFAULT_LEARNING_RATE = 0.1
|
|
15
|
+
RATE_BOOST = 0.02
|
|
16
|
+
RATE_DECAY = 0.01
|
|
17
|
+
TRANSFER_BONUS = 0.05
|
|
18
|
+
|
|
19
|
+
PROFICIENCY_LABELS = {
|
|
20
|
+
(0.8..) => :expert,
|
|
21
|
+
(0.6...0.8) => :proficient,
|
|
22
|
+
(0.4...0.6) => :intermediate,
|
|
23
|
+
(0.2...0.4) => :novice,
|
|
24
|
+
(..0.2) => :beginner
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
EFFICIENCY_LABELS = {
|
|
28
|
+
(0.8..) => :highly_efficient,
|
|
29
|
+
(0.6...0.8) => :efficient,
|
|
30
|
+
(0.4...0.6) => :moderate,
|
|
31
|
+
(0.2...0.4) => :slow,
|
|
32
|
+
(..0.2) => :struggling
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
STRATEGY_TYPES = %i[
|
|
36
|
+
repetition elaboration analogy decomposition
|
|
37
|
+
pattern_matching trial_and_error observation
|
|
38
|
+
interleaving spaced_practice retrieval_practice
|
|
39
|
+
].freeze
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Learning
|
|
9
|
+
module MetaLearning
|
|
10
|
+
module Helpers
|
|
11
|
+
class LearningDomain
|
|
12
|
+
include Constants
|
|
13
|
+
|
|
14
|
+
attr_accessor :preferred_strategy
|
|
15
|
+
attr_reader :id, :name, :proficiency, :learning_rate, :episodes_count, :successes, :failures, :related_domains, :created_at
|
|
16
|
+
|
|
17
|
+
def initialize(name:, learning_rate: DEFAULT_LEARNING_RATE, related_domains: [])
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@name = name
|
|
20
|
+
@proficiency = 0.0
|
|
21
|
+
@learning_rate = learning_rate.clamp(0.001, 1.0)
|
|
22
|
+
@episodes_count = 0
|
|
23
|
+
@successes = 0
|
|
24
|
+
@failures = 0
|
|
25
|
+
@preferred_strategy = nil
|
|
26
|
+
@related_domains = Array(related_domains).dup
|
|
27
|
+
@created_at = Time.now.utc
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def record_success!
|
|
31
|
+
@successes += 1
|
|
32
|
+
@episodes_count += 1
|
|
33
|
+
@proficiency = (@proficiency + @learning_rate).clamp(0.0, 1.0).round(10)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def record_failure!
|
|
37
|
+
@failures += 1
|
|
38
|
+
@episodes_count += 1
|
|
39
|
+
penalty = (@learning_rate * 0.5).round(10)
|
|
40
|
+
@proficiency = (@proficiency - penalty).clamp(0.0, 1.0).round(10)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def efficiency
|
|
44
|
+
total = @successes + @failures
|
|
45
|
+
return 0.0 if total.zero?
|
|
46
|
+
|
|
47
|
+
(@successes.to_f / total).round(10)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def efficiency_label
|
|
51
|
+
EFFICIENCY_LABELS.find { |range, _| range.cover?(efficiency) }&.last || :struggling
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def proficiency_label
|
|
55
|
+
PROFICIENCY_LABELS.find { |range, _| range.cover?(@proficiency) }&.last || :beginner
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def adapt_rate!(delta:)
|
|
59
|
+
@learning_rate = (@learning_rate + delta).clamp(0.001, 1.0).round(10)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def to_h
|
|
63
|
+
{
|
|
64
|
+
id: @id,
|
|
65
|
+
name: @name,
|
|
66
|
+
proficiency: @proficiency,
|
|
67
|
+
proficiency_label: proficiency_label,
|
|
68
|
+
learning_rate: @learning_rate,
|
|
69
|
+
episodes_count: @episodes_count,
|
|
70
|
+
successes: @successes,
|
|
71
|
+
failures: @failures,
|
|
72
|
+
efficiency: efficiency,
|
|
73
|
+
efficiency_label: efficiency_label,
|
|
74
|
+
preferred_strategy: @preferred_strategy,
|
|
75
|
+
related_domains: @related_domains,
|
|
76
|
+
created_at: @created_at
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module MetaLearning
|
|
8
|
+
module Helpers
|
|
9
|
+
class MetaLearningEngine
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :domains, :strategies, :episodes
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@domains = {}
|
|
16
|
+
@strategies = {}
|
|
17
|
+
@episodes = []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_domain(name:, learning_rate: DEFAULT_LEARNING_RATE, related_domains: [])
|
|
21
|
+
return { error: :limit_reached } if @domains.size >= MAX_DOMAINS
|
|
22
|
+
|
|
23
|
+
domain = LearningDomain.new(name: name, learning_rate: learning_rate, related_domains: related_domains)
|
|
24
|
+
@domains[domain.id] = domain
|
|
25
|
+
domain
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create_strategy(name:, strategy_type:)
|
|
29
|
+
return { error: :limit_reached } if @strategies.size >= MAX_STRATEGIES
|
|
30
|
+
return { error: :invalid_strategy_type } unless STRATEGY_TYPES.include?(strategy_type)
|
|
31
|
+
|
|
32
|
+
strategy = Strategy.new(name: name, strategy_type: strategy_type)
|
|
33
|
+
@strategies[strategy.id] = strategy
|
|
34
|
+
strategy
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def record_episode(domain_id:, success:, strategy_id: nil)
|
|
38
|
+
domain = @domains[domain_id]
|
|
39
|
+
return { error: :domain_not_found } unless domain
|
|
40
|
+
|
|
41
|
+
success ? domain.record_success! : domain.record_failure!
|
|
42
|
+
|
|
43
|
+
strategy = @strategies[strategy_id] if strategy_id
|
|
44
|
+
strategy&.use!(success: success, domain_name: domain.name)
|
|
45
|
+
|
|
46
|
+
if strategy && success
|
|
47
|
+
current_preferred_rate = preferred_strategy_rate_for(domain)
|
|
48
|
+
domain.preferred_strategy = strategy.name if strategy.success_rate > current_preferred_rate
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
episode = build_episode(domain, strategy_id, success)
|
|
52
|
+
@episodes << episode
|
|
53
|
+
@episodes.shift while @episodes.size > MAX_EPISODES
|
|
54
|
+
|
|
55
|
+
check_transfer_opportunities(domain)
|
|
56
|
+
|
|
57
|
+
episode
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def recommend_strategy(domain_id:)
|
|
61
|
+
domain = @domains[domain_id]
|
|
62
|
+
return { error: :domain_not_found } unless domain
|
|
63
|
+
|
|
64
|
+
candidate = best_strategy_for_domain(domain)
|
|
65
|
+
return { recommendation: nil, reason: :no_data } if candidate.nil?
|
|
66
|
+
|
|
67
|
+
{ recommendation: candidate.name, strategy_id: candidate.id, success_rate: candidate.success_rate }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def transfer_check(source_domain_id:, target_domain_id:)
|
|
71
|
+
source = @domains[source_domain_id]
|
|
72
|
+
target = @domains[target_domain_id]
|
|
73
|
+
return { error: :domain_not_found } unless source && target
|
|
74
|
+
|
|
75
|
+
eligible = source.proficiency >= 0.6 && target.related_domains.include?(source.name)
|
|
76
|
+
{ eligible: eligible, source_proficiency: source.proficiency, target_domain: target.name }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def apply_transfer(source_domain_id:, target_domain_id:)
|
|
80
|
+
source = @domains[source_domain_id]
|
|
81
|
+
target = @domains[target_domain_id]
|
|
82
|
+
return { error: :domain_not_found } unless source && target
|
|
83
|
+
|
|
84
|
+
check = transfer_check(source_domain_id: source_domain_id, target_domain_id: target_domain_id)
|
|
85
|
+
return { applied: false, reason: :not_eligible } unless check[:eligible]
|
|
86
|
+
|
|
87
|
+
target.adapt_rate!(delta: TRANSFER_BONUS)
|
|
88
|
+
{ applied: true, target_domain: target.name, new_learning_rate: target.learning_rate }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def domain_ranking(limit: 10)
|
|
92
|
+
@domains.values
|
|
93
|
+
.sort_by { |d| -d.proficiency }
|
|
94
|
+
.first(limit)
|
|
95
|
+
.map(&:to_h)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def strategy_ranking(limit: 10)
|
|
99
|
+
@strategies.values
|
|
100
|
+
.sort_by { |s| -s.success_rate }
|
|
101
|
+
.first(limit)
|
|
102
|
+
.map(&:to_h)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def overall_efficiency
|
|
106
|
+
return 0.0 if @domains.empty?
|
|
107
|
+
|
|
108
|
+
total = @domains.values.sum(&:efficiency)
|
|
109
|
+
(total / @domains.size).round(10)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def learning_curve(domain_id:)
|
|
113
|
+
domain = @domains[domain_id]
|
|
114
|
+
return { error: :domain_not_found } unless domain
|
|
115
|
+
|
|
116
|
+
domain_episodes = @episodes.select { |e| e[:domain_id] == domain_id }
|
|
117
|
+
{ domain: domain.name, curve: domain_episodes }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def adapt_rates
|
|
121
|
+
adapted = []
|
|
122
|
+
@domains.each_value do |domain|
|
|
123
|
+
next if domain.episodes_count.zero?
|
|
124
|
+
|
|
125
|
+
if domain.efficiency >= 0.8
|
|
126
|
+
domain.adapt_rate!(delta: RATE_BOOST)
|
|
127
|
+
adapted << { domain: domain.name, direction: :boost, new_rate: domain.learning_rate }
|
|
128
|
+
elsif domain.efficiency < 0.2
|
|
129
|
+
domain.adapt_rate!(delta: -RATE_DECAY)
|
|
130
|
+
adapted << { domain: domain.name, direction: :decay, new_rate: domain.learning_rate }
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
{ adapted: adapted, count: adapted.size }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def prune_stale_domains(min_episodes: 1)
|
|
137
|
+
before = @domains.size
|
|
138
|
+
@domains.reject! { |_, d| d.episodes_count < min_episodes }
|
|
139
|
+
pruned = before - @domains.size
|
|
140
|
+
{ pruned: pruned, remaining: @domains.size }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def to_h
|
|
144
|
+
{
|
|
145
|
+
domain_count: @domains.size,
|
|
146
|
+
strategy_count: @strategies.size,
|
|
147
|
+
episode_count: @episodes.size,
|
|
148
|
+
overall_efficiency: overall_efficiency,
|
|
149
|
+
top_domain: @domains.values.max_by(&:proficiency)&.name,
|
|
150
|
+
top_strategy: @strategies.values.max_by(&:success_rate)&.name
|
|
151
|
+
}
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
def build_episode(domain, strategy_id, success)
|
|
157
|
+
{
|
|
158
|
+
id: SecureRandom.uuid,
|
|
159
|
+
domain_id: domain.id,
|
|
160
|
+
domain_name: domain.name,
|
|
161
|
+
strategy_id: strategy_id,
|
|
162
|
+
success: success,
|
|
163
|
+
proficiency: domain.proficiency,
|
|
164
|
+
recorded_at: Time.now.utc
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def preferred_strategy_rate_for(domain)
|
|
169
|
+
return 0.0 unless domain.preferred_strategy
|
|
170
|
+
|
|
171
|
+
strategy = @strategies.values.find { |s| s.name == domain.preferred_strategy }
|
|
172
|
+
strategy&.success_rate || 0.0
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def best_strategy_for_domain(domain)
|
|
176
|
+
direct = strategies_used_in_domain(domain.name)
|
|
177
|
+
return direct.max_by(&:success_rate) if direct.any?
|
|
178
|
+
|
|
179
|
+
related_strategies = domain.related_domains.flat_map { |rname| strategies_used_in_domain(rname) }.uniq
|
|
180
|
+
related_strategies.max_by(&:success_rate)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def strategies_used_in_domain(domain_name)
|
|
184
|
+
@strategies.values.select { |s| s.domains_used.include?(domain_name) }
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def check_transfer_opportunities(domain)
|
|
188
|
+
@domains.each_value do |target|
|
|
189
|
+
next if target.id == domain.id
|
|
190
|
+
next unless target.related_domains.include?(domain.name)
|
|
191
|
+
|
|
192
|
+
check = transfer_check(source_domain_id: domain.id, target_domain_id: target.id)
|
|
193
|
+
apply_transfer(source_domain_id: domain.id, target_domain_id: target.id) if check[:eligible]
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Learning
|
|
9
|
+
module MetaLearning
|
|
10
|
+
module Helpers
|
|
11
|
+
class Strategy
|
|
12
|
+
include Constants
|
|
13
|
+
|
|
14
|
+
attr_reader :id, :name, :strategy_type, :usage_count,
|
|
15
|
+
:success_count, :domains_used, :created_at
|
|
16
|
+
|
|
17
|
+
def initialize(name:, strategy_type:)
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@name = name
|
|
20
|
+
@strategy_type = strategy_type
|
|
21
|
+
@usage_count = 0
|
|
22
|
+
@success_count = 0
|
|
23
|
+
@domains_used = []
|
|
24
|
+
@created_at = Time.now.utc
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def use!(success:, domain_name: nil)
|
|
28
|
+
@usage_count += 1
|
|
29
|
+
@success_count += 1 if success
|
|
30
|
+
@domains_used << domain_name if domain_name && !@domains_used.include?(domain_name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def success_rate
|
|
34
|
+
return 0.0 if @usage_count.zero?
|
|
35
|
+
|
|
36
|
+
(@success_count.to_f / @usage_count).round(10)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def versatility
|
|
40
|
+
@domains_used.uniq.size
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def to_h
|
|
44
|
+
{
|
|
45
|
+
id: @id,
|
|
46
|
+
name: @name,
|
|
47
|
+
strategy_type: @strategy_type,
|
|
48
|
+
usage_count: @usage_count,
|
|
49
|
+
success_count: @success_count,
|
|
50
|
+
success_rate: success_rate,
|
|
51
|
+
versatility: versatility,
|
|
52
|
+
domains_used: @domains_used,
|
|
53
|
+
created_at: @created_at
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module MetaLearning
|
|
8
|
+
module Runners
|
|
9
|
+
module MetaLearning
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def create_learning_domain(name:, learning_rate: Helpers::Constants::DEFAULT_LEARNING_RATE,
|
|
14
|
+
related_domains: [], **)
|
|
15
|
+
result = engine.create_domain(name: name, learning_rate: learning_rate, related_domains: related_domains)
|
|
16
|
+
if result.is_a?(Hash) && result[:error]
|
|
17
|
+
Legion::Logging.warn "[meta_learning] create_domain failed: #{result[:error]}"
|
|
18
|
+
return result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Legion::Logging.debug "[meta_learning] domain created: #{result.name} id=#{result.id[0..7]}"
|
|
22
|
+
result.to_h
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def register_learning_strategy(name:, strategy_type:, **)
|
|
26
|
+
result = engine.create_strategy(name: name, strategy_type: strategy_type)
|
|
27
|
+
if result.is_a?(Hash) && result[:error]
|
|
28
|
+
Legion::Logging.warn "[meta_learning] create_strategy failed: #{result[:error]}"
|
|
29
|
+
return result
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Legion::Logging.debug "[meta_learning] strategy registered: #{result.name} type=#{result.strategy_type}"
|
|
33
|
+
result.to_h
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def record_learning_episode(domain_id:, success:, strategy_id: nil, **)
|
|
37
|
+
result = engine.record_episode(domain_id: domain_id, strategy_id: strategy_id, success: success)
|
|
38
|
+
if result.is_a?(Hash) && result[:error]
|
|
39
|
+
Legion::Logging.warn "[meta_learning] record_episode failed: #{result[:error]}"
|
|
40
|
+
return result
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Legion::Logging.debug "[meta_learning] episode recorded domain=#{result[:domain_name]} " \
|
|
44
|
+
"success=#{success} proficiency=#{result[:proficiency].round(4)}"
|
|
45
|
+
result
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def recommend_learning_strategy(domain_id:, **)
|
|
49
|
+
result = engine.recommend_strategy(domain_id: domain_id)
|
|
50
|
+
Legion::Logging.debug "[meta_learning] strategy recommendation domain=#{domain_id[0..7]} " \
|
|
51
|
+
"recommendation=#{result[:recommendation]}"
|
|
52
|
+
result
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def check_transfer_learning(source_domain_id:, target_domain_id:, **)
|
|
56
|
+
result = engine.transfer_check(source_domain_id: source_domain_id, target_domain_id: target_domain_id)
|
|
57
|
+
Legion::Logging.debug "[meta_learning] transfer check eligible=#{result[:eligible]}"
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def apply_transfer_bonus(source_domain_id:, target_domain_id:, **)
|
|
62
|
+
result = engine.apply_transfer(source_domain_id: source_domain_id, target_domain_id: target_domain_id)
|
|
63
|
+
Legion::Logging.info "[meta_learning] transfer applied=#{result[:applied]}"
|
|
64
|
+
result
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def learning_domain_ranking(limit: 10, **)
|
|
68
|
+
ranking = engine.domain_ranking(limit: limit)
|
|
69
|
+
Legion::Logging.debug "[meta_learning] domain ranking returned #{ranking.size} domains"
|
|
70
|
+
{ ranking: ranking, count: ranking.size }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def learning_strategy_ranking(limit: 10, **)
|
|
74
|
+
ranking = engine.strategy_ranking(limit: limit)
|
|
75
|
+
Legion::Logging.debug "[meta_learning] strategy ranking returned #{ranking.size} strategies"
|
|
76
|
+
{ ranking: ranking, count: ranking.size }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def learning_curve_report(domain_id:, **)
|
|
80
|
+
result = engine.learning_curve(domain_id: domain_id)
|
|
81
|
+
if result.is_a?(Hash) && result[:error]
|
|
82
|
+
Legion::Logging.warn "[meta_learning] learning_curve failed: #{result[:error]}"
|
|
83
|
+
return result
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
Legion::Logging.debug "[meta_learning] learning curve domain=#{result[:domain]} " \
|
|
87
|
+
"episodes=#{result[:curve].size}"
|
|
88
|
+
result
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def update_meta_learning(**)
|
|
92
|
+
adapt_result = engine.adapt_rates
|
|
93
|
+
prune_result = engine.prune_stale_domains
|
|
94
|
+
stats = engine.to_h
|
|
95
|
+
Legion::Logging.info "[meta_learning] update: adapted=#{adapt_result[:count]} " \
|
|
96
|
+
"pruned=#{prune_result[:pruned]} domains=#{stats[:domain_count]}"
|
|
97
|
+
{ adapt: adapt_result, prune: prune_result, stats: stats }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def meta_learning_stats(**)
|
|
101
|
+
stats = engine.to_h
|
|
102
|
+
Legion::Logging.debug "[meta_learning] stats domains=#{stats[:domain_count]} " \
|
|
103
|
+
"strategies=#{stats[:strategy_count]} efficiency=#{stats[:overall_efficiency]}"
|
|
104
|
+
stats
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def engine
|
|
110
|
+
@engine ||= Helpers::MetaLearningEngine.new
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|