pip install ragleap-rag library. For the hosted business platform (AI Office, WhatsApp/Voice bots, billing), see docs.ragleap.com instead.
ragleap-rag
A narrow, opinionated hybrid retrieval engine — six vector backends, eight embedding providers, twelve-plus generation providers, one honest package.
Install
Requires Python 3.9+. Vector backends beyond PgVector, and non-default embedding providers, are optional extras.
pip install ragleap-rag # or, with uv uv add ragleap-rag
Quick start
from ragleap import RagLeap, ProviderConfig, EmbeddingConfig
rag = RagLeap(
database_url="postgresql://...",
primary=ProviderConfig(provider="gemini", api_key="..."),
embedder=EmbeddingConfig(provider="gemini", api_key="..."),
)
rag.init_schema()
rag.ingest("report.pdf")
answer = rag.ask("What were Q3's key findings?")
chunks = rag.retrieve("What were Q3's key findings?", top_k=5) # new in v0.12.0, no generation
How it fits together
flowchart TD
classDef ingest fill:#1e3a5f,stroke:#4a90d9,color:#fff
classDef query fill:#3d2645,stroke:#a855f7,color:#fff
classDef store fill:#1a4d3a,stroke:#22c55e,color:#fff
subgraph Ingest["Ingestion"]
Sources["Text, 28 formats,
URLs, images, audio, video"]:::ingest
Sources --> Ingest1["rag.ingest(...)
chunk -> embed -> store"]:::ingest
end
Ingest1 --> VectorStore["Vector backend (pluggable)
pgvector default, or FAISS/Pinecone/
Weaviate/Qdrant/Milvus via vector_backend="]:::store
subgraph Query["Query"]
Ask["rag.ask(...)"]:::query --> Rewrite["query_rewrite= (optional)
contextual, hyde, multi_query"]:::query
Rewrite --> Hybrid["Hybrid retrieve
dense + sparse (RRF)"]:::query
Hybrid --> Gen["Generation
temp / prompt / response_format"]:::query
Gen --> Fallback["Fallback chain
on primary provider failure"]:::query
Gen --> Cost["Cost tracking + guardrails
real token usage -> cost_usd"]:::query
Cost --> Memory["Conversation memory (Postgres)
optional session_id"]:::query
end
VectorStore --> Hybrid
Full public API surface
Confirmed via direct source reading during this session's full audit — not via inspect().
from ragleap import RagLeap, ProviderConfig, EmbeddingConfig, TranscriptionConfig
from ragleap.vectorstores import (
VectorBackend, PgVectorBackend, FAISSBackend,
PineconeBackend, WeaviateBackend, QdrantBackend, MilvusBackend,
)
from ragleap.guardrails import GuardrailViolation
from ragleap.query_rewrite import contextual_rewrite, hyde_document, multi_query_variants, reciprocal_rank_fusion
from ragleap.structured import parse_and_validate, parse_and_validate_object
from ragleap.cost import CostTracker, compute_cost, SEED_PRICING_TABLE
Ingestion
rag.ingest(path)rag.ingest_text(text)rag.ingest_url(url)rag.ingest_image(path)rag.ingest_audio(path)rag.ingest_video(path)Query
rag.ask(query, ...)rag.ask_stream(query, ...)ask(). Does not report token usage — each provider streams differently.rag.retrieve(query, top_k=5, hybrid=True, rerank=False, metadata_filter=None)ask()'s exact retrieval pipeline, stopping before generation. Does not support query_rewrite= or session_id= — those need LLM calls ask() owns.rag.evaluate(test_cases)Document management
rag.list_documents()rag.delete_document(id)rag.update_document(id, ...)rag.get_history() / rag.clear_session()ask() calls.rag.cache_stats()Async
aingest* / aask / aask_stream / ingest_batchretrieve() — why it exists
Added specifically so ragleap-graph's GraphRetriever could reach chunk-level retrieval without touching RagLeap's private internals (_vector_backend, _embed_query_cached()) across a package boundary. Shipped as a proper, tested, public method instead.
chunks = rag.retrieve(
query: str,
top_k: int = 5,
hybrid: bool = True,
rerank: bool = False,
metadata_filter: Optional[Dict] = None,
) -> List[Dict]
6 new tests shipped with this method, including one that makes the generator raise if called — proving retrieve() never triggers generation.
Provider & backend counts
Every count below was cross-checked against real code this session, not carried forward from marketing copy.
⚠ not live-verified Pinecone, Weaviate, Qdrant, and Milvus backends, and Mistral/Together/Cohere/Voyage embeddings, are code-complete but have no real test account available. Labeled honestly in each module's own docstring.
Known limitations
Drawn from the package's own docstrings, plus one finding from this session's full audit — not yet fixed.
- ask_stream() reports no token usage — each provider streams differently.
- MAX_CONTEXT_CHARS is a char-count approximation, not exact tokenization.
- Hybrid search's ranking-quality improvement is unverified beyond fusion-math correctness.
- Whisper transcription accuracy varies by language.
Metadata corrections
v0.12.8 — fixed a real, unexplained inconsistency: ingest()'s two siblings for raw-input ingestion, ingest_url() and ingest_image(), both already accepted an optional metadata= parameter threaded to ingest_text(). ingest() silently dropped it - despite being arguably the most commonly used entry point, the one that does format auto-detection. Discovered downstream while fixing the identical gap in ragleap-tools' ingest_document tool (v0.1.1). Backward compatible - defaults to None, no existing caller affected. 2 new live tests against real Postgres.
v0.12.7 — real bug in QdrantBackend, live-verified against a real Qdrant instance: search_dense() returned Qdrant's raw Distance.COSINE score directly as similarity_score - raw cosine similarity in [-1, 1], unlike pgvector/Weaviate/Milvus backends which all normalize to [0, 1]. A caller filtering similarity_score > 0.5 behaved correctly for those three and silently misbehaved for Qdrant's negative scores - the same inconsistency already found and fixed once for MilvusBackend (v0.11.0), previously missed here. Fixed with the identical (x + 1) / 2 transform.
v0.12.1 — The first-draft v0.12.0 PyPI description claimed "knowledge-graph integration via ragleap-graph" — backwards. ragleap-rag has zero dependency on or awareness of ragleap-graph; it's the other way around. Caught before the session moved on and published as a metadata-only patch, along with removing a "neo4j" keyword that implied a dependency that doesn't exist.
v0.12.2 — The PyPI Documentation URL pointed to docs.ragleap.com, the commercial platform's docs, which have zero content about this package. Corrected to point to this reference page instead.
v0.12.6 — fixed a real bug: the Gemini embedder silently ignored dimensions= despite EmbeddingConfig validating it as required at construction time - requesting a specific dimension against gemini-embedding-001 silently returned the model's full 3072-dim default instead. Found live-testing the #153 eval framework tooling, not via code read. Fix passes output_dimensionality to the real google.genai API call. Scoped to Gemini only - the other 7 embedding providers were unaffected.
v0.12.5 — docs-only release: pushed a corrected README (a stale AUTO-STATS test-count badge, three releases behind) to PyPI, since PyPI's displayed README only refreshes on a new upload. No code changes. Also re-verified the three headline capability claims (6 vector backends, 8 embedding providers, 12+ generation providers) against real source - all still exactly accurate.
v0.12.4 — chunk_text()'s token_count field now reflects a real LLM token count via tiktoken (cl100k_base) when available, closing the "known limitation" listed above through v0.12.3. A new token_count_is_exact field reports whether a real tiktoken count was used or the previous word-count fallback applied (e.g. no network egress to fetch the encoding on first use) — the fallback never claims to be exact. Breaking change to token_count's values for callers depending on the previous word-count numbers specifically.