Upload any PDF. Ask anything. Get instant, context-aware AI answers.
QueryMyPDF is a production-grade, cloud-deployable AI document assistant built on a Retrieval-Augmented Generation (RAG) pipeline. It lets users upload PDF files and have rich, intelligent conversations about their content β powered by Google's Gemini 2.5 Flash LLM, a hybrid BM25 + FAISS retrieval engine, and a LangGraph agentic workflow with persistent memory.
The app ships with a fully custom dark-themed Streamlit UI (glassmorphism design, animated bubbles, real-time token streaming) that looks and feels like a modern chat product.
- Hybrid Retrieval β combines BM25 (keyword/lexical search) and FAISS (semantic/vector search) for best-of-both-worlds document retrieval; results are merged and deduplicated so the LLM always gets the most relevant context
- Gemini 2.5 Flash LLM β Google's latest fast multimodal model via
langchain-google-genai - HuggingFace Embeddings β
sentence-transformers/all-MiniLM-L6-v2for fast, high-quality sentence embeddings (free tier friendly) - LangGraph Agentic Loop β the chatbot is a proper tool-calling agent (not a simple chain): it decides when to call the RAG tool and can handle conversational turns without unnecessary retrieval
- Persistent Conversation Memory β
SqliteSavercheckpointer persists the full message graph per session, surviving page re-runs
- Upload any PDF via the sidebar
- Text extracted page-by-page using
PyPDFLoader - Smart chunking with
RecursiveCharacterTextSplitter(1 500-character chunks, 150-character overlap) β preserves semantic coherence across page boundaries - Per-session retriever storage keyed by UUID thread ID β multiple users are fully isolated
- Real-time streaming β tokens appear word-by-word as the model generates them; a blinking cursor shows live generation
- Stop generation button β interrupt streaming at any point
- Graceful error handling β distinguishes between rate-limit (429), service unavailable (503), and generic errors, surfacing human-readable messages
- Fallback
invokepath if the stream yields no content - Clear Chat button to reset conversation while keeping the document loaded
- Document metadata panel shows filename, page count, and chunk count after indexing
- Fully custom CSS dark theme (
#08081abackground, radial violet/indigo gradients) - Glassmorphism sidebar with
backdrop-filter: blur(24px) - Animated chat bubbles β user messages aligned right (purple gradient), AI messages aligned left (frosted glass)
- Animated pulsing dot on the AI label during generation
- Floating empty-state illustrations with CSS
@keyframesanimation - Responsive layout using Streamlit
widemode - Google Fonts: Outfit (headings) + Inter (body)
- Exponential back-off retry on embedding calls β handles HuggingFace free-tier 429 / 503 errors automatically (up to 5 retries, starting at 2 s)
- Batch embedding β texts are embedded in batches of 50 with a 1-second pause between batches to stay within rate limits
@st.cache_resourceon the LLM, embedding model, and compiled graph β these are built exactly once per server process, keeping cold start times low- SQLite-backed graph checkpointing β no Redis or external service needed
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Streamlit UI (APP.py) β
β Sidebar: PDF Upload β "Build Knowledge Base" btn β
β Main: Scrollable chat container + chat_input bar β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β ingest_pdf()
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PDF Ingestion Pipeline β
β PyPDFLoader β RecursiveCharacterTextSplitter β
β β HuggingFace Embeddings (batch + retry) β
β β FAISS vector store + BM25 retriever β
β Stored in _THREAD_RETRIEVERS[thread_id] β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β chatbot.stream()
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LangGraph Agent (StateGraph) β
β β
β START β [chat_node] ββtools_conditionβββΊ [tools] β
β β² β β
β ββββββββββββββββββββββββββββββββββ β
β β
β chat_node: Gemini 2.5 Flash + bound rag_tool β
β tool_node: rag_tool β FAISS + BM25 hybrid search β
β checkpointer: SqliteSaver (chatbot.db) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Upload β User selects a PDF β bytes streamed to
ingest_pdf() - Index β PDF is loaded, split into chunks, embedded, and stored in FAISS + BM25 under the session's
thread_id - Query β User types a question β
HumanMessagefed into the LangGraph agent - Retrieve β Agent calls
rag_tool(query, thread_id)β BM25 finds keyword matches, FAISS finds semantic matches β top 8 unique chunks returned as context - Generate β Gemini 2.5 Flash synthesizes an answer from the retrieved context, streamed token-by-token to the UI
- Persist β Full message history stored in SQLite, survives Streamlit re-runs
| Layer | Technology | Purpose |
|---|---|---|
| UI | Streamlit + Custom CSS | Interactive chat interface |
| LLM | Google Gemini 2.5 Flash | Natural language generation |
| Embeddings | HuggingFace all-MiniLM-L6-v2 |
Dense vector representations |
| Vector Store | FAISS (CPU) | Semantic similarity search |
| Keyword Search | BM25 (rank-bm25) |
Lexical / term-frequency search |
| Agent Framework | LangGraph StateGraph |
Tool-calling agent orchestration |
| Memory | LangGraph SqliteSaver |
Persistent conversation history |
| PDF Parsing | LangChain PyPDFLoader |
Page-level text extraction |
| Text Splitting | RecursiveCharacterTextSplitter |
Semantic chunking |
| Orchestration | LangChain Core | Chains, tools, message types |
| Deployment | Vercel | Static output / serverless |
QueryMyPDF/
βββ APP.py # Streamlit frontend β UI, state management, streaming
βββ RAG_backend.py # RAG pipeline β ingestion, retrieval, LangGraph agent
βββ embed_test.py # Utility script to test Google GenAI embeddings
βββ requirements.txt # Python dependencies
βββ vercel.json # Vercel deployment configuration
βββ assets/ # Screenshot images for documentation
β βββ PDF_loader.png
β βββ PDF_loader2.png
β βββ response.png
β βββ response1.png
β βββ source_doc.png
β βββ source_doc1.png
βββ public/
βββ index.html # Static landing / redirect page
| Visit | Screenshot |
|---|---|
| QueryMyPDF | ![]() |
- Python 3.10+
- A Google Gemini API key β get one free at aistudio.google.com
- A HuggingFace token (free) β generate one at huggingface.co/settings/tokens
Visit - https://querymypdf.onrender.com/
- Upload a PDF using the sidebar file uploader
- Click β‘ Build Knowledge Base to index the document (chunks + embeddings are built)
- The sidebar shows a green β Active badge with page and chunk counts
- Ask any question in the chat input bar at the bottom
- Watch the answer stream in real-time β press βΈ to stop generation at any time
- Click ποΈ Clear Chat to start a fresh conversation on the same document
| Variable | Required | Description |
|---|---|---|
GOOGLE_API_KEY |
β Yes | Google Gemini API key |
GEMINI_API_KEY |
Optional | Alias for GOOGLE_API_KEY |
HF_TOKEN |
β Yes | HuggingFace API token for embeddings |
Pure vector search can miss exact keyword matches (e.g., specific names, codes, dates). Pure BM25 misses semantic similarity. Combining both and deduplicating gives consistently better recall across document types.
LangGraph models the chatbot as a stateful agent with conditional edges. The LLM decides whether retrieval is necessary β avoiding unnecessary API calls on greetings or follow-up clarifications, and allowing the architecture to scale to additional tools (web search, calculator, etc.) without refactoring.
Zero-dependency persistence. The SqliteSaver checkpointer stores the full message graph per thread_id, meaning conversation context survives Streamlit widget re-runs without any external infrastructure.
HuggingFace Inference API free tier enforces strict rate limits. Batching (50 texts/batch) and backing off on 429/503 responses makes the app reliable without requiring a paid plan.
streamlit # Web UI framework
langchain>=0.3 # LLM orchestration
langchain-core>=0.3 # Core abstractions
langchain-community>=0.3 # FAISS, BM25, PyPDFLoader
langchain-text-splitters>=0.3
langchain-google-genai>=2.0 # Gemini LLM integration
langchain-huggingface>=0.1 # HuggingFace embeddings
langgraph # Agentic state graph
langgraph-checkpoint-sqlite # SQLite memory checkpointer
faiss-cpu # Vector similarity search
rank-bm25 # BM25 keyword retrieval
pypdf # PDF parsing
python-dotenv # .env file support
requests # HTTP utilities
google-genai # Google GenAI SDK
Contributions are welcome! Please open an issue first to discuss what you'd like to change.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.
Pawan Chaudhary
GitHub: @chaudhary-pawan




