Class: Legion::Extensions::Agentic::Inference::Abductive::Helpers::AbductionEngine
- Inherits:
-
Object
- Object
- Legion::Extensions::Agentic::Inference::Abductive::Helpers::AbductionEngine
show all
- Includes:
- Constants
- Defined in:
- lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb
Constant Summary
Constants included
from Constants
Constants::CONTRADICTION_PENALTY, Constants::DECAY_RATE, Constants::DEFAULT_PLAUSIBILITY, Constants::EVIDENCE_BOOST, Constants::EXPLANATORY_POWER_WEIGHT, Constants::HYPOTHESIS_STATES, Constants::MAX_EXPLANATIONS, Constants::MAX_HISTORY, Constants::MAX_HYPOTHESES, Constants::MAX_OBSERVATIONS, Constants::PLAUSIBILITY_CEILING, Constants::PLAUSIBILITY_FLOOR, Constants::PRIOR_WEIGHT, Constants::QUALITY_LABELS, Constants::SIMPLICITY_WEIGHT, Constants::STALE_THRESHOLD, Constants::SURPRISE_LEVELS
Instance Method Summary
collapse
Constructor Details
Returns a new instance of AbductionEngine.
12
13
14
15
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 12
def initialize
@observations = {}
@hypotheses = {}
end
|
Instance Method Details
#add_evidence(hypothesis_id:, supporting:) ⇒ Object
59
60
61
62
63
64
65
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 59
def add_evidence(hypothesis_id:, supporting:)
hyp = @hypotheses[hypothesis_id]
return { found: false } unless hyp
hyp.add_evidence(supporting: supporting)
{ found: true, hypothesis_id: hypothesis_id, state: hyp.state, plausibility: hyp.plausibility }
end
|
#best_explanation(observation_id:) ⇒ Object
67
68
69
70
71
72
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 67
def best_explanation(observation_id:)
candidates = active_hypotheses_for(observation_id)
return nil if candidates.empty?
candidates.max_by(&:overall_score)
end
|
#competing_hypotheses(observation_id:) ⇒ Object
74
75
76
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 74
def competing_hypotheses(observation_id:)
active_hypotheses_for(observation_id).sort_by { |h| -h.overall_score }
end
|
#decay_stale ⇒ Object
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 98
def decay_stale
cutoff = Time.now.utc - Constants::STALE_THRESHOLD
decayed = 0
@hypotheses.each_value do |hyp|
next if hyp.state == :refuted
next if hyp.last_evaluated_at >= cutoff
hyp.plausibility = (hyp.plausibility - Constants::DECAY_RATE).clamp(
Constants::PLAUSIBILITY_FLOOR,
Constants::PLAUSIBILITY_CEILING
)
decayed += 1
end
decayed
end
|
#evaluate_hypothesis(hypothesis_id:) ⇒ Object
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 44
def evaluate_hypothesis(hypothesis_id:)
hyp = @hypotheses[hypothesis_id]
return { found: false } unless hyp
hyp.instance_variable_set(:@last_evaluated_at, Time.now.utc)
ranked = ranked_hypotheses_for_observations(hyp.observation_ids)
rank = ranked.index { |h| h.id == hypothesis_id }.to_i + 1
{
score: hyp.overall_score,
rank: rank,
quality_label: hyp.quality_label
}
end
|
#find_by_domain(domain:) ⇒ Object
86
87
88
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 86
def find_by_domain(domain:)
@hypotheses.values.select { |h| h.domain == domain && h.state != :refuted }
end
|
#generate_hypothesis(content:, observation_ids:, domain:, simplicity:, explanatory_power:, prior_probability: Constants::DEFAULT_PLAUSIBILITY) ⇒ Object
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 29
def generate_hypothesis(content:, observation_ids:, domain:, simplicity:,
explanatory_power:, prior_probability: Constants::DEFAULT_PLAUSIBILITY)
hyp = Hypothesis.new(
content: content,
observation_ids: observation_ids,
domain: domain,
simplicity: simplicity,
explanatory_power: explanatory_power,
prior_probability: prior_probability
)
prune_hypotheses if @hypotheses.size >= Constants::MAX_HYPOTHESES
@hypotheses[hyp.id] = hyp
hyp
end
|
#prune_refuted ⇒ Object
114
115
116
117
118
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 114
def prune_refuted
before = @hypotheses.size
@hypotheses.delete_if { |_, h| h.state == :refuted }
before - @hypotheses.size
end
|
#record_observation(content:, domain:, surprise_level: :notable, context: {}) ⇒ Object
17
18
19
20
21
22
23
24
25
26
27
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 17
def record_observation(content:, domain:, surprise_level: :notable, context: {})
obs = Observation.new(
content: content,
domain: domain,
surprise_level: surprise_level,
context: context
)
prune_observations if @observations.size >= Constants::MAX_OBSERVATIONS
@observations[obs.id] = obs
obs
end
|
#refute_hypothesis(hypothesis_id:) ⇒ Object
78
79
80
81
82
83
84
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 78
def refute_hypothesis(hypothesis_id:)
hyp = @hypotheses[hypothesis_id]
return { found: false } unless hyp
hyp.refute!
{ found: true, hypothesis_id: hypothesis_id, state: hyp.state }
end
|
#to_h ⇒ Object
120
121
122
123
124
125
126
127
128
129
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 120
def to_h
{
observation_count: @observations.size,
hypothesis_count: @hypotheses.size,
supported_count: @hypotheses.values.count { |h| h.state == :supported },
refuted_count: @hypotheses.values.count { |h| h.state == :refuted },
candidate_count: @hypotheses.values.count { |h| h.state == :candidate },
unexplained_count: unexplained_observations.size
}
end
|
#unexplained_observations ⇒ Object
90
91
92
93
94
95
96
|
# File 'lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb', line 90
def unexplained_observations
@observations.values.reject do |obs|
@hypotheses.values.any? do |h|
h.state == :supported && h.observation_ids.include?(obs.id)
end
end
end
|