Python client for memila — self-hosted local RAG memory for your apps
Project description
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
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:
./ingest.sh README.md myproject
Query it:
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:
{
"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:
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
# 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:
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.
- 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
/answerendpoint 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 or RAGFlow — memila stays a small, readable sidecar you bolt onto your own apps.
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 memila-0.1.0.tar.gz.
File metadata
- Download URL: memila-0.1.0.tar.gz
- Upload date:
- Size: 14.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc756a034392ddc361e8de6b42d56c1f10c34ffff29500a7ff433573d260b4ac
|
|
| MD5 |
2a4cd93ebee5a86692116241e43f7b2a
|
|
| BLAKE2b-256 |
dea901a422c40036c24e63bf89afd430bc536aa83e732038aeb37ec28d662f81
|
File details
Details for the file memila-0.1.0-py3-none-any.whl.
File metadata
- Download URL: memila-0.1.0-py3-none-any.whl
- Upload date:
- Size: 5.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85c96cb5798dd4bd28f4d1135ebcaf9bc78e67e462a8137fe64024357056d7c9
|
|
| MD5 |
e825807d2e202a7c877fdf7031bd09f6
|
|
| BLAKE2b-256 |
04602b359782875acaa141ba396b68f6c7587cb94ba29d7e37dd61a8303f0999
|