How sachin210506/scholar works
1. Purpose and Runtime Entry Points
scholAR is a local-first academic document retrieval and RAG system: users upload PDFs, search indexed course material, receive cited answers, generate practice questions, and retain chat history. The React/Vite client starts at frontend/src/main.jsx and renders the primary interface in frontend/src/App.jsx. The FastAPI service entry point is backend/src/api.py, run as uvicorn backend.src.api:app.
2. API Orchestration Boundary
backend/src/api.py is the application boundary between browser workflows and backend services. It exposes health/stats, PDF upload, hybrid search, cited answering, practice-question generation, and chat-session routes. The frontend is a single main UI surface that calls this API rather than directly accessing indexes, files, LLMs, or PostgreSQL.
• backend/src/api.py
• frontend/src/App.jsx
• frontend/src/main.jsx
3. Document Ingestion and Local Corpus
Upload processing persists PDFs locally, derives file-hash-based document identity, captures academic metadata, extracts page-level text, and produces retrieval chunks. Extraction is Markdown/page aware and falls back to Tesseract OCR for low-text scanned pages. Chunking preserves page provenance and can merge adjacent continued topics; stable chunk IDs permit both indexes to refer to the same evidence.
• backend/src/extract.py
• backend/src/chunking.py
• backend/src/embed_index.py
4. Dual Retrieval Indexes and Ranking
Indexed chunks are embedded with local sentence-transformers/all-MiniLM-L6-v2 and stored in ChromaDB, while a persisted custom BM25 index supplies lexical matching. search.py joins these result sets by stable chunk ID and applies hybrid scoring: semantic similarity, BM25, exact terms, headings, and source credibility. Request-level metadata filters constrain subject, document/source type, and credibility. A retrieval-confidence gate prevents downstream generation from treating weak context as evidence.
• backend/src/embed_index.py
• backend/src/bm25_index.py
• backend/src/search.py
5. Grounded Generation and Credibility
Answer and practice workflows consume retrieved chunks, build citation-aware prompts, and refuse or request clarification when retrieval is weak. Generated answer/question credibility is separately assessed from source credibility and relevance, using retrieval strength, source quality/variety, and citation use. This is a deliberate boundary: trusted documents do not override poor query relevance.
• backend/src/rag_answer.py
• backend/src/generate_questions.py
• backend/src/output_credibility.py
6. LLM Provider Boundary
Generation routes use an abstraction that invokes Gemini as the configured primary model and Groq as fallback for provider failures such as timeout, quota, or credentials. Provider keys, selected models, and database connection details are supplied through environment variables rather than application code.
• backend/src/llm_provider.py
• .env.example
7. Stateful Chat and External Persistence
Chat has a separate persistence path from corpus data: sessions/messages are stored in Neon PostgreSQL through the database and store layers. Before retrieval, follow-up prompts are rewritten into standalone search queries using a recent-message window; guardrails reject rewrites that lose the prior topic. The final response can still use original wording and conversation context.
• backend/src/db.py
• backend/src/chat_store.py
• backend/src/contextual_query.py
8. Storage and Infrastructure Split
The system intentionally distributes state by workload: local filesystem for uploaded PDFs, local ChromaDB for vectors/chunks, local persisted BM25 for lexical search, and Neon PostgreSQL for durable chat. Material external dependencies are Gemini, Groq, Neon/PostgreSQL, and locally installed Tesseract for OCR; FastAPI/Pydantic serve the backend and React/Vite serve the browser client.
Main entry points: api.py FastAPI service · search.py Hybrid search · extract.py PDF extraction · rag_answer.py Cited answers
Components 20
Browser client
- React/Vite bootstrap
frontend/src/main.jsx - Main UI · Uploads, search, answers, practice, and chat.
frontend/src/App.jsx
API boundary
- FastAPI service · Owns browser-facing upload, retrieval, generation, and chat routes.
backend/src/api.py
Corpus ingestion
- PDF extraction · Uses Tesseract OCR for low-text scanned pages.
backend/src/extract.py - Local PDF corpus · Stores uploaded PDFs under hash-based document identities.
- Provenance chunking · Creates stable, page-aware chunk IDs.
backend/src/chunking.py
Hybrid retrieval
- Embedding indexer · Embeds chunks with local all-MiniLM-L6-v2.
backend/src/embed_index.py - ChromaDB · Persists vectors and chunk evidence.
- BM25 index · Persists lexical matches keyed by stable chunk ID.
backend/src/bm25_index.py - Hybrid search · Joins vector and BM25 evidence, filters metadata, and gates weak retrieval.
backend/src/search.py
Grounded generation
- Cited answers · Builds citation-aware answers or declines weak evidence.
backend/src/rag_answer.py - Practice questions · Generates questions only from retrieved context.
backend/src/generate_questions.py - Output credibility · Separately evaluates relevance, citations, and source variety.
backend/src/output_credibility.py - LLM provider · Uses Gemini primarily and Groq on provider failure.
backend/src/llm_provider.py
Chat persistence
- Contextual query rewrite · Rewrites follow-ups with topic-loss guardrails.
backend/src/contextual_query.py - Chat store
backend/src/chat_store.py - Database layer
backend/src/db.py - Neon PostgreSQL · Stores chat sessions and messages.
Other components
- Gemini / Groq
- Tesseract
Connections 28
- React/Vite bootstrap → Main UI: renders
- Main UI → FastAPI service: API requests
- FastAPI service → Local PDF corpus: stores uploads
- FastAPI service → PDF extraction: starts ingestion
- Local PDF corpus → PDF extraction: PDF input
- PDF extraction → Tesseract: scanned-page OCR
- PDF extraction → Provenance chunking: page text + metadata
- Provenance chunking → Embedding indexer: stable chunks
- Provenance chunking → BM25 index: stable chunks
- Embedding indexer → ChromaDB: vectors + evidence
- FastAPI service → Hybrid search: search requests
- ChromaDB → Hybrid search: semantic candidates
- BM25 index → Hybrid search: lexical candidates
- FastAPI service → Cited answers: answer route
- FastAPI service → Practice questions: practice route
- Hybrid search → Cited answers: gated evidence
- Hybrid search → Practice questions: gated evidence
- Cited answers → Output credibility: answer assessment
- Practice questions → Output credibility: question assessment
- Cited answers → LLM provider: grounded prompt
- Practice questions → LLM provider: grounded prompt
- LLM provider → Gemini / Groq: primary / fallback
- FastAPI service → Contextual query rewrite: follow-up prompt
- Chat store → Contextual query rewrite: recent messages
- Contextual query rewrite → Hybrid search: standalone query
- FastAPI service → Chat store: read/write chat
- Chat store → Database layer: sessions + messages
- Database layer → Neon PostgreSQL: durable persistence