Stop repeating yourself β let AI find it for you
When writing a PhD thesis over months or years, the same ideas inevitably appear in multiple chapters, sometimes word-for-word, sometimes paraphrased. RepeatRadar finds these repetitions semantically (not just exact matches), scores them by severity, and lets you fix them with one click using Gemini AI.
- π Upload PDF or DOCX β supports any academic document format
- π§ Semantic detection β finds repetitions even when phrased differently
- π― Smart scoring β π΄ High / π‘ Medium / π’ Low based on similarity, length, and signpost keywords
- π Three fix strategies β rewrite, shorten to recall sentence, or replace with cross-reference
- β Accept / Reject / Edit β you stay in control, AI just suggests
- π₯ Export fixes β download a
.txtchangelog to apply to your Word/LaTeX document - β‘ Caching β embeddings saved to disk, analysis is instant on repeat runs
- π° 100% free β uses Gemini free tier, no paid API needed
PDF/DOCX Upload
β
LangChain RecursiveCharacterTextSplitter β tagged chunks
β
Gemini gemini-embedding-001 β FAISS FlatIP index (cached)
β
FAISS search (top-K) β cosine similarity pairs
β
Filter: skip preamble / references / math / adjacent chunks
β
Score: similarity + length + signpost keywords β π΄/π‘/π’
β
Streamlit UI β side-by-side pair view
β
Fix on demand β Gemini Flash rewrite β Accept / Reject
| Upload | Analyse | Review & Fix |
|---|---|---|
| Drag & drop PDF/DOCX | Real-time embedding progress bar | Side-by-side pair comparison with fix panel |
- Python 3.11+
- Free Gemini API key β Get one here
git clone https://github.com/bazzal99/RepeatRadar.git
cd RepeatRadarcp .env.example .env
# Open .env and add your Gemini API keypip install -r requirements.txt
pip install streamlit==1.40.0 requests==2.32.3cd backend
uvicorn app.main:app --reload --port 8080cd frontend
streamlit run app.pyhttp://localhost:8501
cp .env.example .env
# Add your API key to .env
cd infra
docker compose up -d- Frontend: http://localhost:8501
- API docs: http://localhost:8080/docs
Edit RepeatRadar/.env:
# Embedding key (gemini-embedding-001)
GOOGLE_API_KEY=your_key_here
# Optional: separate key for fix agent to avoid quota conflicts
GOOGLE_API_KEY_GENERATION=your_second_key_here
# Detection sensitivity (0.92 = recommended, lower = more pairs found)
SIMILARITY_THRESHOLD=0.92
# Chunk size for splitting (characters)
CHUNK_SIZE=400
CHUNK_OVERLAP=80Tip: Use two separate Gemini API keys β one for embeddings and one for the fix agent. This prevents quota conflicts since embedding and generation share the same free tier limits.
RepeatRadar/
βββ backend/
β βββ app/
β β βββ api/routes/
β β β βββ documents.py # Upload & chunk endpoints
β β β βββ analysis.py # Embed, analyse, fix, accept endpoints
β β βββ core/
β β β βββ config.py # Settings from .env
β β βββ services/
β β β βββ ingestor.py # PDF/DOCX β LangChain chunks
β β β βββ embedder.py # Gemini embeddings + FAISS cache
β β β βββ detector.py # FAISS search + pair filtering
β β β βββ scorer.py # π΄/π‘/π’ scoring logic
β β β βββ fixer.py # Gemini Flash rewriting agent
β β βββ main.py
β βββ Dockerfile
βββ frontend/
β βββ app.py # Full Streamlit UI
β βββ Dockerfile
βββ infra/
β βββ docker-compose.yml
βββ .env.example
βββ requirements.txt
βββ LICENSE
βββ README.md
Each flagged pair is scored on three signals:
| Signal | Criteria | Points |
|---|---|---|
| Similarity | β₯ 0.95 (near-identical) | +2 |
| β₯ 0.90 (very similar) | +1 | |
| β₯ 0.92 threshold | 0 | |
| Length | Both chunks β₯ 200 chars | +2 |
| One chunk β₯ 200 chars | +1 | |
| Signpost | "as introduced in", "recall that", etc. | β2 |
Final score β severity:
- π΄ High (4-5 pts) β fix strongly recommended
- π‘ Medium (2-3 pts) β review recommended
- π’ Low (0-1 pts) β likely intentional, shown collapsed
| Strategy | What it does | Best for |
|---|---|---|
| Rewrite | Different phrasing, same meaning | Same-chapter repetition |
| Shorten | Compress to one recall sentence | Intro repeated in Conclusion |
| Reference | Replace with pointer to original | When repetition adds no value |
| Layer | Technology |
|---|---|
| LLM + Embeddings | Google Gemini (free tier) |
| Vector Index | FAISS FlatIP |
| Chunking | LangChain RecursiveCharacterTextSplitter |
| API | FastAPI + Uvicorn |
| Frontend | Streamlit |
| PDF parsing | pypdf |
| DOCX parsing | python-docx |
| Containers | Docker Compose |
Mohammad Bazzal β ML Engineer | PhD Candidate in Telecommunications
IMT Atlantique, Lab-STICC, Brest, France
This project is licensed under the MIT License β see the LICENSE file for details.