@@ -109,17 +109,17 @@ client = QdrantClient("localhost", port=6333)
109109
110110# Create a collection
111111client.recreate_collection(
112- collection_name = " documents" ,
113- vectors_config = {" size" : 1536 , " distance" : " Cosine" }
112+ collection_name = " documents" ,
113+ vectors_config = {" size" : 1536 , " distance" : " Cosine" }
114114)
115115
116116# Add sample embeddings
117117vectors = np.random.rand(5 , 1536 ).tolist()
118118client.upsert(
119- collection_name = " documents" ,
120- points = [
121- {" id" : i, " vector" : vec} for i, vec in enumerate (vectors)
122- ]
119+ collection_name = " documents" ,
120+ points = [
121+ {" id" : i, " vector" : vec} for i, vec in enumerate (vectors)
122+ ]
123123)
124124```
125125
@@ -133,9 +133,9 @@ hound = Hound(db="qdrant", endpoint="localhost:6333")
133133
134134# Diagnose retrieval quality
135135diagnosis = hound.diagnose(
136- query = " your search query" ,
137- top_k = 5 ,
138- expected_docs = [" 0" , " 1" ] # optional: docs that should be retrieved
136+ query = " your search query" ,
137+ top_k = 5 ,
138+ expected_docs = [" 0" , " 1" ] # optional: docs that should be retrieved
139139)
140140
141141# Get actionable report
@@ -153,11 +153,11 @@ kb = OKFDiagnosticKnowledgeBase(Path("./diagnostic_kb"))
153153
154154# Save diagnosis to KB (automatic)
155155kb.record_diagnosis(
156- query_id = " query_20260720_001" ,
157- root_cause = diagnosis.root_cause,
158- confidence = diagnosis.confidence,
159- failure_types = diagnosis.failure_types,
160- recommendations = diagnosis.recommendations
156+ query_id = " query_20260720_001" ,
157+ root_cause = diagnosis.root_cause,
158+ confidence = diagnosis.confidence,
159+ failure_types = diagnosis.failure_types,
160+ recommendations = diagnosis.recommendations
161161)
162162
163163# Now learn from history
@@ -167,13 +167,13 @@ print(f"Found {len(similar)} similar failures in KB")
167167# Get best strategies based on success history
168168patterns = kb.extract_patterns(min_frequency = 2 )
169169for pattern in patterns:
170- print (f " { pattern[' pattern' ]} : { pattern[' frequency' ]} of cases, "
171- f " { pattern[' avg_success_rate' ]} success rate " )
170+ print (f " { pattern[' pattern' ]} : { pattern[' frequency' ]} of cases, "
171+ f " { pattern[' avg_success_rate' ]} success rate " )
172172
173173# Recommendations auto-ranked by what worked before
174174enhanced = kb.generate_enhanced_recommendations(
175- diagnosis.root_cause,
176- diagnosis.recommendations
175+ diagnosis.root_cause,
176+ diagnosis.recommendations
177177)
178178print (" Top recommendation (ranked by success):" )
179179print (f " - { enhanced[0 ][' strategy' ]} " )
@@ -186,7 +186,7 @@ PyVectorhound tells you exactly what's wrong—**and what worked last time**:
186186
187187```
188188=======================================================
189- PyVectorhound Diagnosis Report
189+ PyVectorhound Diagnosis Report
190190=======================================================
191191
192192Query: "quantum computing"
@@ -196,34 +196,34 @@ COMPONENT BREAKDOWN
196196-------------------------------------------------------
197197
198198EMBEDDING MODEL: WEAK
199- Problem: Your embedding model doesn't understand
200- domain-specific concepts. Vectors cluster together
201- instead of spreading across the semantic space.
202-
203- Metrics:
204- - Isotropy: 45% (should be >70%)
205- - Distinctiveness: 21% (should be >60%)
206-
207- Impact: Vector search can't find semantically
208- similar documents
209-
210- VECTOR SEARCH: MODERATE
211- Precision: 62% (should be >85%)
212- Recall: 55% (should be >80%)
213-
214- Impact: 38% of results are irrelevant
199+ Problem: Your embedding model doesn't understand
200+ domain-specific concepts. Vectors cluster together
201+ instead of spreading across the semantic space.
202+
203+ Metrics:
204+ - Isotropy: 45% (should be >70%)
205+ - Distinctiveness: 21% (should be >60%)
206+
207+ Impact: Vector search can't find semantically
208+ similar documents
209+
210+ VECTOR SEARCH: MODERATE
211+ Precision: 62% (should be >85%)
212+ Recall: 55% (should be >80%)
213+
214+ Impact: 38% of results are irrelevant
215215
216216KEYWORD SEARCH (BM25): GOOD
217- Precision: 85%, Recall: 78%
218-
219- Status: Working well, catching many matches
220- that vector search misses
217+ Precision: 85%, Recall: 78%
218+
219+ Status: Working well, catching many matches
220+ that vector search misses
221221
222222RERANKER: GOOD
223- Calibration: 91%
224-
225- Status: Helping but limited by weak upstream
226- components
223+ Calibration: 91%
224+
225+ Status: Helping but limited by weak upstream
226+ components
227227
228228ROOT CAUSE
229229-------------------------------------------------------
@@ -234,27 +234,27 @@ domain-specific corpus.
234234RECOMMENDATIONS (Ranked by Historical Success)
235235-------------------------------------------------------
2362361. HIGHEST PRIORITY: Upgrade Embedding Model
237- Try: text-embedding-3-large OR domain-specific model
238- Expected quality gain: +8-12 F1 points
239- ✅ HISTORICAL SUCCESS: 87% (based on 12 similar cases in KB)
240- Cost impact: +$8/month
241- Implementation time: 2 hours
242- ROI: High (8-12% improvement for 40% cost increase)
237+ Try: text-embedding-3-large OR domain-specific model
238+ Expected quality gain: +8-12 F1 points
239+ HISTORICAL SUCCESS: 87% (based on 12 similar cases in KB)
240+ Cost impact: +$8/month
241+ Implementation time: 2 hours
242+ ROI: High (8-12% improvement for 40% cost increase)
243243
2442442. QUICK WIN: Adjust Hybrid Search Weights
245- Current: BM25 (50%) + Vector (50%)
246- Try: BM25 (40%) + Vector (60%)
247- Expected gain: +2-3 F1 points
248- ✅ HISTORICAL SUCCESS: 65% (based on 4 similar cases in KB)
249- Time: 10 minutes
250- Cost: None
245+ Current: BM25 (50%) + Vector (50%)
246+ Try: BM25 (40%) + Vector (60%)
247+ Expected gain: +2-3 F1 points
248+ HISTORICAL SUCCESS: 65% (based on 4 similar cases in KB)
249+ Time: 10 minutes
250+ Cost: None
251251
2522523. OPTIONAL: Fine-tune Embedding on Your Corpus
253- Requires: 500+ labeled examples
254- Expected gain: +5-8% quality
255- ✅ HISTORICAL SUCCESS: 92% (based on 11 similar cases in KB)
256- Time: 1-2 days
257- Cost: Training infrastructure
253+ Requires: 500+ labeled examples
254+ Expected gain: +5-8% quality
255+ HISTORICAL SUCCESS: 92% (based on 11 similar cases in KB)
256+ Time: 1-2 days
257+ Cost: Training infrastructure
258258
259259KNOWLEDGE BASE INSIGHTS
260260-------------------------------------------------------
@@ -266,7 +266,7 @@ Trending: 3 similar failures in last 2 weeks
266266
267267## Star If This Helps!
268268
269- If PyVectorhound solves your retrieval debugging problem, consider giving it a star ⭐ on GitHub. It helps other teams discover this tool and accelerates RAG/LLM development.
269+ If PyVectorhound solves your retrieval debugging problem, consider giving it a star on GitHub. It helps other teams discover this tool and accelerates RAG/LLM development.
270270
271271## Understanding the Output
272272
@@ -278,40 +278,40 @@ If PyVectorhound solves your retrieval debugging problem, consider giving it a s
278278
279279## FAQ
280280
281- ** Q: Do I need to set up PyVectorhound specially?**
281+ ** Q: Do I need to set up PyVectorhound specially?**
282282A: No. Install via pip, point it at your existing vector database, and run diagnosis.
283283
284- ** Q: Can PyVectorhound work with my existing vector database?**
284+ ** Q: Can PyVectorhound work with my existing vector database?**
285285A: Yes. Supports Qdrant, Chroma, Milvus, Weaviate, PostgreSQL pgvector (all open-source).
286286
287- ** Q: Does PyVectorhound modify my data?**
287+ ** Q: Does PyVectorhound modify my data?**
288288A: No. PyVectorhound is read-only. It analyzes but never modifies your vectors or documents.
289289
290- ** Q: What if I don't have ground truth (expected_docs)?**
290+ ** Q: What if I don't have ground truth (expected_docs)?**
291291A: Ground truth is optional. Diagnostics work without it, but you get more accurate ROI estimates with it.
292292
293- ** Q: How long does a diagnosis take?**
293+ ** Q: How long does a diagnosis take?**
294294A: Typically 45ms for small queries. Larger corpus analysis may take seconds.
295295
296- ** Q: Can I use PyVectorhound in production?**
296+ ** Q: Can I use PyVectorhound in production?**
297297A: Yes. It's designed for production monitoring. Overhead is minimal (<1ms per operation).
298298
299- ** Q: Does PyVectorhound require Rust knowledge?**
299+ ** Q: Does PyVectorhound require Rust knowledge?**
300300A: No. PyVectorhound is pure Python to use. Rust is only for building from source.
301301
302- ** Q: How does PyVectorhound compare to other retrieval diagnostics tools?**
302+ ** Q: How does PyVectorhound compare to other retrieval diagnostics tools?**
303303A: PyVectorhound provides root cause analysis and ranked recommendations, not just monitoring. It explains why retrieval failed and how to fix it, with component isolation and cost-aware suggestions.
304304
305305## Supported Vector Databases
306306
307307All database connectors are open-source compliant:
308308
309- - ** Qdrant** — Open-source vector database
310- - ** Chroma** — Open-source embedding database
311- - ** Milvus** — Open-source vector database
312- - ** Weaviate** — Open-source semantic search engine
313- - ** PostgreSQL (pgvector)** — SQL + open-source pgvector extension
314- - ** Custom** — Query any database
309+ - ** Qdrant** — Open-source vector database
310+ - ** Chroma** — Open-source embedding database
311+ - ** Milvus** — Open-source vector database
312+ - ** Weaviate** — Open-source semantic search engine
313+ - ** PostgreSQL (pgvector)** — SQL + open-source pgvector extension
314+ - ** Custom** — Query any database
315315
316316Add more databases by implementing the ` VectorDB ` protocol.
317317
@@ -323,9 +323,9 @@ Rust Core (pyvectorhound._core)
323323- Pipeline analysis
324324- Drift detection
325325- Improvement tracking
326- |
327- (PyO3 bindings)
328- |
326+ |
327+ (PyO3 bindings)
328+ |
329329Python Wrapper (pyvectorhound)
330330- Hound class (main API)
331331```
@@ -342,20 +342,20 @@ PyVectorHound goes beyond monitoring: it diagnoses retrieval issues, recommends
342342
343343| Capability | Traditional Tools | PyVectorHound |
344344| -----------| ---| ---|
345- | Root cause analysis | ❌ | ✅ |
346- | Component isolation | ❌ | ✅ |
347- | Ranked recommendations | ❌ | ✅ |
348- | Cost-aware suggestions | ❌ | ✅ |
349- | Before/after comparison | ❌ | ✅ |
350- | Model comparison | ❌ | ✅ |
351- | ** Persistent knowledge base** | ❌ | ✅ OKF |
352- | ** Learning from history** | ❌ | ✅ OKF |
353- | ** Pattern recognition** | ❌ | ✅ OKF |
354- | ** Autonomous optimization** | ❌ | ✅ OKF |
345+ | Root cause analysis | | |
346+ | Component isolation | | |
347+ | Ranked recommendations | | |
348+ | Cost-aware suggestions | | |
349+ | Before/after comparison | | |
350+ | Model comparison | | |
351+ | ** Persistent knowledge base** | | OKF |
352+ | ** Learning from history** | | OKF |
353+ | ** Pattern recognition** | | OKF |
354+ | ** Autonomous optimization** | | OKF |
355355
356356** The OKF Difference:**
357- - Traditional tools: "Here's what's wrong" → Forget after you close the report
358- - PyVectorHound: "Here's what's wrong, here's what worked last time, here's what your team learned" → Improve every diagnosis
357+ - Traditional tools: "Here's what's wrong" Forget after you close the report
358+ - PyVectorHound: "Here's what's wrong, here's what worked last time, here's what your team learned" Improve every diagnosis
359359
360360## Speed Comparison
361361
@@ -412,8 +412,8 @@ print(diagnosis.hunt())
412412``` python
413413# Should you upgrade to a larger embedding model?
414414comparison = hound.compare_models(
415- model_type = " embedding" ,
416- candidates = [" 3-small" , " 3-large" , " cohere-v3" ]
415+ model_type = " embedding" ,
416+ candidates = [" 3-small" , " 3-large" , " cohere-v3" ]
417417)
418418print (comparison.report())
419419# Get: quality metrics, cost impact, ROI analysis
@@ -428,12 +428,12 @@ scorer = hound.quality_scorer()
428428# Score embeddings in real-time
429429quality = scorer.score(embedding_vector)
430430if quality[" status" ] == " WEAK" :
431- alert(" Embedding quality degraded" )
431+ alert(" Embedding quality degraded" )
432432
433433# Detect gradual drift
434434health = scorer.corpus_health()
435435if health[" drift" ] > 0.15 :
436- alert(f " 15% quality degradation detected " )
436+ alert(f " 15% quality degradation detected " )
437437```
438438
439439## Troubleshooting
@@ -485,22 +485,22 @@ comparison = hound.compare_models(model_type="embedding", candidates=[...])
485485scorer = hound.quality_scorer()
486486
487487# Diagnosis methods
488- diagnosis.hunt() # Plain English report
489- diagnosis.metrics() # Raw metrics by component
490- diagnosis.recommendations() # Ranked fixes
491- diagnosis.root_cause() # Root cause explanation
488+ diagnosis.hunt() # Plain English report
489+ diagnosis.metrics() # Raw metrics by component
490+ diagnosis.recommendations() # Ranked fixes
491+ diagnosis.root_cause() # Root cause explanation
492492
493493# Comparison methods
494- comparison.report() # Side-by-side comparison
495- comparison.metrics() # Quality/cost/latency data
496- comparison.pareto_frontier() # Optimal models
497- comparison.ab_test(... ) # Setup A/B test
494+ comparison.report() # Side-by-side comparison
495+ comparison.metrics() # Quality/cost/latency data
496+ comparison.pareto_frontier() # Optimal models
497+ comparison.ab_test(... ) # Setup A/B test
498498
499499# Scorer methods
500- scorer.score(embedding) # Score single embedding
501- scorer.corpus_health() # Corpus-wide metrics
502- scorer.detect_anomalies(... ) # Find problematic embeddings
503- scorer.trend_analysis(... ) # Historical trends
500+ scorer.score(embedding) # Score single embedding
501+ scorer.corpus_health() # Corpus-wide metrics
502+ scorer.detect_anomalies(... ) # Find problematic embeddings
503+ scorer.trend_analysis(... ) # Historical trends
504504```
505505
506506## Documentation
@@ -586,7 +586,7 @@ from pyvectorhound.okf_diagnostics import OKFDiagnosticKnowledgeBase
586586kb = OKFDiagnosticKnowledgeBase(Path('diagnostic_kb'))
587587patterns = kb.extract_patterns()
588588for p in patterns:
589- print(f\" {p['pattern']}: {p['frequency']} of cases\" )
589+ print(f\" {p['pattern']}: {p['frequency']} of cases\" )
590590"
591591
592592# Your KB is now a git repo—share with your team!
@@ -621,7 +621,7 @@ Built with:
621621
622622* Diagnose 45ms. Learn forever. Fix autonomously.*
623623
624- ## 🔒 Security & Error Handling
624+ ## Security & Error Handling
625625
626626PyVectorHound includes:
627627
0 commit comments