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.
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