Class: Legion::Extensions::Agentic::Attention::SignalDetection::Helpers::DetectionEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb

Instance Method Summary collapse

Constructor Details

#initializeDetectionEngine

Returns a new instance of DetectionEngine.



10
11
12
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 10

def initialize
  @detectors = {}
end

Instance Method Details

#adjust_bias(detector_id:, amount:) ⇒ Object



43
44
45
46
47
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 43

def adjust_bias(detector_id:, amount:)
  detector = fetch!(detector_id)
  detector.adjust_criterion(amount: amount)
  { detector_id: detector_id, criterion: detector.criterion, bias_label: detector.bias_label }
end

#best_detectors(limit: 5) ⇒ Object



49
50
51
52
53
54
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 49

def best_detectors(limit: 5)
  @detectors.values
            .sort_by { |d| -d.sensitivity }
            .first(limit)
            .map(&:to_h)
end

#by_domain(domain:) ⇒ Object



56
57
58
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 56

def by_domain(domain:)
  @detectors.values.select { |d| d.domain == domain }.map(&:to_h)
end

#compute_sensitivity(detector_id:) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 29

def compute_sensitivity(detector_id:)
  detector = fetch!(detector_id)
  {
    detector_id:       detector_id,
    d_prime:           detector.compute_dprime,
    criterion:         detector.compute_criterion,
    accuracy:          detector.accuracy,
    hit_rate:          detector.hit_rate,
    false_alarm_rate:  detector.false_alarm_rate,
    sensitivity_label: detector.sensitivity_label,
    bias_label:        detector.bias_label
  }
end

#countObject



99
100
101
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 99

def count
  @detectors.size
end

#create_detector(domain:) ⇒ Object

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 14

def create_detector(domain:)
  raise ArgumentError, "max detectors reached (#{Constants::MAX_DETECTORS})" if @detectors.size >= Constants::MAX_DETECTORS

  detector = Detector.new(domain: domain)
  @detectors[detector.id] = detector
  detector
end

#decay_allObject



84
85
86
87
88
89
90
91
92
93
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 84

def decay_all
  count = 0
  @detectors.each_value do |detector|
    next if detector.trial_count.zero?

    detector.adjust_criterion(amount: Constants::DECAY_RATE * -detector.criterion.clamp(-1, 1))
    count += 1
  end
  count
end

#get(detector_id) ⇒ Object



95
96
97
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 95

def get(detector_id)
  @detectors[detector_id]
end

#optimal_criterion(detector_id:, signal_probability: 0.5) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 60

def optimal_criterion(detector_id:, signal_probability: 0.5)
  detector = fetch!(detector_id)
  # Optimal criterion for equal cost: c* = 0.5 * ln((1-p)/p) in likelihood ratio terms
  # In SDT criterion units: shift from neutral based on prior probability
  prior_ratio = (1.0 - signal_probability) / signal_probability.clamp(0.001, 0.999)
  optimal = 0.5 * Math.log(prior_ratio)
  {
    detector_id:        detector_id,
    optimal_criterion:  Constants.clamp_criterion(optimal),
    current_criterion:  detector.criterion,
    signal_probability: signal_probability
  }
end

#record_trial(detector_id:, signal_present:, responded_present:) ⇒ Object



22
23
24
25
26
27
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 22

def record_trial(detector_id:, signal_present:, responded_present:)
  detector = fetch!(detector_id)
  outcome  = classify_outcome(signal_present: signal_present, responded_present: responded_present)
  detector.record_trial(outcome: outcome)
  { detector_id: detector_id, outcome: outcome, trial_count: detector.trial_count }
end

#roc_point(detector_id:) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 74

def roc_point(detector_id:)
  detector = fetch!(detector_id)
  {
    detector_id:      detector_id,
    hit_rate:         detector.hit_rate,
    false_alarm_rate: detector.false_alarm_rate,
    d_prime:          detector.sensitivity
  }
end

#to_hObject



103
104
105
106
107
108
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 103

def to_h
  {
    detector_count: @detectors.size,
    detectors:      @detectors.transform_values(&:to_h)
  }
end