Skip to main content

RAG + LLM Serving Infrastructure

CI PyPI

An installable, vendor-neutral foundation for retrieval-augmented LLM applications: a swappable vector store, a cached embedding index, a provider-agnostic LLM protocol, the observability around them, a FastAPI serving layer, and a retrieval-quality eval gate.

Typed, tested, packaged, and runnable on its own.

Install

pip install rag-llm-infra                                   # core (numpy)
pip install "rag-llm-infra[faiss,qdrant,openai,serve]"      # + native backends, OpenAI, serving
pip install "rag-llm-infra[psutil]"                         # + memory-pressure-aware cache trimming
pip install -e ".[dev]"                                     # from a local clone, for development

Quickstart: end-to-end RAG (no API key, no network)

git clone https://github.com/MarwaBS/rag-llm-infra && cd rag-llm-infra
pip install -e .
python example.py
embed documents -> index in a VectorStore -> retrieve top-k for a query
                -> build a grounded prompt -> answer with an LLMProtocol backend

Runs on the NumPy vector store + the deterministic mock LLM, so it needs no key. In production, swap the demo embedder for EmbeddingEngine and get_llm("mock") for get_llm("openai").

Serve it

pip install "rag-llm-infra[serve]"
export RAG_API_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
uvicorn rag_llm_infra.serve:app
# or: docker build -t rag-llm-infra . && docker run -p 8000:8000 -e RAG_API_KEY=$RAG_API_KEY rag-llm-infra

/index and /query require X-API-Key, and answer 503 while RAG_API_KEY is unset. There is no open mode. /health stays open for container probes. Bodies over 1 MiB and corpora over 20000 documents are refused by default; each document costs a fixed-width vector however short it is, so bytes on the wire do not bound memory. uvicorn binds 127.0.0.1 unless --host or UVICORN_HOST says otherwise; the container passes --host 0.0.0.0 and publishes 8000. One shared key, no rate limiting; see SECURITY.md.

curl -XPOST localhost:8000/index -d '{"documents":["FAISS is in-process vector search","Qdrant is a vector database"]}' -H 'content-type: application/json' -H "X-API-Key: $RAG_API_KEY"
curl -XPOST localhost:8000/query -d '{"query":"vector search","k":1}'      -H 'content-type: application/json' -H "X-API-Key: $RAG_API_KEY"

What's inside

Module Responsibility
rag_llm_infra.llm_protocol LLMProtocol: runtime_checkable Protocol over OpenAI / Anthropic-stub / Mock; factory get_llm()
rag_llm_infra.vector_store VectorStoreProtocol: in-process FAISS IndexFlatIP, pure-NumPy fallback, real Qdrant (batched search). Qdrant needs collection=: add() replaces that collection, so the store owns it
rag_llm_infra.evidence_index EmbeddingEngine: SentenceTransformers embeddings + a cache (insertion-order eviction) guarded by a writer-preferring reader/writer lock, so the slow model.encode runs outside the lock. Memory-pressure-aware trimming activates with the [psutil] extra (pip install "rag-llm-infra[psutil]"); without it the cache is fixed-size
rag_llm_infra.tracing OpenTelemetry spans with console-exporter + no-op fallbacks
rag_llm_infra.log_config structured JSON logging + an llm_call timer. It measures latency; tokens is a field the caller fills
rag_llm_infra.serve FastAPI service over the vector store + LLM protocol. /index and /query need X-API-Key; five routes are open, listed in SECURITY.md. Does not install log_config or tracing; call those yourself at startup
rag_llm_infra.faithfulness groundedness(answer, contexts): lexical faithfulness metric for RAG output
rag_llm_infra.fallback FallbackLLM: budget-aware multi-provider routing; drop-in LLMProtocol

Quality gates

python -m eval.retrieval_eval      # recall@1 / MRR: retrieval mechanics over the demo embedder
python -m eval.generation_eval     # groundedness (faithfulness) of generated answers

Both run in CI: a retrieval regression or a faithfulness regression fails the build and cannot merge. No floor is edited where it is used: every one is computed by scripts/derive_eval_floors.py into eval/eval_floors.json, which records the rule beside the measurement it came from, and a test requires re-running the producer to reproduce that file byte for byte. The generation floors come from the measured scores; the retrieval floors come from the query count and a stated tolerance of one slipped rank.

groundedness is a cheap lexical tripwire, not a faithfulness guarantee. It scores token overlap, so it has three blind spots by construction. It is negation-blind: "X is not Y" reads as grounded. It is dilutable: a false clause appended to a true answer only dents the score. And it scores vocabulary, not propositions, so it cannot tell whether the evidence asserts the claim. It catches the out-of-vocabulary hallucination signature cheaply on every generation. Pair it with an LLM-judge for semantic faithfulness. The limits are in the faithfulness module docstring and pinned by tests.

Engineering principles shown

  • Swap by interface. LLMProtocol / VectorStoreProtocol make the model and the index runtime-swappable.
  • Degrade, don't crash, where a degraded answer is still an answer. FAISS / Qdrant / OpenTelemetry / SentenceTransformers are optional. Each is probed at import behind a handler that treats a missing library and one that fails to load alike, so neither stops import rag_llm_infra; a test simulates both. The LLM factory is the deliberate exception: get_llm("auto") raises rather than falling back to the mock backend, because a fabricated answer is worse than none.
  • Measured, not asserted. A retrieval eval gate, not just unit tests; packaged and CI-built end to end.

Develop / test

pip install -e ".[dev]"     # installs FAISS + Qdrant + serve extras too
ruff check . && pytest && python -m eval.retrieval_eval

CI installs the native backends, so the FAISS and Qdrant tests run there (they skip only when those libraries are absent).

License

MIT. See LICENSE.

Download files

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

Source Distribution

rag_llm_infra-0.2.0.tar.gz (109.0 kB view details)

Uploaded Source

Built Distribution

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

rag_llm_infra-0.2.0-py3-none-any.whl (34.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: rag_llm_infra-0.2.0.tar.gz
  • Upload date:
  • Size: 109.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for rag_llm_infra-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3644776995dfdde06324337ae4fbc9792b7d86ae36700c9c39e1d3b08f6707b9
MD5 46069154a1d05342a600e262fb1f110b
BLAKE2b-256 e3a48fb7693fb6e67eec7f269578485f844e25b94041155c6a070d527defdad7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: rag_llm_infra-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 34.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for rag_llm_infra-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c28c66dc030f17aa7d341e6e87330b2abdae5733e02b319431c5c55037801fd
MD5 7cd7857fd2d9ac37d794a5dec15385ab
BLAKE2b-256 b5c7c9be41acd4c2d450a37320fa055f677cd71872094a930897134da4019af0

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