Skip to main content

piragi

The best RAG interface yet.

from piragi import Ragi

kb = Ragi(["./docs", "s3://bucket/data/**/*.pdf", "https://api.example.com/docs"])
answer = kb.ask("How do I deploy this?")

Built-in vector store, embeddings, citations, and auto-updates. Free & local by default. Ranked #1 Overall on the live AIR-Bench 24.05 Long-Doc Leaderboard (84.96% Recall@10, 75.72% nDCG@10, 80.10% MRR@10) and 32.61% Macro NDCG@10 (2.87x BM25; 71.98% Recall@100) across all 12 splits of BRIGHT (xlangai/BRIGHT, ICLR 2025) (31.43% fully open-weights — details).

Installation

pip install piragi

# Optional: Install Ollama for local LLM
curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3.2

# Optional extras
pip install piragi[s3]       # S3 support
pip install piragi[gcs]      # Google Cloud Storage
pip install piragi[azure]    # Azure Blob Storage
pip install piragi[crawler]  # Recursive web crawling
pip install piragi[graph]    # Knowledge graph
pip install piragi[postgres] # PostgreSQL/pgvector
pip install piragi[pinecone] # Pinecone
pip install piragi[supabase] # Supabase
pip install piragi[all]      # Everything

Features

  • Zero Config - Works with free local models out of the box
  • All Formats - PDF, Word, Excel, Markdown, Code, URLs, Images, Audio
  • Remote Storage - Read from S3, GCS, Azure, HDFS, SFTP with glob patterns
  • Web Crawling - Recursively crawl websites with /** syntax
  • Auto-Updates - Background refresh, queries never blocked
  • Smart Citations - Every answer includes sources
  • Pluggable Stores - LanceDB, PostgreSQL, Pinecone, Supabase, or custom
  • Advanced Retrieval - HyDE, hybrid search, cross-encoder reranking
  • Semantic Chunking - Context-aware and hierarchical chunking
  • Knowledge Graph - Entity/relationship extraction for better answers
  • Async Support - Non-blocking API for web frameworks

Quick Start

from piragi import Ragi

# Local files
kb = Ragi("./docs")

# Multiple sources with globs
kb = Ragi(["./docs/*.pdf", "https://api.docs.com", "./code/**/*.py"])

# Remote filesystems
kb = Ragi("s3://bucket/docs/**/*.pdf")
kb = Ragi("gs://bucket/reports/*.md")

# Ask questions
answer = kb.ask("What is the API rate limit?")
print(answer.text)

# View citations
for cite in answer.citations:
    print(f"{cite.source}: {cite.score:.0%}")

Remote Filesystems

Read files from cloud storage using glob patterns:

# S3
kb = Ragi("s3://my-bucket/docs/**/*.pdf")

# Google Cloud Storage
kb = Ragi("gs://my-bucket/reports/*.md")

# Azure Blob Storage
kb = Ragi("az://my-container/files/*.txt")

# Mix local and remote
kb = Ragi([
    "./local-docs",
    "s3://bucket/remote-docs/**/*.pdf",
    "https://example.com/api-docs"
])

Requires optional extras: pip install piragi[s3], piragi[gcs], or piragi[azure]

Web Crawling

