tegpro commited on
Commit
003d5e9
·
1 Parent(s): edb3b34

Add application file

Browse files
Files changed (5) hide show
  1. DEPLOY.md +46 -0
  2. README.md +16 -7
  3. app.py +57 -0
  4. model.py +15 -0
  5. requirements.txt +3 -0
DEPLOY.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Деплой на HuggingFace Spaces
2
+
3
+ Папка `hf_space/` — готовый Space. Не хватает только одного файла — твоих
4
+ обученных весов. Дальше 5 шагов.
5
+
6
+ ## 0. Положи веса в эту папку
7
+ Скопируй сюда `bert_toxic_classifier.pt` (тот, что сохраняет твой `train.py`).
8
+ Итоговый состав папки:
9
+ app.py
10
+ model.py
11
+ requirements.txt
12
+ README.md
13
+ bert_toxic_classifier.pt <-- добавить
14
+
15
+ Если файла весов нет — перезапусти `train.py` локально, он его создаст.
16
+
17
+ ## 1. Установи CLI и залогинься
18
+ pip install -U "huggingface_hub[cli]"
19
+ hf auth login
20
+ Токен возьми тут (нужен **write**): https://huggingface.co/settings/tokens
21
+
22
+ ## 2. Создай Space
23
+ hf repo create russian-toxic-classifier --repo-type space --space-sdk gradio
24
+ (если флаг назван иначе в твоей версии — глянь `hf repo create --help`)
25
+
26
+ ## 3. Залей содержимое папки
27
+ Из каталога `hf_space/`:
28
+ hf upload TeGPro/russian-toxic-classifier . --repo-type space
29
+ Замени `TeGPro` на свой username на HuggingFace, если он другой.
30
+ Файл весов >10 МБ CLI сам зальёт через LFS — ничего настраивать не надо.
31
+
32
+ ## 4. Открой и проверь
33
+ https://huggingface.co/spaces/TeGPro/russian-toxic-classifier
34
+ Сборка идёт 2–4 минуты. Введи пару фраз.
35
+ Если токсичное/нетоксичное перепутаны местами — поставь `TOXIC_INDEX = 0`
36
+ в app.py и перезалей шагом 3.
37
+
38
+ ## 5. Вставь ссылку в резюме и GitHub
39
+ - В `resume_projects.txt` (Проект 3) добавь строку: `Демо: <ссылка на Space>`
40
+ - В README репозитория `russian-toxic-classifier` добавь бейдж/ссылку на Space.
41
+
42
+ ---
43
+ ## Проверить app.py локально перед деплоем (опционально)
44
+ pip install -r requirements.txt
45
+ python app.py
46
+ Откроется на http://127.0.0.1:7860
README.md CHANGED
@@ -1,13 +1,22 @@
1
  ---
2
- title: Russian Toxic Classifier
3
- emoji: 📚
4
- colorFrom: red
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 6.19.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Russian Toxicity Classifier
3
+ emoji: 🛡️
4
+ colorFrom: indigo
5
+ colorTo: purple
6
  sdk: gradio
 
 
7
  app_file: app.py
8
  pinned: false
9
+ license: mit
10
  ---
11
 
12
+ # Классификатор токсичности русского текста
13
+
14
+ Fine-tuning [`cointegrated/rubert-tiny2`](https://huggingface.co/cointegrated/rubert-tiny2)
15
+ с кастомной FC-головой над `[CLS]`-токеном для бинарной классификации
16
+ русскоязычных комментариев на токсичность.
17
+
18
+ - Датасет: ~300 тыс. строк (`Mnwa/russian-toxic`)
19
+ - Optimizer: AdamW · Loss: CrossEntropy · `max_length=128`
20
+ - Accuracy на отложенном тесте: **96%**
21
+
22
+ Исходный код и обучение: https://github.com/TeGPro/russian-toxic-classifier
app.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import gradio as gr
3
+ from transformers import AutoTokenizer
4
+
5
+ from model import BertClassifier
6
+
7
+ WEIGHTS = "bert_toxic_classifier.pt"
8
+ MAX_LEN = 128
9
+ # Индекс класса "токсичный" в твоём датасете (Mnwa/russian-toxic).
10
+ # Если демо путает токсичное с нетоксичным — поменяй на 0.
11
+ TOXIC_INDEX = 1
12
+
13
+ device = torch.device("cpu")
14
+ tokenizer = AutoTokenizer.from_pretrained("cointegrated/rubert-tiny2")
15
+
16
+ model = BertClassifier(n_classes=2)
17
+ model.load_state_dict(torch.load(WEIGHTS, map_location=device))
18
+ model.to(device).eval()
19
+
20
+
21
+ @torch.no_grad()
22
+ def predict(text: str):
23
+ if not text or not text.strip():
24
+ return {"Введите текст": 1.0}
25
+ enc = tokenizer(
26
+ text,
27
+ max_length=MAX_LEN,
28
+ padding="max_length",
29
+ truncation=True,
30
+ return_tensors="pt",
31
+ )
32
+ logits = model(enc["input_ids"].to(device), enc["attention_mask"].to(device))
33
+ probs = torch.softmax(logits, dim=1)[0]
34
+ toxic = probs[TOXIC_INDEX].item()
35
+ return {"☣️ Токсичный": toxic, "✅ Нетоксичный": 1.0 - toxic}
36
+
37
+
38
+ demo = gr.Interface(
39
+ fn=predict,
40
+ inputs=gr.Textbox(lines=3, placeholder="Введите комментарий на русском…", label="Текст комментария"),
41
+ outputs=gr.Label(num_top_classes=2, label="Оценка токсичности"),
42
+ title="🛡️ Классификатор токсичности русского текста",
43
+ description=(
44
+ "Fine-tuning **cointegrated/rubert-tiny2** на датасете ~300k комментариев. "
45
+ "Accuracy на отложенном тесте — 96%. "
46
+ "Код: https://github.com/TeGPro/russian-toxic-classifier"
47
+ ),
48
+ examples=[
49
+ ["Спасибо большое, очень помогло, всё заработало!"],
50
+ ["Ты вообще читать умеешь? Бесполезный совет, только время потратил."],
51
+ ["Отличная статья, давно искал такое объяснение."],
52
+ ],
53
+ flagging_mode="never",
54
+ )
55
+
56
+ if __name__ == "__main__":
57
+ demo.launch()
model.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn as nn
2
+ from transformers import AutoModel
3
+
4
+
5
+ class BertClassifier(nn.Module):
6
+ def __init__(self, n_classes=2):
7
+ super().__init__()
8
+ self.bert = AutoModel.from_pretrained("cointegrated/rubert-tiny2")
9
+ self.classifier = nn.Linear(312, n_classes)
10
+
11
+ def forward(self, input_ids, attention_mask):
12
+ outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
13
+ cls_output = outputs.last_hidden_state[:, 0, :]
14
+ logits = self.classifier(cls_output)
15
+ return logits
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ torch>=2.0.0
2
+ transformers>=4.30.0
3
+ gradio>=5.0.0