doc-ingestion / rag-spec-evaluation.md
Vamshi Pokala
Redesigned the README and added Citiation and truthfullness in responses
ce71763
|
Raw
History Blame
6.04 kB

RAG Spec Evaluation Report

Context

This is a gap analysis of the Doc-Ingestion app against a production-grade RAG spec across three phases. The goal is to identify what is built, what partially meets the spec, and what is missing or misaligned.


Spec vs. Implementation: Detailed Evaluation

Phase 1 β€” Fundamentals

Requirement Status Detail
Ingest documents βœ… Built PDF, DOCX, TXT, MD, HTML via src/core/document_processor.py
500–800 token chunks ⚠️ Partial / Misaligned Chunking uses characters (default: 1000 chars, 200 overlap), not tokens. Spec requires token-based chunking (500–800 tokens). No tokenizer is applied during chunking.
100-token overlap ⚠️ Partial / Misaligned Overlap is 200 characters, not 100 tokens. Same root issue: characters vs. tokens.
Vector store (Chroma or Qdrant) βœ… Built ChromaDB for dev (data/embeddings/chroma), Qdrant optional for prod. Both present in src/utils/database.py.

Gap to fix:

  • src/core/document_processor.py chunk_text() method uses character sliding window. Needs to be replaced with a tokenizer-aware splitter (e.g., tiktoken or transformers tokenizer) targeting 500–800 tokens with 100-token overlap.
  • config.yaml chunk_size: 1000 and overlap: 200 need to change to token units.

Phase 2 β€” Hybrid Retrieval + Re-ranking

Requirement Status Detail
BM25 keyword search βœ… Built src/core/bm25_search.py, BM25Search using rank-bm25
Vector semantic search βœ… Built src/core/vector_search.py, VectorSearch with ChromaDB
Hybrid retrieval combining both βœ… Built src/core/hybrid_retriever.py, HybridRetriever with Reciprocal Rank Fusion (RRF), parallel execution
Cross-encoder re-ranker βœ… Built src/core/reranker.py, CrossEncoderReranker using cross-encoder/ms-marco-MiniLM-L-6-v2

Phase 2 is fully built and exceeds the spec (adds RRF fusion, LRU caching, confidence scoring, configurable weights).


Phase 3 β€” Evaluation Dataset + CI/CD

Requirement Status Detail
Golden dataset of 50–200 Q&A pairs ⚠️ Missing Only evals/datasets/smoke.jsonl (few entries, 1 KB) and evals/datasets/sample.jsonl (6 KB, estimated ~10–15 pairs). Neither meets the 50–200 pair threshold.
Offline evaluation script βœ… Built evals/run_evals.py (504 lines) with 8+ metrics: answer_relevancy, context_precision, context_recall, ROUGE-L, citation_rate, faithfulness
CI/CD pipeline integration ⚠️ Partial .github/workflows/ci.yml has evals-smoke job, but it runs with --mock flag (MockPipeline). It does not measure real faithfulness β€” it tests the eval harness, not the RAG pipeline.
Measure faithfulness ⚠️ Partial NLI faithfulness via src/evaluation/truthfulness.py exists. RAGAS integration exists in evals/adapters/ragas_llm_adapter.py but is optional (requires ragas>=0.2, langchain-core extra deps) and not wired into CI.

Recommended Tech Stack Alignment

Recommendation Status Detail
LangChain or LangGraph ❌ Not used Core pipeline uses direct HTTP API calls (src/core/llm_provider.py). LangChain only appears as a thin adapter in evals/adapters/ragas_llm_adapter.py to satisfy RAGAS interface β€” it is not the orchestration framework.
ChromaDB or Qdrant βœ… Built Both present
Ragas for evaluation ⚠️ Optional / Incomplete Present as optional adapter, not enforced. CI runs MockPipeline without RAGAS.

Summary: What Is Missing

Must-Fix (spec violations)

  1. Token-based chunking β€” src/core/document_processor.py:chunk_text() uses character counts, not tokens. Replace with tokenizer-aware chunking (e.g., tiktoken) targeting 500–800 tokens, 100-token overlap. Update config.yaml units accordingly.

  2. Golden evaluation dataset (50–200 pairs) β€” evals/datasets/ only has smoke (few entries) and sample (10–15 pairs). Need to create a curated dataset of at least 50 ground-truth Q&A pairs with reference contexts, authored against real ingested documents.

  3. CI/CD runs real faithfulness evaluation β€” The evals-smoke GitHub Actions job uses --mock. A CI job that runs LivePipeline against the golden dataset (or a representative subset) and gates on a faithfulness threshold is required by the spec.

Should-Fix (partial alignment)

  1. RAGAS made non-optional β€” RAGAS faithfulness should be a hard dependency in evals/, not a conditional import behind try/except. The eval report should always include RAGAS faithfulness score.

  2. LangChain / LangGraph adoption β€” The spec recommends LangChain/LangGraph as the orchestration layer. Currently the pipeline is custom HTTP. This is a tech stack deviation, not a functional gap β€” worth noting but lower priority than items 1–3.


What Is Already Production-Grade (exceeds spec)

  • Full hybrid retrieval with RRF fusion, parallel execution, and LRU caching
  • Cross-encoder reranking with batch scoring and threshold filtering
  • Multi-provider LLM routing (Ollama, OpenAI, Anthropic, Gemini) with streaming
  • NLI-based inline truthfulness scoring in the serving path
  • Citation tracking and verification
  • Response caching (Redis + in-memory fallback)
  • Rate limiting, API key auth, audit logging
  • Comprehensive IR metrics module (P@K, R@K, MRR, MAP, NDCG)
  • Unit + integration test coverage with CI

Verification Steps (after fixes)

  1. After token-based chunking: ingest a known document, query it, verify chunk boundaries fall within 500–800 token range using tiktoken inspection script.
  2. After golden dataset: run python -m evals.run_evals --dataset evals/datasets/golden.jsonl --live and confirm dataset size β‰₯ 50.
  3. After CI wiring: confirm GitHub Actions evals-golden job fails when faithfulness drops below threshold (e.g., nli_faithfulness < 0.7).