A full-stack research assistant with a ChatGPT-style frontend and a FastAPI backend for PDF-grounded question answering using Retrieval-Augmented Generation (RAG).
The system lets a user:
- upload a research paper in PDF format
- ask natural-language questions about that paper
- retrieve relevant chunks from the indexed document
- generate grounded answers through an LLM provider
- view the retrieved source chunks used to support the answer
The current implementation is optimized for a strong single-user capstone demonstration and viva discussion.
Frontend:
- Next.js App Router
- React
- Tailwind CSS
- custom component-based chat UI
- markdown and code rendering support
Backend:
- FastAPI
- FAISS
- sentence-transformers
- httpx
- pypdf
- python-dotenv
LLM providers:
- OpenRouter by default
- Ollama optional
Observability and quality:
- LangSmith tracing
- pytest test suite
- retrieval accuracy check script
frontend/
app/
components/
globals.css
layout.tsx
page.tsx
lib/
backend/
main.py
pdf_utils.py
rag_pipeline.py
run_accuracy_check.py
vector_store.py
eval_cases.sample.json
tests/
scripts/
package.json
README.md
- ChatGPT-like dark conversation UI
- dynamic greeting on first load
- sticky bottom input bar
- inline PDF upload from the composer
- streaming assistant responses
- thinking indicator and live streaming state
- markdown rendering
- styled code blocks with copy support
- collapsible source attribution section
- sidebar controls for provider, model, chunk size, and top-k
- identity handling for developer attribution
- reset controls for new chat and PDF clearing
- retrieval debug and retrieval evaluation endpoints
- backend test suite and retrieval accuracy runner
Expected local environment files:
backend/.envfrontend/.env.local
Typical backend variables:
OPENROUTER_API_KEY=your_key_here
OPENROUTER_MODEL=openai/gpt-4o-mini
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OLLAMA_BASE_URL=http://localhost:11434
LANGSMITH_TRACING=true
LANGSMITH_ENDPOINT=https://api.smith.langchain.com
LANGSMITH_API_KEY=your_langsmith_key_here
LANGSMITH_PROJECT=capstone2draft2Frontend uses:
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000cd frontend
npm installcd backend
py -3.13 -m venv .venv
. .venv/Scripts/activate
pip install -r requirements.txtBackend dependencies include:
fastapi==0.115.12uvicorn[standard]==0.34.0faiss-cpu==1.12.0sentence-transformers==3.4.1langsmith==0.1.147pytest==8.4.1
Run the full stack from the project root:
npm run devThe root launcher:
- starts frontend and backend together
- uses the backend virtual environment directly
- auto-selects the first free local frontend and backend ports from a safe range
- prints the actual URLs it chose
If ports such as 3000 or 8000 are already occupied, the launcher will move to the next free port automatically.
Returns healthcheck information and vector store metadata.
Uploads a PDF, extracts text, chunks the content, embeds it, and updates the vector store.
Multipart fields:
file: PDF filechunk_size: optional integer, defaults to700
Accepts a user query, message history, provider, model, and top-k value, then streams newline-delimited JSON events.
Stream event types:
{"type":"thinking"}{"type":"token","token":"..."}{"type":"sources","sources":[...]}{"type":"done"}
Clears indexed PDF context and backend memory state.
Returns retrieved chunks and their scores for a given query.
Returns retrieval evaluation metrics such as:
- matched expected terms
- term recall
- hit status
- retrieved chunk payloads and scores
Run the backend test suite:
cd backend
. .venv/Scripts/activate
pytestCurrent automated coverage includes:
- FastAPI route tests with injected fake pipeline
- upload, reset, chat, and retrieval endpoint behavior
- retrieval evaluation logic
- PDF chunking utility behavior
- aggregate retrieval accuracy reporting
After uploading and indexing a PDF, run:
cd backend
. .venv/Scripts/activate
python run_accuracy_check.py --cases eval_cases.sample.jsonThis produces a report with:
- case count
- average term recall
- hit rate
- matched expected terms per case
- retrieved chunks and scores per case
You can also write the result to a file:
python run_accuracy_check.py --cases eval_cases.sample.json --output accuracy-report.jsonImportant current design choices:
- custom RAG pipeline instead of LangChain orchestration
- local persisted FAISS storage
- one active PDF context at a time
- direct streaming from FastAPI to the frontend
- OpenRouter as default model provider with Ollama as fallback option
- single-PDF indexing only
- not multi-user or session-isolated
- retrieval evaluation is still basic and term-based
- no advanced reranker yet
- PDF extraction quality can affect retrieval precision
- not yet a full multimodal figure/table reasoning system
- security hardening is incomplete for production deployment
- multi-document support
- persistent multi-user document namespaces
- BM25 plus dense retrieval hybrid search
- reranking models
- answer-quality evaluation beyond retrieval recall
- richer figure and table understanding
- LangGraph-style advanced orchestration if the workflow becomes agentic
Recommended deployment split for a free preview setup:
- Frontend: Vercel
- Backend: Render Free Web Service
This is the best free deployment option for the current codebase.
- FastAPI runs cleanly on Render web services.
- The current backend is not a good fit for Vercel serverless because it uses
sentence-transformers,torch, and local vector storage. - Render is simpler than trying to force this backend into a serverless function model.
Official reference:
This repo includes render.yaml, but you can also configure the service manually through the Render dashboard.
- Sign in to Render.
- Click
New +. - Click
Web Service. - Choose
Build and deploy from a Git repository.
- Connect your GitHub account if Render asks.
- Select this repository:
Swetankan/Multimodal-AI-Research-Assistant
Use these settings:
- Name:
multimodal-ai-research-assistant-api - Root Directory:
backend - Runtime:
Python 3 - Build Command:
pip install -r requirements.txt - Start Command:
uvicorn main:app --host 0.0.0.0 --port $PORT - Instance Type:
Free
Add these in the Render dashboard:
OPENROUTER_API_KEY=your_key_hereOPENROUTER_MODEL=openai/gpt-4o-miniOPENROUTER_BASE_URL=https://openrouter.ai/api/v1OPENROUTER_SITE_URL=https://your-frontend-url.vercel.appOPENROUTER_APP_NAME=Multimodal AI Research AssistantFRONTEND_ORIGINS=https://your-frontend-url.vercel.appLANGSMITH_TRACING=trueLANGSMITH_ENDPOINT=https://api.smith.langchain.comLANGSMITH_API_KEY=your_langsmith_key_hereLANGSMITH_PROJECT=capstone2draft2
Optional only if you want Ollama instead of OpenRouter:
OLLAMA_BASE_URL=http://localhost:11434
- Click
Create Web Service. - Wait for the deployment to finish.
- Open the generated Render URL.
- Visit
/on that URL to confirm the healthcheck responds.
Example:
https://multimodal-ai-research-assistant-api.onrender.com/
Official references:
- Sign in to Vercel.
- Click
Add New.... - Click
Project. - Import your GitHub repository:
Swetankan/Multimodal-AI-Research-Assistant
Use these settings:
- Framework Preset:
Next.js - Root Directory:
frontend - Install Command:
npm install - Build Command:
npm run build - Output Directory: leave default for Next.js
Set:
NEXT_PUBLIC_API_BASE_URL=https://your-render-backend.onrender.com
- Click
Deploy. - Wait for the deployment to finish.
- Open the Vercel URL.
After Vercel gives you the real frontend URL, go back to Render and confirm these values are correct:
OPENROUTER_SITE_URL=https://your-real-vercel-url.vercel.appFRONTEND_ORIGINS=https://your-real-vercel-url.vercel.app
Then redeploy the backend once so the updated values are active.
- Vercel automatically creates preview deployments for future pushes and pull requests.
- The backend already allows
*.vercel.appthrough CORS, so those preview frontends can call the Render backend.
Render free services can sleep when idle, and this backend stores indexed document state locally. That means free deployment is suitable for preview/demo use, but uploaded PDFs and indexed vectors should be treated as temporary deployment state.
- If Render fails with a aiss-cpu version resolution error, redeploy after pulling the latest commit where FAISS is pinned to 1.12.0.
- If Vercel shows 404 NOT_FOUND, open the Vercel project settings and confirm Root Directory is set to rontend. The frontend must not be deployed from the repository root.
- On free Render instances, the first PDF upload can still be slow because the embedding model must load on the backend instance.
- The backend now supports MODEL_TIMEOUT_SECONDS to prevent chat requests from hanging forever when the upstream model provider stalls.
- For hosted deployments, prefer EMBEDDING_MODEL=sentence-transformers/paraphrase-MiniLM-L3-v2 unless you specifically want the larger L6 model.