ErzhanAb commited on
Commit
73b552b
·
verified ·
1 Parent(s): 0c002a7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -0
app.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import joblib, json, re
3
+ from html import unescape
4
+
5
+ # -----------------------------
6
+ # 1) Точная копия preprocessor
7
+ # -----------------------------
8
+ _URL_RE = re.compile(r'https?://\S+|www\.\S+')
9
+ _TAG_RE = re.compile(r'[@#]\w+')
10
+ _NUM_RE = re.compile(r'\d+')
11
+ _WS_RE = re.compile(r'\s+')
12
+
13
+ def clean_text(s: str) -> str:
14
+ """ДОЛЖНА совпадать с версией из обучения, иначе pickle не найдёт функцию."""
15
+ if not isinstance(s, str):
16
+ s = str(s)
17
+ s = unescape(s).lower()
18
+ s = _URL_RE.sub(' <url> ', s)
19
+ s = _TAG_RE.sub(' <tag> ', s)
20
+ s = _NUM_RE.sub(' <num> ', s)
21
+ s = s.replace('\n', ' ').replace('\t', ' ')
22
+ s = _WS_RE.sub(' ', s).strip()
23
+ return s
24
+
25
+ # ---------------------------------
26
+ # 2) Загрузка пайплайна и конфига
27
+ # ---------------------------------
28
+ # Важно: clean_text определён ДО загрузки, чтобы joblib смог десериализовать Vectorizer
29
+ PIPE = joblib.load("model.joblib")
30
+
31
+ DEFAULT_THRESHOLD = 0.4
32
+ try:
33
+ with open("config.json", "r", encoding="utf-8") as f:
34
+ cfg = json.load(f)
35
+ DEFAULT_THRESHOLD = float(cfg.get("threshold", DEFAULT_THRESHOLD))
36
+ except Exception:
37
+ pass # если файла нет — оставим дефолт 0.4
38
+
39
+ # ---------------------------------
40
+ # 3) Инференс
41
+ # ---------------------------------
42
+ def predict(comment: str, threshold: float):
43
+ if comment is None or not str(comment).strip():
44
+ return "Пустой ввод", 0.0
45
+ # В PIPE уже внутри есть preprocessor=clean_text, поэтому подаём сырой текст
46
+ proba = float(PIPE.predict_proba([comment])[0, 1])
47
+ label = "Токсичный" if proba >= threshold else "Не токсичный"
48
+ return label, round(proba, 4)
49
+
50
+ DESCRIPTION = """
51
+ Модель для классификации токсичных комментариев (русский язык).
52
+ Архитектура: **TF-IDF (char_wb 4–5) + Logistic Regression (L1, class_weight=balanced)**.
53
+ """
54
+
55
+ demo = gr.Interface(
56
+ fn=predict,
57
+ inputs=[
58
+ gr.Textbox(label="Комментарий", lines=4, placeholder="Введите текст на русском..."),
59
+ gr.Slider(0.0, 1.0, value=DEFAULT_THRESHOLD, step=0.01, label="Порог классификации"),
60
+ ],
61
+ outputs=[
62
+ gr.Textbox(label="Класс"),
63
+ gr.Number(label="Вероятность токсичности"),
64
+ ],
65
+ title="Russian Toxic Comment Classifier — TF-IDF + Logistic Regression",
66
+ description=DESCRIPTION,
67
+ allow_flagging="never",
68
+ examples=[
69
+ ["Ты полный идиот!"],
70
+ ["Спасибо большое за помощь!"],
71
+ ["Посмотри это <url> и скажи, что думаешь"]
72
+ ],
73
+ )
74
+
75
+ if __name__ == "__main__":
76
+ demo.launch()