Recursively crawl websites using /** suffix:

# Crawl entire site
kb = Ragi("https://docs.example.com/**")

# Crawl specific section
kb = Ragi("https://docs.example.com/api/**")

# Mix with other sources
kb = Ragi([
    "./local-docs",
    "https://docs.example.com/**",
    "s3://bucket/data/*.pdf"
])

Crawls same-domain links up to depth 3, max 100 pages by default.

Requires: pip install piragi[crawler]

Vector Store Backends

from piragi import Ragi
from piragi.stores import PineconeStore, SupabaseStore

# LanceDB (default) - local or S3-backed
kb = Ragi("./docs")
kb = Ragi("./docs", store="s3://bucket/indices")

# PostgreSQL with pgvector
kb = Ragi("./docs", store="postgres://user:pass@localhost/db")

# Pinecone
kb = Ragi("./docs", store=PineconeStore(api_key="...", index_name="my-index"))

# Supabase
kb = Ragi("./docs", store=SupabaseStore(url="https://xxx.supabase.co", key="..."))

Advanced Retrieval

kb = Ragi("./docs", config={
    "retrieval": {
        "use_hyde": True,                  # Hypothetical document embeddings
        "use_hybrid_search": True,         # BM25 + vector search (RRF)
        "use_cross_encoder": True,         # Neural reranking
    }
})

# Reasoning-Intensive Retrieval (BRIGHT-grade multi-hop theorem/code search)
kb_reason = Ragi("./docs", config={
    "retrieval": {
        "use_think_then_retrieve": True,   # Pre-retrieval CoT decomposition
        "use_hybrid_search": True,
        "use_rrf": True,
        "use_cross_encoder": True,
        "reranker_type": "causal_llm",     # "cross_encoder" | "causal_llm" | "listwise"
        "cross_encoder_model": "Qwen/Qwen3-Reranker-4B",
        "rerank_instruction": "Retrieve passages providing foundational theorems or APIs.",
    }
})

Local Evidence Decisions (SemIf / OpenJev)

Optionally judge retrieved passages before the answer model sees them:

kb = Ragi("./docs", config={"decision": {"engine": "openjev"}})

Requires a separate SemIf installation. Piragi selects the device and downloads/caches a pinned model on the first decision. model_path is an optional offline override. Piragi retrieves a wider hybrid candidate pool, batches relevance judgments, then checks whether the retained passages support an answer. Insufficient evidence skips generation; inference errors fall back to ordinary retrieval and appear in answer.decision. Scores are not calibrated confidence. See setup, behavior, and evaluation.

Chunking Strategies

# Semantic - splits at topic boundaries
kb = Ragi("./docs", config={"chunk": {"strategy": "semantic"}})

# Hierarchical - parent-child for context + precision
kb = Ragi("./docs", config={"chunk": {"strategy": "hierarchical"}})

# Contextual - LLM-generated context per chunk
kb = Ragi("./docs", config={"chunk": {"strategy": "contextual"}})

Knowledge Graph

Extract entities and relationships for better multi-hop reasoning:

# Enable with single flag
kb = Ragi("./docs", graph=True)

# Automatic - extracts entities/relationships during ingestion
# Uses them to augment retrieval for relationship questions
answer = kb.ask("Who reports to Alice?")

# Direct graph access
kb.graph.entities()           # ["alice", "bob", "project x"]
kb.graph.neighbors("alice")   # ["bob", "engineering team"]
kb.graph.triples()            # [("alice", "manages", "bob"), ...]

Requires: pip install piragi[graph]

Configuration

from piragi import Ragi, RagiConfig

# Pydantic validation catches typos and invalid types
config = RagiConfig(llm={"model": "gpt-4", "api_key": "sk-..."})
kb = Ragi("./docs", config=config)

Configuration supports typed fields and automatic validation.

Async Support

Use AsyncRagi for non-blocking operations in async web frameworks:

from piragi import AsyncRagi

kb = AsyncRagi("./docs")

# Simple await
await kb.add("./more-docs")
answer = await kb.ask("What is X?")

# With progress tracking
async for progress in kb.add("./large-docs", progress=True):
    print(progress)
    # "Discovering files..."
    # "Found 10 documents"
    # "Chunking 1/10: doc1.md"
    # ...
    # "Generating embeddings for 150 chunks..."
    # "Embedded 32/150 chunks"
    # "Embedded 64/150 chunks"
    # ...
    # "Embeddings complete"
    # "Done"

# With FastAPI
@app.post("/ingest")
async def ingest(files: list[str]):
    await kb.add(files)
    return {"status": "done"}

All methods are async: add(), ask(), retrieve(), refresh(), count(), clear().

Retrieval Only

Use piragi as a retrieval layer without LLM:

chunks = kb.retrieve("How does auth work?", top_k=5)
for chunk in chunks:
    print(chunk.chunk, chunk.source, chunk.score)

# Use with your own LLM
context = "\n".join(c.chunk for c in chunks)
response = your_llm(f"Context:\n{context}\n\nQuestion: {query}")

LLM Client

from piragi import LLMClient

# Standalone unified client with connection pooling and backoff retries
client = LLMClient(model="gpt-4", api_key="sk-...")
response = client.generate("Hello!")

Pipelines & Advanced API

from piragi.pipelines import IngestionPipeline, RetrievalPipeline
from piragi.loader import DocumentLoader

# Composable pipelines for power users
ingest = IngestionPipeline(store=store, embedder=embedder)
# Memory-efficient streaming loader for large corpora
ingest.run(DocumentLoader.stream("./large-corpora/**/*.pdf")) 

