File size: 7,002 Bytes
78a22a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb51816
78a22a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb51816
78a22a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb51816
78a22a6
fb51816
78a22a6
 
fb51816
78a22a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb51816
78a22a6
fb51816
78a22a6
 
fb51816
78a22a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb51816
 
78a22a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
"""
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"
    )