Class: Legion::Extensions::Agentic::Executive::DualProcess::Helpers::DualProcessEngine
- Inherits:
-
Object
- Object
- Legion::Extensions::Agentic::Executive::DualProcess::Helpers::DualProcessEngine
show all
- Includes:
- Constants
- Defined in:
- lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb
Constant Summary
Constants included
from Constants
Constants::COMPLEXITY_THRESHOLD, Constants::CONFIDENCE_CEILING, Constants::CONFIDENCE_FLOOR, Constants::DECAY_RATE, Constants::DECISION_OUTCOMES, Constants::DEFAULT_CONFIDENCE, Constants::EFFORT_COST, Constants::EFFORT_RECOVERY_RATE, Constants::FATIGUE_PENALTY, Constants::HEURISTIC_BOOST, Constants::MAX_DECISIONS, Constants::MAX_EFFORT_BUDGET, Constants::MAX_HEURISTICS, Constants::MAX_HISTORY, Constants::ROUTING_LABELS, Constants::SYSTEMS, Constants::SYSTEM_ONE_THRESHOLD
Instance Method Summary
collapse
Constructor Details
Returns a new instance of DualProcessEngine.
12
13
14
15
16
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 12
def initialize
@effort_budget = MAX_EFFORT_BUDGET
@heuristics = {}
@decisions = []
end
|
Instance Method Details
#best_heuristics(limit: 5) ⇒ Object
145
146
147
148
149
150
151
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 145
def best_heuristics(limit: 5)
@heuristics.values
.select(&:reliable?)
.sort_by { |h| [-h.success_rate, -h.use_count] }
.first(limit)
.map(&:to_h)
end
|
#decay_heuristics ⇒ Object
122
123
124
125
126
127
128
129
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 122
def decay_heuristics
@heuristics.each_value do |h|
next unless h.use_count.positive?
delta = -DECAY_RATE
h.instance_variable_set(:@confidence, (h.confidence + delta).clamp(CONFIDENCE_FLOOR, CONFIDENCE_CEILING))
end
end
|
#effort_level ⇒ Object
110
111
112
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 110
def effort_level
@effort_budget / MAX_EFFORT_BUDGET
end
|
#execute_system_one(query:, domain:) ⇒ Object
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 43
def execute_system_one(query:, domain:)
matching = find_matching_heuristic(query, domain)
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
if matching
matching.use!(success: true)
confidence = matching.confidence
response = matching.response
else
confidence = (DEFAULT_CONFIDENCE - FATIGUE_PENALTY).clamp(CONFIDENCE_FLOOR, CONFIDENCE_CEILING)
response = :no_heuristic
end
elapsed = ((::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start) * 1000).round
decision = Decision.new(
query: query,
domain: domain,
system_used: :system_one,
confidence: confidence,
complexity: 0.0,
heuristic_id: matching&.id,
effort_cost: 0.0,
processing_time_ms: elapsed
)
store_decision(decision)
{ decision_id: decision.id, system: :system_one, response: response, confidence: confidence }
end
|
#execute_system_two(query:, domain:, deliberation: {}) ⇒ Object
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 72
def execute_system_two(query:, domain:, deliberation: {})
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
@effort_budget = (@effort_budget - EFFORT_COST).clamp(0.0, MAX_EFFORT_BUDGET)
confidence = deliberation.fetch(:confidence, DEFAULT_CONFIDENCE + HEURISTIC_BOOST)
.clamp(CONFIDENCE_FLOOR, CONFIDENCE_CEILING)
response = deliberation.fetch(:response, :deliberated)
elapsed = ((::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start) * 1000).round
decision = Decision.new(
query: query,
domain: domain,
system_used: :system_two,
confidence: confidence,
complexity: deliberation.fetch(:complexity, COMPLEXITY_THRESHOLD),
effort_cost: EFFORT_COST,
processing_time_ms: elapsed
)
store_decision(decision)
{ decision_id: decision.id, system: :system_two, response: response, confidence: confidence }
end
|
#record_outcome(decision_id:, outcome:) ⇒ Object
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 94
def record_outcome(decision_id:, outcome:)
return { success: false, reason: :invalid_outcome } unless Constants::DECISION_OUTCOMES.include?(outcome)
decision = @decisions.find { |d| d.id == decision_id }
return { success: false, reason: :not_found } unless decision
decision.outcome = outcome
if decision.heuristic_id
heuristic = @heuristics[decision.heuristic_id]
heuristic&.use!(success: outcome == :correct)
end
{ success: true, decision_id: decision_id, outcome: outcome }
end
|
#recover_effort ⇒ Object
118
119
120
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 118
def recover_effort
@effort_budget = (@effort_budget + EFFORT_RECOVERY_RATE).clamp(0.0, MAX_EFFORT_BUDGET)
end
|
#register_heuristic(pattern:, domain:, response:, confidence: DEFAULT_CONFIDENCE) ⇒ Object
18
19
20
21
22
23
24
25
26
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 18
def register_heuristic(pattern:, domain:, response:, confidence: DEFAULT_CONFIDENCE)
heuristic = Heuristic.new(pattern: pattern, domain: domain, response: response, confidence: confidence)
if @heuristics.size >= MAX_HEURISTICS
oldest_key = @heuristics.min_by { |_, h| h.last_used_at || h.created_at }.first
@heuristics.delete(oldest_key)
end
@heuristics[heuristic.id] = heuristic
heuristic
end
|
#route_decision(query:, domain:, complexity:) ⇒ Object
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 28
def route_decision(query:, domain:, complexity:)
matching = find_matching_heuristic(query, domain)
use_system_one = complexity < COMPLEXITY_THRESHOLD &&
matching &&
matching.confidence >= SYSTEM_ONE_THRESHOLD
if use_system_one
{ system: :system_one, reason: :heuristic_match, heuristic_id: matching.id }
elsif @effort_budget >= EFFORT_COST
{ system: :system_two, reason: complexity_reason(complexity, matching) }
else
{ system: :system_one, reason: :effort_depleted, fatigue: true }
end
end
|
#routing_label ⇒ Object
114
115
116
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 114
def routing_label
ROUTING_LABELS.find { |range, _| range.cover?(effort_level) }&.last || :unknown
end
|
#system_stats ⇒ Object
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 131
def system_stats
s1 = @decisions.count { |d| d.system_used == :system_one }
s2 = @decisions.count { |d| d.system_used == :system_two }
total = @decisions.size
{
system_one: s1,
system_two: s2,
total: total,
s1_ratio: total.zero? ? 0.0 : (s1.to_f / total).round(3),
s2_ratio: total.zero? ? 0.0 : (s2.to_f / total).round(3)
}
end
|
#to_h ⇒ Object
153
154
155
156
157
158
159
160
161
162
|
# File 'lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb', line 153
def to_h
{
effort_budget: @effort_budget,
effort_level: effort_level,
routing_label: routing_label,
heuristic_count: @heuristics.size,
decision_count: @decisions.size,
system_stats: system_stats
}
end
|