Paste news URLs. Ask questions. Get cited, streamed answers.
Drop any news URL β ask anything β get a grounded, cited answer streamed in real time.
| Feature | Description |
|---|---|
| π Paste & Ask | Drop any news URL and start chatting immediately |
| π Hybrid Search | BM25 + dense vector retrieval via Weaviate for high recall |
| π― Cross-Encoder Reranking | ms-marco-MiniLM reranks top 24 candidates β top 6 |
| β‘ SSE Streaming | Answers stream token-by-token via Server-Sent Events |
| π Source Citations | Every answer links back to the exact article |
| π Multi-Article Chat | Ingest multiple articles and filter by source |
| π§ Intent Routing | Summary/comparison queries routed to a stronger model |
| π Session Isolation | Fresh start on every server restart, no stale data |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INGESTION PIPELINE β
β β
β News URL βββΊ Scrape βββΊ Chunk βββΊ Embed βββΊ Weaviate Index β
β (trafilatura) (~300 tok) (BGE-small) (HNSW+BM25) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β QUERY PIPELINE β
β β
β Question βββΊ Intent βββΊ Embed βββΊ Hybrid Retrieve βββΊ Rerank β
β Detect (BGE) (BM25 35%+HNSW 65%) (Cross- β
β top 24 encoder) β
β β β
β Groq LLM β
β β β
β Streamed SSE β
β Answer β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Step | Tool | Detail |
|---|---|---|
| π·οΈ Scrape | trafilatura | Extracts clean article text from any news URL |
| βοΈ Chunk | Sentence-boundary | ~300 tokens / 1200 chars per chunk, with section labels |
| π’ Embed | BAAI/bge-small-en-v1.5 | 384-dim dense vectors via ONNX Runtime (fastembed) |
| ποΈ Store | Weaviate | HNSW (ef=128) + BM25 (k1=1.5, b=0.4) dual index |
| π Retrieve | Hybrid | alpha=0.65 dense + 0.35 BM25, top 24 candidates |
| π Diversify | Custom | Max 3 chunks per article to prevent flooding |
| π― Rerank | ms-marco-MiniLM-L-6-v2 | Cross-encoder scores, keeps top 6 |
| π¬ Generate | Groq API | Llama 3.3 70B / DeepSeek-R1, SSE streaming |
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite + CSS Modules |
| Backend | FastAPI + Python 3.10+ |
| Vector DB | Weaviate Cloud (HNSW + BM25) |
| Embeddings | BAAI/bge-small-en-v1.5 (fastembed / ONNX) |
| Reranker | ms-marco-MiniLM-L-6-v2 (fastembed / ONNX) |
| LLM | Groq API β Llama 3.3 70B + DeepSeek-R1 |
| Scraper | trafilatura |
| Metadata DB | SQLite |
paper-trail/
βββ π backend/
β βββ main.py # FastAPI app β all endpoints
β βββ scraper.py # Article scraping with trafilatura
β βββ chunker.py # Sentence-boundary text chunking
β βββ embedder.py # BAAI/bge-small-en-v1.5 via fastembed
β βββ retriever.py # Hybrid search + cross-encoder reranking
β βββ llm.py # Groq SSE streaming
β βββ database.py # SQLite article tracking
β βββ query_processor.py # Intent detection + starter questions
β βββ eval_ragas.py # RAGAS-style LLM-as-judge evaluation
β βββ requirements.txt
βββ π frontend/
β βββ src/
β β βββ App.jsx
β β βββ components/
β β β βββ Sidebar.jsx # Article manager + URL ingest
β β β βββ Message.jsx # Chat bubbles with markdown
β β β βββ InputBar.jsx # Question input + send
β β β βββ Welcome.jsx # Empty state + starter cards
β β β βββ SourceChips.jsx # Cited source links
β β βββ hooks/useChat.js # SSE streaming hook
β β βββ utils/markdown.js
β βββ index.html
β βββ vite.config.js
βββ docker-compose.yml # Local Weaviate
βββ π docs/
βββ Application-Snapshot.png
- Python 3.10+
- Node.js 18+
- Docker Desktop
- Groq API key β free at console.groq.com
docker-compose up -dWeaviate runs on
http://localhost:8080. Data persists in a Docker volume.
cd backend
python -m venv .venvActivate virtual environment
PowerShell:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
.venv\Scripts\Activate.ps1Command Prompt:
.venv\Scripts\activate.batmacOS / Linux:
source .venv/bin/activatepip install -r requirements.txt
cp .env.example .envEdit .env:
GROQ_API_KEY=your_groq_api_key_here
WEAVIATE_URL=http://localhost:8080python -m uvicorn main:app --host 0.0.0.0 --port 8000cd frontend
npm install
npm run dev1. Paste one or more news article URLs in the left sidebar
β
βΌ
2. Click "Add Articles" β scraped, chunked & indexed in seconds
β
βΌ
3. Type any question in the input bar
β
βΌ
4. Get a streamed, cited answer with clickable source links
π‘ Use the starter question cards on the welcome screen for inspiration.
Base URL: https://paper-trail-g0xr.onrender.com
Interactive docs: /docs
| Method | Endpoint | Description |
|---|---|---|
POST |
/ingest |
Scrape and index article URLs |
POST |
/query |
Stream an SSE answer |
GET |
/articles |
List all ingested articles |
DELETE |
/articles/{doc_id} |
Remove an article |
GET |
/starters |
Starter questions for the UI |
GET |
/health |
Health check + Weaviate status |
Example: Ingest an article
curl -X POST https://paper-trail-g0xr.onrender.com/ingest \
-H "Content-Type: application/json" \
-d '{"urls": ["https://www.bbc.com/news/articles/example"]}'Response:
{
"results": [{
"url": "https://...",
"status": "ok",
"doc_id": "2b32ba4b-...",
"title": "Article Title",
"chunks": 14
}]
}Example: Ask a question
curl -X POST https://paper-trail-g0xr.onrender.com/query \
-H "Content-Type: application/json" \
-d '{"question": "What happened?", "history": [], "doc_ids": []}'Response: SSE stream of data: {"type": "token", "text": "..."} events.
Run the RAGAS-style evaluation (requires articles ingested first):
cd backend
python eval_ragas.pyGroq acts as LLM judge across three metrics:
| Metric | What It Measures |
|---|---|
| π― Faithfulness | Answer is grounded in retrieved chunks β no hallucination |
| π¬ Answer Relevancy | Answer directly addresses the question |
| π Context Precision | Retrieved chunks are relevant to the question |
Sample results (2 articles ingested):
Question Faith Relev Prec
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Why did Sensex crash 1500 points? 1.00 1.00 0.83
Which stocks were buzzing during crash? 1.00 1.00 0.83
What happened to Kalyan Jewellers stock? 1.00 1.00 0.83
Why did Mumbai shut schools? 1.00 1.00 1.00
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Overall RAG Score ββββββββββββββββββββ 0.905
| Service | Platform | Status |
|---|---|---|
| π Frontend | Vercel | |
| β‘ Backend | Render | |
| ποΈ Vector DB | Weaviate Cloud | Serverless Sandbox |
GROQ_API_KEY=your_groq_key
WEAVIATE_URL=https://your-cluster.weaviate.network
WEAVIATE_API_KEY=your_weaviate_key
β οΈ Weaviate free tier pauses after 14 days of inactivity. Resume it from the Weaviate Cloud dashboard if you get a 503 error.
# Stop Weaviate
docker-compose down
# Wipe all data (removes weaviate_data volume)
docker-compose down -vMade with β€οΈ using FastAPI, React, Weaviate, and Groq
β Star this repo if you found it useful!
