Class: Engram::Memory

Inherits:
Object
  • Object
show all
Defined in:
lib/engram/memory.rb

Overview

The friendly facade. Bound to one ‘scope` (an owner), it wires the configured store and embedder into the use cases. This is what `user.memory` returns in Rails.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope:, store: Engram.config.store, embedder: Engram.config.embedder) ⇒ Memory

Returns a new instance of Memory.



9
10
11
12
13
# File 'lib/engram/memory.rb', line 9

def initialize(scope:, store: Engram.config.store, embedder: Engram.config.embedder)
  @scope = scope
  @store = store
  @embedder = embedder
end

Instance Attribute Details

#scopeObject (readonly)

Returns the value of attribute scope.



7
8
9
# File 'lib/engram/memory.rb', line 7

def scope
  @scope
end

Instance Method Details

#add(content, kind: :fact, importance: 1.0, metadata: {}) ⇒ Object

Persist a memory record of the given kind. Returns nil when the configured persistence policy rejects the record.



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/engram/memory.rb', line 17

def add(content, kind: :fact, importance: 1.0, metadata: {})
  Engram::Instrumentation.instrument("add", Engram::Instrumentation.payload(scope: scope, store: @store, kind: kind)) do
    record = Record.new(
      content: content,
      scope: scope,
      embedding: @embedder.embed(content),
      kind: kind,
      importance: importance,
      metadata: 
    )
    persist(record)
  end
end

#allObject



84
85
86
# File 'lib/engram/memory.rb', line 84

def all
  @store.all(scope: scope)
end

#forget_stale(older_than:, min_importance: Float::INFINITY) ⇒ Object

Prune stale memories. ‘older_than` is a duration in seconds; `min_importance` keeps memories at or above that importance even when old. Returns the forgotten records.



90
91
92
93
# File 'lib/engram/memory.rb', line 90

def forget_stale(older_than:, min_importance: Float::INFINITY)
  UseCases::Forget.new(store: @store)
    .call(scope: scope, older_than: older_than, min_importance: min_importance)
end

#inject_into(prompt, query:, limit: Engram.config.default_limit, kinds: nil) ⇒ Object

Recall, then inject into a prompt string.



44
45
46
47
# File 'lib/engram/memory.rb', line 44

def inject_into(prompt, query:, limit: Engram.config.default_limit, kinds: nil)
  memories = recall(query, limit: limit, kinds: kinds)
  UseCases::Inject.new.call(prompt: prompt, memories: memories)
end

#observe(messages, completion: Engram.config.completion) ⇒ Object

Derive memories from a conversation turn and consolidate them (v0.2). ‘messages` is an Array of content: hashes (or plain strings). Returns the Array<Decision> applied. Requires a configured Completion.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/engram/memory.rb', line 52

def observe(messages, completion: Engram.config.completion)
  if completion.nil?
    raise Engram::Error, "observe requires a Completion. Set Engram.config.completion."
  end

  UseCases::Observe.new(
    store: @store,
    extractor: build_extractor(completion),
    consolidator: build_consolidator(completion),
    processed_turns: Engram.config.processed_turns,
    embedder: @embedder
  ).call(
    messages: messages,
    scope: scope,
    idempotency_key: TurnDigest.digest(scope: scope, messages: messages)
  )
end

#observe_later(messages) ⇒ Object

Enqueue observation as a background job (Rails only).



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/engram/memory.rb', line 71

def observe_later(messages)
  unless defined?(Engram::ObserveJob)
    raise Engram::Error, "observe_later needs ActiveJob (Rails). Use #observe outside Rails."
  end

  Engram::Instrumentation.instrument(
    "observe_later",
    Engram::Instrumentation.payload(scope: scope, store: @store, message_count: messages.size)
  ) do
    Engram::ObserveJob.perform_later(scope, messages)
  end
end

#recall(query, limit: Engram.config.default_limit, kinds: nil) ⇒ Object

Return the most relevant memories for a query.



32
33
34
35
36
37
38
39
40
41
# File 'lib/engram/memory.rb', line 32

def recall(query, limit: Engram.config.default_limit, kinds: nil)
  UseCases::Recall.new(
    store: @store,
    embedder: @embedder,
    importance_weight: Engram.config.importance_weight,
    recency_weight: Engram.config.recency_weight,
    recency_halflife: Engram.config.recency_halflife,
    touch: Engram.config.touch_on_recall
  ).call(query, scope: scope, limit: limit, kinds: kinds)
end