shabir-786 commited on
Commit
62552f8
·
1 Parent(s): 6af8a2d

Deploy FastAPI AI vs Human detector

Browse files
.dockerignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ .qodo
2
+ venv/
3
+ test_api.py
4
+ new-file.ipynb
5
+ ai-vs-humanizer2.ipynb
.gitattributes CHANGED
@@ -33,3 +33,9 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+
37
+ .qodo
38
+ venv/
39
+ test_api.py
40
+ new-file.ipynb
41
+ ai-vs-humanizer2.ipynb
Dockerfile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a Python base image, preferably a slim version
2
+ FROM python:3.11-slim
3
+
4
+ # Set the working directory inside the container
5
+ WORKDIR /app
6
+
7
+ # Copy the dependency file and install them
8
+ COPY requirements.txt requirements.txt
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # Copy your saved model and the application code
12
+ # Assuming your model folder is named 'saved_human_ai_model'
13
+ COPY saved_human_ai_model ./saved_human_ai_model
14
+ COPY ./app.py ./app.py
15
+
16
+ # Expose the port (Cloud Run uses environment variable $PORT, but 8080 is a good default)
17
+ EXPOSE 8080
18
+
19
+ # Define the command to run the FastAPI application using Uvicorn
20
+ # The command format is: uvicorn [ASGI_MODULE]:[ASGI_APP_OBJECT] --host 0.0.0.0 --port $PORT
21
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
22
+ # NOTE: Cloud Run automatically maps the internal port 8080 to the external port
app.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uvicorn
2
+ from fastapi import FastAPI, HTTPException, Security, Depends
3
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ from pydantic import BaseModel
6
+ import tensorflow as tf
7
+ from transformers import AutoTokenizer, TFAutoModelForSequenceClassification
8
+ import numpy as np
9
+ import os
10
+ import jwt
11
+
12
+ # Initialize FastAPI app
13
+ app = FastAPI(title="AI vs Human Detector API")
14
+
15
+ # CORS Middleware
16
+ app.add_middleware(
17
+ CORSMiddleware,
18
+ allow_origins=["*"], # Allows all origins
19
+ allow_credentials=True,
20
+ allow_methods=["*"], # Allows all methods
21
+ allow_headers=["*"], # Allows all headers
22
+ )
23
+
24
+ # Security
25
+ security = HTTPBearer()
26
+ SECRET_KEY = "mysecretkey" # In production, use environment variable
27
+
28
+ # Global variables for model and tokenizer
29
+ model = None
30
+ tokenizer = None
31
+ MODEL_PATH = "saved_human_ai_model"
32
+
33
+ class PredictionRequest(BaseModel):
34
+ text: str
35
+
36
+ class PredictionResponse(BaseModel):
37
+ label: str
38
+ confidence: float
39
+ probabilities: dict
40
+
41
+ def verify_token(credentials: HTTPAuthorizationCredentials = Security(security)):
42
+ token = credentials.credentials
43
+ try:
44
+ # Just verify the signature using the SECRET_KEY
45
+ # We don't need to parse/use the payload for user verification
46
+ jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
47
+ except jwt.ExpiredSignatureError:
48
+ raise HTTPException(status_code=401, detail="Token has expired")
49
+ except jwt.InvalidTokenError:
50
+ raise HTTPException(status_code=401, detail="Invalid token")
51
+
52
+ @app.on_event("startup")
53
+ async def load_model():
54
+ global model, tokenizer
55
+ try:
56
+ print(f"Loading model from {MODEL_PATH}...")
57
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
58
+ model = TFAutoModelForSequenceClassification.from_pretrained(MODEL_PATH)
59
+ print("Model and Tokenizer loaded successfully!")
60
+ except Exception as e:
61
+ print(f"Error loading model: {e}")
62
+ raise RuntimeError(f"Could not load model: {e}")
63
+
64
+ @app.post("/predict", response_model=PredictionResponse, dependencies=[Depends(verify_token)])
65
+ async def predict(request: PredictionRequest):
66
+ if not model or not tokenizer:
67
+ raise HTTPException(status_code=503, detail="Model not loaded")
68
+
69
+ try:
70
+ # Tokenize input
71
+ inputs = tokenizer(
72
+ request.text,
73
+ return_tensors="tf",
74
+ padding=True,
75
+ truncation=True,
76
+ max_length=512
77
+ )
78
+
79
+ # Inference
80
+ outputs = model(inputs)
81
+ logits = outputs.logits
82
+
83
+ # Softmax
84
+ probabilities = tf.nn.softmax(logits, axis=-1).numpy()[0]
85
+
86
+ # Get prediction
87
+ predicted_class_id = np.argmax(probabilities)
88
+ confidence = float(probabilities[predicted_class_id])
89
+
90
+ # Map labels (Assuming 0=Human, 1=AI based on notebook)
91
+ labels_map = {0: "Human", 1: "AI"}
92
+ predicted_label = labels_map.get(predicted_class_id, "Unknown")
93
+
94
+ return PredictionResponse(
95
+ label=predicted_label,
96
+ confidence=confidence,
97
+ probabilities={
98
+ "Human": float(probabilities[0]),
99
+ "AI": float(probabilities[1])
100
+ }
101
+ )
102
+
103
+ except Exception as e:
104
+ raise HTTPException(status_code=500, detail=str(e))
105
+
106
+ if __name__ == "__main__":
107
+ uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ tensorflow
4
+ transformers
5
+ numpy
6
+ tf-keras
7
+ pyjwt
8
+ pydantic
saved_human_ai_model/added_tokens.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "[MASK]": 128000
3
+ }
saved_human_ai_model/config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DebertaV2ForSequenceClassification"
4
+ ],
5
+ "attention_probs_dropout_prob": 0.1,
6
+ "hidden_act": "gelu",
7
+ "hidden_dropout_prob": 0.1,
8
+ "hidden_size": 768,
9
+ "initializer_range": 0.02,
10
+ "intermediate_size": 3072,
11
+ "layer_norm_eps": 1e-07,
12
+ "legacy": true,
13
+ "max_position_embeddings": 512,
14
+ "max_relative_positions": -1,
15
+ "model_type": "deberta-v2",
16
+ "norm_rel_ebd": "layer_norm",
17
+ "num_attention_heads": 12,
18
+ "num_hidden_layers": 6,
19
+ "pad_token_id": 0,
20
+ "pooler_dropout": 0,
21
+ "pooler_hidden_act": "gelu",
22
+ "pooler_hidden_size": 768,
23
+ "pos_att_type": [
24
+ "p2c",
25
+ "c2p"
26
+ ],
27
+ "position_biased_input": false,
28
+ "position_buckets": 256,
29
+ "relative_attention": true,
30
+ "share_att_key": true,
31
+ "transformers_version": "4.57.3",
32
+ "type_vocab_size": 0,
33
+ "vocab_size": 128100
34
+ }
saved_human_ai_model/special_tokens_map.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": "[CLS]",
3
+ "cls_token": "[CLS]",
4
+ "eos_token": "[SEP]",
5
+ "mask_token": "[MASK]",
6
+ "pad_token": "[PAD]",
7
+ "sep_token": "[SEP]",
8
+ "unk_token": {
9
+ "content": "[UNK]",
10
+ "lstrip": false,
11
+ "normalized": true,
12
+ "rstrip": false,
13
+ "single_word": false
14
+ }
15
+ }
saved_human_ai_model/spm.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c679fbf93643d19aab7ee10c0b99e460bdbc02fedf34b92b05af343b4af586fd
3
+ size 2464616
saved_human_ai_model/tf_model.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ffbac1a30ba77feb1efb6a8874a9ccf768ab1075ec9c868cea2e9f98d4cb599e
3
+ size 567742256
saved_human_ai_model/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
saved_human_ai_model/tokenizer_config.json ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "[CLS]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "[SEP]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "[UNK]",
29
+ "lstrip": false,
30
+ "normalized": true,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "128000": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "bos_token": "[CLS]",
45
+ "clean_up_tokenization_spaces": false,
46
+ "cls_token": "[CLS]",
47
+ "do_lower_case": false,
48
+ "eos_token": "[SEP]",
49
+ "extra_special_tokens": {},
50
+ "mask_token": "[MASK]",
51
+ "model_max_length": 1000000000000000019884624838656,
52
+ "pad_token": "[PAD]",
53
+ "sep_token": "[SEP]",
54
+ "sp_model_kwargs": {},
55
+ "split_by_punct": false,
56
+ "tokenizer_class": "DebertaV2Tokenizer",
57
+ "unk_token": "[UNK]",
58
+ "vocab_type": "spm"
59
+ }