Class: Legion::Extensions::Agentic::Memory::SemanticPriming::Helpers::PrimingNetwork

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb

Constant Summary

Constants included from Constants

Constants::ACTIVATION_DECAY, Constants::ACTIVATION_LABELS, Constants::ACTIVATION_THRESHOLD, Constants::DEFAULT_ACTIVATION, Constants::DEFAULT_WEIGHT, Constants::DEPTH_DECAY_FACTOR, Constants::MAX_ACTIVATION, Constants::MAX_CONNECTIONS, Constants::MAX_NODES, Constants::MAX_SPREAD_DEPTH, Constants::MIN_WEIGHT, Constants::NODE_TYPES, Constants::PRIMING_BOOST, Constants::PRIMING_LABELS, Constants::RESTING_ACTIVATION, Constants::SPREADING_FACTOR, Constants::WEIGHT_DECAY_RATE, Constants::WEIGHT_GROWTH_RATE, Constants::WEIGHT_LABELS

Instance Method Summary collapse

Constructor Details

#initializePrimingNetwork

Returns a new instance of PrimingNetwork.



12
13
14
15
16
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 12

def initialize
  @nodes       = {}
  @connections = {}
  @adjacency   = Hash.new { |h, k| h[k] = [] }
end

Instance Method Details

#active_nodesObject



104
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 104

def active_nodes = @nodes.values.select(&:active?)

#add_node(label:, node_type: :concept) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 18

def add_node(label:, node_type: :concept)
  return nil unless NODE_TYPES.include?(node_type)

  prune_nodes_if_needed
  node = SemanticNode.new(label: label, node_type: node_type)
  @nodes[node.id] = node
  node
end

#average_activationObject



108
109
110
111
112
113
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 108

def average_activation
  return DEFAULT_ACTIVATION if @nodes.empty?

  vals = @nodes.values.map(&:activation)
  (vals.sum / vals.size).round(10)
end

#average_connection_weightObject



115
116
117
118
119
120
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 115

def average_connection_weight
  return DEFAULT_WEIGHT if @connections.empty?

  vals = @connections.values.map(&:weight)
  (vals.sum / vals.size).round(10)
end

#connect(source_id:, target_id:, weight: DEFAULT_WEIGHT) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 37

def connect(source_id:, target_id:, weight: DEFAULT_WEIGHT)
  return nil unless @nodes[source_id] && @nodes[target_id]
  return nil if source_id == target_id

  prune_connections_if_needed
  conn = Connection.new(source_id: source_id, target_id: target_id, weight: weight)
  @connections[conn.id] = conn
  @adjacency[source_id] << conn.id
  @adjacency[target_id] << conn.id
  conn
end

#connection_between(source_id:, target_id:) ⇒ Object



96
97
98
99
100
101
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 96

def connection_between(source_id:, target_id:)
  @connections.values.find do |c|
    (c.source_id == source_id && c.target_id == target_id) ||
      (c.source_id == target_id && c.target_id == source_id)
  end
end

#decay_all!Object



75
76
77
78
79
80
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 75

def decay_all!
  @nodes.each_value(&:decay!)
  @connections.each_value { |c| c.weaken!(amount: WEIGHT_DECAY_RATE) }
  prune_weak_connections
  { nodes_decayed: @nodes.size, connections_remaining: @connections.size }
end

#find_node_by_label(label:) ⇒ Object



83
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 83

def find_node_by_label(label:) = @nodes.values.find { |n| n.label == label.to_s }

#most_primed(limit: 5) ⇒ Object



105
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 105

def most_primed(limit: 5) = @nodes.values.sort_by { |n| -n.activation }.first(limit)

#neighbors(node_id:) ⇒ Object



85
86
87
88
89
90
91
92
93
94
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 85

def neighbors(node_id:)
  conn_ids = @adjacency[node_id] || []
  conn_ids.filter_map do |cid|
    conn = @connections[cid]
    next unless conn

    other_id = conn.source_id == node_id ? conn.target_id : conn.source_id
    @nodes[other_id]
  end
end

#network_densityObject



122
123
124
125
126
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 122

def network_density
  return 0.0 if @nodes.size < 2

  (@connections.size.to_f / (@nodes.size * (@nodes.size - 1) / 2)).round(10)
end

#prime_and_spread(node_id:, amount: PRIMING_BOOST, depth: MAX_SPREAD_DEPTH) ⇒ Object



66
67
68
69
70
71
72
73
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 66

def prime_and_spread(node_id:, amount: PRIMING_BOOST, depth: MAX_SPREAD_DEPTH)
  node = prime_node(node_id: node_id, amount: amount)
  return nil unless node

  node.access!
  spread = spread_activation(source_id: node_id, depth: depth)
  { primed_node: node.to_h, spread: spread }
end

#prime_node(node_id:, amount: PRIMING_BOOST) ⇒ Object



49
50
51
52
53
54
55
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 49

def prime_node(node_id:, amount: PRIMING_BOOST)
  node = @nodes[node_id]
  return nil unless node

  node.prime!(amount: amount)
  node
end

#primed_nodesObject



103
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 103

def primed_nodes = @nodes.values.select(&:primed?)

#priming_reportObject



128
129
130
131
132
133
134
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 128

def priming_report
  to_h.merge(
    average_weight:        average_connection_weight,
    most_primed:           most_primed(limit: 3).map(&:to_h),
    strongest_connections: strongest_connections(limit: 3).map(&:to_h)
  )
end

#remove_node(node_id:) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 27

def remove_node(node_id:)
  node = @nodes.delete(node_id)
  return nil unless node

  @adjacency.delete(node_id)
  @adjacency.each_value { |list| list.reject! { |cid| connection_involves?(cid, node_id) } }
  @connections.reject! { |_, c| c.source_id == node_id || c.target_id == node_id }
  node
end

#reset_all!Object



82
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 82

def reset_all! = @nodes.each_value(&:reset!) && { nodes_reset: @nodes.size }

#spread_activation(source_id:, depth: MAX_SPREAD_DEPTH) ⇒ Object



57
58
59
60
61
62
63
64
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 57

def spread_activation(source_id:, depth: MAX_SPREAD_DEPTH)
  source = @nodes[source_id]
  return nil unless source

  activated = {}
  spread_recursive(source_id, source.activation, depth, 0, activated)
  activated.map { |nid, amount| { node_id: nid, label: @nodes[nid]&.label, activation_added: amount } }
end

#strongest_connections(limit: 5) ⇒ Object



106
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 106

def strongest_connections(limit: 5) = @connections.values.sort_by { |c| -c.weight }.first(limit)

#to_hObject



136
137
138
139
140
141
142
143
144
145
# File 'lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb', line 136

def to_h
  {
    total_nodes:        @nodes.size,
    total_connections:  @connections.size,
    primed_count:       primed_nodes.size,
    active_count:       active_nodes.size,
    average_activation: average_activation,
    network_density:    network_density
  }
end