Skip to main content

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 /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 or RAGFlow — memila stays a small, readable sidecar you bolt onto your own apps.


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

memila-0.1.0.tar.gz (14.1 kB view details)

Uploaded Source

Built Distribution

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

memila-0.1.0-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

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

Hashes for memila-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cc756a034392ddc361e8de6b42d56c1f10c34ffff29500a7ff433573d260b4ac
MD5 2a4cd93ebee5a86692116241e43f7b2a
BLAKE2b-256 dea901a422c40036c24e63bf89afd430bc536aa83e732038aeb37ec28d662f81

See more details on using hashes here.

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

Hashes for memila-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 85c96cb5798dd4bd28f4d1135ebcaf9bc78e67e462a8137fe64024357056d7c9
MD5 e825807d2e202a7c877fdf7031bd09f6
BLAKE2b-256 04602b359782875acaa141ba396b68f6c7587cb94ba29d7e37dd61a8303f0999

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