lex-episodic-buffer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/legion/extensions/episodic_buffer/actors/decay.rb +41 -0
- data/lib/legion/extensions/episodic_buffer/client.rb +21 -0
- data/lib/legion/extensions/episodic_buffer/helpers/constants.rb +32 -0
- data/lib/legion/extensions/episodic_buffer/helpers/episode.rb +100 -0
- data/lib/legion/extensions/episodic_buffer/helpers/episodic_binding.rb +53 -0
- data/lib/legion/extensions/episodic_buffer/helpers/episodic_store.rb +137 -0
- data/lib/legion/extensions/episodic_buffer/runners/episodic_buffer.rb +106 -0
- data/lib/legion/extensions/episodic_buffer/version.rb +9 -0
- data/lib/legion/extensions/episodic_buffer.rb +16 -0
- metadata +70 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1cd282b5729f073c270e41c5c9e96c351297f6fec517ac799d10a8357b908e45
|
|
4
|
+
data.tar.gz: bd8a210f73d8577c0e98eb5c040797f1e1dcc06592cace5a9c5af95f70488c41
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5c1841812d99d688556a87112f239909c8d8fb98ff6633c6269d29be81c26db79633597e4c4c9e9a56c42f89446a72abae1246ffb28f8603484865687b63744d
|
|
7
|
+
data.tar.gz: a2ffe44c971e1ee908855949938f461cfab27a9d4ff9244e9ed3bef00f5e64586f5bad10f6fd956c478d1053c64da2087e49297469f6b3f603bac68ef12fea85
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/actors/every'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module EpisodicBuffer
|
|
8
|
+
module Actor
|
|
9
|
+
class Decay < Legion::Extensions::Actors::Every
|
|
10
|
+
def runner_class
|
|
11
|
+
Legion::Extensions::EpisodicBuffer::Runners::EpisodicBuffer
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def runner_function
|
|
15
|
+
'update_episodic_buffer'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def time
|
|
19
|
+
15
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run_now?
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def use_runner?
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def check_subtask?
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def generate_task?
|
|
35
|
+
false
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/episodic_buffer/runners/episodic_buffer'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module EpisodicBuffer
|
|
8
|
+
class Client
|
|
9
|
+
include Legion::Extensions::EpisodicBuffer::Runners::EpisodicBuffer
|
|
10
|
+
|
|
11
|
+
def initialize(store: nil, **)
|
|
12
|
+
@default_store = store || Helpers::EpisodicStore.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
attr_reader :default_store
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module EpisodicBuffer
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_EPISODES = 30
|
|
9
|
+
MAX_BINDINGS_PER_EPISODE = 10
|
|
10
|
+
MAX_HISTORY = 200
|
|
11
|
+
EPISODE_TTL = 120
|
|
12
|
+
BINDING_STRENGTH_FLOOR = 0.05
|
|
13
|
+
BINDING_DECAY = 0.015
|
|
14
|
+
DEFAULT_BINDING_STRENGTH = 0.5
|
|
15
|
+
ATTENTION_BOOST = 0.2
|
|
16
|
+
REHEARSAL_BOOST = 0.15
|
|
17
|
+
INTEGRATION_THRESHOLD = 0.4
|
|
18
|
+
RECENTLY_ACCESSED_WINDOW = 30
|
|
19
|
+
|
|
20
|
+
MODALITIES = %i[verbal visual spatial semantic emotional procedural temporal].freeze
|
|
21
|
+
|
|
22
|
+
COHERENCE_LABELS = {
|
|
23
|
+
(0.0...0.3) => :fragmented,
|
|
24
|
+
(0.3...0.6) => :partial,
|
|
25
|
+
(0.6...0.85) => :coherent,
|
|
26
|
+
(0.85..1.0) => :vivid
|
|
27
|
+
}.freeze
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module EpisodicBuffer
|
|
8
|
+
module Helpers
|
|
9
|
+
class Episode
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :bindings, :created_at, :last_accessed
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@id = SecureRandom.uuid
|
|
16
|
+
@bindings = {}
|
|
17
|
+
@created_at = Time.now
|
|
18
|
+
@last_accessed = Time.now
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_binding(modality:, content:, source:, strength: DEFAULT_BINDING_STRENGTH)
|
|
22
|
+
return { added: false, reason: :capacity_full } if @bindings.size >= MAX_BINDINGS_PER_EPISODE
|
|
23
|
+
|
|
24
|
+
binding = EpisodicBinding.new(modality: modality, content: content, source: source, strength: strength)
|
|
25
|
+
@bindings[binding.id] = binding
|
|
26
|
+
{ added: true, binding_id: binding.id }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def remove_binding(binding_id:)
|
|
30
|
+
removed = !@bindings.delete(binding_id).nil?
|
|
31
|
+
{ removed: removed, binding_id: binding_id }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def attend
|
|
35
|
+
@last_accessed = Time.now
|
|
36
|
+
@bindings.each_value { |b| b.strengthen(ATTENTION_BOOST) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def rehearse
|
|
40
|
+
@last_accessed = Time.now
|
|
41
|
+
@bindings.each_value { |b| b.strengthen(REHEARSAL_BOOST) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def modalities_present
|
|
45
|
+
@bindings.values.map(&:modality).uniq
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def coherence
|
|
49
|
+
integrated = @bindings.values.select(&:integrated?)
|
|
50
|
+
return 0.0 if integrated.empty?
|
|
51
|
+
|
|
52
|
+
integrated.sum(&:strength) / integrated.size
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def coherence_label
|
|
56
|
+
score = coherence
|
|
57
|
+
COHERENCE_LABELS.each do |range, label|
|
|
58
|
+
return label if range.cover?(score)
|
|
59
|
+
end
|
|
60
|
+
:fragmented
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def multimodal?
|
|
64
|
+
modalities_present.size >= 2
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def expired?
|
|
68
|
+
age = Time.now - @created_at
|
|
69
|
+
age > EPISODE_TTL && !recently_accessed?
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def decay_bindings
|
|
73
|
+
@bindings.each_value(&:decay)
|
|
74
|
+
@bindings.delete_if { |_, b| b.faded? }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_h
|
|
78
|
+
{
|
|
79
|
+
id: @id,
|
|
80
|
+
bindings: @bindings.transform_values(&:to_h),
|
|
81
|
+
created_at: @created_at,
|
|
82
|
+
last_accessed: @last_accessed,
|
|
83
|
+
modalities: modalities_present,
|
|
84
|
+
coherence: coherence,
|
|
85
|
+
coherence_label: coherence_label,
|
|
86
|
+
multimodal: multimodal?,
|
|
87
|
+
binding_count: @bindings.size
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def recently_accessed?
|
|
94
|
+
(Time.now - @last_accessed) <= RECENTLY_ACCESSED_WINDOW
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module EpisodicBuffer
|
|
8
|
+
module Helpers
|
|
9
|
+
class EpisodicBinding
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :modality, :content, :source, :strength
|
|
13
|
+
|
|
14
|
+
def initialize(modality:, content:, source:, strength: DEFAULT_BINDING_STRENGTH)
|
|
15
|
+
raise ArgumentError, "invalid modality: #{modality}" unless MODALITIES.include?(modality.to_sym)
|
|
16
|
+
|
|
17
|
+
@id = SecureRandom.uuid
|
|
18
|
+
@modality = modality.to_sym
|
|
19
|
+
@content = content
|
|
20
|
+
@source = source.to_sym
|
|
21
|
+
@strength = strength.to_f.clamp(0.0, 1.0)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def decay
|
|
25
|
+
@strength = [@strength - BINDING_DECAY, 0.0].max
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def strengthen(amount)
|
|
29
|
+
@strength = [@strength + amount.to_f, 1.0].min
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def integrated?
|
|
33
|
+
@strength >= INTEGRATION_THRESHOLD
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def faded?
|
|
37
|
+
@strength <= BINDING_STRENGTH_FLOOR
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_h
|
|
41
|
+
{
|
|
42
|
+
id: @id,
|
|
43
|
+
modality: @modality,
|
|
44
|
+
content: @content,
|
|
45
|
+
source: @source,
|
|
46
|
+
strength: @strength
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module EpisodicBuffer
|
|
6
|
+
module Helpers
|
|
7
|
+
class EpisodicStore
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :episodes, :history
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@episodes = {}
|
|
14
|
+
@history = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_episode
|
|
18
|
+
evict_if_full
|
|
19
|
+
episode = Episode.new
|
|
20
|
+
@episodes[episode.id] = episode
|
|
21
|
+
record_history(:create, episode.id)
|
|
22
|
+
episode
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_to_episode(episode_id:, modality:, content:, source:, strength: DEFAULT_BINDING_STRENGTH)
|
|
26
|
+
episode = @episodes[episode_id]
|
|
27
|
+
return { success: false, reason: :episode_not_found } unless episode
|
|
28
|
+
|
|
29
|
+
result = episode.add_binding(modality: modality, content: content, source: source, strength: strength)
|
|
30
|
+
record_history(:add_binding, episode_id) if result[:added]
|
|
31
|
+
result
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def attend_episode(episode_id:)
|
|
35
|
+
episode = @episodes[episode_id]
|
|
36
|
+
return { success: false, reason: :episode_not_found } unless episode
|
|
37
|
+
|
|
38
|
+
episode.attend
|
|
39
|
+
record_history(:attend, episode_id)
|
|
40
|
+
{ success: true, episode_id: episode_id }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def rehearse_episode(episode_id:)
|
|
44
|
+
episode = @episodes[episode_id]
|
|
45
|
+
return { success: false, reason: :episode_not_found } unless episode
|
|
46
|
+
|
|
47
|
+
episode.rehearse
|
|
48
|
+
record_history(:rehearse, episode_id)
|
|
49
|
+
{ success: true, episode_id: episode_id }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def integrate(episode_id:)
|
|
53
|
+
episode = @episodes[episode_id]
|
|
54
|
+
return { integrated: false, reason: :episode_not_found } unless episode
|
|
55
|
+
|
|
56
|
+
coherence = episode.coherence
|
|
57
|
+
integrated = coherence >= INTEGRATION_THRESHOLD
|
|
58
|
+
{
|
|
59
|
+
integrated: integrated,
|
|
60
|
+
episode_id: episode_id,
|
|
61
|
+
coherence: coherence,
|
|
62
|
+
coherence_label: episode.coherence_label
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def retrieve_by_modality(modality:)
|
|
67
|
+
mod = modality.to_sym
|
|
68
|
+
@episodes.values.select { |ep| ep.modalities_present.include?(mod) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def retrieve_multimodal
|
|
72
|
+
@episodes.values.select(&:multimodal?)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def most_coherent(limit: 5)
|
|
76
|
+
@episodes.values
|
|
77
|
+
.sort_by { |ep| -ep.coherence }
|
|
78
|
+
.first(limit)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def tick
|
|
82
|
+
expired_count = 0
|
|
83
|
+
@episodes.delete_if do |_, ep|
|
|
84
|
+
ep.decay_bindings
|
|
85
|
+
if ep.expired?
|
|
86
|
+
expired_count += 1
|
|
87
|
+
true
|
|
88
|
+
else
|
|
89
|
+
false
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
{ decayed: @episodes.size, expired: expired_count }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def count
|
|
96
|
+
@episodes.size
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def to_h
|
|
100
|
+
{
|
|
101
|
+
episode_count: @episodes.size,
|
|
102
|
+
history_size: @history.size,
|
|
103
|
+
multimodal_count: retrieve_multimodal.size,
|
|
104
|
+
avg_coherence: average_coherence
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def evict_if_full
|
|
111
|
+
return unless @episodes.size >= MAX_EPISODES
|
|
112
|
+
|
|
113
|
+
expired = @episodes.values.select(&:expired?)
|
|
114
|
+
if expired.any?
|
|
115
|
+
oldest = expired.min_by(&:created_at)
|
|
116
|
+
@episodes.delete(oldest.id)
|
|
117
|
+
else
|
|
118
|
+
lowest = @episodes.values.min_by(&:coherence)
|
|
119
|
+
@episodes.delete(lowest.id) if lowest
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def record_history(event, episode_id)
|
|
124
|
+
@history << { event: event, episode_id: episode_id, at: Time.now }
|
|
125
|
+
@history.shift if @history.size > MAX_HISTORY
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def average_coherence
|
|
129
|
+
return 0.0 if @episodes.empty?
|
|
130
|
+
|
|
131
|
+
@episodes.values.sum(&:coherence) / @episodes.size
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module EpisodicBuffer
|
|
6
|
+
module Runners
|
|
7
|
+
module EpisodicBuffer
|
|
8
|
+
def create_episode(**)
|
|
9
|
+
store = default_store
|
|
10
|
+
episode = store.create_episode
|
|
11
|
+
Legion::Logging.debug "[episodic_buffer] created episode id=#{episode.id[0..7]}"
|
|
12
|
+
{ success: true, episode_id: episode.id, created_at: episode.created_at }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_binding(episode_id:, modality:, content:, source:,
|
|
16
|
+
strength: Helpers::Constants::DEFAULT_BINDING_STRENGTH, **)
|
|
17
|
+
unless Helpers::Constants::MODALITIES.include?(modality.to_sym)
|
|
18
|
+
raise ArgumentError, "invalid modality: #{modality}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
store = default_store
|
|
22
|
+
result = store.add_to_episode(
|
|
23
|
+
episode_id: episode_id,
|
|
24
|
+
modality: modality.to_sym,
|
|
25
|
+
content: content,
|
|
26
|
+
source: source,
|
|
27
|
+
strength: strength
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
if result[:added]
|
|
31
|
+
Legion::Logging.debug "[episodic_buffer] add_binding ep=#{episode_id[0..7]} mod=#{modality}"
|
|
32
|
+
{ success: true, episode_id: episode_id, binding_id: result[:binding_id] }
|
|
33
|
+
else
|
|
34
|
+
Legion::Logging.debug "[episodic_buffer] add_binding failed ep=#{episode_id[0..7]} r=#{result[:reason]}"
|
|
35
|
+
{ success: false, episode_id: episode_id, reason: result[:reason] }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def attend_episode(episode_id:, **)
|
|
40
|
+
store = default_store
|
|
41
|
+
result = store.attend_episode(episode_id: episode_id)
|
|
42
|
+
Legion::Logging.debug "[episodic_buffer] attend ep=#{episode_id[0..7]} success=#{result[:success]}"
|
|
43
|
+
result.merge(success: result[:success])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def rehearse_episode(episode_id:, **)
|
|
47
|
+
store = default_store
|
|
48
|
+
result = store.rehearse_episode(episode_id: episode_id)
|
|
49
|
+
Legion::Logging.debug "[episodic_buffer] rehearse ep=#{episode_id[0..7]} success=#{result[:success]}"
|
|
50
|
+
result.merge(success: result[:success])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def check_integration(episode_id:, **)
|
|
54
|
+
store = default_store
|
|
55
|
+
result = store.integrate(episode_id: episode_id)
|
|
56
|
+
Legion::Logging.debug "[episodic_buffer] check_integration ep=#{episode_id[0..7]} ok=#{result[:integrated]}"
|
|
57
|
+
result.merge(success: true)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def retrieve_by_modality(modality:, **)
|
|
61
|
+
store = default_store
|
|
62
|
+
episodes = store.retrieve_by_modality(modality: modality.to_sym)
|
|
63
|
+
Legion::Logging.debug "[episodic_buffer] retrieve_by_modality mod=#{modality} count=#{episodes.size}"
|
|
64
|
+
{ success: true, modality: modality, count: episodes.size, episodes: episodes.map(&:to_h) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def retrieve_multimodal(**)
|
|
68
|
+
store = default_store
|
|
69
|
+
episodes = store.retrieve_multimodal
|
|
70
|
+
Legion::Logging.debug "[episodic_buffer] retrieve_multimodal count=#{episodes.size}"
|
|
71
|
+
{ success: true, count: episodes.size, episodes: episodes.map(&:to_h) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def most_coherent(limit: 5, **)
|
|
75
|
+
store = default_store
|
|
76
|
+
episodes = store.most_coherent(limit: limit)
|
|
77
|
+
Legion::Logging.debug "[episodic_buffer] most_coherent limit=#{limit} returned=#{episodes.size}"
|
|
78
|
+
{ success: true, count: episodes.size, episodes: episodes.map(&:to_h) }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def update_episodic_buffer(**)
|
|
82
|
+
store = default_store
|
|
83
|
+
result = store.tick
|
|
84
|
+
Legion::Logging.debug "[episodic_buffer] tick decayed=#{result[:decayed]} expired=#{result[:expired]}"
|
|
85
|
+
{ success: true }.merge(result)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def episodic_buffer_stats(**)
|
|
89
|
+
store = default_store
|
|
90
|
+
stats = store.to_h
|
|
91
|
+
Legion::Logging.debug "[episodic_buffer] stats episodes=#{stats[:episode_count]}"
|
|
92
|
+
{ success: true }.merge(stats)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def default_store
|
|
98
|
+
@default_store ||= Helpers::EpisodicStore.new
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/episodic_buffer/version'
|
|
4
|
+
require 'legion/extensions/episodic_buffer/helpers/constants'
|
|
5
|
+
require 'legion/extensions/episodic_buffer/helpers/episodic_binding'
|
|
6
|
+
require 'legion/extensions/episodic_buffer/helpers/episode'
|
|
7
|
+
require 'legion/extensions/episodic_buffer/helpers/episodic_store'
|
|
8
|
+
require 'legion/extensions/episodic_buffer/runners/episodic_buffer'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module EpisodicBuffer
|
|
13
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-episodic-buffer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-gaia
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Baddeley's episodic buffer — binds multimodal information into coherent
|
|
27
|
+
episodic representations for the LegionIO cognitive architecture
|
|
28
|
+
email:
|
|
29
|
+
- matthewdiverson@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/legion/extensions/episodic_buffer.rb
|
|
35
|
+
- lib/legion/extensions/episodic_buffer/actors/decay.rb
|
|
36
|
+
- lib/legion/extensions/episodic_buffer/client.rb
|
|
37
|
+
- lib/legion/extensions/episodic_buffer/helpers/constants.rb
|
|
38
|
+
- lib/legion/extensions/episodic_buffer/helpers/episode.rb
|
|
39
|
+
- lib/legion/extensions/episodic_buffer/helpers/episodic_binding.rb
|
|
40
|
+
- lib/legion/extensions/episodic_buffer/helpers/episodic_store.rb
|
|
41
|
+
- lib/legion/extensions/episodic_buffer/runners/episodic_buffer.rb
|
|
42
|
+
- lib/legion/extensions/episodic_buffer/version.rb
|
|
43
|
+
homepage: https://github.com/LegionIO/lex-episodic-buffer
|
|
44
|
+
licenses:
|
|
45
|
+
- MIT
|
|
46
|
+
metadata:
|
|
47
|
+
homepage_uri: https://github.com/LegionIO/lex-episodic-buffer
|
|
48
|
+
source_code_uri: https://github.com/LegionIO/lex-episodic-buffer
|
|
49
|
+
documentation_uri: https://github.com/LegionIO/lex-episodic-buffer
|
|
50
|
+
changelog_uri: https://github.com/LegionIO/lex-episodic-buffer
|
|
51
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-episodic-buffer/issues
|
|
52
|
+
rubygems_mfa_required: 'true'
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
require_paths:
|
|
55
|
+
- lib
|
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.4'
|
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
requirements: []
|
|
67
|
+
rubygems_version: 3.6.9
|
|
68
|
+
specification_version: 4
|
|
69
|
+
summary: LEX Episodic Buffer
|
|
70
|
+
test_files: []
|