RagLeap Packages
Looking for the RagLeap platform? This page documents the open-source pip install ragleap-rag library. For the hosted business platform (AI Office, WhatsApp/Voice bots, billing), see docs.ragleap.com instead.
255 / 255 tests passing · live-verified against real infrastructure

ragleap-rag

A narrow, opinionated hybrid retrieval engine — six vector backends, eight embedding providers, twelve-plus generation providers, one honest package.

0.12.8
PyPI version
255
Tests passing
4,853
Lines audited end-to-end
28
Ingestion formats

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)
Ingest a file — 28 supported formats.
rag.ingest_text(text)
Ingest raw text directly.
rag.ingest_url(url)
Fetch and ingest a web page.
rag.ingest_image(path)
Ingest an image (vision-capable providers).
rag.ingest_audio(path)
Transcribe and ingest audio via Whisper.
rag.ingest_video(path)
Extract audio track, transcribe, and ingest.

Query

rag.ask(query, ...)
Full pipeline: embed → search → (optional rerank) → generate.
rag.ask_stream(query, ...)
Streaming variant of ask(). Does not report token usage — each provider streams differently.
rag.retrieve(query, top_k=5, hybrid=True, rerank=False, metadata_filter=None)
New in v0.12.0. Reuses 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)
Run a labeled evaluation set against the pipeline.

Document management

rag.list_documents()
List ingested documents.
rag.delete_document(id)
Remove a document and its chunks.
rag.update_document(id, ...)
Re-ingest or patch an existing document.
rag.get_history() / rag.clear_session()
Conversation history for session-based ask() calls.
rag.cache_stats()
Inspect embedding-cache hit/miss counters.

Async

aingest* / aask / aask_stream / ingest_batch
Async variants of the above, plus batch ingestion.

retrieve() — 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.

6
Vector backends
PgVector, FAISS, Pinecone, Weaviate, Qdrant, Milvus
8
Embedding providers
Gemini + 4 OpenAI-compatible + 2 custom-shape + custom
12+
Generation providers
10 base URLs + Gemini + Anthropic + custom = 13

⚠ 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.