Skip to content

Module Overview

This page is the narrative map of the codebase: what each module does and how the pieces compose into the encode / retrieve pipeline. For the symbol-level reference (classes, methods, signatures) follow the links into the auto-generated API Reference. For the theory behind each layer see Research.

The 5-layer emotional model

emotional_memory implements Affective Field Theory (AFT) — emotion modelled as a distributed, dynamic, multi-layer field rather than a discrete label. Five layers are captured at encoding time:

Layer Class Theory Reference
1 CoreAffect Russell 1980 valence-arousal circumplex (+ PAD dominance) Affect
2 AffectiveMomentum Spinozist velocity + acceleration over a 3-point history Affect
3 MoodField Heidegger's slow-moving PAD mood background (EMA) Mood
4 AppraisalVector Scherer's 5 Stimulus Evaluation Checks → CoreAffect Appraisal
5 ResonanceLink Bidirectional associative graph; spreading activation (Collins & Loftus 1975) + Hebbian strengthening (Hebb 1949) Resonance

The runtime affective state that ties the first three layers together lives in AffectiveState; the Plutchik categorization of an (valence, arousal) pair into a labelled emotion lives in categorize.

Orchestration

Module Purpose API
engine.py EmotionalMemory, EmotionalMemoryConfig — sync orchestrator for the full encode/retrieve/observe/elaborate/prune pipeline Engine (sync)
async_engine.py AsyncEmotionalMemory — async facade mirroring the sync engine Engine (async)
models.py Memory, EmotionalTag — Pydantic models for stored memories and their affective annotations Models
retrieval.py 6-signal composite scoring, build_retrieval_plan(), retrieval config and explanation types Retrieval
decay.py ACT-R power-law decay with arousal modulation (McGaugh 2004) and spacing effect Decay
appraisal_schema.py Pluggable appraisal-theory schemas (Scherer CPM, OCC, GRID, custom) Appraisal Schema
query_classifier.py Pluggable query-type routing driving per-type retrieval weights Query Classifier
logging_config.py configure_logging() — package logger (always on; JSON optional) Logging
telemetry.py traced_span() — OpenTelemetry spans, no-op without the [otel] extra Telemetry
visualization.py 8 matplotlib plotting functions (optional [viz] extra) Visualization

Extension points (protocols)

Embedder, MemoryStore, and AffectiveStateStore are typing.Protocols — duck-typed, no inheritance required. Bring your own implementation, or use the bundled ones:

Module Purpose API
interfaces.py Embedder, MemoryStore, AffectiveStateStore protocols + SequentialEmbedder base class Interfaces
interfaces_async.py AsyncEmbedder, AsyncMemoryStore, AsyncAppraisalEngine protocols Interfaces
embedders/ SentenceTransformerEmbedder (production embedder, [sentence-transformers] extra) Embedders
stores/ SQLiteStore (sqlite-vec ANN), QdrantStore, ChromaStore — plus the in-memory reference store Stores
state_stores/ InMemoryAffectiveStateStore, SQLiteAffectiveStateStore, RedisAffectiveStateStore — persist runtime affect across sessions State Stores
appraisal_llm.py LLMAppraisalEngine (LLM-backed, cached) + KeywordAppraisalEngine (rule-based fallback) Appraisal
integrations/ LangChain (tutorial), mem0 (tutorial), and affective-fly host (tutorial) adapters —

Key data flow

encode — AppraisalVector → CoreAffect → AffectiveState.update() → EmotionalTag → [Plutchik label if auto_categorize] → embed → store → resonance links (forward + backward).

encode (dual-path, LeDoux 1996) — with dual_path_encoding=True and an appraisal engine: the fast path skips appraisal, uses the raw core_affect, and marks pending_appraisal=True; a later elaborate(memory_id) runs full appraisal and blends core affect (default 70% appraised / 30% raw).

retrieve — embed query → build_retrieval_plan() → Pass 1 (6-signal score, no spreading) → seed set → spreading_activation() (multi-hop BFS) → Pass 2 (activation boost) → per-memory APE computation → APE-gated reconsolidation → Hebbian strengthening on co-retrieved links → top-k. Use retrieve_with_explanations() to expose the per-signal breakdown. Optional retrieve-time paths: query_affect= / retrieve_with_query_appraisal() (Addendum T) score s3 against the query's own affect; retrieve_query_gated() (Addendum Y) routes neutral queries to cosine.

observe — update the affective state from content without storing a retrievable memory (useful for assistant turns or system events).

prune — iterate all memories, compute effective strength via decay, delete those below the threshold.

state persistence — save_state()/load_state() round-trip the affective state (including momentum history) as a JSON-safe dict; persist_state()/restore_persisted_state() delegate to the configured AffectiveStateStore.

See also

  • Mental Model — a 5-minute developer walkthrough of the same pipeline
  • Getting Started — install and run a first example
  • Research — the theoretical foundations of each layer