ChatVerse is a multi-mode Retrieval-Augmented Generation (RAG) platform that lets you chat with four different kinds of sources β PDFs, YouTube videos, GitHub repositories, and Gmail inboxes β through one unified interface.
Every mode shares the same underlying pattern: ingest a source, chunk and embed it into an isolated vector collection, then retrieve and generate answers through a LangGraph pipeline. Only the ingestion step changes per source β everything else is identical, which keeps the system small and easy to reason about instead of four separate apps bolted together.
- Page-Aware Chunking: Documents are split with
RecursiveCharacterTextSplitter, preserving page metadata - Grounded Answers: Every reply is generated only from retrieved chunks β no answer without a citation
- Transcript Retrieval: Pulls captions via
youtube-transcript-api, no API key required - Timestamp Windows: Transcript segments are grouped into ~60s windows so answers can point to
t=6:40
- Repo Walking: Uses
PyGithubto list and read source files without a localgit clone - File-Path Citations: Answers reference the exact file a chunk came from
- OAuth2 Flow: One-time browser consent, cached and auto-refreshed via
google-auth-oauthlib - Plain-Language Search: Ask about your inbox instead of guessing the right search operators
- LangGraph Pipelines: Every mode is a
StateGraphwithretrieveβgeneratenodes - Isolated Vector Storage: Chroma collections scoped per
mode + session_id - Uniform API Contract: All four modes expose identical
/ingest,/chat,/sessions/{id}shapes
- Landing Page: Marketing site with a live mode-switching demo
- Dashboard: Dark, sidebar-driven chat UI β pick a source, ingest, and chat
- React Router:
/for the landing page,/appfor the dashboard
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β React Frontend (Vite) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β LandingPage.jsx β HomePage.jsx (Sidebar + Chat) β β
β β β’ Mode selection (PDF / YouTube / GitHub / Gmail) β β
β β β’ Source ingestion UI β β
β β β’ Chat window + source citations β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β axios (client.js)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI Backend β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β POST /api/{mode}/ingest β β
β β POST /api/{mode}/chat β β
β β GET /api/{mode}/sessions/{id} β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LangGraph Orchestration β
β βββββββββββββββ βββββββββββββββ β
β β retrieve β β β generate β β
β β (Chroma) β β (LLM) β β
β βββββββββββββββ βββββββββββββββ β
β one graph per mode: pdf_graph / youtube_graph / β
β github_graph / gmail_graph β identical shape, different β
β ingestion feeding the same collection β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββ¬βββββββββββββββ¬ββββββββββββββββ¬βββββββββββ
β β β β
βββββββββββ ββββββββββββ ββββββββββββββ ββββββββββββ
β PyPDF β β YouTube β β PyGithub β β Gmail API β
β Loader β β Transcriptβ β (repo walk)β β (OAuth2) β
βββββββββββ ββββββββββββ ββββββββββββββ ββββββββββββ
- retrieve: Searches the mode's Chroma collection for the top-k relevant chunks
- generate: Builds a context-grounded prompt and calls the LLM for an answer
chatverse/
βββ chatverse-backend/
β βββ app/
β β βββ main.py # FastAPI app, CORS, router mounting
β β βββ config.py # .env-loaded settings
β β βββ schemas.py # IngestResponse / ChatRequest / ChatResponse
β β βββ core/
β β β βββ llm.py # LLM + embeddings client factory
β β β βββ vectorstore.py # Chroma collection helper
β β β βββ gmail_auth.py # OAuth2 credential flow
β β βββ graphs/
β β β βββ pdf_graph.py
β β β βββ youtube_graph.py
β β β βββ github_graph.py
β β β βββ gmail_graph.py
β β βββ routers/
β β βββ pdf.py
β β βββ youtube.py
β β βββ github.py
β β βββ gmail.py
β βββ requirements.txt
β βββ .env
β
βββ chatverse-frontend/
β βββ src/
β β βββ main.jsx # mounts <App/> in <BrowserRouter>
β β βββ App.jsx # routes: "/" and "/app"
β β βββ api/
β β β βββ client.js # axios calls matching the API contract
β β βββ hooks/
β β β βββ useDocuments.js # ingest state
β β β βββ useChat.js # chat state
β β βββ pages/
β β β βββ LandingPage.jsx
β β β βββ HomePage.jsx
β β βββ components/
β β β βββ Sidebar.jsx
β β βββ styles/
β β βββ global.css
β β βββ landing.css
β β βββ app.css
β βββ package.json
β
βββ README.md
http://127.0.0.1:8000
Every mode (pdf, youtube, github, gmail) exposes the same three endpoints.
Load a source and index it for retrieval
POST /api/pdf/ingest
Content-Type: multipart/form-data
file: <PDF file>POST /api/youtube/ingest
Content-Type: application/json
{ "url": "https://youtube.com/watch?v=..." }POST /api/github/ingest
Content-Type: application/json
{ "repo_url": "owner/repo" }POST /api/gmail/ingest
Content-Type: application/json
{ "query": "from:someone@example.com" }Response:
{
"session_id": "a1b2c3d4-...",
"status": "success",
"chunks_indexed": 42
}Ask a question about an ingested source
POST /api/{mode}/chat
Content-Type: application/json
{
"session_id": "a1b2c3d4-...",
"message": "What does chapter 3 conclude?"
}Response:
{
"answer": "Chapter 3 reports 91.4% accuracy on the held-out test set...",
"sources": [
{ "content": "...", "metadata": { "source": "chapter3.pdf", "page": 18 } }
],
"session_id": "a1b2c3d4-..."
}Status Codes:
200: Success404: Unknownsession_idβ ingest a source first500: Server error (usually a missing/invalid API key)
GET /api/{mode}/sessions/{session_id}Response:
{
"session_id": "a1b2c3d4-...",
"history": [
{ "role": "user", "content": "..." },
{ "role": "assistant", "content": "..." }
]
}# System Requirements
- Python 3.12+
- Node.js 18+
- Gemini API key (or OpenAI API key)
- GitHub token (optional, for higher rate limits on GitHub mode)
- Google Cloud OAuth credentials (for Gmail mode)cd chatverse-backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtCreate chatverse-backend/.env:
# LLM Configuration (Gemini)
GOOGLE_API_KEY=your_gemini_api_key_here
# Vector Store
CHROMA_PERSIST_DIR=./chroma_db
# GitHub Mode
GITHUB_TOKEN=your_github_token_here
# Gmail Mode
GMAIL_CREDENTIALS_PATH=./credentials.json
# CORS
CORS_ORIGINS=http://localhost:5173Terminal 1 β Backend:
source venv/bin/activate
cd chatverse-backend
uvicorn app.main:app --reloadTerminal 2 β Frontend:
cd chatverse-frontend
npm install
npm run devAccess the Application:
- Web Interface: http://localhost:5173
- API Documentation (Swagger): http://127.0.0.1:8000/docs
- Health Check: http://127.0.0.1:8000/health
Using the Web Interface:
- Navigate to http://localhost:5173
- Click Start chatting free
- Pick a mode (PDF / YouTube / GitHub / Gmail)
- Upload a file or paste a link
- Ask questions in the chat window
Using cURL:
# Ingest a PDF
curl -X POST http://127.0.0.1:8000/api/pdf/ingest \
-F "file=@/path/to/document.pdf"
# Chat with it
curl -X POST http://127.0.0.1:8000/api/pdf/chat \
-H "Content-Type: application/json" \
-d '{"session_id": "PASTE_SESSION_ID", "message": "Summarize this document"}'Using Python:
import requests
response = requests.post(
"http://127.0.0.1:8000/api/pdf/chat",
json={"session_id": "PASTE_SESSION_ID", "message": "What is this about?"}
)
print(response.json())# Loaded from .env via pydantic-settings
GOOGLE_API_KEY # Gemini LLM + embeddings authentication
CHROMA_PERSIST_DIR # Vector store location on disk
GITHUB_TOKEN # GitHub API rate-limit headroom
GMAIL_CREDENTIALS_PATH # OAuth2 client secret file
CORS_ORIGINS # Allowed frontend origin(s)Centralizes the LLM and embeddings client β swapping providers (OpenAI β Gemini) means editing this one file only.
Each mode was built in order of rising ingestion complexity, not feature priority:
Build Order
βββ PDF β no auth, no external API (simplest)
βββ YouTube β transcript API, no key required
βββ GitHub β GitHub API, optional token
βββ Gmail β OAuth2 + privacy-sensitive data (most complex)
- Navigate to http://127.0.0.1:8000/docs
- Expand
POST /api/pdf/ingest - Click Try it out
- Upload a PDF via the file picker
- Click Execute and copy the returned
session_id - Repeat for
POST /api/pdf/chatusing thatsession_id
Test 1: PDF ingestion
curl -X POST http://127.0.0.1:8000/api/pdf/ingest -F "file=@notes.pdf"Test 2: Chat on an ingested PDF
{
"session_id": "<from test 1>",
"message": "What are the main topics covered?"
}Test 3: Health check
curl http://127.0.0.1:8000/health- Store API keys in
.envfile (never commit) - Never commit
chroma_db/ortoken.jsonβ both contain indexed personal data - Use a throwaway Gmail account when demoing Gmail mode publicly
- Validate uploaded file types before processing
- Use HTTPS in production
- Rotate
GITHUB_TOKENandGOOGLE_API_KEYperiodically
uvicorn app.main:app --reloaduvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4cd chatverse-frontend
npm run build # outputs to dist/- Chunking: PDF/GitHub use ~1000-1200 char chunks with overlap; YouTube uses ~60s transcript windows
- Isolated Collections: Each
mode + session_idgets its own Chroma collection β no cross-session leakage - In-Memory History: Chat history currently lives in a Python dict per router; swap for Redis/SQLite before scaling past local development
- Fork the repository
- Create a feature branch (
git checkout -b feature/YourFeature) - Follow the existing
retrieveβgenerategraph pattern for new modes - Commit with descriptive messages (
git commit -m 'feat: Add YourFeature') - Push to your branch and open a Pull Request
- Follow PEP 8 for Python, keep components small and prop-driven in React
- Add docstrings to new graph nodes and router functions
- Keep the API contract (
schemas.py) as the source of truth for request/response shapes
| Component | Technology |
|---|---|
| LLM Framework | LangChain |
| Workflow Orchestration | LangGraph |
| Web Framework | FastAPI |
| ASGI Server | Uvicorn |
| Vector Database | ChromaDB |
| LLM Provider | Google Gemini |
| PDF Parsing | PyPDF |
| YouTube Transcripts | youtube-transcript-api |
| GitHub Access | PyGithub |
| Gmail Access | google-api-python-client + google-auth-oauthlib |
| Frontend Framework | React 18 + Vite |
| Routing | react-router-dom |
| HTTP Client | axios |
| Icons | lucide-react |