Skip to content
GitHub

Guide

PackageRequiredPurpose
lexigramYesCore framework
lexigram-contractsYesProtocol definitions
lexigram-ai-llmOptionalSummary memory
lexigram-vectorOptionalSemantic memory

LLM conversations are stateless — each call is independent. AI systems need memory to remember past interactions, learn from experience, and manage limited context windows. lexigram-ai-memory provides three tiers:

TierWhat it storesRetentionAnalogy
WorkingCurrent conversation contextSingle requestScratchpad
EpisodicPast conversations, eventsHours–daysDiary
SemanticExtracted facts, entitiesDays–foreverEncyclopedia

Memory entries are stored with importance and temporal metadata, enabling hybrid scoring (recency + relevance + importance) during retrieval.

Every piece of memory is a MemoryEntry:

from lexigram.contracts.ai.memory import MemoryEntry
from datetime import UTC, datetime
entry = MemoryEntry(
id="entry-123",
content="User prefers dark mode.",
role="assistant",
timestamp=datetime.now(UTC),
importance=0.8, # 0.0–1.0
metadata={"source": "preferences"},
)

Working memory assembles the context window for the current request. It allocates a token budget across system prompt, recent turns, episodic recall, and semantic facts:

from lexigram.ai.memory.working import WorkingMemoryManager
from lexigram.ai.memory.config import WorkingMemoryConfig
config = WorkingMemoryConfig(
system_prompt_tokens=512,
recent_turns_fraction=0.4,
episodic_fraction=0.3,
semantic_fraction=0.2,
max_recent_turns=20,
)

Episodic memory stores timestamped conversation history with hybrid retrieval:

  • Recency — how recent the entry is
  • Relevance — semantic similarity to the query
  • Importance — how important the entry was marked
from lexigram.contracts.ai.memory import MemoryQuery
results = await episodic.recall(
MemoryQuery(
query="previous booking",
top_k=5,
recency_weight=0.3,
relevance_weight=0.5,
importance_weight=0.2,
)
)

Semantic memory stores facts as subject-predicate-object triples with confidence scores:

await semantic.store_fact(
subject="Alice",
predicate="prefers",
object_="dark_mode",
confidence=0.95,
)
facts = await semantic.query_facts("Alice")

The consolidation pipeline periodically promotes important episodic memories into semantic storage, deduplicates, prunes low-importance entries, and extracts entities:

from lexigram.ai.memory.consolidation import (
MemoryConsolidator,
ConsolidationScheduler,
)

Scheduling is configured via ConsolidationConfig and activated through MemoryProvider.boot().

from lexigram import Application
from lexigram.ai.memory import MemoryModule, MemoryConfig
config = MemoryConfig(
default_backend="in_memory",
ttl_seconds=86400 * 30,
)
async with Application.boot(
name="app",
modules=[MemoryModule.configure(config, enable_consolidation=True)],
) as app:
# Resolve individual tiers
working = await app.container.resolve(WorkingMemoryProtocol)
episodic = await app.container.resolve(EpisodicMemoryProtocol)
semantic = await app.container.resolve(SemanticMemoryProtocol)
store = await app.container.resolve(MemoryStoreProtocol)
consolidator = await app.container.resolve(MemoryConsolidatorProtocol)
from datetime import UTC, datetime
# Store conversation turns
await episodic.record(MemoryEntry(
id="turn-1", content="User: Hello", role="user",
timestamp=datetime.now(UTC), importance=0.5,
))
# Assemble context for the next LLM call
entries = await working.assemble(
query="What was my last question?",
token_budget=4096,
)
for entry in entries:
print(f"[{entry.role}] {entry.content}")
from lexigram.ai.memory.retrieval import MemoryRetriever
retriever = await app.container.resolve(MemoryRetriever)
results = await retriever.retrieve(
MemoryQuery(query="user preferences", top_k=10),
)
for r in results:
print(f"[{r.source}] {r.entry.content} (score: {r.score:.2f})")
from lexigram.ai.memory.pruning import DynamicContextPruner
pruner = await app.container.resolve(DynamicContextPruner)
pruned = await pruner.prune(
entries=all_entries,
max_tokens=2048,
query="current topic",
)

MemoryStoreProtocol methods are fire-and-forget (None return) or return lists directly — they do not use Result for expected operations. Exceptions (MemoryStoreError, MemoryCapacityError) are raised for infrastructure failures.