Skip to main content

Memory Fast and Slow for AI Agents - dual-store memory with keyword triggers and pluggable search

Project description

agent-memfas

Memory Fast and Slow for AI Agents

A dual-store memory system inspired by Kahneman's "Thinking, Fast and Slow":

  • Type 1 (Fast): Keyword triggers for instant pattern matching - O(1) lookup
  • Type 2 (Slow): Pluggable search backends - FTS5 (default) or embeddings

Zero external dependencies for the default. Optional embedding support with local models.

Installation

# Core (FTS5 only, zero deps)
pip install agent-memfas

# With local embeddings (recommended)
pip install agent-memfas[embeddings]

# With Ollama support
pip install agent-memfas[ollama]

# Everything
pip install agent-memfas[all]

Quick Start

CLI Usage

# Initialize in your agent's workspace
cd ~/my-agent
memfas init

# Add keyword triggers (Type 1 - fast)
memfas remember family --hint "User's family context"
memfas remember yupp --hint "Current company, LLM routing"
memfas remember running --hint "Marathon training"

# Index your memory files (Type 2 - slow)
memfas index ./memory/
memfas index ./MEMORY.md

# Recall memories for context
memfas recall "How's the family doing?"
memfas recall "What papers were interesting?"

# Search directly
memfas search "preference learning RLHF"

# Check stats
memfas stats

# Auto-suggest triggers from your content
memfas suggest

Python Usage

from agent_memfas import Memory

# Default (FTS5, zero deps)
mem = Memory("./memfas.yaml")

# Add triggers
mem.add_trigger("family", "User's family context")
mem.add_trigger("work", "Current projects and job")

# Index files
mem.index_file("./MEMORY.md")
mem.index_sources()  # Index all sources from config

# Recall (combines Type 1 + Type 2)
context = mem.recall("How's the family?")
print(context)

# Search only (Type 2)
results = mem.search("preference learning", limit=5)
for r in results:
    print(f"[{r.source}] {r.text[:100]}...")

mem.close()

With Embeddings (Semantic Search)

from agent_memfas import Memory
from agent_memfas.embedders.fastembed import FastEmbedEmbedder

# Local embeddings via FastEmbed (~130MB model, runs on CPU)
embedder = FastEmbedEmbedder()  # Uses BAAI/bge-small-en-v1.5
mem = Memory("./memfas.yaml", search_backend="embedding", embedder=embedder)

# Now search uses semantic similarity
results = mem.search("machine learning concepts")  # Finds related content

Or with Ollama:

from agent_memfas.embedders.ollama import OllamaEmbedder

# Requires: ollama pull nomic-embed-text
embedder = OllamaEmbedder(model="nomic-embed-text")
mem = Memory("./memfas.yaml", search_backend="embedding", embedder=embedder)

Search Backends

FTS5 (Default)

  • Zero dependencies - uses SQLite's built-in FTS5
  • BM25 ranking with recency decay
  • Great for exact keyword matching
  • Best for: most use cases, low resource environments

Embedding (Optional)

  • Semantic search - finds conceptually related content
  • Uses local models via FastEmbed or Ollama
  • Requires: pip install agent-memfas[embeddings]
  • Best for: finding related concepts, multilingual content
Backend Dependencies Quality Speed Use Case
FTS5 None Good for keywords Fast Default, most cases
Embedding fastembed, sqlite-vec Better semantics Slower Semantic search

Embedder Options

Embedder Install Model Size Notes
FastEmbed pip install fastembed ~130MB Recommended, runs on CPU
Ollama ollama pull nomic-embed-text ~270MB Good if you already use Ollama

Configuration

Create memfas.yaml:

db_path: ./memfas.db

