Class: Legion::Extensions::Agentic::Learning::Anchoring::Helpers::AnchorStore

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb

Constant Summary

Constants included from Constants

Constants::ADJUSTMENT_RATE, Constants::ANCHOR_DECAY, Constants::ANCHOR_FLOOR, Constants::ANCHOR_LABELS, Constants::DEFAULT_ANCHOR_WEIGHT, Constants::LOSS_AVERSION_FACTOR, Constants::MAX_ANCHORS_PER_DOMAIN, Constants::MAX_DOMAINS, Constants::REFERENCE_SHIFT_THRESHOLD

Instance Method Summary collapse

Constructor Details

#initializeAnchorStore

Returns a new instance of AnchorStore.



12
13
14
15
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 12

def initialize
  @anchors    = {} # domain (Symbol) -> Array<Anchor>
  @references = {} # domain (Symbol) -> Float (explicit reference point)
end

Instance Method Details

#add(value:, domain: :general) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 17

def add(value:, domain: :general)
  domain = domain.to_sym
  @anchors[domain] ||= []

  anchor = Anchor.new(value: value, domain: domain)
  @anchors[domain] << anchor

  if @anchors[domain].size > Constants::MAX_ANCHORS_PER_DOMAIN
    @anchors[domain] = @anchors[domain].sort_by(&:strength).last(Constants::MAX_ANCHORS_PER_DOMAIN)
  end

  prune_domains
  anchor
end

#decay_allObject



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 79

def decay_all
  pruned = 0
  @anchors.each_value do |arr|
    arr.each(&:decay)
    before = arr.size
    arr.reject! { |a| a.strength < Constants::ANCHOR_FLOOR }
    pruned += (before - arr.size)
  end
  @anchors.reject! { |_, arr| arr.empty? }
  pruned
end

#domainsObject



102
103
104
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 102

def domains
  @anchors.keys.select { |d| @anchors[d]&.any? }
end

#evaluate(estimate:, domain: :general) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 47

def evaluate(estimate:, domain: :general)
  domain  = domain.to_sym
  anchor  = strongest(domain: domain)
  return { anchored_estimate: estimate.to_f, pull_strength: 0.0, anchor_value: nil, correction: 0.0 } if anchor.nil?

  anchored  = anchor.pull(estimate: estimate)
  pull_str  = anchor.strength * Constants::DEFAULT_ANCHOR_WEIGHT
  correction = estimate.to_f - anchored

  anchor.reinforce(observed_value: estimate)

  {
    anchored_estimate: anchored,
    pull_strength:     pull_str,
    anchor_value:      anchor.value,
    correction:        correction
  }
end

#find(id:) ⇒ Object



40
41
42
43
44
45
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 40

def find(id:)
  @anchors.each_value do |arr|
    arr.each { |a| return a if a.id == id }
  end
  nil
end

#reference_frame(value:, domain: :general) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 66

def reference_frame(value:, domain: :general)
  domain    = domain.to_sym
  reference = @references[domain] || strongest(domain: domain)&.value
  return { perceived_value: value.to_f, gain_or_loss: :neutral, magnitude: 0.0 } if reference.nil?

  diff       = value.to_f - reference
  gain_loss  = diff >= 0 ? :gain : :loss
  raw_mag    = diff.abs
  magnitude  = gain_loss == :loss ? raw_mag * Constants::LOSS_AVERSION_FACTOR : raw_mag

  { perceived_value: value.to_f, gain_or_loss: gain_loss, magnitude: magnitude, reference: reference, raw_diff: diff }
end

#shift_reference(domain:, new_reference:) ⇒ Object



91
92
93
94
95
96
97
98
99
100
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 91

def shift_reference(domain:, new_reference:)
  domain              = domain.to_sym
  old                 = @references[domain]
  @references[domain] = new_reference.to_f

  diff = (new_reference.to_f - old.to_f).abs
  significant = diff >= Constants::REFERENCE_SHIFT_THRESHOLD

  { domain: domain, old_reference: old, new_reference: new_reference.to_f, significant: significant }
end

#strongest(domain: :general) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 32

def strongest(domain: :general)
  domain   = domain.to_sym
  anchors  = @anchors[domain]
  return nil if anchors.nil? || anchors.empty?

  anchors.max_by(&:strength)
end

#to_hObject



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb', line 106

def to_h
  total_anchors = @anchors.values.flatten.size
  domain_count  = domains.size

  {
    total_anchors: total_anchors,
    domain_count:  domain_count,
    domains:       domains,
    references:    @references.dup
  }
end