Skip to content

Getting Started

Install emotional_memory, encode your first memories, and run an emotionally-weighted retrieval. The install recipes and quickstart below are sourced from the top-level README.md (SSOT) so the PyPI page and this guide never drift.

Installation

uv pip install emotional-memory
uv pip install "emotional-memory[sentence-transformers]"  # real semantic embeddings (recommended)
uv pip install "emotional-memory[sqlite]"                 # SQLite persistence via sqlite-vec
uv pip install "emotional-memory[qdrant]"                 # Qdrant vector database
uv pip install "emotional-memory[chroma]"                 # ChromaDB HTTP client
uv pip install "emotional-memory[otel]"                   # OpenTelemetry tracing (no-op without this extra)
uv pip install "emotional-memory[redis]"                  # shared affective-state persistence via Redis
uv pip install "emotional-memory[viz]"                    # matplotlib visualization
uv pip install "emotional-memory[dotenv]"                 # .env file loading via python-dotenv

For development:

git clone https://github.com/gianlucamazza/emotional-memory
cd emotional-memory
make install
# optional local demo stack:
make install-demo

Quickstart

Try it in the browser: Hugging Face demo — a Gradio chat that encodes messages as memories and recalls them with affect-aware ranking (a free Space; it may take a few seconds to wake up). Benchmark dataset on Hugging Face: emotional-memory-benchmarks.

uv pip install "emotional-memory[sentence-transformers]"
from emotional_memory import EmotionalMemory, InMemoryStore, CoreAffect
from emotional_memory.embedders import SentenceTransformerEmbedder

em = EmotionalMemory(
    store=InMemoryStore(),
    embedder=SentenceTransformerEmbedder(),  # all-MiniLM-L6-v2 by default
)

# Set current emotional state
em.set_affect(CoreAffect(valence=0.8, arousal=0.6))

# Encode memories — each one captures the full affective context
em.encode("Just shipped the feature after three hard weeks.")
em.encode("Team celebration in the office.", metadata={"source": "slack"})

# Retrieve — ranked by semantic relevance AND emotional congruence
results = em.retrieve("difficult project success", top_k=3)
for mem in results:
    print(mem.content, mem.tag.core_affect)

# Or inspect why a memory ranked where it did
explained = em.retrieve_with_explanations("difficult project success", top_k=1)
top = explained[0]
print(top.score)
print(top.breakdown.raw_signals)

Bring your own embedder — any object with .embed(text) -> list[float] works:

class MyEmbedder:
    def embed(self, text: str) -> list[float]: ...
    def embed_batch(self, texts: list[str]) -> list[list[float]]: ...

Or subclass SequentialEmbedder and implement only embed() — embed_batch() is provided.

Async

import asyncio
from emotional_memory import EmotionalMemory, InMemoryStore, as_async
from emotional_memory.embedders import SentenceTransformerEmbedder

sync_em = EmotionalMemory(store=InMemoryStore(), embedder=SentenceTransformerEmbedder())
em = as_async(sync_em)  # wraps sync components with asyncio.to_thread bridges

async def main():
    await em.encode("Meeting went surprisingly well today.")
    results = await em.retrieve("work meeting", top_k=3)

asyncio.run(main())

For native async embedders or stores, construct AsyncEmotionalMemory directly with SyncToAsyncEmbedder, SyncToAsyncStore, or your own AsyncEmbedder/AsyncMemoryStore.

Next steps

  • Mental Model — a 5-minute walkthrough of the AFT pipeline
  • Module Overview — how the modules compose
  • Tutorials — async, persistence, LangChain, fly circuit, query routing, custom appraisal schemas
  • API Reference — full symbol-level documentation
  • Research — the theory and current evidence behind each layer