Modular, project-agnostic RAG retrieval layer: independent retrieval strategies behind a small shared core.
Project description
mkd-retriever
A modular, project-agnostic RAG retrieval layer. Several retrieval strategies — intent classification, text-to-SQL database query, and more to come (top-N vector search, query rewriting, RAPTOR, agentic flows) — live side by side in one package without depending on one another.
The PyPI name is mkd-retriever; the import name is retrieval
(import retrieval).
pip install mkd-retriever # core only
pip install "mkd-retriever[intent_classification]"
pip install "mkd-retriever[db_query]"
pip install "mkd-retriever[all]" # everything implemented so far
Why it is built this way
Building retrieval methods on top of one another is a Jenga tower: changing or
removing one piece topples the rest. Instead, every method is an independent
module. The hard rules (enforced, see ARCHITECTURE.md):
- A module never imports another module. Cross-module communication is the consuming project's job, not this library's.
- Everything shared lives in
retrieval.core, and core stays small. Only minimal interfaces and common data schemas — never a module's implementation detail. The dependency arrow is always module → core. - Dependencies are isolated per module. Each module has its own optional-dependency group; a library one module needs never leaks into another module's environment.
- Each module is understandable and testable on its own.
- Intent classification only returns a label — it does not route. Mapping a label to a retrieval method is the consuming project's decision.
What's inside
retrieval/
core/ shared interfaces + ingestion-contract schemas (small, stable)
eval/ golden-set format + metrics + async runner (cross-cutting)
modules/
intent_classification/ query -> intent label (usable)
db_query/ query -> SQL -> rows (usable)
top_n/ vector search (planned)
query_rewriting/ rewriting / expansion (planned)
raptor/ hierarchical retrieval (planned)
agentic/ multi-step flows (planned)
retrieval.core
The whole surface every module shares:
RetrievalResult— a single scored item, returned identically by every backend (id,score,text,metadata).Retriever— the one async method a backend implements:async def retrieve(query, k) -> list[RetrievalResult].run_syncis a thin convenience for synchronous callers.IntentLabel(9 classes) /IntentResult.- Ingestion-contract schemas — pydantic models for the JSON an upstream
ingestion/parsing project emits (chunks, product graph, document metadata).
The contract is defined by shape, not by importing the producer, so any
project emitting these shapes can feed this layer. Models set
extra="ignore"to stay resilient to upstream format drift.
intent_classification
A prompt-based classifier over any langchain-core BaseChatModel. It returns
one IntentResult and nothing more — the label → strategy mapping is the
consuming project's job.
from retrieval.modules.intent_classification import (
LLMIntentClassifier, build_default_chat_model,
)
clf = LLMIntentClassifier(build_default_chat_model())
result = await clf.classify("de1000 fiyati ne kadar") # -> IntentResult
In tests, inject a fake BaseChatModel instead of the factory — no network,
no model download.
db_query
Retrieval by generating SQL and running it. A natural-language query is turned
into a SQL string by the text2sql-engine
package (a 2-stage LLM pipeline), that SQL runs against a ready-made
database, and the rows come back as RetrievalResult items.
from retrieval.modules.db_query import build_default_retriever
retriever = build_default_retriever(db_path="specs.db")
results = await retriever.retrieve("operating temperature of DE9001", k=5)
Two injected seams keep it testable and dependency-isolated:
SqlGenerator(NL → SQL) — the production impl wraps atext2sqlengine hitting a remote endpoint; unit tests inject a fake returning canned SQL.SqlExecutor(SQL → rows) — the shippedSQLiteExecutoruses only stdlibsqlite3and opens the database read-only by default, so a stray write in generated SQL fails at the engine level.
The score is a constant 1.0 (a SQL result is an exact match set, not a
similarity ranking; ordering is the query's own ORDER BY). The full row is in
RetrievalResult.metadata. This module connects to an existing database — it
does not build one.
Inference & the GPU rule
Model inference (LLM/embedding) is expected to run on a separate machine
behind an OpenAI-compatible endpoint. This library only sends requests to that
endpoint; it never downloads models or runs local inference. The default test
run (pytest) is fully mocked and never reaches a network endpoint — tests that
hit a live endpoint are marked integration and skipped by default.
Development
pip install -e ".[all,dev]"
pytest
License
MIT. See LICENSE.
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 mkd_retriever-0.1.0.tar.gz.
File metadata
- Download URL: mkd_retriever-0.1.0.tar.gz
- Upload date:
- Size: 25.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78004fb11899009ffe0225eff041edb0e82594e5ae8a17791a22c952f43dbf49
|
|
| MD5 |
39fe8fb29e27d86faed8c270b0c5c5ec
|
|
| BLAKE2b-256 |
028c5dfe06decffda321c87a5357505db1dac926947cb1265732187c6938da62
|
File details
Details for the file mkd_retriever-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mkd_retriever-0.1.0-py3-none-any.whl
- Upload date:
- Size: 31.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa30d5dcdf6e92031182aa1abdb7865d3aba9a44386aead7aafbc76ab0443fbe
|
|
| MD5 |
3a6e3cfb4d4d62c01b2c0eced2227ec1
|
|
| BLAKE2b-256 |
8c26648531b0c7d2c95cf5ea145aca132111d4f0ac161e5533af0a7dcce20afc
|