Class: Engram::Consolidators::LLMConsolidator

Inherits:
Object
  • Object
show all
Includes:
Ports::Consolidator
Defined in:
lib/engram/consolidators/llm_consolidator.rb

Overview

LLM-as-judge consolidation. For each candidate it gathers the nearest existing memories (vector pre-filter) and asks the model, in a single batched call, what to do: add / update / forget / noop.

Constant Summary collapse

SYSTEM =
<<~PROMPT
  You maintain a user's long-term memory. For each candidate fact, decide how it
  relates to the existing memories provided:
    - "add":    genuinely new information
    - "update": supersedes a specific existing memory (e.g. a changed preference)
    - "forget": an existing memory is now contradicted or obsolete
    - "noop":   already known, or not worth storing
  Use "update"/"forget" only with the id of an existing memory shown for that candidate.
  Return one decision per candidate, referencing it by its index.
PROMPT
SCHEMA =
{
  type: "object",
  properties: {
    decisions: {
      type: "array",
      items: {
        type: "object",
        properties: {
          index: {type: "integer"},
          action: {type: "string", enum: %w[add update forget noop]},
          target_id: {type: %w[integer string null]},
          reason: {type: "string"}
        },
        required: %w[index action]
      }
    }
  },
  required: %w[decisions]
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(store:, completion:, neighbors: 5) ⇒ LLMConsolidator

Returns a new instance of LLMConsolidator.



44
45
46
47
48
# File 'lib/engram/consolidators/llm_consolidator.rb', line 44

def initialize(store:, completion:, neighbors: 5)
  @store = store
  @completion = completion
  @neighbors = neighbors
end

Instance Method Details

#reconcile_all(candidates:, scope:) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/engram/consolidators/llm_consolidator.rb', line 50

def reconcile_all(candidates:, scope:)
  candidates = Array(candidates)
  return [] if candidates.empty?

  result = @completion.complete(
    system: SYSTEM,
    user: JSON.generate(payload(candidates, scope)),
    schema: SCHEMA
  )
  map_decisions(decisions(result), candidates)
end