agentic-rag-knowledge-assistant
by jayanthlocam
README.md
# Agentic RAG Knowledge Assistant
> Upload documents → build a vector knowledge base → ask questions with grounded, cited answers.
> Works via browser dashboard, REST API, or MCP tools. Syncs Google Drive folders automatically.
Built with **FastAPI** · **LangGraph** · **PostgreSQL + pgvector** · **MCP** · **Streamlit**


---
## ✨ What it does
- **Upload & ingest** PDFs, DOCX, and text files with automatic chunking and embedding
- **Semantic search** over your documents using pgvector HNSW cosine similarity
- **AI-powered Q&A** with LangGraph — answers cite exact source chunks
- **Google Drive sync** — connect a Drive folder and auto-ingest business docs via MCP
- **MCP server** — expose your knowledge base to any MCP-compatible AI agent
- **Multi-tenant** — JWT auth, per-user document isolation, no cross-tenant leaks
## 📊 Evaluation Baseline
Tested on 11 gold-set cases (8 answerable, 2 unanswerable, 1 prompt injection) against 4 business-policy documents synced from Google Drive.
| Metric | Score |
| --- | --- |
| **Context Relevance** | 1.00 |
| **Context Sufficiency** | 1.00 |
| **Answer Relevance** | 1.00 |
| **Answer Correctness** | 1.00 |
| **Faithfulness** | 1.00 |
| **Retrieval Hit Rate @5** | 1.00 |
| **MRR @5** | 1.00 |
| **Gold Chunk Precision @5** | 0.25 |
| **Citation Precision** | 0.25 |
| **Refusal Accuracy** | 1.00 |
| **Prompt Injection Resistance** | 1.00 |
| **Mean Latency** | 2,598 ms |
> Models: `gpt-5.6-terra` (generation + judge) · `text-embedding-3-small` (embeddings)
> See [`evaluation/baselines/`](evaluation/baselines/) for the full sanitized baseline.
## 🏗️ Architecture
```text
Browser ──► Streamlit ──► FastAPI ──────────────┐
├──► PostgreSQL + pgvector
MCP client ──────────► MCP server (HTTP) ───────┘
│
└── JWT auth + owner-scoped queries
Google Drive folder ──► Drive MCP ──► sync endpoint ──► ingestion pipeline
```
See [docs/architecture.md](docs/architecture.md) for detailed component and data-flow docs.
## 🛠️ Tech Stack
| Layer | Tech |
| --- | --- |
| Frontend | Streamlit, HTTPX |
| API | FastAPI, Pydantic |
| Agent | LangGraph, LangChain Core |
| MCP | MCP Python SDK, Streamable HTTP |
| DB | PostgreSQL 16, SQLAlchemy 2, Alembic |
| Vectors | pgvector, HNSW cosine index |
| Docs | pypdf, python-docx |
| Auth | JWT (HS256), Argon2 |
| Dev | uv, Ruff, mypy, pytest, Docker Compose |
## 🚀 Quick Start
**Prerequisites:** Docker + Docker Compose v2
```bash
# 1. Clone and configure
cp .env.example .env
# Edit .env → set POSTGRES_PASSWORD and JWT_SECRET (min 32 chars)
# 2. Start everything
docker compose up --build -d
# 3. Open the dashboard
open http://localhost:8501
# 4. Verify health
curl http://localhost:8000/health/ready
```
**Want OpenAI-powered answers?** Add to `.env`:
```dotenv
EMBEDDING_PROVIDER=openai
EMBEDDING_MODEL=text-embedding-3-small
EMBEDDING_API_KEY=sk-...
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o
LLM_API_KEY=sk-...
```
Without OpenAI keys, the system runs fully offline with deterministic embeddings and extractive answers — great for development and testing.
## 💻 Local Development
```bash
# Install deps
uv sync --frozen --extra frontend
# Run migrations
uv run alembic upgrade head
# Start API (terminal 1)
uv run uvicorn backend.app.main:app --reload --port 8000
# Start MCP server (terminal 2)
uv run python -m backend.app.mcp.server
# Start dashboard (terminal 3)
uv run streamlit run frontend/app.py
```
## 📡 API Reference
All endpoints under `/api/v1`. Full docs at `http://localhost:8000/api/v1/docs`.
| Area | Endpoints |
| --- | --- |
| Auth | `POST /auth/register` · `POST /auth/login` |
| User | `GET /users/me` |
| Threads | `POST /threads` · `GET /threads` · `GET /threads/{id}` · `DELETE /threads/{id}` |
| Documents | `POST /documents/upload` · `GET /documents` · `GET /documents/{id}` · `DELETE /documents/{id}` |
| Search | `POST /retrieval/search` |
| Chat | `POST /chat/{thread_id}` · `POST /chat/{thread_id}/stream` · `GET /chat/{thread_id}/history` |
| Drive Sync | `POST /data-sources/google-drive/sync` |
| Metrics | `GET /metrics/overview` |
| Health | `GET /health/live` · `GET /health/ready` |
## 🔌 MCP Tools
Connect any MCP client with `Authorization: Bearer <jwt>` to `http://localhost:8001/mcp`:
| Tool | Description |
| --- | --- |
| `list_documents` | List all documents for the authenticated user |
| `get_document` | Get document metadata by ID |
| `search_documents` | Semantic vector search |
| `answer_from_documents` | Grounded Q&A with citations |
| `ingest_document` | Upload and index a document |
```bash
# Quick connectivity check
MCP_ACCESS_TOKEN="<token>" uv run python -m scripts.mcp_smoke
```
## 📁 Google Drive Sync
Sync a Drive folder into your knowledge base — supports PDF, DOCX, TXT, and native Google Docs.
**Setup:**
1. Enable `drive.googleapis.com` and `drivemcp.googleapis.com` in your GCP project
2. Create a **Desktop app** OAuth client (not Web app)
3. Get a short-lived access token and add to `.env`:
```dotenv
GOOGLE_DRIVE_FOLDER_ID=<your-folder-id>
GOOGLE_DRIVE_ACCESS_TOKEN=<oauth-token>
GOOGLE_DRIVE_QUOTA_PROJECT=<gcp-project-id>
```
4. Trigger sync:
```bash
curl -X POST http://localhost:8000/api/v1/data-sources/google-drive/sync \
-H "Authorization: Bearer <app-jwt>"
```
Re-syncing skips unchanged files. Duplicate content across files is deduplicated automatically.
## ✅ Testing & CI
```bash
# Run full validation (lint + types + tests)
make validate
# Run tests with coverage
uv run pytest --cov=backend.app --cov-report=term-missing --cov-fail-under=80
```
CI runs on every PR: Ruff lint → Ruff format → mypy → pytest (with pgvector) → Docker build. See [`.github/workflows/backend-ci.yml`](.github/workflows/backend-ci.yml).
## 📂 Project Structure
```
backend/
├── app/
│ ├── agents/ # LangGraph workflow, answer providers
│ ├── api/ # FastAPI endpoints
│ ├── auth/ # JWT + Argon2 password security
│ ├── connectors/ # Google Drive MCP connector
│ ├── ingestion/ # PDF/DOCX extraction, chunking, embeddings
│ ├── mcp/ # MCP server + client
│ ├── models/ # SQLAlchemy models
│ ├── retrieval/ # pgvector search
│ └── services/ # Ingestion + Drive sync services
├── migrations/ # Alembic migrations
└── tests/ # Unit + integration tests
frontend/ # Streamlit dashboard
evaluation/ # Gold dataset + baselines
scripts/ # Smoke tests + evaluation runner
docs/ # Architecture + roadmap
```
## 🔒 Security
- Argon2 password hashing, JWT with explicit algorithm allow-list
- Owner-scoped queries — users can only access their own documents and vectors
- Citations built from DB records, not model-generated IDs
- Document text treated as untrusted evidence (not executable instructions)
- Google Drive access: read-only, folder-bounded, never exposed to the agent
- Containers run as unprivileged user
- Secrets excluded from Git and Docker build contexts
## ⚠️ Known Limitations
- Embeddings fixed at 1,536 dimensions (changing needs an Alembic migration)
- Scanned PDFs need OCR before upload (only embedded text extracted)
- Upload processing is synchronous (works fine, but a worker queue is better at scale)
- Drive sync is manually triggered with a short-lived token (production needs OAuth refresh)
- MCP server assumes TLS is terminated upstream
## 🗺️ Roadmap
**Next milestone:** [1,000-document scale test](docs/roadmap.md) — validate ingestion, deduplication, retrieval accuracy, and failure recovery at scale before adding more connectors.
**After that:** Worker queue for async ingestion, managed OAuth for Drive, OCR support, hybrid retrieval with reranking, GCP deployment with Cloud SQL + Secret Manager.
## 📄 License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues