Spaces:
Running
Running
| title: Vector Auditor | |
| emoji: π | |
| colorFrom: indigo | |
| colorTo: blue | |
| sdk: docker | |
| pinned: false | |
| # Vector Auditor | |
| https://vector-auditor-frontend.vercel.app | |
| **Agentic document intelligence** β upload PDFs, ask questions, get cited answers with page-level citations. | |
| <p align="center"> | |
| <img src="https://img.shields.io/badge/Python-3.11-3776AB?style=for-the-badge&logo=python&logoColor=white" alt="Python 3.11"/> | |
| <img src="https://img.shields.io/badge/FastAPI-0.115-009688?style=for-the-badge&logo=fastapi&logoColor=white" alt="FastAPI"/> | |
| <img src="https://img.shields.io/badge/PostgreSQL-17-4169E1?style=for-the-badge&logo=postgresql&logoColor=white" alt="PostgreSQL"/> | |
| <img src="https://img.shields.io/badge/Qdrant-Cloud-7B1FA2?style=for-the-badge&logo=qdrant&logoColor=white" alt="Qdrant"/> | |
| <img src="https://img.shields.io/badge/Redis-7-FF4438?style=for-the-badge&logo=redis&logoColor=white" alt="Redis"/> | |
| <img src="https://img.shields.io/badge/Docker-24-2496ED?style=for-the-badge&logo=docker&logoColor=white" alt="Docker"/> | |
| <img src="https://img.shields.io/badge/HuggingFace-Spaces-FFD21E?style=for-the-badge&logo=huggingface&logoColor=black" alt="HuggingFace Spaces"/> | |
| <img src="https://img.shields.io/badge/Prometheus-0.53-E6522C?style=for-the-badge&logo=prometheus&logoColor=white" alt="Prometheus"/> | |
| <img src="https://img.shields.io/badge/SentenceTransformers-MiniLM-FF6F00?style=for-the-badge&logo=huggingface&logoColor=white" alt="SentenceTransformers"/> | |
| <img src="https://img.shields.io/badge/Presidio-PII-00ACC1?style=for-the-badge&logo=microsoft&logoColor=white" alt="Presidio PII"/> | |
| <img src="https://img.shields.io/badge/Cloudinary-3448C5?style=for-the-badge&logo=cloudinary&logoColor=white" alt="Cloudinary"/> | |
| <img src="https://img.shields.io/badge/JWT-Auth-000000?style=for-the-badge&logo=jsonwebtokens&logoColor=white" alt="JWT Auth"/> | |
| <img src="https://img.shields.io/badge/GitHub-OAuth-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub OAuth"/> | |
| </p> | |
| **No LangChain.** Three LLM tiers: RAG-grounded (Mercury-2, Minimax-M3) and free-form reasoning chat (NexAGI via OpenRouter). Qdrant vector store, Postgres persistence, Redis caching, circuit-breaker resilience. | |
| ## Demo | |
| ``` | |
| POST /query {"question": "What are the key findings?", "mode": "white_box"} | |
| β 200 {"answer": "...", "citations": [{"page": 3, "quote": "..."}], ...} | |
| ``` | |
| ## Features | |
| - **Three LLM Tiers** β Mercury-2 (Inception Labs, fast), Minimax-M3 (NVIDIA, reasoning-heavy) for RAG; NexAGI (OpenRouter, `nex-agi/nex-n2-pro:free`) for free-form reasoning chat with chain-of-thought continuation | |
| - **Structured Document Analysis** β `POST /analyze` returns full report with summary, key findings, methodology, research gaps, contradictions, open questions, limitations | |
| - **Semantic Search** β `all-MiniLM-L6-v2` embeddings (384-d) for meaning-based retrieval | |
| - **Cross-Encoder Reranker** β `BAAI/bge-reranker-base` re-scores 10 candidates β top 5 before LLM | |
| - **Cited Grounding** β inline `[N]` markers with page-level citations from pdfplumber, click to jump | |
| - **Section-Aware Chunking** β 1000-char windows with 200-char overlap, split by markdown headers | |
| - **Multi-Document Q&A** β select any subset of uploaded PDFs, scoped answers | |
| - **AI-Powered Answers** β grounded in source documents with verification + gap analysis | |
| - **PII Redaction** β Presidio analyzer; skips PERSON, LOCATION, ORGANIZATION (only contact/financial IDs masked) | |
| - **Multi-Hop Retrieval** β iterative search across 3 hops for comprehensive coverage | |
| - **Two modes** β `white_box` (full reasoning + verification + gap analysis) and `black_box` (temperature=0) | |
| - **Parallel uploads** β 5 concurrent jobs with SHA256 dedup & Cloudinary storage | |
| - **Graceful degradation** β circuit breakers on LLM, Qdrant, embedding; raw-context fallback when LLM is down | |
| - **LRU query cache** β repeated queries skip embedding + vector search (600s TTL) | |
| - **Guardrails** β NeMo Guardrails with regex fallback for prompt injection detection | |
| - **Dead letter queue** β failed uploads captured for replay | |
| - **Streaming SSE** β `citations` / `token` / `verification` / `gap_analysis` / `done` / `error` | |
| - **Multi-user** β JWT auth with GitHub OAuth, document isolation per user | |
| - **Feedback loop** β thumbs up/down per query | |
| - **Observability** β JSON structured logs, Prometheus `/metrics`, health `/health`, readiness `/readyz` | |
| ## Architecture | |
| --- | |
| ```mermaid | |
| --- | |
| config: | |
| layout: elk | |
| theme: neo-dark | |
| --- | |
| graph TB | |
| subgraph Clients | |
| User["User Browser"] | |
| FE["Frontend (separate repo)"] | |
| end | |
| subgraph "HF Spaces (Docker, 1 worker)" | |
| API["FastAPI App<br/>src/api/main.py"] | |
| MW["Middleware<br/>Logging Β· CORS Β· Auth"] | |
| Auth["Auth Service<br/>JWT Β· GitHub OAuth"] | |
| Rate["Rate Limiter<br/>slowapi"] | |
| end | |
| subgraph "Document Processing Pipeline" | |
| Parser["Document Parser<br/>MarkItDown + pdfplumber"] | |
| PII["PII Detection<br/>presidio-analyzer"] | |
| Cloud["Cloudinary<br/>raw file storage"] | |
| Chunker["Text Chunker<br/>RecursiveCharacterTextSplitter<br/>1000 chars Β· 200 overlap"] | |
| end | |
| subgraph "Vector Store" | |
| Qdrant["Qdrant Cloud<br/>Vector DB"] | |
| Embedder["Embedding Model<br/>all-MiniLM-L6-v2 (384d)"] | |
| CB_Q["Circuit Breaker<br/>search: 5/30s Β· index: 3/60s"] | |
| end | |
| subgraph "LLM / RAG" | |
| Agent["Document Agent<br/>src/agents/document_agent.py"] | |
| Reranker["Cross-Encoder Reranker<br/>BAAI/bge-reranker-base"] | |
| MERCURY["Fast Mode<br/>Mercury-2 via Inception Labs<br/>(INCEPTION_API_KEY)"] | |
| MINIMAX["Reasoning Mode<br/>Minimax-M3 via NVIDIA<br/>(LLM_API_KEY / LLM_BASE_URL)"] | |
| CB_L["Circuit Breaker<br/>5 failures / 30s recovery"] | |
| Retry["Retry w/ Backoff<br/>0.5s β 1s β 2s"] | |
| Guard["Guardrails<br/>NeMo Guardrails"] | |
| Degrade["Graceful Degradation<br/>auto-fallback mercury β minimax"] | |
| end | |
| subgraph "Free-Form Chat (No RAG)" | |
| NexAGI["NexAGI<br/>POST /NexAGI<br/>nex-agi/nex-n2-pro:free<br/>via OpenRouter<br/>(OPENROUTER_API_KEY)"] | |
| end | |
| subgraph "Infrastructure" | |
| PG[("PostgreSQL<br/>(Qdrant Cloud or in-memory fallback)")] | |
| Redis[("Redis<br/>(session cache)")] | |
| JobQ["Job Queue<br/>max_concurrent=5"] | |
| Metrics["Prometheus Metrics"] | |
| Cache["LRU Query Cache<br/>TTLCache 600s"] | |
| Shutdown["Graceful Shutdown"] | |
| TokenCounter["Token Counter"] | |
| end | |
| %% Connections | |
| User --> FE --> API | |
| API --> MW --> Auth | |
| MW --> Rate | |
| API --> JobQ --> Parser --> PII --> Cloud | |
| Parser --> Chunker --> Qdrant | |
| Qdrant --> Embedder | |
| Qdrant --> CB_Q | |
| API --> Agent | |
| Agent --> Qdrant | |
| Agent --> Reranker | |
| Agent --> MERCURY | |
| Agent --> MINIMAX | |
| MERCURY --> CB_L --> Degrade | |
| MERCURY --> Retry | |
| MERCURY --> Guard | |
| MINIMAX --> CB_L | |
| MINIMAX --> Retry | |
| MINIMAX --> Guard | |
| API --> NexAGI | |
| API --> PG | |
| API --> Redis | |
| API --> Metrics | |
| API --> Shutdown | |
| API --> TokenCounter | |
| %% Color Styling | |
| classDef client fill:#0f172a,stroke:#38bdf8,color:#f0f9ff | |
| classDef api fill:#0a2647,stroke:#60a5fa,color:#e0f2fe | |
| classDef process fill:#111827,stroke:#2dd4bf,color:#f0fdfa | |
| classDef vector fill:#22092C,stroke:#f59e0b,color:#fff7ed | |
| classDef llm fill:#1e1b4b,stroke:#a78bfa,color:#f5f3ff | |
| classDef chat fill:#1c1917,stroke:#f97316,color:#fff7ed | |
| classDef infra fill:#1c1917,stroke:#d4d4d8,color:#f5f5f4 | |
| class User,FE client | |
| class API,MW,Auth,Rate api | |
| class Parser,PII,Cloud,Chunker process | |
| class Qdrant,Embedder,CB_Q vector | |
| class Agent,Reranker,MERCURY,MINIMAX,CB_L,Retry,Guard,Degrade llm | |
| class NexAGI chat | |
| class PG,Redis,JobQ,Metrics,Cache,Shutdown,TokenCounter infra | |
| ``` | |
| ## Tech Stack | |
| | Layer | Technology | | |
| |-------|-----------| | |
| | API | FastAPI + Uvicorn + Pydantic v2 | | |
| | Auth | JWT (python-jose) + bcrypt | | |
| | Database | PostgreSQL (SQLAlchemy async) / in-memory JSONL fallback | | |
| | Vector Store | Qdrant (Cloud / local / in-memory, collection `documents`) | | |
| | Reranker | Cross-Encoder BAAI/bge-reranker-base | | |
| | Embeddings | SentenceTransformers all-MiniLM-L6-v2 (384-d) | | |
| | LLM | Mercury-2 (Inception Labs) Β· Minimax-M3 (NVIDIA) Β· NexAGI (OpenRouter, `nex-agi/nex-n2-pro:free`) | | |
| | Cache | Redis / in-process TTLCache | | |
| | File Store | Cloudinary (PDF serving) | | |
| | PDF Parse | MarkItDown (text) + pdfplumber (page numbers) | | |
| | Resilience | Circuit breakers + exponential backoff retry + LRU query cache + auto-fallback between models | | |
| | Observability | JSON logs + Prometheus | | |
| | Rate Limiting | slowapi (200/min default) | | |
| | Workers | 1 uvicorn worker (prevent OOM on HF Spaces) | | |
| ```bash | |
| # Clone | |
| git clone https://github.com/AKXLR8/vector-auditor.git | |
| cd vector-auditor | |
| # Environment | |
| cp .env.example .env | |
| # Edit .env β set at minimum: LLM_API_KEY, JWT_SECRET_KEY | |
| # Install | |
| python -m pip install -r requirements.txt | |
| # Run | |
| uvicorn src.api.main:app --reload --port 8000 | |
| Open http://localhost:8000/docs for interactive API docs. | |
| ## Configuration | |
| | Variable | Required | Default | Notes | | |
| |----------|----------|---------|-------| | |
| | `LLM_API_KEY` | Yes | β | NVIDIA API key (used for Minimax-M3) | | |
| | `INCEPTION_API_KEY` | Yes | β | Inception Labs API key (used for Mercury-2) | | |
| | `JWT_SECRET_KEY` | Yes | β | `python -c "import secrets; print(secrets.token_urlsafe(32))"` | | |
| | `OPENROUTER_API_KEY` | No | β | API key for NexAGI free-form reasoning chat | | |
| | `LLM_BASE_URL` | No | NVIDIA endpoint | Base URL for Minimax-M3 provider | | |
| | `DATABASE_URL` | No | in-memory | PostgreSQL with asyncpg | | |
| | `QDRANT_URL` | No | in-memory | Qdrant Cloud URL | | |
| | `QDRANT_API_KEY` | No | β | Qdrant Cloud API key | | |
| | `REDIS_URL` | No | in-memory | Redis for cache | | |
| | `CLOUDINARY_*` | No | local only | PDF file serving | | |
| | `LOG_FORMAT` | No | `json` | `text` for human-readable | | |
| | `JOB_MAX_CONCURRENT` | No | `5` | Parallel upload jobs | | |
| ## API Overview (28 endpoints) | |
| ### Auth `/auth/*` | |
| `POST register` Β· `POST login` Β· `POST login/mfa` Β· `POST logout` Β· `GET token/refresh` Β· `POST mfa/setup` Β· `POST mfa/verify` Β· `GET oauth/config` Β· `POST oauth/github` | |
| ### Query `/query` | |
| `POST /query` β single answer with citations Β· `POST /query/stream` β SSE streaming Β· `POST /analyze` β multi-document analysis Β· `POST /NexAGI` β free-form reasoning chat (no RAG) | |
| ### Documents `/documents` | |
| `POST /documents` β upload (multi-file) Β· `GET /documents` β list Β· `GET /documents/{id}` β detail Β· `DELETE /documents/{id}` β remove Β· `GET /documents/{id}/pdf` β stream PDF | |
| ### Sessions `/sessions` | |
| `GET /sessions` β list Β· `POST /sessions` β create Β· `GET /sessions/{id}` β detail with messages Β· `PUT /sessions/{id}` β rename Β· `DELETE /sessions/{id}` Β· `GET /sessions/{id}/messages` Β· `POST /sessions/{id}/messages` | |
| ### Operations | |
| `POST /NexAGI` Β· `POST /feedback` Β· `GET /admin/dlq` Β· `POST /cache/flush` Β· `GET /health` Β· `GET /readyz` Β· `GET /metrics` | |
| ## Deploy | |
| ### Hugging Face Spaces | |
| ```bash | |
| git remote add hf https://huggingface.co/spaces/akshayyy1/vector-auditor | |
| git push hf main | |
| ``` | |
| Set secrets in HF Space Settings β Variables. See `DEPLOY_HF_SPACES.md`. | |
| ### Docker | |
| ```bash | |
| docker build -t vector-auditor . | |
| docker run -p 7860:7860 -e LLM_API_KEY=... -e JWT_SECRET_KEY=... vector-auditor | |
| ``` | |
| ## Production Checklist | |
| - [x] Circuit breakers (LLM, Qdrant, embedding) | |
| - [x] Retry with exponential backoff | |
| - [x] Graceful degradation when LLM is down | |
| - [x] Health check + readiness probe | |
| - [x] Rate limiting (200/min default) | |
| - [x] Security headers (X-Frame-Options, X-Content-Type-Options, Referrer-Policy) | |
| - [x] Request ID tracking | |
| - [x] Shutdown gate (drain in-flight requests) | |
| - [x] JSON structured logging | |
| - [x] Prometheus metrics | |
| - [x] Dead letter queue for failed uploads | |
| - [x] PII detection (enabled by default) | |
| - [x] Guardrails against prompt injection | |
| - [x] JWT auth with role-based access | |
| - [x] Document isolation per user | |
| - [x] SHA256 dedup on upload | |
| - [x] Parallel upload processing | |
| - [x] Multi-stage Docker build (slim image) | |
| - [ ] Golden dataset evals | |
| - [ ] LangSmith cost monitoring | |
| ## Project Structure | |
| ``` | |
| src/ | |
| βββ api/ # FastAPI routes (main.py, auth.py, middleware.py) | |
| βββ agents/ # DocumentAgent (lite RAG pipeline) | |
| βββ services/ # LLM, cache, parsers, guardrails, PII, circuit_breaker | |
| βββ database/ # SQLAlchemy models, repository, session | |
| βββ vectorstore/ # Qdrant wrapper with user isolation | |
| βββ models/ # Pydantic schemas | |
| βββ observability.py # JSON logs + Prometheus | |
| βββ shutdown.py # Graceful shutdown | |
| βββ job_queue.py # Upload pipeline orchestrator | |
| βββ config.py # pydantic-settings | |
| scripts/ # download_model.py | |
| alembic/ # DB migrations | |
| models/ # embedding_model.pkl (gitignored, built at deploy) | |
| ``` | |
| ## License | |
| MIT | |