Skip to main content

Home · Projects · Applied AI / RAG

ContextIQ

Eval-first RAG for production knowledge systems: hybrid retrieval, citations, refusal, and a CI quality gate.

Role
Full Stack · RAG Engineering
Type
Eval-first RAG platform
Client
Personal · Open source
Status
Live
Next.jsPythonStarletteSSEBGE-smallOpenAI APIVercelRailway
ContextIQ — eval-first RAG platform overview, pipeline, and evaluation dashboard

Outcome

Measured RAG end to end: dense-only recall@5 was 3.9% on the golden set; hybrid + rerank reached 89.3% context recall with 100% faithfulness and 100% refusal accuracy on unanswerable queries.

89.3%

Context recall

100%

Faithfulness

100%

Refusal accuracy

0%

Hallucination

Problem

Tutorial RAG stops at embed-and-cosine: exact terms (API names, quotas, error codes) get missed, models invent APIs when context is thin, and changing chunking silently tanks quality with no regression test.

Solution

Full pipeline: ingest structured docs, chunk with measured strategies, embed (BGE-small), retrieve dense + sparse → Reciprocal Rank Fusion → rerank, generate with citations or refuse, evaluate 75 golden queries in CI against floors and a baseline.

Architecture
UI
Next.js on VercelChat · eval · traces · architecture pages
API
Python Starlette SSERailway-hosted retrieval + generation
Retrieval
BGE-small embeddingsBM25 sparseRRF · rerank
Quality
golden.jsonl evalGitHub Actions gateFailure dashboard
Frontend
Next.js App Router on Vercel — landing, streaming chat (/chat?demo=1), eval and trace dashboards.
Backend
Python Starlette API on Railway — ingest, retrieve, generate, trace stages.
APIs
SSE streaming for chat; JSON for eval metrics and job status.
Databases
Optional pgvector for embeddings; corpus and indexes versioned with the repo shape.
Infrastructure
Docker Compose for local full stack; split deploy Vercel + Railway in production.
Auth
Optional API key; rate limits and input caps on public demo routes.
Deployment
Vercel (frontend) + Railway (API). Local path is $0; Bedrock Haiku cost surfaced in UI when used.
Key features
  • Hybrid retrieval (dense + BM25) with RRF fusion and reranking
  • Grounded answers with source citations; refusal on weak context or injection-shaped queries
  • Golden eval suite (75 queries) with context recall, faithfulness, refusal, and hallucination metrics
  • Product surfaces: /chat demo, /eval dashboard, /failures, /traces, /architecture
  • Streaming SSE chat; optional OpenAI-compatible and local (Ollama) generation paths
  • API auth, rate limits, input caps; per-stage latency and cost in traces
  • Docker Compose locally; Vercel (UI) + Railway (Python API) in production
Engineering challenges

Challenge

Dense-only vector search missed exact strings in technical docs.

Decision

Measure hybrid retrieval instead of guessing.

Implementation

BM25 + dense embeddings, RRF merge, then rerank. Tracked recall@5 on the same answerable golden set.

Result

Recall@5 rose from 3.9% (dense-only) to 89.3% context recall with hybrid + rerank on that suite.

Challenge

Models answered when they should refuse.

Decision

Refusal is a first-class outcome, tested in eval.

Implementation

Nine unanswerable golden queries; generation path refuses when context is insufficient.

Result

100% refusal accuracy on those nine; 0% hallucination rate on the published suite.

Challenge

Retrieval regressions do not show up in unit tests.

Decision

CI eval gate on committed metrics, separate from TypeScript/Python unit tests.

Implementation

GitHub Actions runs eval/golden.jsonl; PR fails if context recall drops below 0.85 vs baseline.

Result

Chunking and retrieval changes cannot merge without measured proof.

Technology decisions

Eval before “make it smarter”

golden.jsonl and baseline metrics exist before tuning prompts or chunk sizes.

Alternative. Eyeball a few chat answers after each change.

Tradeoff. Upfront eval work; regressions become visible instead of silent.

Hybrid + rerank over dense-only

This corpus is full of exact tokens embeddings blur.

Alternative. Single embedding index.

Tradeoff. More moving parts; measured 3.9% → 89.3% recall story on the same set.

Extractive / grounded generation for faithfulness metrics

100% faithfulness on the suite is on answers tied to retrieved context—not a frontier model free-writing.

Alternative. Chatty LLM with post-hoc citation.

Tradeoff. Faithfulness number is honest but not a claim about GPT-4-level robustness.

Applied AI
Problem
Support and docs Q&A fails when retrieval misses exact terms and models invent APIs.
Model / provider
BGE-small embeddings; OpenAI-compatible / Ollama / optional Bedrock Haiku for generation
Why this model
Small embedding model for cost; generation path chosen per environment (local $0 vs hosted).
Architecture
Ingest → chunk → embed → hybrid retrieve → RRF → rerank → cite or refuse → trace.
Retrieval
Dense + BM25 sparse, reciprocal rank fusion, rerank; structural chunking default in production.
Validation
Golden eval in CI; refusal and faithfulness scored separately from unit tests.
Failure handling
Refuse when ungrounded; /failures page documents remaining miss cases.
Rate limiting
Public demo rate limits and optional API key.
Cost controls
Local stack $0; Bedrock Haiku pricing shown in UI when that path is enabled.
Evaluation
75-query golden set; GitHub Actions fails PRs below recall floor 0.85 vs baseline.
Human in the loop
Eval dashboard and failure browser for operator review—not fully autonomous support.
My ownership
  • BuiltEnd-to-end RAG pipeline, hybrid retrieval, and eval suite
  • BuiltNext.js product surfaces (chat, eval, failures, traces, architecture)
  • BuiltPython SSE API, Docker Compose, CI eval gate, Vercel + Railway deploy
  • Context precision 41.6% on the suite — next lever is tighter chunks / rerank / citation packing.
  • Demo auth is API key or open rate limit — not multi-tenant SaaS.
Results

Published suite (n=75): 89.3% context recall, 100% faithfulness (extractive path), 100% refusal accuracy (9/9 unanswerable), 0% hallucination. Context precision 41.6% — documented as the open quality lever.