sources:
  - path: ./MEMORY.md
    type: markdown
  - path: ./memory/*.md
    type: markdown
  - path: ./intuition.md
    type: markdown
    always_load: true  # Include in every recall

triggers:
  - keyword: family
    hint: "User's family context"
  - keyword: work
    hint: "Current job and projects"

search:
  backend: fts5  # or "embedding"
  max_results: 5
  recency_weight: 0.3  # Higher = favor recent memories
  min_score: 0.1
  
  # For embedding backend:
  # embedder_type: fastembed  # or "ollama"
  # embedder_model: BAAI/bge-small-en-v1.5

Or use JSON:

{
  "db_path": "./memfas.db",
  "sources": [
    {"path": "./MEMORY.md", "type": "markdown"}
  ],
  "triggers": [
    {"keyword": "family", "hint": "User's family context"}
  ]
}

How It Works

Type 1: Keyword Triggers (Fast Path)

When you call recall(), it first checks for keyword matches:

Input: "How's the family doing?"
       ↓
Triggers table: family → "User's family context"
       ↓
Match found! Return instantly (O(1))

Type 2: Search (Slow Path)

If no triggers match, or you want more context, it searches:

FTS5 Backend:

Input: "What papers were interesting?"
       ↓
FTS5 query with BM25 ranking
       ↓
Apply recency decay
       ↓
Top results returned

Embedding Backend:

Input: "machine learning concepts"
       ↓
Generate query embedding
       ↓
KNN search via sqlite-vec
       ↓
Top results by similarity

Recency Decay (FTS5)

Recent memories score higher:

recency_score = 1.0 / (1.0 + days_old * recency_weight * 0.01)
final_score = bm25_score * recency_score

API Reference

Memory Class

Memory(
    config: str | Config | None = None,
    search_backend: str = None,  # "fts5" or "embedding"
    embedder: Embedder = None    # Required for embedding backend
)

Methods:

Method Description
recall(context) Main entry - combines Type 1 + Type 2
search(query, limit) Type 2 only - search
add_trigger(keyword, hint) Add Type 1 trigger
remove_trigger(keyword) Remove trigger
list_triggers() List all triggers
index_file(path, type) Index a single file
index_sources() Index all config sources
clear() Clear all indexed memories
stats() Get statistics
suggest_triggers() Auto-suggest triggers
reindex(backend, embedder) Re-index with new backend
close() Close database connection

Search Backends

from agent_memfas.search.fts5 import FTS5Backend
from agent_memfas.search.embedding import EmbeddingBackend

# Direct backend usage
backend = FTS5Backend("./memfas.db")
backend.index("doc1", "Hello world", {"source": "test.md"})
results = backend.search("hello")

CLI Commands

Command Description
memfas init Initialize in current directory
memfas recall <context> Recall memories
memfas search <query> Search memories
memfas remember <kw> --hint <h> Add trigger
memfas forget <keyword> Remove trigger
memfas triggers List triggers
memfas index <paths...> Index files/dirs
memfas stats Show statistics
memfas clear Clear memories
memfas suggest Auto-suggest triggers
memfas reindex -b <backend> Re-index with new backend

Use Case: Surviving Context Compaction

AI agents running long conversations hit context limits. When the window fills up, older messages get compacted and critical context can be lost.

memfas maintains persistent memory outside the context window:

# Agent's workspace setup
cd ~/agent-workspace
memfas init

# Add triggers for active work
memfas remember project --hint "Building agent-memfas"
memfas remember "working on" --hint "Memory system for AI agents"

# Index memory files  
memfas index ./memory/ ./MEMORY.md

# After compaction, agent recovers context:
$ memfas recall "what were we working on"

📚 Memory Context:

**Triggered Memories:**
[project] Building agent-memfas
[working on] Memory system for AI agents

Migrating from v0.1

v0.2 is backward compatible. Your existing FTS5 data keeps working.

To upgrade to embeddings via CLI:

# Install embedding dependencies
pip install agent-memfas[embeddings]

# Re-index with embedding backend
memfas reindex -b embedding -e fastembed --save-config

Or via Python:

from agent_memfas import Memory
from agent_memfas.embedders.fastembed import FastEmbedEmbedder

# Load existing memory with new embedding backend
mem = Memory("./memfas.yaml")
mem.reindex(new_backend="embedding", embedder=FastEmbedEmbedder())

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_memfas-0.2.0.tar.gz (29.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_memfas-0.2.0-py3-none-any.whl (26.1 kB view details)

Uploaded Python 3

File details

Details for the file agent_memfas-0.2.0.tar.gz.

File metadata

  • Download URL: agent_memfas-0.2.0.tar.gz
  • Upload date:
  • Size: 29.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for agent_memfas-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a8b0d6ba3abd4fd3d09d4399d69e17bf0c0aab52bde1512bebc771ab6c806401
MD5 ce0feb0b9a6875fe82f295027c699ad9
BLAKE2b-256 47e258fba3a25d44fd820ce1c6058029b12b7164686ad1c8b94129a686077793

See more details on using hashes here.

File details

Details for the file agent_memfas-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: agent_memfas-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 26.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for agent_memfas-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 585d3d88ea3d7f79b96252838193f24a0d353db4e839ec2103fb35c4878db7fb
MD5 51f2dc6df6cd20619016fcb569703110
BLAKE2b-256 8679dc5269e5b8039edc1b0b047ababf3069db051bb1188bab40e33315d0e285

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page