| # DocuAsk β Full-Stack Document Q&A Web App |
|
|
| ## Purpose (read first) |
|
|
| A customer-facing web app where a user uploads a PDF (or pastes text), asks |
| questions in a chat box, and gets answers with the source passage shown. The |
| retrieval backend is intentionally lightweight β the point of this project is |
| the front-end product loop and user-facing data collection, not the RAG. Spend |
| effort on the UI, error handling, and the feedback/telemetry layer. |
|
|
| Target reviewer: general software-engineering apprenticeship (React front-end, |
| REST API, CI/CD, deployed live URL, product metrics). |
|
|
| ## Stack (fixed β do not substitute) |
|
|
| - **Frontend:** React + Vite + Tailwind CSS |
| - **Backend:** FastAPI (Python) |
| - **Retrieval:** BM25 + FAISS (keep minimal; a single in-memory index is fine) |
| - **Persistence:** SQLite (question/answer/latency/feedback log) |
| - **Tests:** pytest (backend) |
| - **CI:** GitHub Actions running pytest on every push |
| - **Deploy:** Docker Compose locally; frontend to Vercel/Netlify, backend to |
| Render/Railway |
|
|
| ## Repository setup (Session 0) |
|
|
| Public GitHub repo named `docuask` under github.com/Sriyansh-28. |
|
|
| - `git init`, add a Python + Node `.gitignore`, MIT license, `README.md`. |
| - Structure: |
|
|
| ``` |
| docuask/ |
| backend/ # FastAPI app, retrieval, db, tests |
| frontend/ # Vite React app |
| docker-compose.yml |
| .github/workflows/ci.yml |
| README.md |
| PROJECT_SPEC.md |
| ``` |
|
|
| - First commit: skeleton only. Push to the new remote before writing features. |
|
|
| ## Session 1 β Skeleton end to end |
|
|
| Goal: browser shows data fetched from the API. |
|
|
| - FastAPI app with `GET /health` returning `{"status":"ok"}`. |
| - Vite React app with one page that calls `/health` and renders the status. |
| - Docker Compose brings both up with one `docker compose up`. |
| - CORS configured so frontend can call backend in dev. |
|
|
| **Acceptance criteria** |
|
|
| - [x] `docker compose up` starts both services with no errors. |
| - [x] Opening the frontend URL shows "API status: ok" pulled live from the backend. |
| - [x] Repo pushed; README has a one-line run instruction. |
|
|
| ## Session 2 β Upload & parse flow |
|
|
| Goal: user uploads a PDF; backend extracts and chunks the text. |
|
|
| - `POST /documents` accepts a PDF or raw text, extracts text (pypdf), splits |
| into chunks, builds/stores the index in memory keyed by a document id. |
| - Frontend: drag-and-drop upload widget with loading and success states. |
| - Handle failures visibly: encrypted PDF, non-PDF file, empty/huge file β clear |
| error message in the UI, no crash. |
|
|
| **Acceptance criteria** |
|
|
| - [x] Uploading a normal PDF returns a document id and shows "ready" in the UI. |
| - [x] Uploading a broken/encrypted PDF shows a friendly error, backend logs it. |
| - [x] A pytest test covers the parse-failure path. |
|
|
| ## Session 3 β Retrieval + chat loop |
|
|
| Goal: the core questionβanswer experience. |
|
|
| - `POST /ask` takes `{document_id, question}`, runs BM25 + FAISS retrieval, |
| returns the answer text plus the top source passage. |
| - Frontend: chat interface β question input, message history, each answer shows |
| the source passage underneath. |
| - Show a loading indicator while `/ask` is in flight. |
|
|
| **Acceptance criteria** |
|
|
| - [x] Asking a question about an uploaded doc returns a relevant passage. |
| - [x] The source passage is visibly shown under each answer. |
| - [x] Empty question or unknown document id is handled gracefully. |
|
|
| ## Session 4 β Data-collection & feedback layer (the score-lifting part) |
|
|
| Goal: turn this into a web-enabled system for data collection with product |
| metrics. |
|
|
| - SQLite table |
| `interactions(id, document_id, question, answer, latency_ms, feedback, created_at)`. |
| - Every `/ask` call logs the row with measured `latency_ms`. |
| - π / π buttons on each answer β `POST /feedback` updates the row. |
| - `GET /stats` returns: total questions, median latency, thumbs-up rate. |
| - A small `/dashboard` page in the frontend reads `/stats` and shows 3 numbers + |
| a simple bar of questions-over-time. |
|
|
| **Acceptance criteria** |
|
|
| - [x] Each question persists with its real latency. |
| - [x] Feedback buttons update the record and reflect in `/stats`. |
| - [x] Dashboard page renders the three metrics live from the DB. |
|
|
| ## Session 5 β Polish, test, deploy |
|
|
| Goal: live URL + green CI + a README a recruiter can skim. |
|
|
| - Backend pytest suite covers `/health`, upload success + failure, `/ask`, |
| `/feedback`. |
| - `.github/workflows/ci.yml` runs pytest on every push; badge in README. |
| - Deploy backend (Render/Railway) and frontend (Vercel/Netlify); wire the live |
| API URL. |
| - README: one-paragraph description, screenshot/GIF of the chat + dashboard, |
| live demo link, run instructions, tech stack. |
|
|
| > Deployed as the single-image combined app (`Dockerfile` + `app/server.py`) on |
| > **Railway** β one container serving the React frontend and the FastAPI API |
| > under `/api` from one origin. (A Hugging Face Static Space + separate API is |
| > also supported; see the README.) |
|
|
| **Acceptance criteria** |
|
|
| - [x] CI badge is green on the default branch. |
| - [x] Live demo URL works end to end (upload β ask β feedback β dashboard) β |
| verified against https://docuask-production-c732.up.railway.app. |
| - [x] README has a screenshot and the live link. |
| |
| ## Guardrails |
|
|
| - Keep retrieval simple; do not over-engineer the RAG. If a session is running |
| long, cut retrieval sophistication, never the front-end or telemetry. |
| - Only report metrics you actually measured. No invented user counts. |
|
|