PDF Insight Pro is built on a modular, layered architecture that enforces a strict separation of concerns — each layer has one clearly defined responsibility, and no layer skips a layer below it. HTTP requests enter at the presentation layer, travel through FastAPI route handlers inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Jatin-Mehra119/PDF-Insight-Beta/llms.txt
Use this file to discover all available pages before exploring further.
api/, are processed by the business-logic services in services/, and are finally resolved by purpose-built utility functions in utils/. External I/O — vector storage, LLM inference, and web search — is isolated at the edges, making the core pipeline easy to test and extend.
Layers
Presentation Layer
End-user clients that speak HTTP/JSON to the API. Includes the Web Browser UI (served from
static/) and the Android WebView Client bundled in the Android App/ directory. Neither client contains business logic; they delegate everything to the API layer.API Layer
FastAPI route handlers living in
api/. Four modules divide responsibilities cleanly:upload_routes.py— PDF intake and chunkingchat_routes.py— query processing and response streamingsession_routes.py— session lifecycle endpointsutility_routes.py— model listing and health checks
app.py via the create_app() factory.Service Layer
Core business logic in
services/:rag_service.py—RAGServiceclass: agent creation, tool orchestration, fallback strategyllm_service.py—ChatGroqinstantiation and Tavily tool factorysession_service.py—SessionManagerclass: in-memory cache + file persistence
Utility Layer
Stateless helper functions in
utils/:text_processing.py— PDF loading, paragraph chunking, embedding generation, context assemblyfaiss_utils.py— FAISS HNSW index construction, similarity search, filteringsession_utils.py— pickle serialisation/deserialisation, file-path helpers, validation
Storage
The
uploads/ directory (Config.UPLOAD_DIR) is the single physical store. It holds two artefact types side-by-side:{session_id}_{filename}.pdf— the original uploaded PDF{session_id}_session.pkl— the pickle-serialised session snapshot (chunks + chat history)
External Services
Two external APIs are consumed at the service layer:
- Groq LLM API (
GROQ_API_KEY) — powers allChatGroqinstances used for inference. Default model:llama-3.1-8b-instant. - Tavily Web Search API (
TAVILY_API_KEY) — optional web-augmentation tool exposed to the LangChain agent whenuse_search=True.
Project Structure
Data Flow
The following sequence describes how a chat query travels through the full stack and returns a response.HTTP Request arrives at app.py
The browser or Android WebView sends a
POST /chat JSON body (ChatRequest) to the FastAPI application created by create_app(). CORS middleware validates the origin, then the request is dispatched to chat_handler in api/chat_routes.py.Route handler validates and loads session
chat_handler validates the query string (non-empty, ≥ 3 characters), then calls session_manager.get_session(session_id, model_name). The SessionManager checks the in-memory cache first; if the session is absent it loads the pickle from uploads/ and reconstructs the FAISS index on the fly.Initial retrieval via utilities
The handler calls
retrieve_similar_chunks() from utils/faiss_utils.py to pull Config.INITIAL_CONTEXT_CHUNKS (5) candidate chunks from the FAISS index before handing off to the service layer.RAG service builds and runs the agent
rag_service.generate_response() prepares the context string via prepare_context_from_chunks(), creates a LangChain AgentExecutor with up to two tools (vector_database_search and optionally tavily_search_results_json), then calls execute_agent(). If the agent fails, the service falls back to fallback_response() — direct tool use plus a plain LLM call.Groq / Tavily I/O
The LangChain agent calls the Groq API (via
ChatGroq) for LLM inference, and optionally calls the Tavily Search API for web-augmented context. Both calls are made synchronously within the AgentExecutor invocation.Response returned and session persisted
The chat response is extracted from
response["output"], appended to session_data["chat_history"], and re-serialised to uploads/{session_id}_session.pkl via save_session_to_file(). A ChatResponse Pydantic model — including the answer text and a context_used array of (text, score, metadata) objects — is returned as JSON to the client.Configuration constants referenced throughout the codebase — chunk size, similarity threshold, FAISS parameters, agent iterations — are all centralised in
configs/config.py as class attributes on Config. Refer to that file as the single source of truth for all tunable values.Further Reading
- RAG Pipeline — detailed breakdown of document ingestion, FAISS indexing, the agentic query loop, and evaluation metrics.
- Session Management — how sessions are created, cached, serialised, reloaded, and cleaned up across server restarts.