A Retrieval-Augmented Generation (RAG) chatbot that lets you upload PDF documents (if a password is supplied) and ask questions about their contents. The backend extracts, chunks, and embeds PDF text into a vector database. When you send a message, the most relevant chunks are retrieved and fed to an LLM as context.
The app is hosted on AWS and accessible through the following link: https://d79rdqmz8tzz8.cloudfront.net/
Two PDFs are uploaded, a paper about sepsis prediction and a paper about cardiac arrest prediction.
To upload a PDF, an upload key is required. The file is then stored, and the text is processed using pdfplumber. The full text is split into overlapping windows: 512 words per chunk, 50-word overlap. The indexes of chunks are stored so that the LLM can cite them. Pinecone is used to construct embeddings using llama-text-embed-v2. The result of this is stored using Pinecone vector storage.
The core functionality of the RAG uses sessions stored in DynamoDB. The user's message is embedded and compared against the stored chunk embeddings. The top 3 chunks are returned ranked by cosine similarity. The LLM that is connected to is instructed to only use the provided context and to reference which chunk is used.
After calling the Groq API, the result is read as a stream, processing each token as it arrives.
┌─────────────────────────────────────────────────────────────┐
│ Browser (React + Vite) │
│ Sidebar (upload + doc list) ChatWindow (JSON stream) │
└────────────────────┬────────────────────────────────────────┘
│ HTTPS
┌────────────────────▼────────────────────────────────────────┐
│ CloudFront │
│ /* → S3 │
│ /api/* → Lambda Function URL │
└────────────────────┬────────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────────┐
│ AWS Lambda (Python 3.12, container image) │
│ POST /api/upload POST /api/sessions POST /api/chat │
│ ┌──────────────┐ ┌─────────────────┐ ┌───────────────┐ │
│ │ pdf_processor│ │ database │ │ embeddings │ │
│ │ (pdfplumber) │ │ (DynamoDB) │ │ (Pinecone │ │
│ └──────────────┘ └─────────────────┘ │ Inference) │ │
│ ┌──────────────┐ └───────┬───────┘ │
│ │ storage │ ┌──────────────────────▼────────┐ │
│ │ (S3) │ │ PineconeVectorStore │ │
│ └──────────────┘ └───────────────────────────────┘ │
│ │ context chunks │
│ ┌─────────▼─────────┐ │
│ │ llm (Groq) │ │
│ │ llama-3.1-8b │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────┘
AWS Lambda AWS DynamoDB AWS S3
(backend) (sessions + (PDFs)
messages)
cp .env.example .env # fill in API keys
docker compose upThis starts:
backend— FastAPI on port 8000 with hot reloaddynamodb-local— DynamoDB Local on port 8002
Set DYNAMODB_ENDPOINT_URL=http://localhost:8002 in your .env for the backend to use the local DynamoDB instance.
Frontend dev server:
cd frontend
npm install
npm run dev # Vite on http://localhost:5173Set VITE_API_URL=http://localhost:8000 in frontend/.env.local so the frontend talks to the local backend.
- AWS CLI configured (
aws configure) - Node.js (for the frontend build)
- A Groq API key
- A Pinecone account with a serverless index (dimension: 1024, metric: cosine — matching
llama-text-embed-v2)
sam build && sam deploy --guidedSAM will prompt for a stack name, region, and the required secrets (GroqApiKey, PineconeApiKey, PineconeIndexName, UploadApiKey). On first run it also creates an ECR repository and pushes the container image automatically. At the end it prints:
FrontendUrl = https://xxxxxxxxxxxx.cloudfront.net
FrontendBucketName = pdf-rag-frontend-<account-id>
Save both values.
cd frontend
npm install
VITE_API_URL='' npm run build # BASE is empty; CloudFront routes /api/* to Lambda
aws s3 sync dist/ s3://<FrontendBucketName> --deleteOpen FrontendUrl in the browser — the app is live.
| Changed | Command |
|---|---|
| Backend code / dependencies | sam build && sam deploy |
| Frontend only | npm run build && aws s3 sync dist/ s3://<FrontendBucketName> --delete |
Tests mock all external services (DynamoDB, Pinecone, Groq) so no live AWS credentials are needed.
cd backend
pip install -r requirements.txt
pytest tests/ -v