Class: Legion::Extensions::Agentic::Inference::ExpectationViolation::Helpers::ViolationEngine

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb

Constant Summary

Constants included from Constants

Constants::ADAPTATION_RATE, Constants::AROUSAL_BASE, Constants::AROUSAL_LABELS, Constants::AROUSAL_MULTIPLIER, Constants::DECAY_RATE, Constants::DEFAULT_EXPECTATION, Constants::EXPECTATION_CEILING, Constants::EXPECTATION_FLOOR, Constants::MAX_EXPECTATIONS, Constants::MAX_HISTORY, Constants::MAX_VIOLATIONS, Constants::VIOLATION_LABELS, Constants::VIOLATION_TYPES

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeViolationEngine

Returns a new instance of ViolationEngine.



14
15
16
17
18
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 14

def initialize
  @expectations = {}
  @violations   = []
  @history      = []
end

Instance Attribute Details

#historyObject (readonly)

Returns the value of attribute history.



12
13
14
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 12

def history
  @history
end

Instance Method Details

#adapt_expectation(expectation_id:, actual_value:) ⇒ Object



55
56
57
58
59
60
61
62
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 55

def adapt_expectation(expectation_id:, actual_value:)
  expectation = @expectations[expectation_id]
  return { success: false, reason: :not_found } unless expectation

  expectation.adapt!(actual_value: actual_value)
  record_history(:adapted, expectation_id)
  { success: true, new_expected: expectation.expected_value.round(3) }
end

#create_expectation(context:, domain:, expected_value: DEFAULT_EXPECTATION, tolerance: 0.2) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 20

def create_expectation(context:, domain:, expected_value: DEFAULT_EXPECTATION, tolerance: 0.2)
  evict_oldest if @expectations.size >= MAX_EXPECTATIONS

  expectation = Expectation.new(
    context:        context,
    domain:         domain,
    expected_value: expected_value,
    tolerance:      tolerance
  )
  @expectations[expectation.id] = expectation
  record_history(:created, expectation.id)
  expectation
end

#evaluate_against(expectation_id:, actual_value:) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 34

def evaluate_against(expectation_id:, actual_value:)
  expectation = @expectations[expectation_id]
  return { success: false, reason: :not_found } unless expectation

  result = expectation.evaluate(actual_value: actual_value)

  if result[:violated]
    @violations << {
      expectation_id: expectation_id,
      type:           result[:type],
      deviation:      result[:deviation],
      arousal:        result[:arousal],
      at:             Time.now.utc
    }
    trim_violations
  end

  record_history(:evaluated, expectation_id)
  { success: true }.merge(result)
end

#expectations_by_domain(domain:) ⇒ Object



72
73
74
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 72

def expectations_by_domain(domain:)
  @expectations.values.select { |exp| exp.domain == domain }
end

#most_violated(limit: 5) ⇒ Object



76
77
78
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 76

def most_violated(limit: 5)
  @expectations.values.sort_by { |exp| -exp.violation_count }.first(limit)
end

#positive_violation_ratioObject



88
89
90
91
92
93
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 88

def positive_violation_ratio
  return 0.0 if @violations.empty?

  positive = @violations.count { |vio| vio[:type] == :positive }
  (positive.to_f / @violations.size).round(3)
end

#recent_violations(limit: 10) ⇒ Object



64
65
66
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 64

def recent_violations(limit: 10)
  @violations.last(limit)
end

#to_hObject



95
96
97
98
99
100
101
102
103
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 95

def to_h
  {
    total_expectations: @expectations.size,
    total_violations:   @violations.size,
    violation_rate:     violation_rate,
    positive_ratio:     positive_violation_ratio,
    history_count:      @history.size
  }
end

#violation_rateObject



80
81
82
83
84
85
86
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 80

def violation_rate
  total = @expectations.values.sum(&:violation_count)
  evals = @history.count { |entry| entry[:event] == :evaluated }
  return 0.0 if evals.zero?

  (total.to_f / evals).round(3)
end

#violations_by_type(type:) ⇒ Object



68
69
70
# File 'lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb', line 68

def violations_by_type(type:)
  @violations.select { |vio| vio[:type] == type }
end