Metadata-Version: 2.4
Name: memila
Version: 0.1.0
Summary: Python client for memila — self-hosted local RAG memory for your apps
Project-URL: Homepage, https://github.com/fuu354-droid/memila
Project-URL: Repository, https://github.com/fuu354-droid/memila
Project-URL: Roadmap, https://github.com/fuu354-droid/memila/blob/main/ROADMAP.md
Author: Mila Chen
License-Expression: MIT
Keywords: llm-memory,qdrant,rag,self-hosted,vector-search
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# memila

**Self-hosted local RAG memory for your apps — ingest anything, retrieve anywhere, your data never leaves your machine.**

A lightweight RAG service you run locally or on your own server. Ingest documents, query them semantically, and retrieve relevant chunks over a plain HTTP API. No cloud dependency, no vendor lock-in, no data leaving your machine.

```
POST /ingest    → chunk + embed + store (SHA dedup, idempotent)
POST /retrieve  → embed query + return top-k hits
POST /augment   → Claude Code hook: inject context before each prompt
DELETE /source  → remove a document by source tag
GET  /stats/ns  → collection stats
```

Stack: **FastAPI** + **Qdrant** (vector store) + **BGE-M3** via **Ollama** (embedder). Swap the embedder for any OpenAI-compatible `/v1/embeddings` endpoint — OpenAI, Gemini, Cohere, or another local model.

---

## Quick start

```bash
git clone https://github.com/fuu354-droid/memila.git
cd memila
cp .env.example .env
docker compose up -d
```

On first run, `ollama-pull` downloads `bge-m3:latest` (~1.2 GB). Subsequent starts are instant.

Ingest a document:

```bash
./ingest.sh README.md myproject
```

Query it:

```bash
curl -s -X POST http://localhost:6452/retrieve \
  -H "Content-Type: application/json" \
  -d '{"namespace": "myproject", "query": "how does ingestion work?", "top_k": 3}' | jq .
```

---

## Integrations

### Claude Code — automatic context injection

Every prompt you type can be silently augmented with relevant chunks from your knowledge base before Claude sees it.

Merge this into `~/.claude/settings.json`:

```json
{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -sS -X POST http://127.0.0.1:6452/augment -H 'Content-Type: application/json' --data-binary @- --max-time 5 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}
```

The `|| true` keeps Claude Code working normally if rag-api is unavailable. The `/augment` endpoint returns an empty string when no chunks score above the threshold — nothing is injected.

Namespace is derived automatically from your working directory:
`/home/alice/projects/my-api` → namespace `claude:my-api`

### LINE Bot (or any chatbot)

Call `/retrieve` before forwarding the user's message to your LLM:

```python
import httpx

def get_context(user_message: str, namespace: str) -> str:
    resp = httpx.post("http://localhost:6452/retrieve", json={
        "namespace": namespace,
        "query": user_message,
        "top_k": 3,
        "min_score": 0.45,
    })
    hits = resp.json()["hits"]
    if not hits:
        return ""
    return "\n\n".join(f"[{h['source']}]\n{h['text']}" for h in hits)

# Prepend context to your system prompt before calling OpenAI / Gemini / Claude / etc.
```

### Any HTTP client

`/retrieve` is a plain JSON endpoint. Call it from Python, Go, Node, shell — anything that speaks HTTP.

---

## Ingest

```bash
# Single file
./ingest.sh notes.md

# Into a named namespace (isolated corpus per project)
./ingest.sh architecture.md myproject

# Bulk
for f in docs/*.md; do ./ingest.sh "$f" myproject; done

# From stdin
cat log.txt | ./ingest.sh - myproject log-2026-06
```

Ingestion is idempotent. Re-ingesting the same file only re-embeds chunks whose content has changed (SHA-256 dedup per chunk).

---

## Configuration

Copy `.env.example` to `.env`. Key settings:

| Variable | Default | Purpose |
|---|---|---|
| `RAG_PORT` | `6452` | Host port for rag-api |
| `EMBED_MODEL` | `bge-m3:latest` | Embedding model name |
| `EMBED_DIM` | `1024` | Vector dimension (must match model) |
| `HOOK_MIN_SCORE` | `0.55` | Min similarity for `/augment` injection |
| `HOOK_TOP_K` | `3` | Max chunks injected per prompt |
| `RAG_MIN_SCORE` | `0.40` | Min similarity for `/retrieve` |
| `RAG_TOP_K` | `5` | Default top-k for `/retrieve` |

**Using a different embedder** — set `EMBED_API_URL` and `EMBED_MODEL` to point at any OpenAI-compatible endpoint:

```env
EMBED_API_URL=https://api.openai.com/v1
EMBED_API_KEY=sk-...
EMBED_MODEL=text-embedding-3-small
EMBED_DIM=1536
```

---

## Architecture notes

- **No LLM API keys in the service** — rag-api embeds text and returns chunks. Reasoning happens in your application layer.
- **Fail-open** — the Claude Code hook uses `|| true`; a slow or unavailable service never blocks a prompt.
- **SHA-256 dedup** — chunk identity is `(source, content_hash)`. Re-ingesting unchanged content is a no-op.
- **Namespace isolation** — each namespace maps to its own Qdrant collection (`rag_<namespace>`). Different projects, different corpora, no cross-contamination.

---

## Roadmap

memila stores data that, by design, exists nowhere else — project logs, internal docs, private notes. The roadmap hardens that promise. Details and progress in [ROADMAP.md](ROADMAP.md).

- **v0.2 — Hardening**: API key auth (today any local process can read or wipe any namespace), test suite, fail-fast config validation
- **v0.3 — Fully local answering**: optional `/answer` endpoint backed by a local Ollama LLM — retrieve + generate with citations, zero bytes leaving your machine
- **v0.4 — Source connectors**: config-driven ingest daemon (watch a directory, a git repo, a URL list) so keeping the knowledge base fresh is not a manual job

**Non-goals**: a chat UI, OCR / complex document parsing, agent frameworks. If you need those, use [AnythingLLM](https://github.com/Mintplex-Labs/anything-llm) or [RAGFlow](https://github.com/infiniflow/ragflow) — memila stays a small, readable sidecar you bolt onto your own apps.

---

## License

MIT
