lex-agentic-inference 0.1.1 → 0.1.3
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/CHANGELOG.md +13 -1
- data/LICENSE +201 -21
- data/README.md +2 -2
- data/lex-agentic-inference.gemspec +8 -0
- data/lib/legion/extensions/agentic/inference/abductive/runners/abductive_reasoning.rb +19 -19
- data/lib/legion/extensions/agentic/inference/affordance/runners/affordance.rb +6 -6
- data/lib/legion/extensions/agentic/inference/analogical/runners/analogical_reasoning.rb +17 -14
- data/lib/legion/extensions/agentic/inference/argument_mapping/runners/argument_mapping.rb +10 -10
- data/lib/legion/extensions/agentic/inference/bayesian/runners/bayesian_belief.rb +14 -14
- data/lib/legion/extensions/agentic/inference/causal_attribution/runners/causal_attribution.rb +13 -13
- data/lib/legion/extensions/agentic/inference/causal_reasoning/runners/causal_reasoning.rb +14 -14
- data/lib/legion/extensions/agentic/inference/coherence/runners/cognitive_coherence.rb +16 -16
- data/lib/legion/extensions/agentic/inference/counterfactual/runners/counterfactual.rb +11 -11
- data/lib/legion/extensions/agentic/inference/debugging/runners/cognitive_debugging.rb +29 -29
- data/lib/legion/extensions/agentic/inference/enactive_cognition/runners/enactive_cognition.rb +17 -17
- data/lib/legion/extensions/agentic/inference/expectation_violation/runners/expectation_violation.rb +12 -12
- data/lib/legion/extensions/agentic/inference/gravity/runners/gravity.rb +16 -16
- data/lib/legion/extensions/agentic/inference/horizon/runners/cognitive_horizon.rb +10 -10
- data/lib/legion/extensions/agentic/inference/hypothesis_testing/runners/hypothesis_testing.rb +11 -11
- data/lib/legion/extensions/agentic/inference/magnet/helpers/magnet_engine.rb +2 -0
- data/lib/legion/extensions/agentic/inference/magnet/runners/cognitive_magnet.rb +13 -13
- data/lib/legion/extensions/agentic/inference/momentum/runners/cognitive_momentum.rb +16 -16
- data/lib/legion/extensions/agentic/inference/perceptual_inference/helpers/perceptual_field.rb +2 -0
- data/lib/legion/extensions/agentic/inference/perceptual_inference/runners/perceptual_inference.rb +12 -12
- data/lib/legion/extensions/agentic/inference/prediction/runners/prediction.rb +11 -11
- data/lib/legion/extensions/agentic/inference/predictive_coding/runners/predictive_coding.rb +13 -13
- data/lib/legion/extensions/agentic/inference/predictive_processing/runners/predictive_processing.rb +11 -11
- data/lib/legion/extensions/agentic/inference/reality_testing/helpers/reality_engine.rb +5 -3
- data/lib/legion/extensions/agentic/inference/reality_testing/runners/reality_testing.rb +4 -4
- data/lib/legion/extensions/agentic/inference/schema/runners/schema.rb +8 -8
- data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/runners/uncertainty_tolerance.rb +14 -14
- data/lib/legion/extensions/agentic/inference/version.rb +1 -1
- data/spec/spec_helper.rb +21 -23
- metadata +99 -1
data/lib/legion/extensions/agentic/inference/perceptual_inference/runners/perceptual_inference.rb
CHANGED
|
@@ -11,31 +11,31 @@ module Legion
|
|
|
11
11
|
|
|
12
12
|
def register_percept_hypothesis(content:, modality:, domain: :general, prior: Helpers::DEFAULT_PRIOR, **)
|
|
13
13
|
hypothesis = field.register_hypothesis(content: content, modality: modality, domain: domain, prior: prior)
|
|
14
|
-
|
|
14
|
+
log.debug "[perceptual_inference] registered hypothesis modality=#{modality} id=#{hypothesis.id[0..7]}"
|
|
15
15
|
{ success: true, hypothesis_id: hypothesis.id, modality: modality, prior: hypothesis.prior }
|
|
16
16
|
rescue ArgumentError => e
|
|
17
|
-
|
|
17
|
+
log.warn "[perceptual_inference] register failed: #{e.message}"
|
|
18
18
|
{ success: false, error: e.message }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def present_perceptual_evidence(modality:, content:, strength: 0.5, **)
|
|
22
22
|
count = field.present_evidence(modality: modality, content: content, strength: strength)
|
|
23
|
-
|
|
23
|
+
log.debug "[perceptual_inference] evidence presented modality=#{modality} strength=#{strength} updated=#{count}"
|
|
24
24
|
{ success: true, modality: modality, hypotheses_updated: count, rivalry: field.rivalry?(modality: modality) }
|
|
25
25
|
rescue ArgumentError => e
|
|
26
|
-
|
|
26
|
+
log.warn "[perceptual_inference] evidence failed: #{e.message}"
|
|
27
27
|
{ success: false, error: e.message }
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def select_percept(modality:, **)
|
|
31
31
|
winner = field.select_percept(modality: modality)
|
|
32
32
|
if winner
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
log.info "[perceptual_inference] percept selected modality=#{modality} " \
|
|
34
|
+
"posterior=#{winner.posterior.round(3)} label=#{winner.percept_label}"
|
|
35
35
|
{ success: true, selected: true, hypothesis: winner.to_h }
|
|
36
36
|
else
|
|
37
37
|
rivalry = field.rivalry?(modality: modality)
|
|
38
|
-
|
|
38
|
+
log.debug "[perceptual_inference] no percept selected modality=#{modality} rivalry=#{rivalry}"
|
|
39
39
|
{ success: true, selected: false, rivalry: rivalry }
|
|
40
40
|
end
|
|
41
41
|
rescue ArgumentError => e
|
|
@@ -46,7 +46,7 @@ module Legion
|
|
|
46
46
|
rival = field.rivalry?(modality: modality)
|
|
47
47
|
candidates = field.hypotheses_for(modality)
|
|
48
48
|
top_two = candidates.select { |h| %i[active selected].include?(h.state) }.max_by(2, &:posterior)
|
|
49
|
-
|
|
49
|
+
log.debug "[perceptual_inference] rivalry check modality=#{modality} rival=#{rival}"
|
|
50
50
|
{ success: true, rivalry: rival, modality: modality, top_hypotheses: top_two.map(&:to_h) }
|
|
51
51
|
rescue ArgumentError => e
|
|
52
52
|
{ success: false, error: e.message }
|
|
@@ -65,7 +65,7 @@ module Legion
|
|
|
65
65
|
|
|
66
66
|
def adapt_perception(modality:, correct_hypothesis_id:, **)
|
|
67
67
|
field.adapt_priors(modality: modality, correct_hypothesis_id: correct_hypothesis_id)
|
|
68
|
-
|
|
68
|
+
log.info "[perceptual_inference] priors adapted modality=#{modality} correct=#{correct_hypothesis_id[0..7]}"
|
|
69
69
|
{ success: true, modality: modality, correct_hypothesis_id: correct_hypothesis_id }
|
|
70
70
|
rescue ArgumentError => e
|
|
71
71
|
{ success: false, error: e.message }
|
|
@@ -73,20 +73,20 @@ module Legion
|
|
|
73
73
|
|
|
74
74
|
def suppress_percept(hypothesis_id:, **)
|
|
75
75
|
suppressed = field.suppress_hypothesis(hypothesis_id: hypothesis_id)
|
|
76
|
-
|
|
76
|
+
log.debug "[perceptual_inference] suppress hypothesis_id=#{hypothesis_id[0..7]} result=#{suppressed}"
|
|
77
77
|
{ success: true, suppressed: suppressed, hypothesis_id: hypothesis_id }
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def perceptual_ambiguity(**)
|
|
81
81
|
level = field.ambiguity_level
|
|
82
82
|
label = ambiguity_label(level)
|
|
83
|
-
|
|
83
|
+
log.debug "[perceptual_inference] ambiguity=#{level.round(3)} label=#{label}"
|
|
84
84
|
{ success: true, ambiguity_level: level, label: label }
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def update_perceptual_inference(**)
|
|
88
88
|
field.decay_all
|
|
89
|
-
|
|
89
|
+
log.debug "[perceptual_inference] decay cycle complete remaining=#{field.hypotheses.size}"
|
|
90
90
|
{ success: true, remaining_hypotheses: field.hypotheses.size }
|
|
91
91
|
end
|
|
92
92
|
|
|
@@ -29,8 +29,8 @@ module Legion
|
|
|
29
29
|
prediction_store.store(prediction)
|
|
30
30
|
|
|
31
31
|
actionable = prediction[:confidence] >= Helpers::Modes::PREDICTION_CONFIDENCE_MIN
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
log.debug "[prediction] new: mode=#{mode} confidence=#{prediction[:confidence].round(2)} " \
|
|
33
|
+
"actionable=#{actionable} id=#{prediction[:prediction_id][0..7]}"
|
|
34
34
|
|
|
35
35
|
{
|
|
36
36
|
prediction_id: prediction[:prediction_id],
|
|
@@ -43,25 +43,25 @@ module Legion
|
|
|
43
43
|
def resolve_prediction(prediction_id:, outcome:, actual: nil, **)
|
|
44
44
|
pred = prediction_store.resolve(prediction_id, outcome: outcome, actual: actual)
|
|
45
45
|
if pred
|
|
46
|
-
|
|
46
|
+
log.info "[prediction] resolved #{prediction_id[0..7]} outcome=#{outcome}"
|
|
47
47
|
record_outcome_trace(pred, outcome)
|
|
48
48
|
{ resolved: true, prediction_id: prediction_id, outcome: outcome }
|
|
49
49
|
else
|
|
50
|
-
|
|
50
|
+
log.debug "[prediction] resolve failed: #{prediction_id[0..7]} not found"
|
|
51
51
|
{ resolved: false, reason: :not_found }
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def pending_predictions(**)
|
|
56
56
|
preds = prediction_store.pending
|
|
57
|
-
|
|
57
|
+
log.debug "[prediction] pending count=#{preds.size}"
|
|
58
58
|
{ predictions: preds, count: preds.size }
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def prediction_accuracy(window: 100, **)
|
|
62
62
|
acc = prediction_store.accuracy(window: window)
|
|
63
63
|
total = prediction_store.outcomes.size
|
|
64
|
-
|
|
64
|
+
log.debug "[prediction] accuracy=#{acc.round(2)} total_outcomes=#{total}"
|
|
65
65
|
{ accuracy: acc, total_outcomes: total }
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -77,7 +77,7 @@ module Legion
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
remaining = prediction_store.pending.size
|
|
80
|
-
|
|
80
|
+
log.debug "[prediction] expire sweep: expired=#{expired_count} remaining=#{remaining}"
|
|
81
81
|
|
|
82
82
|
{ expired_count: expired_count, remaining_pending: remaining }
|
|
83
83
|
end
|
|
@@ -105,7 +105,7 @@ module Legion
|
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
def record_outcome_trace(prediction, outcome)
|
|
108
|
-
return unless defined?(Legion::Extensions::Memory::Runners::Traces)
|
|
108
|
+
return unless defined?(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces)
|
|
109
109
|
|
|
110
110
|
trace_params = case outcome
|
|
111
111
|
when :correct
|
|
@@ -118,7 +118,7 @@ module Legion
|
|
|
118
118
|
return
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
-
runner = Object.new.extend(Legion::Extensions::Memory::Runners::Traces)
|
|
121
|
+
runner = Object.new.extend(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces)
|
|
122
122
|
runner.store_trace(
|
|
123
123
|
type: trace_params[:type],
|
|
124
124
|
content_payload: "prediction #{outcome}: mode=#{prediction[:mode]} confidence=#{prediction[:confidence]}",
|
|
@@ -133,9 +133,9 @@ module Legion
|
|
|
133
133
|
store = runner.send(:default_store)
|
|
134
134
|
store.flush if store.respond_to?(:flush)
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
log.debug "[prediction] created #{trace_params[:type]} trace for #{outcome} prediction"
|
|
137
137
|
rescue StandardError => e
|
|
138
|
-
|
|
138
|
+
log.warn "[prediction] failed to create outcome trace: #{e.message}"
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
end
|
|
@@ -14,15 +14,15 @@ module Legion
|
|
|
14
14
|
|
|
15
15
|
def generate_prediction(domain:, context: {}, **)
|
|
16
16
|
prediction = generative_model.predict(domain: domain, context: context)
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
log.debug "[predictive_coding] generate_prediction domain=#{domain} " \
|
|
18
|
+
"predicted=#{prediction[:predicted]} confidence=#{prediction[:confidence].round(3)}"
|
|
19
19
|
{ success: true, domain: domain, predicted: prediction[:predicted], confidence: prediction[:confidence] }
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def report_outcome(domain:, predicted:, actual:, **)
|
|
23
23
|
error = generative_model.update(domain: domain, predicted: predicted, actual: actual)
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
log.debug "[predictive_coding] report_outcome domain=#{domain} " \
|
|
25
|
+
"error_magnitude=#{error.error_magnitude.round(3)} surprising=#{error.surprising?}"
|
|
26
26
|
{
|
|
27
27
|
success: true,
|
|
28
28
|
domain: domain,
|
|
@@ -36,20 +36,20 @@ module Legion
|
|
|
36
36
|
|
|
37
37
|
def precision_for(domain:, **)
|
|
38
38
|
value = generative_model.precision_for(domain: domain)
|
|
39
|
-
|
|
39
|
+
log.debug "[predictive_coding] precision_for domain=#{domain} precision=#{value.round(3)}"
|
|
40
40
|
{ success: true, domain: domain, precision: value }
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def surprising_errors(**)
|
|
44
44
|
errors = generative_model.surprising_errors
|
|
45
|
-
|
|
45
|
+
log.debug "[predictive_coding] surprising_errors count=#{errors.size}"
|
|
46
46
|
{ success: true, errors: errors.map(&:to_h), count: errors.size }
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def free_energy_status(**)
|
|
50
50
|
fe = generative_model.free_energy
|
|
51
51
|
level = generative_model.free_energy_level
|
|
52
|
-
|
|
52
|
+
log.debug "[predictive_coding] free_energy_status fe=#{fe.round(3)} level=#{level}"
|
|
53
53
|
{
|
|
54
54
|
success: true,
|
|
55
55
|
free_energy: fe,
|
|
@@ -60,7 +60,7 @@ module Legion
|
|
|
60
60
|
|
|
61
61
|
def active_inference_candidates(**)
|
|
62
62
|
candidates = generative_model.active_inference_candidates
|
|
63
|
-
|
|
63
|
+
log.debug "[predictive_coding] active_inference_candidates count=#{candidates.size}"
|
|
64
64
|
{ success: true, candidates: candidates, count: candidates.size }
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -77,14 +77,14 @@ module Legion
|
|
|
77
77
|
|
|
78
78
|
prune_active_inferences
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
log.debug "[predictive_coding] register_active_inference domain=#{domain} id=#{inference_id[0..7]}"
|
|
81
81
|
{ success: true, inference_id: inference_id, domain: domain, status: :pending }
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def resolve_active_inference(domain:, action:, actual_outcome:, inference_id: nil, **)
|
|
85
85
|
record = find_inference(domain, action, inference_id)
|
|
86
86
|
unless record
|
|
87
|
-
|
|
87
|
+
log.debug "[predictive_coding] resolve_active_inference not found domain=#{domain}"
|
|
88
88
|
return { success: false, reason: :not_found }
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -100,8 +100,8 @@ module Legion
|
|
|
100
100
|
record[:resolved_at] = Time.now.utc
|
|
101
101
|
record[:error_magnitude] = error.error_magnitude
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
log.info "[predictive_coding] resolve_active_inference domain=#{domain} " \
|
|
104
|
+
"error=#{error.error_magnitude.round(3)} id=#{record[:inference_id][0..7]}"
|
|
105
105
|
|
|
106
106
|
{
|
|
107
107
|
success: true,
|
|
@@ -115,7 +115,7 @@ module Legion
|
|
|
115
115
|
def update_predictive_coding(**)
|
|
116
116
|
generative_model.decay_all
|
|
117
117
|
pruned = prune_resolved_inferences
|
|
118
|
-
|
|
118
|
+
log.debug "[predictive_coding] update_predictive_coding pruned_inferences=#{pruned}"
|
|
119
119
|
{ success: true, pruned_inferences: pruned }
|
|
120
120
|
end
|
|
121
121
|
|
data/lib/legion/extensions/agentic/inference/predictive_processing/runners/predictive_processing.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Legion
|
|
|
14
14
|
return { added: false, reason: :missing_domain } if domain.nil? || domain.to_s.strip.empty?
|
|
15
15
|
|
|
16
16
|
result = default_processor.add_model(domain: domain.to_sym)
|
|
17
|
-
|
|
17
|
+
log.debug "[predictive_processing] add_model domain=#{domain} added=#{result[:added]}"
|
|
18
18
|
result
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -22,8 +22,8 @@ module Legion
|
|
|
22
22
|
return { predicted: false, reason: :missing_domain } if domain.nil?
|
|
23
23
|
|
|
24
24
|
prediction = default_processor.predict(domain: domain.to_sym, context: context)
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
log.debug "[predictive_processing] predict domain=#{domain} " \
|
|
26
|
+
"expected=#{prediction[:expected_value]&.round(3)}"
|
|
27
27
|
{ predicted: true, domain: domain, prediction: prediction }
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -43,7 +43,7 @@ module Legion
|
|
|
43
43
|
return { mode: nil, reason: :missing_domain } if domain.nil?
|
|
44
44
|
|
|
45
45
|
mode = default_processor.inference_mode(domain.to_sym)
|
|
46
|
-
|
|
46
|
+
log.debug "[predictive_processing] inference_mode domain=#{domain} mode=#{mode}"
|
|
47
47
|
{ domain: domain, mode: mode }
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -60,25 +60,25 @@ module Legion
|
|
|
60
60
|
|
|
61
61
|
def models_needing_update(**)
|
|
62
62
|
needing = default_processor.models_needing_update
|
|
63
|
-
|
|
63
|
+
log.debug "[predictive_processing] models_needing_update count=#{needing.size}"
|
|
64
64
|
{ count: needing.size, models: needing }
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def active_inference_candidates(**)
|
|
68
68
|
candidates = default_processor.active_inference_candidates
|
|
69
|
-
|
|
69
|
+
log.debug "[predictive_processing] active_inference_candidates count=#{candidates.size}"
|
|
70
70
|
{ count: candidates.size, domains: candidates }
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def update_predictive_processing(**)
|
|
74
74
|
default_processor.tick
|
|
75
|
-
|
|
75
|
+
log.debug '[predictive_processing] tick: precision decayed on all models'
|
|
76
76
|
{ ticked: true, model_count: default_processor.models.size }
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def predictive_processing_stats(**)
|
|
80
80
|
stats = default_processor.to_h
|
|
81
|
-
|
|
81
|
+
log.debug "[predictive_processing] stats global_fe=#{stats[:global_free_energy]&.round(3)}"
|
|
82
82
|
{ success: true, stats: stats }
|
|
83
83
|
end
|
|
84
84
|
|
|
@@ -91,9 +91,9 @@ module Legion
|
|
|
91
91
|
def log_observe(domain, result)
|
|
92
92
|
return unless result[:observed]
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
log.debug "[predictive_processing] observe domain=#{domain} " \
|
|
95
|
+
"error=#{result[:prediction_error]&.round(3)} " \
|
|
96
|
+
"mode=#{result[:inference_mode]}"
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
end
|
|
@@ -7,6 +7,8 @@ module Legion
|
|
|
7
7
|
module RealityTesting
|
|
8
8
|
module Helpers
|
|
9
9
|
class RealityEngine
|
|
10
|
+
include Legion::Logging::Helper
|
|
11
|
+
|
|
10
12
|
def initialize
|
|
11
13
|
@beliefs = {}
|
|
12
14
|
@next_id = 1
|
|
@@ -19,7 +21,7 @@ module Legion
|
|
|
19
21
|
@next_id += 1
|
|
20
22
|
belief = Belief.new(id: id, claim: claim, domain: domain, confidence: confidence)
|
|
21
23
|
@beliefs[id] = belief
|
|
22
|
-
|
|
24
|
+
log.debug "[reality_testing] create_belief id=#{id} domain=#{domain} confidence=#{confidence.round(2)}"
|
|
23
25
|
{ created: true, belief: belief.to_h }
|
|
24
26
|
end
|
|
25
27
|
|
|
@@ -28,7 +30,7 @@ module Legion
|
|
|
28
30
|
return { tested: false, reason: :not_found } unless belief
|
|
29
31
|
|
|
30
32
|
belief.test_with_evidence!(evidence_type: evidence_type, weight: weight)
|
|
31
|
-
|
|
33
|
+
log.debug "[reality_testing] test_belief id=#{belief_id} evidence=#{evidence_type} confidence=#{belief.confidence.round(2)}"
|
|
32
34
|
{ tested: true, belief: belief.to_h }
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -68,7 +70,7 @@ module Legion
|
|
|
68
70
|
before = @beliefs.size
|
|
69
71
|
@beliefs.delete_if { |_id, b| b.confidence < 0.1 }
|
|
70
72
|
pruned = before - @beliefs.size
|
|
71
|
-
|
|
73
|
+
log.debug "[reality_testing] prune_rejected pruned=#{pruned} remaining=#{@beliefs.size}"
|
|
72
74
|
pruned
|
|
73
75
|
end
|
|
74
76
|
|
|
@@ -13,7 +13,7 @@ module Legion
|
|
|
13
13
|
def create_belief(claim:, domain: :general, confidence: nil, **)
|
|
14
14
|
conf = confidence || Helpers::Constants::DEFAULT_CONFIDENCE
|
|
15
15
|
result = reality_engine.create_belief(claim: claim, domain: domain, confidence: conf)
|
|
16
|
-
|
|
16
|
+
log.info "[reality_testing] create_belief claim=#{claim[0, 60]} domain=#{domain}"
|
|
17
17
|
result
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -32,7 +32,7 @@ module Legion
|
|
|
32
32
|
|
|
33
33
|
def beliefs_needing_testing(**)
|
|
34
34
|
beliefs = reality_engine.beliefs_needing_testing
|
|
35
|
-
|
|
35
|
+
log.debug "[reality_testing] needs_testing count=#{beliefs.size}"
|
|
36
36
|
{ count: beliefs.size, beliefs: beliefs.map(&:to_h) }
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -53,13 +53,13 @@ module Legion
|
|
|
53
53
|
|
|
54
54
|
def overall_coherence(**)
|
|
55
55
|
coherence = reality_engine.overall_reality_coherence
|
|
56
|
-
|
|
56
|
+
log.debug "[reality_testing] coherence=#{coherence.round(3)}"
|
|
57
57
|
{ coherence: coherence.round(3) }
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def decay_beliefs(**)
|
|
61
61
|
count = reality_engine.decay_all
|
|
62
|
-
|
|
62
|
+
log.debug "[reality_testing] decay_all count=#{count}"
|
|
63
63
|
{ decayed: count }
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -14,8 +14,8 @@ module Legion
|
|
|
14
14
|
extract_prediction_outcomes(tick_results)
|
|
15
15
|
world_model.decay_all
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
log.debug "[schema] relations=#{world_model.relation_count} " \
|
|
18
|
+
"domains=#{world_model.domain_count} established=#{world_model.established_relations.size}"
|
|
19
19
|
|
|
20
20
|
world_model.to_h
|
|
21
21
|
end
|
|
@@ -25,7 +25,7 @@ module Legion
|
|
|
25
25
|
result = world_model.add_relation(cause: cause, effect: effect, relation_type: relation_sym, confidence: confidence)
|
|
26
26
|
return { success: false, error: 'invalid relation type' } unless result
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
log.info "[schema] learned: #{cause} #{relation_sym} #{effect} (#{result.confidence.round(2)})"
|
|
29
29
|
{ success: true, relation: result.to_h }
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -33,19 +33,19 @@ module Legion
|
|
|
33
33
|
result = world_model.weaken_relation(cause: cause, effect: effect, relation_type: relation_type.to_sym)
|
|
34
34
|
return { success: false, error: 'relation not found' } unless result
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
log.debug "[schema] weakened: #{cause} #{relation_type} #{effect}"
|
|
37
37
|
{ success: true, relation: result.to_h }
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def explain(outcome:, **)
|
|
41
41
|
chain = world_model.explain(outcome)
|
|
42
|
-
|
|
42
|
+
log.debug "[schema] explanation for #{outcome}: #{chain.size} links"
|
|
43
43
|
{ outcome: outcome, chain: chain, depth: chain.size }
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def counterfactual(cause:, **)
|
|
47
47
|
affected = world_model.counterfactual(cause)
|
|
48
|
-
|
|
48
|
+
log.debug "[schema] counterfactual for #{cause}: #{affected.size} effects"
|
|
49
49
|
{ cause: cause, affected: affected, impact: affected.size }
|
|
50
50
|
end
|
|
51
51
|
|
|
@@ -61,12 +61,12 @@ module Legion
|
|
|
61
61
|
|
|
62
62
|
def contradictions(**)
|
|
63
63
|
result = world_model.contradictions
|
|
64
|
-
|
|
64
|
+
log.debug "[schema] contradictions: #{result.size}"
|
|
65
65
|
{ contradictions: result, count: result.size }
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def schema_stats(**)
|
|
69
|
-
|
|
69
|
+
log.debug '[schema] stats'
|
|
70
70
|
world_model.to_h.merge(
|
|
71
71
|
top_relations: world_model.established_relations.first(10).map(&:to_h)
|
|
72
72
|
)
|
data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/runners/uncertainty_tolerance.rb
CHANGED
|
@@ -16,9 +16,9 @@ module Legion
|
|
|
16
16
|
domain: domain,
|
|
17
17
|
certainty_level: certainty_level
|
|
18
18
|
)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
log.debug "[uncertainty_tolerance] recorded decision: id=#{decision.id[0..7]} " \
|
|
20
|
+
"domain=#{domain} certainty=#{certainty_level.round(2)} " \
|
|
21
|
+
"type=#{decision.decision_type}"
|
|
22
22
|
{
|
|
23
23
|
decision_id: decision.id,
|
|
24
24
|
domain: domain,
|
|
@@ -32,12 +32,12 @@ module Legion
|
|
|
32
32
|
def resolve_uncertain_decision(decision_id:, outcome:, **)
|
|
33
33
|
decision = engine.resolve_decision(decision_id: decision_id, outcome: outcome)
|
|
34
34
|
unless decision
|
|
35
|
-
|
|
35
|
+
log.debug "[uncertainty_tolerance] resolve failed: #{decision_id[0..7]} not found"
|
|
36
36
|
return { resolved: false, reason: :not_found }
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
log.info "[uncertainty_tolerance] resolved: id=#{decision_id[0..7]} " \
|
|
40
|
+
"outcome=#{outcome} tolerance=#{engine.current_tolerance.round(3)}"
|
|
41
41
|
{
|
|
42
42
|
resolved: true,
|
|
43
43
|
decision_id: decision_id,
|
|
@@ -50,8 +50,8 @@ module Legion
|
|
|
50
50
|
def should_act_assessment(certainty:, **)
|
|
51
51
|
act = engine.should_act?(certainty: certainty)
|
|
52
52
|
gap = (certainty - engine.current_tolerance).round(3)
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
log.debug "[uncertainty_tolerance] should_act? certainty=#{certainty.round(2)} " \
|
|
54
|
+
"tolerance=#{engine.current_tolerance.round(2)} act=#{act}"
|
|
55
55
|
{
|
|
56
56
|
should_act: act,
|
|
57
57
|
certainty: certainty,
|
|
@@ -63,14 +63,14 @@ module Legion
|
|
|
63
63
|
|
|
64
64
|
def uncertainty_profile(**)
|
|
65
65
|
profile = engine.to_h
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
log.debug "[uncertainty_tolerance] profile: tolerance=#{profile[:current_tolerance].round(3)} " \
|
|
67
|
+
"label=#{profile[:tolerance_label]} decisions=#{profile[:total_decisions]}"
|
|
68
68
|
profile
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def decisions_under_uncertainty_report(threshold: nil, **)
|
|
72
72
|
decisions = engine.decisions_under_uncertainty(threshold: threshold)
|
|
73
|
-
|
|
73
|
+
log.debug "[uncertainty_tolerance] under_uncertainty: count=#{decisions.size}"
|
|
74
74
|
{
|
|
75
75
|
decisions: decisions.map(&:to_h),
|
|
76
76
|
count: decisions.size,
|
|
@@ -80,7 +80,7 @@ module Legion
|
|
|
80
80
|
|
|
81
81
|
def domain_tolerance_report(domain:, **)
|
|
82
82
|
avg = engine.domain_tolerance(domain: domain)
|
|
83
|
-
|
|
83
|
+
log.debug "[uncertainty_tolerance] domain_tolerance: domain=#{domain} avg=#{avg&.round(3)}"
|
|
84
84
|
{
|
|
85
85
|
domain: domain,
|
|
86
86
|
average_certainty: avg,
|
|
@@ -94,8 +94,8 @@ module Legion
|
|
|
94
94
|
Helpers::Constants::TOLERANCE_CEILING
|
|
95
95
|
)
|
|
96
96
|
engine.instance_variable_set(:@current_tolerance, clamped)
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
log.info "[uncertainty_tolerance] tolerance updated: #{clamped.round(3)} " \
|
|
98
|
+
"label=#{engine.tolerance_label}"
|
|
99
99
|
{
|
|
100
100
|
updated: true,
|
|
101
101
|
current_tolerance: clamped,
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'bundler/setup'
|
|
4
|
+
require 'legion/logging'
|
|
5
|
+
require 'legion/settings'
|
|
6
|
+
require 'legion/cache/helper'
|
|
7
|
+
require 'legion/crypt/helper'
|
|
8
|
+
require 'legion/data/helper'
|
|
9
|
+
require 'legion/json/helper'
|
|
10
|
+
require 'legion/transport'
|
|
4
11
|
|
|
5
12
|
module Legion
|
|
6
|
-
module Logging
|
|
7
|
-
def self.debug(_msg); end
|
|
8
|
-
def self.info(_msg); end
|
|
9
|
-
def self.warn(_msg); end
|
|
10
|
-
def self.error(_msg); end
|
|
11
|
-
def self.fatal(_msg); end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
13
|
module Extensions
|
|
15
|
-
module Core
|
|
16
|
-
def self.extended(_base); end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
14
|
module Helpers
|
|
20
15
|
module Lex
|
|
21
|
-
|
|
16
|
+
include Legion::Logging::Helper
|
|
17
|
+
include Legion::Settings::Helper
|
|
18
|
+
include Legion::Cache::Helper
|
|
19
|
+
include Legion::Crypt::Helper
|
|
20
|
+
include Legion::Data::Helper
|
|
21
|
+
include Legion::JSON::Helper
|
|
22
|
+
include Legion::Transport::Helper
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
25
|
|
|
27
|
-
# rubocop:disable Lint/EmptyClass, Style/OneClassPerFile
|
|
28
|
-
module Legion
|
|
29
|
-
module Extensions
|
|
30
26
|
module Actors
|
|
31
|
-
class Every
|
|
32
|
-
|
|
27
|
+
class Every
|
|
28
|
+
include Helpers::Lex
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class Subscription
|
|
32
|
+
include Helpers::Lex
|
|
33
|
+
end
|
|
33
34
|
end
|
|
34
35
|
end
|
|
35
36
|
end
|
|
36
|
-
$LOADED_FEATURES << 'legion/extensions/actors/every'
|
|
37
|
-
$LOADED_FEATURES << 'legion/extensions/actors/once'
|
|
38
|
-
# rubocop:enable Lint/EmptyClass, Style/OneClassPerFile
|
|
39
37
|
|
|
40
38
|
require 'legion/extensions/agentic/inference'
|
|
41
39
|
|