Argus is an advanced, AST-based code plagiarism detection system with AI-powered authorship analysis. It structurally compares code submissions using Tree-sitter N-gram Jaccard similarity, verifies flagged pairs with a Groq LLM, and can detect if code was written by an AI (ChatGPT, Claude, etc.).
- Live Deployment: argus-two-beta.vercel.app
| Feature | Description |
|---|---|
| Multi-Language AST Parsing | Supports Python, Java, C++, JavaScript, HTML, CSS, and Rust via Tree-sitter |
| N-gram Jaccard Similarity | Extracts AST node-type sequences into sliding-window N-grams and computes structural overlap |
| AI Plagiarism Verification | Uses Groq LLM to verify if flagged pairs solve the same problem with the same logic |
| 2-Pass Batch Context | Filters out false positives from generic/trivial solutions common across large classrooms |
| AI Authorship Detection | Detects whether submitted code was likely generated by an LLM |
| Language Mismatch Validation | Pre-checks that pasted code matches the selected language before processing |
| Dual File Comparison | Side-by-side editor for comparing two code snippets |
| ZIP Batch Analysis | Upload a ZIP of student submissions for pairwise structural comparison |
| AI Single Scan | Paste a single snippet to check if it was AI-generated |
| AI Batch Scan | Upload a ZIP to scan all files for AI authorship |
Argus follows a client-server architecture:
┌──────────────────────────┐ ┌──────────────────────────────┐
│ Frontend (HTML) │ HTTP │ Backend (FastAPI) │
│ index.html + script.js │ ◄─────► │ api/server.py │
│ style.css │ │ api/ast_engine.py │
└──────────────────────────┘ │ Groq API (LLM) │
└──────────────────────────────┘
- Frontend — A premium dark-mode single-page app with 4 tabs (Dual Files, ZIP Batch, AI Single, AI Batch). Communicates with the backend via REST API on
localhost:8000. - Backend — A FastAPI server that handles AST parsing (via Tree-sitter), N-gram generation, Jaccard similarity, and AI-powered checks (via Groq's
llama-3.3-70b-versatile).
Antigravity/
├── api/ # Backend API package
│ ├── __init__.py
│ ├── ast_engine.py # Tree-sitter AST extraction, N-gram generation, Jaccard comparison
│ └── server.py # FastAPI endpoints (/compare, /compare_zip, /detect_ai_single, /detect_ai_batch, etc.)
│
├── src/ # Original CLI modules (standalone usage)
│ ├── __init__.py
│ ├── main.py # CLI entry point
│ ├── parser.py # Python AST parser (legacy, pre-Tree-sitter)
│ ├── ngrams.py # N-gram generation utilities
│ └── similarity.py # Jaccard similarity computation
│
├── data/ # Sample test scripts
│ ├── script_a.py # Clean Two-Sum solution
│ └── script_b.py # Obfuscated Two-Sum solution
│
├── tests/ # Unit tests
│ ├── __init__.py
│ └── test_detector.py # Tests for AST extraction, N-grams, similarity
│
├── index.html # Frontend — main HTML page
├── script.js # Frontend — all JavaScript logic (tab switching, API calls, results rendering)
├── style.css # Frontend — dark-mode CSS styling
├── run.py # One-click launcher (starts server + opens browser)
├── requirements.txt # Python dependencies
├── .env # API keys (not committed to Git)
├── .gitignore # Git ignore rules
├── pyrightconfig.json # Pyright type-checker configuration
└── Argus.command # macOS double-click launcher script
| Package | Purpose |
|---|---|
fastapi |
Web framework for the REST API |
uvicorn[standard] |
ASGI server to run FastAPI |
python-multipart |
Handles file uploads (ZIP) |
httpx |
HTTP client for fetching random code from GitHub |
groq |
Groq SDK for LLM-powered AI checks |
python-dotenv |
Loads API keys from .env file |
tree-sitter |
Core parser generator framework |
tree-sitter-python |
Python grammar for Tree-sitter |
tree-sitter-java |
Java grammar for Tree-sitter |
tree-sitter-cpp |
C++ grammar for Tree-sitter |
tree-sitter-javascript |
JavaScript grammar for Tree-sitter |
tree-sitter-html |
HTML grammar for Tree-sitter |
tree-sitter-css |
CSS grammar for Tree-sitter |
tree-sitter-rust |
Rust grammar for Tree-sitter |
pytest |
Test runner |
No build tools required — pure vanilla HTML, CSS, and JavaScript. Served as static files directly from the filesystem.
git clone https://github.com/prakharjaiswal/Argus.git
cd Argus/Antigravitypython3 -m venv .venv
source .venv/bin/activatepip install -r requirements.txt
pip install tree-sitter tree-sitter-python tree-sitter-java tree-sitter-cpp \
tree-sitter-javascript tree-sitter-html tree-sitter-css tree-sitter-rustCreate a .env file in the project root with your Groq API key:
echo 'GROQ_API_KEY=your_groq_api_key_here' > .envNote: The
.envfile is listed in.gitignoreand will never be committed to version control.
python run.pyThis will:
- Start the FastAPI server on
http://localhost:8000 - Automatically open the frontend in your default browser
| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Liveness probe |
POST |
/compare |
Compare two code snippets (AST + AI verification) |
POST |
/compare_zip |
Upload a ZIP for pairwise batch comparison |
POST |
/detect_ai_single |
Analyze a single snippet for AI authorship |
POST |
/detect_ai_batch |
Upload a ZIP to batch-scan files for AI authorship |
GET |
/random_code |
Fetch a random code file from GitHub (for demo/testing) |
When code is submitted, Argus parses it using Tree-sitter into an Abstract Syntax Tree. It then performs a depth-first traversal to extract a flat list of structural node types (e.g., function_definition, if_statement, binary_expression, identifier). Generic noise nodes like module and program are filtered out.
The extracted node-type list is broken into sliding-window N-grams (default size 3). Two code snippets are compared by computing the Jaccard Index of their N-gram sets:
Jaccard = |A ∩ B| / |A ∪ B|
A score of 0.0 means completely different structure; 1.0 means structurally identical.
If the Jaccard score is ≥ 40%, Argus sends both snippets to Groq's llama-3.3-70b-versatile model to verify:
- Whether the two codes solve the same problem
- Whether they use the same algorithmic logic
If the AI determines they solve different problems, the score is overridden to 0.0 and the verdict becomes "Different Problem Statements", preventing false positives.
For batch ZIP uploads, Argus uses a 2-pass algorithm:
- Pass 1: Computes pairwise Jaccard similarity for all file combinations.
- Cluster Identification: Files that are highly similar to many others (≥ 15% of the class or ≥ 3 files) are marked as "Generic Templates".
- Pass 2: Pairs where both files are generic templates get the verdict
Common Generic Solution — Ignored, bypassing the expensive AI check. Pairs with at least one non-generic file are flagged as genuinely suspicious.
Argus can evaluate whether a code snippet was likely written by an AI. The LLM prompt is extremely conservative — it assumes every piece of code is human-written unless it contains undeniable hallmarks of LLM generation (hallucinated libraries, robotic/sterile variable naming, essay-length comments on trivial code).
Before processing, Argus verifies that the pasted code matches the language selected in the UI. If there's a mismatch (e.g., Java code with "Python" selected), a clear error is returned:
"Language Mismatch: You selected PYTHON, but the code appears to be JAVA."
pytest tests/ -vArgus uses the Groq API for all LLM features. You can provide your API key in two ways (checked in this order):
- Enter it in the API Key field in the UI (per-request override)
- Set
GROQ_API_KEYin the.envfile (recommended for persistent use)
This project is for educational and academic integrity purposes.