Metadata-Version: 2.4
Name: kemi
Version: 0.4.0
Summary: Persistent memory for AI agents. Three methods. Zero infra.
Project-URL: Homepage, https://github.com/alokvadera/kemi
Project-URL: Documentation, https://github.com/alokvadera/kemi/tree/main/docs
Project-URL: Repository, https://github.com/alokvadera/kemi
Project-URL: Issues, https://github.com/alokvadera/kemi/issues
Project-URL: Changelog, https://github.com/alokvadera/kemi/blob/main/CHANGELOG.md
Author-email: Vadera Alok <alokvadera123@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agent-framework,ai-agent,chatgpt,claude,embeddings,langchain,llm,mcp,memory,persistent-memory,rag,semantic-search,vector-search
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: bcrypt>=5.0.0
Provides-Extra: all
Requires-Dist: chromadb>=0.4.0; extra == 'all'
Requires-Dist: fastembed>=0.2.0; extra == 'all'
Requires-Dist: langchain>=0.1.0; extra == 'all'
Requires-Dist: mcp>=1.0.0; extra == 'all'
Requires-Dist: openai>=1.0.0; extra == 'all'
Requires-Dist: pgvector>=0.3; extra == 'all'
Requires-Dist: psycopg[binary]>=3.2; extra == 'all'
Requires-Dist: qdrant-client>=1.9.0; extra == 'all'
Requires-Dist: redis>=5.0; extra == 'all'
Requires-Dist: spacy>=3.7.0; extra == 'all'
Requires-Dist: sqlite-vec>=0.1.0; extra == 'all'
Provides-Extra: chroma
Requires-Dist: chromadb>=0.4.0; extra == 'chroma'
Provides-Extra: dev
Requires-Dist: cryptography>=41.0.0; extra == 'dev'
Requires-Dist: fastapi>=0.100.0; extra == 'dev'
Requires-Dist: httpx>=0.24.0; extra == 'dev'
Requires-Dist: matplotlib>=3.7.0; extra == 'dev'
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest-randomly>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Requires-Dist: scikit-learn>=1.3.0; extra == 'dev'
Provides-Extra: encryption
Requires-Dist: cryptography>=41.0.0; extra == 'encryption'
Provides-Extra: langchain
Requires-Dist: langchain>=0.1.0; extra == 'langchain'
Provides-Extra: local
Requires-Dist: fastembed>=0.2.0; extra == 'local'
Provides-Extra: mcp
Requires-Dist: mcp>=1.0.0; extra == 'mcp'
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == 'openai'
Provides-Extra: postgres
Requires-Dist: pgvector>=0.3; extra == 'postgres'
Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
Provides-Extra: qdrant
Requires-Dist: qdrant-client>=1.9.0; extra == 'qdrant'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Provides-Extra: spacy
Requires-Dist: spacy>=3.7.0; extra == 'spacy'
Provides-Extra: sqlcipher
Requires-Dist: sqlcipher3>=0.5.0; extra == 'sqlcipher'
Provides-Extra: vec
Requires-Dist: sqlite-vec>=0.1.0; extra == 'vec'
Description-Content-Type: text/markdown

# kemi

**Persistent memory for AI agents. Three methods. Zero infra.**

