Spaces:
Runtime error
Runtime error
File size: 5,079 Bytes
3a8e2ae bf6ec13 3a8e2ae 8a4f04c dc37c6d 3a8e2ae 76c71df 3a8e2ae 8a4f04c dc37c6d 3a8e2ae 8a4f04c 3a8e2ae bf6ec13 8a4f04c 3a8e2ae 8a4f04c dc37c6d 8a4f04c 3a8e2ae 8a4f04c 3a8e2ae bf6ec13 3a8e2ae bf6ec13 3a8e2ae 8a4f04c 3a8e2ae bf6ec13 a0c838b 3a8e2ae a0c838b 3a8e2ae a0c838b 3a8e2ae a0c838b bf6ec13 3a8e2ae bf6ec13 3a8e2ae 8a4f04c d991985 | 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 | import os
import re
import json
import torch
import torch.nn.functional as F
from flask import Flask, request, jsonify
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from pyvi import ViTokenizer
from PIL import Image
from torchvision import transforms
import timm
import requests
from flask_cors import CORS
# =====================
# CONFIG
# =====================
os.environ["TRANSFORMERS_CACHE"] = "/tmp/hf_cache" # tránh vượt storage limit
TEXT_MODEL_REPO = "phuongsuga/PBL6_AI_Model_Text_Image"
IMAGE_MODEL_REPO = "phuongsuga/PBL6_AI_Model_Image"
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
THRESHOLD = 0.65
# =====================
# LOAD TEXT MODEL
# =====================
print("🔹 Downloading text model...")
tokenizer = AutoTokenizer.from_pretrained(
TEXT_MODEL_REPO,
subfolder="text_model",
use_fast=False
)
text_model = AutoModelForSequenceClassification.from_pretrained(
TEXT_MODEL_REPO,
subfolder="text_model/checkpoint-3390"
)
text_model.to(DEVICE).eval()
# load label2id.json
label_url = f"https://huggingface.co/{TEXT_MODEL_REPO}/resolve/main/text_model/label2id.json"
label2id = requests.get(label_url).json()
id2label_text = {i: l for l, i in label2id.items()}
# =====================
# LOAD IMAGE MODEL
# =====================
print("🔹 Downloading image model...")
class_names = ["an_toan", "bao_luc", "khieu_dam_doi_truy", "nhay_cam_chinh_tri"]
def build_model(num_classes=4):
return timm.create_model("efficientnet_b3", pretrained=False, num_classes=num_classes)
image_model = build_model()
# tải model tạm trong /tmp để không chiếm storage
image_model_path = "/tmp/efficientnet_b3.pth"
if not os.path.exists(image_model_path):
url = f"https://huggingface.co/{IMAGE_MODEL_REPO}/resolve/main/image_model/efficientnet_b3.pth"
torch.hub.download_url_to_file(url, image_model_path)
image_model.load_state_dict(torch.load(image_model_path, map_location=DEVICE))
image_model.to(DEVICE).eval()
# chuẩn hóa ảnh
val_transforms = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
# =====================
# UTILS
# =====================
def seg_pyvi(text: str) -> str:
try:
seg = ViTokenizer.tokenize(text)
seg = seg.replace(" ", "_")
except Exception:
seg = text
return seg
def split_sentences(text: str):
sents = re.split(r'(?<=[.!?])\s+|\n+', text.strip())
return [s for s in sents if s.strip()]
def predict_text(text: str):
sentences = split_sentences(text)
results = []
for sent in sentences:
seg = seg_pyvi(sent)
inputs = tokenizer(seg, truncation=True, padding="max_length",
max_length=128, return_tensors="pt").to(DEVICE)
with torch.no_grad():
logits = text_model(**inputs).logits
probs = F.softmax(logits, dim=-1).cpu().numpy()[0]
pred_id = probs.argmax()
label = id2label_text[int(pred_id)]
prob = float(probs[pred_id])
if label != "an_toan" and prob >= THRESHOLD:
results.append({"sentence": sent, "label": label, "confidence": prob})
else:
results.append({
"sentence": sent,
"label": "an_toan",
"confidence": float(probs[label2id["an_toan"]])
})
return results
def predict_image(pil_image: Image.Image):
img = val_transforms(pil_image).unsqueeze(0).to(DEVICE)
with torch.no_grad():
outputs = image_model(img)
probs = F.softmax(outputs, dim=1)[0].cpu().numpy()
pred_id = probs.argmax()
label = class_names[pred_id]
prob = float(probs[pred_id])
if label != "an_toan" and prob >= THRESHOLD:
return {"label": label, "confidence": prob}
else:
return {
"label": "an_toan",
"confidence": float(probs[class_names.index("an_toan")])
}
# =====================
# FLASK APP
# =====================
app = Flask(__name__)
CORS(app)
@app.route("/")
def home():
return jsonify({"message": "✅ AI moderation API is running!"})
@app.route("/analyze", methods=["POST"])
def analyze():
result = {"text_result": [], "image_result": []}
# 🧠 PHÂN TÍCH TEXT
if "content" in request.form:
text_input = request.form["content"]
result["text_result"] = predict_text(text_input)
# 🧠 PHÂN TÍCH NHIỀU ẢNH
if "image" in request.files:
image_files = request.files.getlist("image")
for image_file in image_files:
image = Image.open(image_file.stream).convert("RGB")
image_result = predict_image(image)
result["image_result"].append(image_result)
return jsonify(result)
# =====================
# RUN APP
# =====================
if __name__ == "__main__":
port = int(os.environ.get("PORT", 7860)) # Hugging Face Space truyền PORT vào
app.run(host="0.0.0.0", port=port) |