Human-like memory for AI applications
Project description
recollect
Cognitive memory system for AI applications. Activation-based retrieval with time decay, spreading activation, and token-budgeted recall.
Install
pip install recollect # pydantic-ai provider included
Quick Start
import asyncio
from recollect import CognitiveMemory
async def main():
memory = CognitiveMemory()
await memory.connect()
await memory.experience(
"The team decided to migrate from Redis to PostgreSQL for persistence."
)
thoughts = await memory.think_about("database decisions", token_budget=500)
for thought in thoughts:
print(f"[{thought.activation:.2f}] {thought.content}")
await memory.close()
asyncio.run(main())
How it works
Bi-encoder cosine similarity reflects semantic overlap, not causal relationships. A query about "Friday dinner plans" has near-zero similarity to "Alex has a severe peanut allergy" -- yet the allergy is safety-critical for a Thai restaurant dinner. Three mechanisms address this gap: concept attention at query time, spreading activation through pre-computed associations, and Hebbian recall tokens that link causally related memories at write time.
Write path. experience(content) sends the text to an LLM which extracts entities, concepts, context tags, and a significance score. A 768-dimensional embedding is generated locally via FastEmbed (nomic-embed-text-v1.5-Q). Both the embedding and the extracted metadata are stored in PostgreSQL with an HNSW index.
Read path. think_about(query) embeds the query and runs an HNSW search for candidate traces. Concept attention (ColBERT-style MaxSim over per-trace concept vectors stored at write time) re-ranks those candidates. Spreading activation then traverses the association graph -- a recursive CTE in PostgreSQL that follows temporal, entity, and semantic edges -- to surface traces that did not rank in the initial search but are strongly linked to those that did. Recall tokens apply a gated score bonus for traces that share ambiguous entities with the query. The final list is clipped to fit within the token_budget.
Working memory. A 7 +/- 2 slot buffer (range 5-9, enforced) mirrors Miller's Law. When it is full, the weakest trace is displaced to storage.
Strength and decay. Every trace has a strength in [0.0, 1.0] that decays exponentially over time. Retrieval boosts strength. consolidate() merges related traces and removes those below the consolidation threshold.
Recall token lifecycle. Each recall token also carries a strength in [0.0, 1.0]. When a token participates in a successful recall, its strength increments by 0.1 (capped at 1.0). During consolidate(), inactive token strengths decay by a factor of 0.9 per pass. Tokens that fall below 0.01 are archived: they become invisible to query-time activation but retain their label, stamps, and significance score. If a future write-time assessment extends or revises an archived token, it reactivates with strength = significance -- a health or safety token with significance 0.85 comes back strong, a low-significance token comes back weak but viable. Archived tokens are never deleted; the situational group survives at negligible storage cost and can re-enter the active pool whenever the situation recurs.
Scoring. All candidates from the five retrieval sources merge through a single formula:
effective_sim = 0.7 * concept_maxsim + 0.3 * biencoder_cosine
[falls back to biencoder when concept_maxsim = 0]
score = effective_sim
+ significance * 0.15
+ |valence| * 0.05
+ activation_level * 0.10 [spreading activation candidates]
+ entity_sim * 0.1 * significance * concept_sim [entity match; zero when concept_maxsim = 0]
+ propagated_sim * 0.50 [recall token candidates]
The entity bonus is multiplicatively gated by concept_sim: entity name matches contribute zero signal when the trace has no semantic overlap with the query, preventing unrelated traces from floating up because they share a name. All parameters are tunable via TOML config.
API
| Method | Description |
|---|---|
connect(db_url=None) |
Connect to PostgreSQL. Uses DATABASE_URL env var if no argument. |
experience(content) |
Store a memory trace. LLM extracts entities, concepts, significance. |
think_about(query, token_budget) |
Retrieve memories that fit within a token limit. Returns list[Thought]. |
consolidate(threshold=None) |
Merge and prune weak traces. |
forget(trace_id) |
Remove a trace. |
reinforce(trace_id, factor=1.1) |
Strengthen a trace. |
facts(subject=None) |
List persona facts. |
start_session(user_id) |
Begin a scoped session. |
close() |
Disconnect and release resources. |
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | postgresql://localhost:5432/memory_sdk |
PostgreSQL connection string. |
PYDANTIC_AI_MODEL |
No | -- | pydantic-ai model string in provider:model format (e.g., ollama:ministral-3, anthropic:claude-haiku-4-5-20251001). |
ANTHROPIC_API_KEY |
For Anthropic models | -- | Anthropic API key. Read by pydantic-ai's Anthropic backend. |
OPENAI_API_KEY |
For OpenAI models | -- | OpenAI API key. Read by pydantic-ai's OpenAI backend. |
OLLAMA_BASE_URL |
No | http://localhost:11434/v1 |
Ollama API endpoint. |
MEMORY_EXTRACTION_MAX_TOKENS |
No | 8192 |
Max tokens for LLM extraction. Reasoning models consume thinking tokens before output; 8192 covers most cases. |
MEMORY_CONFIG |
No | -- | Path to custom TOML config file. |
MEMORY_EXTRACTION_INSTRUCTIONS |
No | -- | Override extraction prompt instructions. |
MEMORY_RECALL_TOKENS_ENABLED |
No | true |
Enable write-time token stamping and query-time activation. |
MEMORY_RECALL_TOKENS_TOP_K |
No | 5 |
Max related traces to consider for token assessment. |
MEMORY_RECALL_TOKENS_THRESHOLD |
No | 0.3 |
Min cosine similarity to consider a trace as related. |
MEMORY_RECALL_TOKENS_STRENGTH_THRESHOLD |
No | 0.1 |
Min token strength to activate at query time. |
MEMORY_RECALL_TOKENS_SCORE_BONUS |
No | 0.1 |
Gated additive bonus: token_strength * bonus * effective_sim. |
MEMORY_RECALL_TOKENS_REINFORCE_BOOST |
No | 0.1 |
Strength increment on token activation (capped at 1.0). |
MEMORY_RECALL_TOKENS_DECAY_FACTOR |
No | 0.9 |
Multiply inactive token strength by this during consolidation. |
Configuration
Defaults ship in config.toml. Override by placing a memory.toml in your working directory, or set MEMORY_CONFIG to a custom path. Only include keys you want to change:
[memory]
decay_rate = 0.05
[retrieval]
max_retrievals = 10
[extraction]
max_tokens = 2048
pydantic_ai_model = "ollama:ministral-3" # pydantic-ai provider:model format
Config sections
| Section | Controls | Key parameters |
|---|---|---|
[database] |
PostgreSQL connection | url |
[memory] |
Core memory model | initial_strength, consolidation_threshold, decay_rate |
[working_memory] |
Working memory capacity | capacity (default 7, range 5-9) |
[retrieval] |
Retrieval pipeline tuning | max_retrievals, search_limit, selection_threshold |
[extraction] |
LLM extraction | max_tokens, max_concepts, max_relations, pydantic_ai_model |
[embedding] |
Local embedding model | model, dimensions |
[persona] |
Persona fact management | auto_extract, confidence_threshold |
[session] |
Session summaries | summary_strength, summary_max_tokens |
Full defaults: config.toml
Or pass a path directly:
from recollect.config import MemoryConfig
config = MemoryConfig(config_path=Path("./my-config.toml"))
memory = CognitiveMemory(config=config)
LLM Provider
Single provider behind the LLMProvider protocol. Routes calls through pydantic-ai's Agent abstraction, giving access to 20+ model backends through a single dependency.
The model string uses pydantic-ai format (provider:model). Credentials are read from the environment by the underlying provider (e.g., ANTHROPIC_API_KEY for Anthropic, OLLAMA_BASE_URL for Ollama).
from recollect.llm.pydantic_ai import PydanticAIProvider
# Model configured via PYDANTIC_AI_MODEL env var, or pass explicitly:
provider = PydanticAIProvider() # uses PYDANTIC_AI_MODEL
provider = PydanticAIProvider(model="anthropic:claude-sonnet-4-6")
provider = PydanticAIProvider(model="ollama:llama3")
Reasoning models
Models that use internal chain-of-thought (OpenAI o1/o3, Qwen3, DeepSeek-R1) consume thinking tokens from the max_tokens budget. If extraction returns empty responses, increase the token budget:
# memory.toml
[extraction]
max_tokens = 8192
The default is 4096, which provides sufficient headroom for most models.
Requirements
- Python 3.12+
- PostgreSQL 17 with pgvector
DATABASE_URLenvironment variable
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file recollect-0.5.3.tar.gz.
File metadata
- Download URL: recollect-0.5.3.tar.gz
- Upload date:
- Size: 64.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
889be267f340882c95914a9a1163f0be93b708da23353cc8141f5a3f16e70b2f
|
|
| MD5 |
348005feb4e82c1286ef4ce57655ace0
|
|
| BLAKE2b-256 |
e245295bef007bf494ed0d423b5638e252d3a0f5818af5c2f461fd95c5e01f22
|
File details
Details for the file recollect-0.5.3-py3-none-any.whl.
File metadata
- Download URL: recollect-0.5.3-py3-none-any.whl
- Upload date:
- Size: 74.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
691dc380a479b0b54fe1ab17ca8acd127ed5e9e05b05715871a7857fbd33b271
|
|
| MD5 |
beb6ce8bf90c461876bab8d5db755284
|
|
| BLAKE2b-256 |
78bb87d5f605e3818c0627f9952a8b2e8d6cd6d41e3bf53fd74190ec15264e97
|