[![PyPI version](https://img.shields.io/pypi/v/kemi?color=blue)](https://pypi.org/project/kemi/)
[![Python versions](https://img.shields.io/pypi/pyversions/kemi)](https://pypi.org/project/kemi/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Tests](https://github.com/alokvadera/kemi/actions/workflows/ci.yml/badge.svg)](https://github.com/alokvadera/kemi/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/badge/coverage-92%25-brightgreen)](https://github.com/alokvadera/kemi)

```python
from kemi import MemoryService

memory = MemoryService()  # SQLite + local embeddings, no API keys needed

memory.remember("user123", "User prefers dark mode")
memory.remember("user123", "User is vegetarian")

results = memory.recall("user123", "what are the user's preferences?")
# Returns ranked, deduplicated memories

memory.forget("user123")  # GDPR-compliant deletion
```

> **Note:** `from kemi import Memory` still works as a backwards-compatible alias.
> New code should import `MemoryService` directly.

---

## Why kemi?

Every other memory library **either hosts your data on their servers, requires Docker and 4 services to run, or locks you into a specific framework.**

**kemi is different:**

| | |
|---|---|
| **Zero infrastructure** | `pip install kemi`, no Docker, no cloud, no setup |
| **Zero hard dependencies** | Only the core library + SQLite. Optional backends live behind extras (`[chroma]`, `[qdrant]`, `[postgres]`, etc.) |
| **Your data stays yours** | Stored in SQLite on your machine, never leaves |
| **Bring your own embedding** | OpenAI, local models (fastembed), or any function |
| **Framework agnostic** | Works with LangChain, CrewAI, AutoGen, or plain Python |
| **MCP ready** | Use as a memory server for Claude Desktop, Cursor, and Continue |
| **100% free** | MIT license, no paid tiers, no cloud lock-in |

---

## Install

```bash
pip install kemi                    # Core only — zero hard dependencies
pip install "kemi[local]"           # + local embeddings (no API key, ~130MB download)
pip install "kemi[openai]"          # + OpenAI embeddings (1536-dim)
pip install "kemi[postgres]"        # + PostgreSQL + pgvector (ANN, FTS, hybrid search)
pip install "kemi[mcp]"            # + MCP server (Claude Desktop, Cursor, Continue)
pip install "kemi[langchain]"      # + LangChain BaseChatMemory adapter
pip install "kemi[chroma]"         # + ChromaDB vector store
pip install "kemi[qdrant]"         # + Qdrant vector store
pip install "kemi[redis]"          # + Redis vector store
pip install "kemi[all]"            # Everything (heavy)
```

---

## Quick Start

### Zero-config (local embeddings)

```python
from kemi import MemoryService

memory = MemoryService()
memory.remember("user123", "User is vegetarian", importance=0.9)
results = memory.recall("user123", "food preferences")
```

### With OpenAI embeddings

```python
from kemi import MemoryService
from kemi.adapters.embedding.openai import OpenAIEmbedAdapter

memory = MemoryService(embed=OpenAIEmbedAdapter())
memory.remember("user123", "User prefers concise responses")
results = memory.recall("user123", "communication style")
```

### With PostgreSQL + pgvector

```python
from kemi import MemoryService
from kemi.adapters.storage.postgres import PostgresStorageAdapter

store = PostgresStorageAdapter(dsn="postgresql://user:pass@localhost:5432/kemi", embedding_dim=384)
memory = MemoryService(store=store)
memory.remember("user123", "User prefers dark mode")
results = memory.recall("user123", "color theme preferences")
```

### Inject into system prompts

```python
context = memory.context_block("user123", query="user preferences", max_tokens=500)
# Returns formatted string ready to paste into an LLM system prompt
```

### Async (FastAPI)

```python
from fastapi import FastAPI
from kemi import MemoryService

app = FastAPI()
memory = MemoryService()

@app.post("/chat")
async def chat(user_id: str, message: str):
    await memory.aremember(user_id, message)
    context = await memory.acontext_block(user_id, message)
    return {"context": context}
```

### GDPR-compliant deletion

```python
memory.forget("user123")            # Delete all memories for a user
memory.forget("user123", memory_id) # Delete one specific memory
```

---

## Features

| Feature | What it does |
|---|---|
| **Semantic deduplication** | "I'm vegetarian" and "I don't eat meat" are detected as the same memory |
| **Importance-weighted scoring** | Recent, important memories rank higher in search results |
| **Temporal decay** | Memories fade if never recalled -- transitions from ACTIVE to DECAYING |
| **Conflict detection** | Flags contradictory memories ("I love coffee" vs "I hate coffee") |
| **Hybrid search** | Combines semantic (vector) search with keyword (BM25) search |
| **MMR reranking** | Ensures diverse results -- not 5 nearly-identical memories |
| **Lifecycle management** | Automatic state transitions: ACTIVE -> DECAYING -> ARCHIVED -> DELETED |
| **Query decomposition** | Breaks complex queries into sub-queries with Reciprocal Rank Fusion |
| **Entity extraction** | Zero-dependency regex or spaCy-based entity linking |
| **Version history** | Track changes to memories with rollback support |
| **Webhooks** | Dispatch lifecycle events (remembered, updated, deleted, conflict) to HTTP endpoints |
| **Audit trail** | Compliance-grade operation log with retention and export |
| **Plugin system** | Four extension points: WebhookSink, AuditSink, QueryCacheProvider, HookSink |

---

## MCP Server

Any MCP-compatible agent (Claude Desktop, Cursor, Continue) can use kemi as its memory layer:

```bash
pip install "kemi[mcp]"
python -m kemi
```

Claude can then remember facts about you across sessions -- no API keys, no cloud, everything local.

### Exposed tools

`remember`, `recall`, `recall_stream`, `recall_explain`, `forget`, `context_block`, `prune`, `stats`, `consolidate`, `topics`, `graph`, `list_users`

---

## Adapters

| Type | Default | Alternatives |
|---|---|---|
| **Embedding** | fastembed (local, 384-dim) | OpenAI (1536-dim), custom function |
| **Storage** | SQLite (WAL mode) | SQLite-vec (ANN), PostgreSQL + pgvector, Redis, Qdrant, Chroma, JSON file, custom |

---

## Integrations

### LangChain

```python
from kemi import MemoryService
from kemi.integrations.langchain import KemiMemory

memory = MemoryService()
chat_memory = KemiMemory(user_id="alice", memory=memory)
```

### LangGraph / CrewAI / AutoGen

kemi works with any framework. Just use the core `remember` / `recall` / `forget` methods wherever you need persistent memory.

### Export / Import

```python
memory.export("backup.json")       # backup all memories
memory.import_from("backup.json")  # restore from backup
```

---

## CLI

```bash
kemi remember user123 "User prefers dark mode"
kemi recall user123 "preferences"
kemi forget user123
kemi stats user123
kemi export backup.json
kemi import backup.json
```

Use `--json` for machine-readable output or `--quiet` to suppress info messages.

---

## Documentation

| Guide | What you'll learn |
|---|---|
| [Architecture](docs/ARCHITECTURE.md) | Module map, data flow diagrams, plugin extension points |
| [Quickstart](docs/quickstart.md) | Get running in 5 minutes |
| [Recipes](docs/recipes.md) | Complete working examples |
| [Configuration](docs/configuration.md) | Tuning kemi for your use case |
| [Adapters](docs/adapters.md) | Embeddings, storage, custom implementations |
| [API Stability](docs/API_STABILITY.md) | Stability tiers and deprecation policy |
| [Contributing](CONTRIBUTING.md) | How to contribute, changelog conventions |

---

## Data Privacy

kemi is designed so **your data never leaves your machine**:

- All memories stored in local SQLite at `~/.kemi/memories.db`
- Embeddings computed locally (fastembed) or via your own API key (OpenAI)
- No telemetry, no analytics, no phone-home
- Full GDPR-compliant deletion with `memory.forget()`
- Optional field-level Fernet encryption for content, metadata, and user IDs

---

## Requirements

- Python 3.10+

---

## License

MIT -- free forever, no exceptions.
