PDF Reviewer is a full-stack PDF question-answering app. Upload a PDF, ask questions about it, and get grounded answers with page-level citations. The backend extracts and indexes the document locally, while the frontend gives users a clean chat interface with an integrated PDF viewer.
- Uploads and validates PDF files.
- Extracts text page by page with PyMuPDF.
- Splits document text into overlapping chunks with page and section metadata.
- Builds a local TF-IDF search index with scikit-learn.
- Retrieves the most relevant chunks for each question.
- Uses Groq to generate answers strictly from the retrieved PDF context.
- Returns citations for the pages used in each answer.
- Refuses to answer when the information is not present in the uploaded PDF.
- Supports short multi-turn chat sessions with backend memory.
- Rewrites follow-up questions into standalone retrieval queries.
- Reranks retrieved chunks by similarity and keyword overlap.
- Opens the uploaded PDF beside the chat and jumps to cited pages.
- Preserves grounding and citation structure when answering supported non-English questions from the PDF.
PDF Reviewer is built for document-grounded review workflows where the assistant should answer from the uploaded file, cite the source pages, and refuse unsupported questions instead of guessing. It keeps the retrieval layer lightweight by using a local TF-IDF index, making the app simple to run without a hosted vector database.
This is an AI agent workflow, not just a static JavaScript app. The React frontend handles upload, chat, citations, and PDF viewing. The FastAPI backend performs PDF extraction, retrieval, query rewriting, prompt construction, Groq LLM generation, refusal detection, and citation metadata assembly.
The chat flow is intentionally strict and document-grounded:
- The frontend sends the user question with the current
document_idandsession_id. - The backend loads the recent session memory for follow-up context.
- Short lookups and follow-up questions are rewritten into standalone retrieval queries.
- The local TF-IDF index retrieves candidate chunks from the active PDF.
- Retrieval reranks candidates by cosine similarity plus keyword overlap and filters weak matches.
- If no reliable chunks are found, the backend returns the fixed refusal message without using outside knowledge.
- Groq receives only the retrieved PDF excerpts, recent conversation turns, and strict grounding rules.
- The backend normalizes the response, attaches page citations, and exposes retrieval debug metadata.
- The frontend renders the grounded answer, clickable page sources, recent questions, and retrieval debug panel.
Frontend:
- React
- Vite
- Tailwind CSS
- Axios
- React PDF
- Lucide React
Backend:
- FastAPI
- Uvicorn
- PyMuPDF
- scikit-learn
- NumPy
- Groq Python SDK
- python-dotenv
PDF-Reviewer/
backend/
main.py # FastAPI app and API routes
config.py # Environment and app configuration
pdf_processor.py # PDF saving, text extraction, and chunking
vector_store.py # Local TF-IDF index and similarity search
chat_engine.py # Groq-powered grounded chat pipeline
models.py # Pydantic request/response models
requirements.txt # Backend dependencies
.env.example # Example environment file
frontend/
src/
App.jsx # Main UI and app state
api.js # API client helpers
components/ # Upload, chat, PDF viewer, and UI components
package.json # Frontend scripts and dependencies
vite.config.js # Vite config and API proxy
samples/
sample-review-policy.pdf # Reviewer-ready sample PDF
test-cases.md # 5 valid and 3 invalid test cases
sample-review-policy-source.md # Source text for the sample PDF
Install these before running the app:
- Python 3.12 recommended
- Node.js 18 or newer
- npm
- A Groq API key from Groq Console
Python 3.14 may try to build some scientific packages from source on Windows. Python 3.12 is recommended because the pinned dependencies have prebuilt wheels available.
Create a backend environment file:
cd backend
copy .env.example .envOpen backend/.env and set:
GROQ_API_KEY=your_groq_api_key_hereDo not commit the real .env file. It is already ignored by Git.
From the project root, install and run the backend:
cd backend
py -3.12 -m venv .venv312
.\.venv312\Scripts\python.exe -m pip install --upgrade pip
.\.venv312\Scripts\python.exe -m pip install -r requirements.txt
.\.venv312\Scripts\python.exe -m uvicorn main:app --host 0.0.0.0 --port 8000 --reloadIn another terminal, install and run the frontend:
cd frontend
npm install
npm run dev -- --host 0.0.0.0Open the app:
http://localhost:5173/
The backend runs at:
http://localhost:8000/
- Start the backend server.
- Start the frontend dev server.
- Open
http://localhost:5173/. - Upload a PDF.
- Wait for the upload and indexing process to finish.
- Ask questions about the uploaded PDF.
- Click citation badges to open the PDF viewer on the referenced page.
- Use the reset button to upload a different PDF.
Checks whether the backend is running.
Response:
{
"status": "ok",
"message": "PDFChat API is running"
}Uploads and processes a PDF.
Request:
- Form field:
file - Accepted format:
.pdf - Maximum size: 50 MB
Response includes:
document_idtotal_pagestotal_chunks- status message
Asks a question about an uploaded PDF.
Request body:
{
"question": "What is this document about?",
"document_id": "document-id-from-upload",
"session_id": null
}Response includes:
- grounded answer
- citations
- session ID
- refusal flag
Returns the uploaded PDF for inline viewing in the frontend.
Deletes a processed document index.
- The user uploads a PDF.
- The backend stores the PDF under
backend/uploads. - PyMuPDF extracts readable page text, including cleanup for letter-spaced resume headings.
- The text is chunked into overlapping sections with page metadata.
- The chunks are indexed using TF-IDF with compact aliases for better name matching.
- A user question is rewritten when needed and converted into the same search space.
- The backend retrieves, filters, reranks, and merges the most relevant chunks.
- If retrieval fails, the assistant returns the fixed refusal message.
- Groq receives only the retrieved PDF context and recent session memory.
- The frontend displays the answer, citations, recent questions, retrieval debug data, and PDF viewer.
- Uploaded PDFs and generated indexes are local runtime data.
- The app uses a local lightweight retrieval index instead of an external vector database.
- The Groq API key must be configured locally in
backend/.env. - The real API key is intentionally not included in this repository.