esicodehub-ai / api.py
WissalllK's picture
Add ESIcodeHub AI detection service
a937307
"""
api.py
======
FastAPI wrapper around the 3-phase AI code detector.
Endpoints:
GET / β†’ welcome + available endpoints
GET /health β†’ status check
POST /detect β†’ run detection on submitted code
Usage:
cd C:\\Users\\DEY STORE\\ai-code-detector
uvicorn api:app --reload --port 8000
Then visit http://localhost:8000/docs for the Swagger UI.
Test from PowerShell:
$body = @{ code = "def hello():\n print('hi')\n return 42\n\nhello()\nprint('done')\nprint('end')\nprint('really')\nprint('yes')"; language = "python" } | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8000/detect" -Method POST -Body $body -ContentType "application/json"
"""
import sys
import os
from pathlib import Path
# Make project root importable
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from orchestrator import detect, build_report
app = FastAPI(
title="AI Code Detector",
description=(
"Three-phase detector for AI-generated source code.\n\n"
"Phase 1: Stylometric analysis (Python only, AUC 0.966)\n"
"Phase 2: Multi-LLM rewrite similarity (AUC 0.653)\n"
"Phase 3: Neural code classifier (AUC 0.753)\n\n"
"Based on: 'Uncovering LLM-Generated Code' (AAAI 2025)"
),
version="1.0.0",
)
# ── Request / Response models ─────────────────────────────────────────────────
class DetectRequest(BaseModel):
code: str = Field(
...,
min_length=1,
description="Source code to analyze",
json_schema_extra={
"example": "import sys\nfrom collections import Counter\n\ndef solve(arr):\n if not arr:\n return 0\n return max(Counter(arr).values())\n\nif __name__ == '__main__':\n arr = list(map(int, sys.stdin.read().split()))\n print(solve(arr))"
},
)
language: str = Field(
"python",
description="Programming language of the code",
json_schema_extra={"example": "python"},
)
class DetectResponse(BaseModel):
verdict: str
confidence: float | None
p1: float | None = None
p2: float | None = None
p3: float | None = None
suspected_model: str | None = None
language: str
phases_used: int | None = None
report: str
timings: dict | None = None
total_time_seconds: float | None = None
errors: dict | None = None
# ── Endpoints ─────────────────────────────────────────────────────────────────
@app.get("/")
def root():
return {
"name": "AI Code Detector",
"version": "1.0.0",
"status": "running",
"endpoints": {
"/detect": "POST β€” submit code for detection",
"/health": "GET β€” health check",
"/docs": "GET β€” Swagger UI (interactive API docs)",
},
}
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/detect", response_model=DetectResponse)
def detect_endpoint(req: DetectRequest):
"""
Analyze a code snippet for AI authorship.
Runs up to 3 detection phases in parallel and returns a combined verdict.
Phase 2 requires a Groq API key and may take 5-15 seconds.
"""
if len(req.code.strip()) < 10:
raise HTTPException(status_code=400, detail="Code too short (< 10 chars)")
try:
result = detect(req.code, req.language)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Detection failed: {e}")
result["report"] = build_report(result)
return result
# ── Run directly ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
import uvicorn
print("Starting API server at http://localhost:8000")
print("Swagger UI at http://localhost:8000/docs")
uvicorn.run("api:app", host="0.0.0.0", port=8000, reload=True)