Skip to content

mars-alien/paper-trail

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“° PaperTrail

Multi-Article RAG Research Assistant

Paste news URLs. Ask questions. Get cited, streamed answers.

Python FastAPI React Weaviate Groq License

Live Demo Backend


πŸ“Έ Demo

PaperTrail Screenshot

Drop any news URL β†’ ask anything β†’ get a grounded, cited answer streamed in real time.


✨ Features

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

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        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      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Pipeline Steps

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

πŸ› οΈ Tech Stack

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

πŸ“ Project Structure

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

πŸš€ Quick Start

Prerequisites

  • Python 3.10+
  • Node.js 18+
  • Docker Desktop
  • Groq API key β€” free at console.groq.com

Step 1 β€” Start Weaviate

docker-compose up -d

Weaviate runs on http://localhost:8080. Data persists in a Docker volume.


Step 2 β€” Backend

cd backend
python -m venv .venv
Activate virtual environment

PowerShell:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
.venv\Scripts\Activate.ps1

Command Prompt:

.venv\Scripts\activate.bat

macOS / Linux:

source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

Edit .env:

GROQ_API_KEY=your_groq_api_key_here
WEAVIATE_URL=http://localhost:8080
python -m uvicorn main:app --host 0.0.0.0 --port 8000

Step 3 β€” Frontend

cd frontend
npm install
npm run dev

Open http://localhost:5173


πŸ’‘ Usage

1. 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.


πŸ”Œ API Reference

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.


πŸ“Š Evaluation Results

Run the RAGAS-style evaluation (requires articles ingested first):

cd backend
python eval_ragas.py

Groq 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

☁️ Deployment

Service Platform Status
🌐 Frontend Vercel Vercel
⚑ Backend Render Render
πŸ—„οΈ Vector DB Weaviate Cloud Serverless Sandbox

Environment Variables (Render)

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.


πŸ›‘ Stopping Local Services

# Stop Weaviate
docker-compose down

# Wipe all data (removes weaviate_data volume)
docker-compose down -v

Made with ❀️ using FastAPI, React, Weaviate, and Groq

⭐ Star this repo if you found it useful!

About

Multi-article RAG web app built with FastAPI + React. Scrapes news URLs, chunks & embeds with BAAI/BGE-small, indexes in Weaviate (BM25 + HNSW hybrid search), reranks with cross-encoder, and streams cited answers via Groq (Llama 3.3 70B / DeepSeek-R1). RAGAS eval score: 0.905.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors