Jaja-09's picture
.
fb51816
"""
FastAPI Backend Server for AuthorCheck AI Detection
Uses DeBERTa model for AI-generated text detection
"""
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import List, Optional
import uvicorn
from model_handler import AIDetectionModelHandler
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Initialize FastAPI app
app = FastAPI(
title="AuthorCheck API",
description="AI-powered text analysis and detection API",
version="1.0.0"
)
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialize model handler
model_handler = AIDetectionModelHandler()
# Request/Response Models
class AnalysisRequest(BaseModel):
text: str = Field(..., min_length=1, description="Text to analyze")
analysisTypes: Optional[List[str]] = Field(
default=["all"],
description="Types of analysis to perform"
)
model: Optional[str] = Field(
default="ai-detector",
description="Model to use for analysis"
)
class EmotionData(BaseModel):
emotion: str
score: float
intensity: str
class AdvancedSentiment(BaseModel):
emotions: List[EmotionData]
confidence: float
context: str
avg_polarity: Optional[float] = None
polarity_variance: Optional[float] = None
class TopicData(BaseModel):
topic: str
relevance: float
keywords: List[str]
class WritingStyle(BaseModel):
tone: str
formality: str
complexity: str
style: List[str]
audience: str
sentiment_consistency: Optional[str] = None
class Insight(BaseModel):
type: str
title: str
description: str
suggestion: Optional[str] = None
class PlagiarismRisk(BaseModel):
score: int
level: str
details: str
class ContentQuality(BaseModel):
overall: int
clarity: int
coherence: int
engagement: int
originality: int
class AnalysisResponse(BaseModel):
advancedSentiment: AdvancedSentiment
topics: List[TopicData]
writingStyle: WritingStyle
insights: List[Insight]
plagiarismRisk: PlagiarismRisk
contentQuality: ContentQuality
aiOrHuman: str
aiOrHumanConfidence: float
aiOrHumanExplanation: str
# API Endpoints
@app.get("/")
async def root():
"""Root endpoint - API health check"""
return {
"status": "online",
"message": "AuthorCheck API is running",
"version": "1.0.0"
}
@app.get("/health")
async def health_check():
"""Health check endpoint"""
try:
model_loaded = model_handler.is_loaded()
return {
"status": "healthy" if model_loaded else "degraded",
"model_loaded": model_loaded,
"model_type": "DeBERTa AI Detector"
}
except Exception as e:
logger.error(f"Health check failed: {e}")
return {
"status": "unhealthy",
"error": str(e)
}
@app.post("/api/analyze")
async def analyze_text(request: AnalysisRequest):
"""
Analyze text using the DeBERTa AI detection model
Returns comprehensive analysis including:
- AI vs Human detection
- Sentiment analysis
- Topic detection
- Writing style analysis
- Content quality metrics
"""
try:
if not request.text or len(request.text.strip()) == 0:
raise HTTPException(status_code=400, detail="Text cannot be empty")
# Check text length for meaningful analysis (50-7000 words)
word_count = len(request.text.split())
if word_count < 50:
raise HTTPException(
status_code=400,
detail="Text is too short for analysis. Please provide at least 50 words for accurate AI detection and sentiment analysis."
)
if word_count > 7000:
raise HTTPException(
status_code=400,
detail="Text is too long for analysis. Maximum 7,000 words allowed."
)
# Perform AI detection using the model
logger.info(f"Analyzing text of length: {len(request.text)}")
analysis_result = model_handler.analyze_text(request.text)
logger.info(f"Analysis complete: {analysis_result['aiOrHuman']} ({analysis_result['aiOrHumanConfidence']:.2f}%)")
return analysis_result
except HTTPException:
raise
except Exception as e:
logger.error(f"Analysis error: {e}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"Analysis failed: {str(e)}"
)
@app.post("/api/detect")
async def detect_ai(request: AnalysisRequest):
"""
Simple endpoint for AI detection only
Returns just the AI/Human classification
"""
try:
if not request.text or len(request.text.strip()) == 0:
raise HTTPException(status_code=400, detail="Text cannot be empty")
# Check text length (50-7000 words)
word_count = len(request.text.split())
if word_count < 50:
raise HTTPException(
status_code=400,
detail="Text is too short. Please provide at least 50 words."
)
elif word_count > 7000:
raise HTTPException(
status_code=400,
detail="Text is too long. Maximum 7,000 words allowed."
)
result = model_handler.detect_ai(request.text)
return {
"text": request.text[:100] + "..." if len(request.text) > 100 else request.text,
"classification": result["classification"],
"prediction": result.get("prediction", result["classification"]),
"probability": result["probability"],
"confidence": result["confidence"],
"explanation": result["explanation"],
"mixed_analysis": result.get("mixed_analysis", None),
"modelProcessingTime": result.get("modelProcessingTime", None)
}
except HTTPException:
raise
except Exception as e:
logger.error(f"Detection error: {e}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"Detection failed: {str(e)}"
)
@app.get("/api/model/info")
async def model_info():
"""Get information about the loaded model"""
try:
return model_handler.get_model_info()
except Exception as e:
logger.error(f"Model info error: {e}")
raise HTTPException(status_code=500, detail=str(e))
# Run the server
if __name__ == "__main__":
uvicorn.run(
"app:app",
host="0.0.0.0",
port=8000,
reload=True,
log_level="info"
)