Class: Llmemory::LongTerm::Episodic::Episode

Inherits:
Object
  • Object
show all
Defined in:
lib/llmemory/long_term/episodic/episode.rb

Overview

An Episode is a trajectory of an agent’s experience: an ordered list of steps (observation -> action -> result) plus a summary, an outcome label and an importance score. This is CoALA’s “episodic memory” — distinct from semantic memory (facts), it stores what happened so it can later be retrieved as examples or distilled into semantic knowledge (see P2, reflection).

Constant Summary collapse

STEP_KEYS =
%i[observation action result timestamp].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id:, user_id:, steps: [], summary: nil, outcome: nil, importance: 0.5, provenance: nil, created_at: nil) ⇒ Episode

Returns a new instance of Episode.



19
20
21
22
23
24
25
26
27
28
# File 'lib/llmemory/long_term/episodic/episode.rb', line 19

def initialize(id:, user_id:, steps: [], summary: nil, outcome: nil, importance: 0.5, provenance: nil, created_at: nil)
  @id = id
  @user_id = user_id
  @steps = self.class.normalize_steps(steps)
  @summary = summary
  @outcome = outcome
  @importance = importance.nil? ? 0.5 : importance.to_f
  @provenance = provenance
  @created_at = created_at || Time.now
end

Instance Attribute Details

#created_atObject (readonly)

Returns the value of attribute created_at.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def created_at
  @created_at
end

#idObject (readonly)

Returns the value of attribute id.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def id
  @id
end

#importanceObject (readonly)

Returns the value of attribute importance.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def importance
  @importance
end

#outcomeObject (readonly)

Returns the value of attribute outcome.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def outcome
  @outcome
end

#provenanceObject (readonly)

Returns the value of attribute provenance.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def provenance
  @provenance
end

#stepsObject (readonly)

Returns the value of attribute steps.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def steps
  @steps
end

#summaryObject (readonly)

Returns the value of attribute summary.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def summary
  @summary
end

#user_idObject (readonly)

Returns the value of attribute user_id.



15
16
17
# File 'lib/llmemory/long_term/episodic/episode.rb', line 15

def user_id
  @user_id
end

Class Method Details

.from_h(hash) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/llmemory/long_term/episodic/episode.rb', line 59

def self.from_h(hash)
  new(
    id: hash[:id] || hash["id"],
    user_id: hash[:user_id] || hash["user_id"],
    steps: hash[:steps] || hash["steps"] || [],
    summary: hash[:summary] || hash["summary"],
    outcome: hash[:outcome] || hash["outcome"],
    importance: hash[:importance] || hash["importance"] || 0.5,
    provenance: hash[:provenance] || hash["provenance"],
    created_at: parse_created_at(hash[:created_at] || hash["created_at"])
  )
end

.normalize_steps(steps) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/llmemory/long_term/episodic/episode.rb', line 42

def self.normalize_steps(steps)
  Array(steps).filter_map do |step|
    next nil unless step.is_a?(Hash)
    {
      observation: step[:observation] || step["observation"],
      action: step[:action] || step["action"],
      result: step[:result] || step["result"],
      timestamp: normalize_time(step[:timestamp] || step["timestamp"])
    }
  end
end

.normalize_time(value) ⇒ Object



54
55
56
57
# File 'lib/llmemory/long_term/episodic/episode.rb', line 54

def self.normalize_time(value)
  return nil if value.nil?
  value.respond_to?(:iso8601) ? value.iso8601 : value.to_s
end

.parse_created_at(value) ⇒ Object



72
73
74
75
76
77
# File 'lib/llmemory/long_term/episodic/episode.rb', line 72

def self.parse_created_at(value)
  return value if value.nil? || value.is_a?(Time)
  Time.parse(value.to_s)
rescue ArgumentError
  nil
end

Instance Method Details

#searchable_textObject

Flat, searchable representation used for keyword retrieval and, in the future, embedding. Combines summary, outcome and every step field.



32
33
34
35
36
37
38
39
40
# File 'lib/llmemory/long_term/episodic/episode.rb', line 32

def searchable_text
  parts = [summary, outcome]
  steps.each do |s|
    parts << s[:observation]
    parts << s[:action]
    parts << s[:result]
  end
  parts.compact.map(&:to_s).reject(&:empty?).join("\n")
end

#to_hObject



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/llmemory/long_term/episodic/episode.rb', line 79

def to_h
  {
    id: id,
    user_id: user_id,
    steps: steps,
    summary: summary,
    outcome: outcome,
    importance: importance,
    provenance: provenance,
    created_at: created_at.respond_to?(:iso8601) ? created_at.iso8601(6) : created_at
  }
end