# Parallel multi-query search via ThreadPoolExecutor
retrieve = RetrievalPipeline(store=store, llm=llm, max_parallel_queries=4)
retrieve.run("What is X?") 

Pipelines offer fine-grained control over ingestion and parallelized retrieval.

Observability

Built-in RED/USE metrics (p50/p95/p99), W3C distributed traces, structured JSON logs, and symptom alerts — zero setup:

stats = kb.stats()
print(stats["red"]["ask"])   # {'requests': 12, 'errors': 0, 'p50_ms': 41.2, 'p99_ms': 89.4, ...}
print(stats["alerts"])       # Active symptom-based alerts linked to docs/runbooks/

API

# Sync API
kb = Ragi(sources, persist_dir=".piragi", config=None, store=None, graph=False)
kb.add("./more-docs")
text, citations = kb.ask(query, top_k=5)
kb.retrieve(query, top_k=5)
kb.filter(**metadata).ask(query)  # Thread-safe filtering returns FilteredRagi
kb.refresh("./docs")
kb.count()
kb.stats()
kb.clear()

# Async API (same methods, just await them)
kb = AsyncRagi(sources, persist_dir=".piragi", config=None, store=None, graph=False)
await kb.add("./more-docs")
text, citations = await kb.ask(query, top_k=5)
await kb.stats()

Full docs: API.md

Playground

Interactive playground with zero setup — works in demo mode on GitHub Pages or live with a local backend:

pip install piragi
piragi playground

Features: multi-cell code editor, simulated outputs, LLM config, file browser.

License

MIT

Metadata

Release files for piragi 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for piragi 1.3.0
File Size Uploaded Provenance Actions
piragi-1.3.0.tar.gz 258.4 kB Without provenance Details for piragi-1.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for piragi 1.3.0
File Interpreter ABI Platform Actions
piragi-1.3.0-py3-none-any.whl Python 3 none any Details for piragi-1.3.0-py3-none-any.whl

Total release size: 380.9 kB

Release files / piragi-1.3.0.tar.gz

Download URL piragi-1.3.0.tar.gz
Size 258.4 kB
Tags Source
SHA-256 checksum
How to use checksums
cdccb0e4401b3f5a340bb859f6592d3a170d9f4948aa02e898c178c1bfa6819a
BLAKE2b-256 checksum
How to use checksums
76046dabbb7c391a59220d6bbcd3014d7df3c30e63357eb99e67e9f2fd402ef1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / piragi-1.3.0-py3-none-any.whl

Download URL piragi-1.3.0-py3-none-any.whl
Size 122.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9c1782ba0b1c58c0d0591bd1013a7ace7ee472e987d9b614913c71a78b08d134
BLAKE2b-256 checksum
How to use checksums
7ffb62163965da6fec555a9a66839848644052795fd33b50e65170df513542d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for piragi 1.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page