PyHound is a diagnostic tool for RAG/LLM retrieval systems, built with:
- Rust core — High-performance diagnostics
- Python wrapper — Easy integration with Python ML workflows
┌─────────────────────────────────────────────────────────────┐
│ User Application (Python) │
│ from pyhound import Hound │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────▼───────────────────────────────────────┐
│ PyHound Python API (pyhound/) │
│ ├─ Hound (main interface) │
│ ├─ Diagnosis (analysis results) │
│ ├─ ModelComparison (model selection) │
│ └─ QualityScorer (embedding monitoring) │
└─────────────────────┬───────────────────────────────────────┘
│ (PyO3 bindings)
┌─────────────────────▼───────────────────────────────────────┐
│ PyHound Rust Core (src/lib.rs) │
│ ├─ Isotropy calculation │
│ ├─ Coverage analysis │
│ ├─ Distinctiveness metrics │
│ ├─ Drift detection │
│ ├─ Component analysis │
│ └─ Improvement tracking │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────▼───────────────────────────────────────┐
│ Database Adapters (All Open-Source) │
│ ├─ Qdrant adapter │
│ ├─ Chroma adapter │
│ ├─ Milvus adapter │
│ ├─ Weaviate adapter │
│ └─ PostgreSQL pgvector adapter │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────▼───────────────────────────────────────┐
│ Vector Databases (Open-Source) │
│ ├─ Qdrant │
│ ├─ Chroma │
│ ├─ Milvus │
│ ├─ Weaviate │
│ └─ PostgreSQL + pgvector │
└─────────────────────────────────────────────────────────────┘
PyHound analyzes retrieval at four stages:
-
Embedding Quality — How well embeddings capture semantics
- Isotropy: Vector space utilization
- Coverage: Diversity of embeddings
- Distinctiveness: Semantic separation
-
Vector Search — Similarity matching quality
- Precision: Correctness of results
- Recall: Completeness of results
- Ranking quality: Relevance ordering
-
Keyword Search (BM25) — Full-text matching
- Precision and recall
- Match quality
-
Reranker — Final result ordering
- Calibration: Are scores correct?
- NDCG: Ranking quality
User Query
│
├─→ Retrieve results (vector DB)
│
├─→ Compute metrics for each component:
│ ├─ Embedding quality (Rust core)
│ ├─ Vector search metrics
│ ├─ BM25 metrics
│ └─ Reranker metrics
│
├─→ Identify root cause
│
├─→ Generate recommendations
│
└─→ Return Diagnosis object
Main interface. Coordinates diagnosis, comparison, and monitoring.
Analyzes retrieval failures and generates reports.
Compares models (embedding, reranker) for selection.
Monitors embedding quality in production.
Rust core implementing:
- Embedding metrics (isotropy, coverage, distinctiveness)
- Drift detection
- Performance-critical calculations
hound = Hound(db="qdrant")
diagnosis = hound.diagnose(query="...", top_k=5)- Query is sent to vector database
- Top-K results retrieved
- Rust core computes metrics
- Python layer analyzes results
- Diagnosis object generated with recommendations
comparison = hound.compare_models(
model_type="embedding",
candidates=["3-small", "3-large"]
)- Sample queries selected
- Each model tested on samples
- Metrics computed (quality, cost, latency)
- Recommendations generated
- Rust core — Sub-millisecond metric calculations
- Database queries — Depends on database (typically 1-100ms)
- Python overhead — Minimal via PyO3
- Caching — Results cached when possible
Target: <100ms end-to-end diagnosis per query
Implement the VectorDB protocol:
class CustomDBAdapter(VectorDB):
def connect(self, endpoint: str) -> None: ...
def search(self, query: np.ndarray, top_k: int) -> List[Result]: ...
def get_embeddings(self, doc_ids: List[str]) -> List[np.ndarray]: ...Rust functions are exposed via PyO3:
#[pyfunction]
fn compute_custom_metric(embeddings: Vec<Vec<f32>>) -> PyResult<f32> {
// Implementation
}- Unit tests — Rust metrics calculation
- Integration tests — Full diagnosis workflow
- Database tests — Each adapter
- Benchmark tests — Performance regressions
See tests/ for examples.